FrontPage さーて。ザビビもついにリリースと相成りました。これからなにしていこうかな。
とりあえず、現在あっきーさが取り組んでいるFDの読み書きをオイラも試してみよう。 (多分できないとは思うけどね。(^^; )
とりあえず一回体当たり!
はりぼてWikiにこんなページがあるので参考にしてなんかやってみよう。
ええと?なになに?
- FDCへはコマンドを送信して制御する
- コマンドを送っても遅いのでIRQ-06でお返事がくるまで待つ
なるほどなるほど。 とりあえず現在はコンソールはシステム側で動いていたはず。コンソールに適当なコマンドを搭載して実験するのがよさそうですね。
・・・おっと!その前に、IRQ-06の割り込みが発生したらなにかさせないと。
これまでのパターンだと、こういう手の割り込みの信号はFIFOバッファに積んでメインルーチンに監視させるってパターンだったよね?
ええと。現在、キーボードやマウスの割り込みはどこでどうやって制御しているんだっけ・・・
まずはIDT
割り込みを使えるようにするためには、IDTを設定しなくちゃいけない。まずはdsctbl.cに、IRQ6を登録してみよう。ちなみに現在は・・・・
load_idtr(LIMIT_IDT, ADR_IDT); /* IDTの設定 */ set_gatedesc(idt + 0x0c, (int) asm_inthandler0c, 2 * 8, AR_INTGATE32); set_gatedesc(idt + 0x0d, (int) asm_inthandler0d, 2 * 8, AR_INTGATE32); set_gatedesc(idt + 0x20, (int) asm_inthandler20, 2 * 8, AR_INTGATE32); set_gatedesc(idt + 0x21, (int) asm_inthandler21, 2 * 8, AR_INTGATE32); set_gatedesc(idt + 0x2c, (int) asm_inthandler2c, 2 * 8, AR_INTGATE32); set_gatedesc(idt + 0x40, (int) asm_hrb_api, 2 * 8, AR_INTGATE32 + 0x60);
これは5日目と6日目にやった状態とほぼ同じかな?。とりあえずここいらへんをもう一度読んでみた。
うむむ。けっこう忘れてるなぁ。そうか。IRQ番号とINT番号はピタっと対応していない。(P130参照)_0x20しないといけないんだっけね。
えーっと?そうすると、こうだよね?
IRQ | INT | 通常用途 |
0 | 0x20 | タイマー |
1 | 0x21 | キーボード |
2 | 0x22 | aaaa |
3 | 0x23 | aaaa |
4 | 0x24 | aaaa |
5 | 0x25 | aaaa |
6 | 0x26 | aaaa |
7 | 0x27 | aaaa |
8 | 0x28 | aaaa |
9 | 0x29 | aaaa |
10 | 0x2A | aaaa |
11 | 0x2B | aaaa |
12 | 0x2C | マウス |
13 | 0x2D | aaaa |
14 | 0x2E | aaaa |
15 | 0x2F | aaaa |
12日目からタイマー割り込みを後付けで導入しているので、ここらへんの手法を参考に実装してみまそー!
まずとりあえずIDTテーブルを書き換えちゃう。
load_idtr(LIMIT_IDT, ADR_IDT); /* IDTの設定 */ set_gatedesc(idt + 0x0c, (int) asm_inthandler0c, 2 * 8, AR_INTGATE32); set_gatedesc(idt + 0x0d, (int) asm_inthandler0d, 2 * 8, AR_INTGATE32); set_gatedesc(idt + 0x20, (int) asm_inthandler20, 2 * 8, AR_INTGATE32); set_gatedesc(idt + 0x21, (int) asm_inthandler21, 2 * 8, AR_INTGATE32); /*ここ。IRQ6。フロッピーからのお返事 set_gatedesc(idt + 0x26, (int) asm_inthandler26, 2 * 8, AR_INTGATE32); set_gatedesc(idt + 0x2c, (int) asm_inthandler2c, 2 * 8, AR_INTGATE32); set_gatedesc(idt + 0x40, (int) asm_hrb_api, 2 * 8, AR_INTGATE32 + 0x60);
さてこれだけじゃダメ。asm_inthandler26という関数(正確には番地ね)を設置してやらないといけない。これはnaskfunc.nas内に置かれている。P234を参考に実装。(とは言ってもほぼ丸写しでOKかな。)
_asm_inthandler26: PUSH ES PUSH DS PUSHAD MOV EAX,ESP PUSH EAX MOV AX,SS MOV DS,AX MOV ES,AX CALL _inthandler26 POP EAX POPAD POP DS POP ES IRETD
独立させておいたほうがよさそうなので、fd.cというファイルを追加した。内容はとりあえずなにもしない関数を設置。(これもP234を参照した)
void inthandler26(int *esp) { return; }
さて。このままうっかりメイクしておもいっきりエラーを吐かれてしまった。(笑 分割コンパイルしているのだ。ちゃんとbootpac.cに新関数を書いておかないとね。
よーし! OK。とりあえず設置は完了したぞ。じゃまず、この割り込みがやってきたらどうするか実装してみようかな。
まずはやっぱり、ここへ来てもあの手法が一番簡単で確実だよね。P137のキーボードのコードを表示するやつ。
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO; unsigned char data, s[4]; io_out8(PIC0_OCW2, 0x61); /* IRQ-01受付完了をPICに通知 */ data = io_in8(PORT_KEYDAT); sprintf(s, "%02X", data); boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31); putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s); return;
これをほぼそのままパクッて設置してみよう。
ちなみに、これがちゃんと現在でも稼動するかどうかあやしいのでキーボードのほうにも設置。(確認のため)
void inthandler21(int *esp) { int data; io_out8(PIC0_OCW2, 0x61); /* IRQ-01受付完了をPICに通知 */ data = io_in8(PORT_KEYDAT); fifo32_put(keyfifo, data + keydata0); /*実験部分*/ struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO; unsigned char s[4]; sprintf(s, "%02X", data); boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31); putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s); /*-------------------*/ return; }
よーし!OK。この手法はまだちゃんと使えるようだね。じゃ、これと同じように、FDからの割り込みが来た場合も反応できるようにしておこう。
fd.c
/* フロッピー関係 */
#include <stdio.h> #include "bootpack.h" void inthandler26(int *esp) /* FDコントローラからの割り込み */ { /*実験部分*/ io_out8(PIC0_OCW2, 0x66); /* IRQ-06受付完了をPICに通知 */ struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO; unsigned char s[4]; sprintf(s, "%02X", data); boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31); putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FF00FF, s); /*-------------------*/ return; }
よしよし! 無事コンパイルできたな。たぶんこれで、IRQ-6から割り込み(FDのコマンド結果)がくれば受信できるはずだ。
コマンドを送ってみよう
さて、じゃ、コマンドを送信してみたいんだけど、どうすればいいかな??はりぼてWikiには、
まず io_in8(0x03f4) & 0x11 の値が0になるのを待ちます
とあるけど、これ、どういう意味だろう??
OS-Wikiにも資料があるな。 ん????。読み出したデータのおのおののビットに意味があるの??。つーことは、0X11って 10001でしょ?。 「&」って、読み出したデータをand演算しろってこと?
うーん。あってるかどうかわからんが、とにもかくにもコマンドラインにこんなコマンドを実装。
/*FDの実験*/ void cmd_fdtest(struct CONSOLE *cons) { char a; a = io_in8(0x03f4); int s[70]; sprintf(s, "0x03f4 = %d, 0x11 & = %d",a,a & 0x11); cons_putstr0(cons, s); cons_newline(cons); return; } /*---------------------*/
結果、ほぼいつでも0であることがわかった。
はりぼてWikiでは、この確認が終わったら
次に以下を送信したいバイト数だけ繰り返します。 * io_in8(0x03f4) & 0xc0 が 0x80 になるのを待つ * io_out8(0x03f5, データ);
とある。ええと。これはどういうことかな? たとえば、シリンダ0へのシークを行いたい場合は、[07] [00] (INT) って書いてあるけど、これは
- io_in8(0x03f4) & 0xc0 が 0x80 になるのを待つ(まだかな〜?)
- よし! 0x80になったぞ!!
- io_out8(0x03f5, 0x07); でコマンドを送信!
- 再びio_in8(0x03f4) & 0xc0 が 0x80 になるのを待つ(まだかな〜?)
- よし! 0x80になったぞ!!
- こんどはio_out8(0x03f5, 0x00); でコマンドを送信!
- コマンドは送ったぞ。あとは、IRC6からお返事が来るまで待とう
- よし!割り込みが来た! ステータスレジスタを見て、成功したか失敗かを確認しなくちゃ!
・・・っとまあ、こういうことでいいのかなぁ????
・・・ところで、このFDの制御はどうも1秒とか3秒とかそういう時間の制御が必要ではないかと感じ始めた。なんかだんだん大げさになってくるけど、APIもあるし、タイマー制御してみることにしよう!!
ええと。このへんのことはP507あたりに書いてあるのでと。
そんなわけで、こんな内臓コマンドを試作して実行してみたが、割り込みもなにも発生しないようだ。コマンドの解釈が間違っているのだろうなぁ・・・
/*FDの実験*/ void cmd_fdtest(struct CONSOLE *cons) { char s[30]; char counter = 3; int p; struct FIFO32 timerfifox; struct TIMER *timerx; int timerbuf[128]; fifo32_init(&timerfifox,128,timerbuf,0); timerx = timer_alloc(); timer_init(timerx,&timerfifox,128); timer_settime(timerx,100); //3秒待ち for(;;){ io_cli(); p = fifo32_get(&timerfifox); if (counter == 0){break;} if( p == 128 ){ sprintf(s, "Wait %dSec...\n",counter); cons_putstr0(cons, s); counter--; timer_settime(timerx,100); } io_sti(); } io_sti(); //0x03f4のチェック sprintf(s, "Check 0x03f4"); cons_putstr0(cons, s); cons_newline(cons); char a; a = io_in8(0x03f4);a = a & 0x11; if ( a == 0 ) { sprintf(s, "OK! 0x03f4 & 0x11 is 0!"); cons_putstr0(cons, s); cons_newline(cons); } //コマンドの送信 sprintf(s, "Start command send..."); cons_putstr0(cons, s); cons_newline(cons); io_out8(0x03f5, 0x07); sprintf(s, "Send 0x03f5 [0x07]"); cons_putstr0(cons, s); cons_newline(cons); while(io_in8(0x03f4) & 0xC0 == 0x80 ) io_out8(0x03f5, 0x00); sprintf(s, "Send 0x03f5 [0x00]"); cons_putstr0(cons, s); cons_newline(cons); timer_free(&timerx); return; } /*---------------------*/