えーっと。最初に言えるのは、
キタ━━━━(゚∀゚)━━━━
ってことでしょう。エミュ上ではありますが、FDが読めました。以下のコードで、とりあえずセクター19の内容(バイナリエディタでイメージを開くと、0X004800付近ですな)を表示してくれた。
void cmd_fdtest(struct CONSOLE *cons) { char s[30]; char counter = 3; int p; char reza; 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); while(io_in8(0x03f4) & 0xC0 != 0x80 ){} io_out8(0x03f5, 0x07); sprintf(s, "Send 0x03f5 [0x07]\n"); cons_putstr0(cons, s); while(io_in8(0x03f4) & 0xC0 != 0x80 ){} io_out8(0x03f5, 0x00); sprintf(s, "Send 0x03f5 [0x00]\n"); cons_putstr0(cons, s); //--------------------------------------- //DMAの初期化 io_out8(0x00d6, 0xc0); /* マスタのch0をカスケードモードに */ io_out8(0x00c0, 0x00); /* スレーブのDMAを許可 */ io_out8(0x000a, 0x06); /* マスタのch2のDMAをマスク */ //読み込み用にセットアップ //モード設定:デマンド・アドレス増加方向・メモリへの書き込み・ch2 io_out8(0x000b, 0x06); // バイト数の設定 io_out8(0x0005, 0xff); io_out8(0x0005, 1 * 2 - 1); /* メモリ番地の設定 */ io_out8(0x0004, 0x000a0000 & 0xff); io_out8(0x0004, (0x000a0000 >> 8) & 0xff); io_out8(0x0081, (0x000a0000 >> 16) & 0xff); io_out8(0x000a, 0x02); /* マスタのch2のDMAをマスク解除 */ //読み込み用のFDCコマンド発行! // (FDCへのコマンド送信開始)(FATの情報を) //E6] [H<<2] [C] [H] [S] [02] [12] [01] [FF] (INT) //: [ST0] [ST1] [ST2] [C] [H] [S] [02] while(io_in8(0x03f4) & 0xC0 != 0x80 ){} io_out8(0x03f5, 0xE6); sprintf(s, "Send [E6],"); cons_putstr0(cons, s); while(io_in8(0x03f4) & 0xC0 != 0x80 ){} io_out8(0x03f5, 0x00<<2); sprintf(s, "[0x00<<2],"); cons_putstr0(cons, s); while(io_in8(0x03f4) & 0xC0 != 0x80 ){} io_out8(0x03f5, 0x01); sprintf(s, "[0x01],"); cons_putstr0(cons, s); while(io_in8(0x03f4) & 0xC0 != 0x80 ){} io_out8(0x03f5, 0x00); sprintf(s, "[0x00],"); cons_putstr0(cons, s); while(io_in8(0x03f4) & 0xC0 != 0x80 ){} io_out8(0x03f5, 0x01); sprintf(s, "[0x01],"); cons_putstr0(cons, s); while(io_in8(0x03f4) & 0xC0 != 0x80 ){} io_out8(0x03f5, 0x02); sprintf(s, "[0x02],"); cons_putstr0(cons, s); while(io_in8(0x03f4) & 0xC0 != 0x80 ){} io_out8(0x03f5, 0x12); sprintf(s, "[0x12],"); cons_putstr0(cons, s); while(io_in8(0x03f4) & 0xC0 != 0x80 ){} io_out8(0x03f5, 0x01); sprintf(s, "[0x01],"); cons_putstr0(cons, s); while(io_in8(0x03f4) & 0xC0 != 0x80 ){} io_out8(0x03f5, 0xFF); sprintf(s, "[0xFF]\n"); cons_putstr0(cons, s); // (FDCが実行) //3秒待ち counter=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(); // (FDCからのINT) sprintf(s, "Come on! INT!\n"); cons_putstr0(cons, s); // (FDCからリザルトステータス読み取り) while(io_in8(0x03f4) & 0xC0 != 0xC0 ){} reza = io_in8(0x03f5); sprintf(s, "[ST0]&0xC0=%X,",reza & 0xC0); cons_putstr0(cons, s); while(io_in8(0x03f4) & 0xC0 != 0xC0 ){} reza = io_in8(0x03f5); sprintf(s, "ST1=%X,",reza); cons_putstr0(cons, s); while(io_in8(0x03f4) & 0xC0 != 0xC0 ){} reza = io_in8(0x03f5); sprintf(s, "ST2=%X,",reza); cons_putstr0(cons, s); while(io_in8(0x03f4) & 0xC0 != 0xC0 ){} reza = io_in8(0x03f5); sprintf(s, "[C]=%X,",reza); cons_putstr0(cons, s); while(io_in8(0x03f4) & 0xC0 != 0xC0 ){} reza = io_in8(0x03f5); sprintf(s, "[H]=%X,",reza); cons_putstr0(cons, s); while(io_in8(0x03f4) & 0xC0 != 0xC0 ){} reza = io_in8(0x03f5); sprintf(s, "[S]=%X\n",reza); cons_putstr0(cons, s); while(io_in8(0x03f4) & 0xC0 != 0xC0 ){} reza = io_in8(0x03f5); sprintf(s, "Last Code = %X\n",reza); cons_putstr0(cons, s); //------------------------------------------- //マスタのch2のDMAをマスク */ io_out8(0x000a, 0x06); char *vvv; vvv = 0x000a0000; for(;;){ vvv++; if (vvv == 0x000a002f){break;} sprintf(s,"%02x,",*vvv); cons_putstr0(cons, s); } sprintf(s, "End...\n"); cons_putstr0(cons, s); timer_free(&timerx); return; } /*---------------------*/
さて、じゃ、なんで前はうまくいかなかったのか?ってことだけど、
- 送信コマンドを間違えていた <バカ
- DMAの設定をイマイチ理解していない
まず、送信コマンド。2のコード見てもらえばわかるよね?。間違ってます・・・orz
さて、次にもう一個。DMACの設定部分。
Kタンのサンプルで一番解らなかったのが、
io_out8(0x0005, 0xff); io_out8(0x0005, セクタ数 * 2 - 1); /* バイト数の設定 */ io_out8(0x0004, 番地 & 0xff); io_out8(0x0004, (番地 >> 8) & 0xff); io_out8(0x0081, (番地 >> 16) & 0xff); /* メモリ番地の設定 */
この、セクタ数や番地のこと。
これ、よーく考えてみて初めて意味がわかった。まず、io_out8ってことは、全てのデータは8bitだということ!
そう。8bit。0x00〜0xFF(十進数で256) までしか設定できないわけ。
「え?それじゃ、セクター(512)を設定したり、バッファのメモリ番地を0x000a0000に設定したりはできないの!?」
と、こういう話になりますね?。
ここらへんのレジスタは特殊で、同じレジスタに連続で2回とか書き込むと16bitや20bitと解釈してくれるという。エラク特殊な形なんですねぇ〜。(なーーんだ!)
だから、もう一度上のサンプルを良く見ると、こんなふうに割れませんか?
/* バイト数の設定 */ io_out8(0x0005, 0xff); io_out8(0x0005, セクタ数 * 2 - 1); /* メモリ番地の設定 */ io_out8(0x0004, 番地 & 0xff); io_out8(0x0004, (番地 >> 8) & 0xff); io_out8(0x0081, (番地 >> 16) & 0xff);
そう。こうやって、一見無意味に複数回書き込んでいるのがまさにそれなんです。
さらに!!。セクタ数や番地の後ろにあるヘンテコな計算式。これは、8bit以上になる各数値を自動的に8bitに切り出してくれる計算式なんですねぇ〜。
じゃ、たとえば、セクターを一つだけ。DMAバッファを0x000a0000番地にして読み込みを行いたいとしましょう。
セクター1個は通常512バイト。16進数にすると、0x0200になるよね。で、OS-Wikiの資料によると、
データ転送はDMAのTC(ターミナルカウント)に依存しており、この仕様のために、カウント値は実際の転送量-1をセットする。
とのことなので、ここは 0x0200 - 1 = 0x01FF をセットします。
ほらね!!!
io_out8(0x0005, 0xFF); io_out8(0x0005, 0x01); <- セクタ数(1個) * 2 - 1 = 1なので。
同じくDMAバッファのメモリ番地の設定。DMAバッファは仕様上、0x00ffffff以下でないと設置できません。よーく見て。最大は0xffffffでしょ? つまり、8bit三回分だよね?
今回の例。0x0a0000を設置したいとした場合、こうなる!
io_out8(0x0004, 0x00); <- 0x0a0000 & 0xff = 0 io_out8(0x0004, 0x00); <- (0x0a0000 >> 8) & 0xff = 0 io_out8(0x0081, 0x0a); <- (0x0a0000 >> 16) & 0xff = 0a
ほらね。こういう書式になるわけ。ちょっと値を複雑にしてみるともっと解るよ。
例:0xa1b2c3 番地を設定したい場合 io_out8(0x0004, 0xc3); <- 0xa1b2c3 & 0xff = c3 io_out8(0x0004, 0xb2); <- (0xa1b2c3 >> 8) & 0xff = b2 io_out8(0x0081, 0xa1); <- (0xa1b2c3 >> 16) & 0xff = a1
これでもう、解ったでしょ〜? (^^