雑記帳
ここはhideyosiの雑記帳です。テケトーに書き散らしてるだけなので間違っていたりとは普通にしてます。信用度は相当低いことをあらかじめご了承を。またご覧のようにWikiを使ってますが、hideyosi意外は書き込めません。

FrontPage さーて。ザビビもついにリリースと相成りました。これからなにしていこうかな。

とりあえず、現在あっきーさが取り組んでいるFDの読み書きをオイラも試してみよう。 (多分できないとは思うけどね。(^^; )

まずはエミュで anchor.png Edit

はりぼてをAドライブ(起動)、そして今は亡き?Bドライブに適当なFDイメージを用意して、これを読んでみる実験〜。

Page Top

とりあえず一回体当たり! anchor.png Edit

はりぼてWikiにこんなページがあるので参考にしてなんかやってみよう。

ええと?なになに? 

  • FDCへはコマンドを送信して制御する
  • コマンドを送っても遅いのでIRQ-06でお返事がくるまで待つ

なるほどなるほど。 とりあえず現在はコンソールはシステム側で動いていたはず。コンソールに適当なコマンドを搭載して実験するのがよさそうですね。

・・・おっと!その前に、IRQ-06の割り込みが発生したらなにかさせないと。

これまでのパターンだと、こういう手の割り込みの信号はFIFOバッファに積んでメインルーチンに監視させるってパターンだったよね?

ええと。現在、キーボードやマウスの割り込みはどこでどうやって制御しているんだっけ・・・

Page Top

まずはIDT anchor.png Edit

割り込みを使えるようにするためには、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しないといけないんだっけね。

えーっと?そうすると、こうだよね?

IRQINT通常用途
00x20タイマー
10x21キーボード
20x22aaaa
30x23aaaa
40x24aaaa
50x25aaaa
60x26aaaa
70x27aaaa
80x28aaaa
90x29aaaa
100x2Aaaaa
110x2Baaaa
120x2Cマウス
130x2Daaaa
140x2Eaaaa
150x2Faaaa

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のコマンド結果)がくれば受信できるはずだ。

Page Top

コマンドを送ってみよう anchor.png Edit

さて、じゃ、コマンドを送信してみたいんだけど、どうすればいいかな??はりぼて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;
}
/*---------------------*/

最終更新: 2024-01-06 (土) 22:39:09 (JST) (114d) by