雑記帳
ここはhideyosiの雑記帳です。テケトーに書き散らしてるだけなので間違っていたりとは普通にしてます。信用度は相当低いことをあらかじめご了承を。またご覧のようにWikiを使ってますが、hideyosi意外は書き込めません。
1: 2007-01-21 (日) 11:32:43 ソース バックアップ No.1 を復元して編集 現: 2024-01-06 (土) 22:39:09 ソース 編集
Line 8: Line 8:
はりぼてをAドライブ(起動)、そして今は亡き?Bドライブに適当なFDイメージを用意して、これを読んでみる実験〜。 はりぼてをAドライブ(起動)、そして今は亡き?Bドライブに適当なFDイメージを用意して、これを読んでみる実験〜。
 +
 +*とりあえず一回体当たり! [#e4650372]
 +はりぼてWikiに[[こんなページ:http://hrb.osask.jp/wiki/index.php?advance%2FFDC]]があるので参考にしてなんかやってみよう。
 +
 +ええと?なになに? 
 +
 +-FDCへはコマンドを送信して制御する
 +-コマンドを送っても遅いのでIRQ-06でお返事がくるまで待つ
 +
 +なるほどなるほど。
 +とりあえず現在はコンソールはシステム側で動いていたはず。コンソールに適当なコマンドを搭載して実験するのがよさそうですね。
 +
 +・・・おっと!その前に、IRQ-06の割り込みが発生したらなにかさせないと。
 +
 +これまでのパターンだと、こういう手の割り込みの信号はFIFOバッファに積んでメインルーチンに監視させるってパターンだったよね?
 +
 +ええと。現在、キーボードやマウスの割り込みはどこでどうやって制御しているんだっけ・・・
 +
 +***まずはIDT [#cd689a3e]
 +割り込みを使えるようにするためには、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|通常用途|h
 +|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のコマンド結果)がくれば受信できるはずだ。
 +
 +
 +**コマンドを送ってみよう [#g01cffbc]
 +さて、じゃ、コマンドを送信してみたいんだけど、どうすればいいかな??はりぼてWikiには、
 +
 + まず io_in8(0x03f4) & 0x11 の値が0になるのを待ちます
 +
 +とあるけど、これ、どういう意味だろう??
 +
 +[[OS-Wiki:http://community.osdev.info/index.php?(FDC)765A]]にも資料があるな。
 +ん????。読み出したデータのおのおののビットに意味があるの??。つーことは、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;
 + }
 + /*---------------------*/