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

FDDを動かすためのタスクを妄想してみる。

まずは初期化! anchor.png Edit

FDD用のDMAバッファやらBIOSからの情報やらを設定しないといけないよね?

Page Top

FDD情報の取得 anchor.png Edit

・・・スマソ。今回はパス。

どうせまだFDD起動だし

Page Top

DMAバッファ anchor.png Edit

初期化せんと使えん。なので、

初期化コードだけど、32bit化して各部のメモリコピーが済み、セグメントレジスタの設定が安定したらってことでどうだろうか?

とりあえず、bootpack.cのマウス許可の後当たりに置いてみた。

io_out8(PIC0_IMR, 0xb8); /* PITとPIC1とキーボードを許可とFDCの許可(10111000) */
io_out8(PIC1_IMR, 0xef); /* マウスを許可(11101111) */
fifo32_init(&keycmd, 32, keycmd_buf, 0);

//DMAの初期化
io_out8(0x00d6, 0xc0); /* マスタのch0をカスケードモードに */
io_out8(0x00c0, 0x00); /* スレーブのDMAを許可 */
io_out8(0x000a, 0x06); /* マスタのch2のDMAをマスク */      

memtotal = memtest(0x00400000, 0xbfffffff);

うむ・・・たぶん大丈夫だと思う。

Page Top

FDアクセス用のタスク anchor.png Edit

これ専用のタスクを設置してみよう。

まず、bootpac.cの先頭部でタスク作成。じゃ、名前はtask_fdとでもしておこうか。

	unsigned char *buf_back, buf_mouse[256];
	struct SHEET *sht_back, *sht_mouse;
	struct TASK *task_a, *task,*task_fd;
	static char keytable0[0x80] = {

そして、このtask_fdは常に動いている。他のタスクが指令を出せばいつでも単独でFDを読み込み、その結果を番地で返す。ただし用が終わるとほぼスリープ状態でじっと待っている。そんなタスクにしないといけない。

  • そういうわけで、こんなところにこんあタスク定義を置いてみた。
                        :
    	*((int *) 0x0fe4) = (int) shtctl;
    	task_a->langmode = 0;
    
    	/*fdタスク実験部*/
    	task_fdctl  = task_alloc();
    	task_fdctl->tss.esp = memman_alloc_4k(memman,64*1024)+64*1024;
    	task_fdctl->tss.eip = ( int ) &task_fdctl_main;
    	task_fdctl->tss.es = 1*8;
    	task_fdctl->tss.cs = 2*8;
    	task_fdctl->tss.ss = 1*8;
    	task_fdctl->tss.ds = 1*8;
    	task_fdctl->tss.fs = 1*8;
    	task_fdctl->tss.gs = 1*8;
    	task_run(task_fdctl,2,2);
    	/*=============================*/
    
    	/* sht_back */
    	sht_back  = sheet_alloc(shtctl);
                         :
  • あとは、この新設タスクがちゃんと動いてくれるかどうかをチェックするため、とりあえずtask_fd_main()をfd.c内に仮設置してみる。
void task_fdctl_main(){

  	struct FIFO32 fifo_fd;
	struct TIMER *timer_1s;
	int i = 0;
	int fifost, fifobuf[128];

	fifo32_init(&fifo_fd, 128, fifobuf, 0);
	timer_1s = timer_alloc();
	timer_init(timer_1s, &fifo_fd, 100);
	timer_settime(timer_1s, 100);
 
     	struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
  	unsigned char s[8];

		for(;;){

		  io_cli();
		  fifost = fifo32_get(&fifo_fd);
			if ( fifost = 100){
	  		  i = i++;;

			  sprintf(s, "%02X",i);
			  boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 31, 31);
			  putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FF00FF, s);
	timer_settime(timer_1s, 100);
			}
			
			io_sti();
		}
}
  • うむ。細かいところはアレだが、たぶんこれでタスクとしてはうまく動いているだろう。とりあえず雛形は完成としよう。
Page Top

場所と大きさ anchor.png Edit

たぶん、FDDの場合、シーク(シリンダの移動)に時間がかなりかかるらしい。逆に言えば、もしシリンダ移動なしで読み込めるような配置だったら一気に読んじゃったほうが高速だよね?(シークが必要ならさせる。で、その間にメモリ転送とかできるし)

なので、オイラはとりあえず、1シリンダx2(裏表)で、18x2x512B=18KB を確保しておくことにしようと思います。

場所はとりあえず、メモリマップから 0x00008400〜0x0000E3FFまでを確保することにしよう。

Page Top

FDタスクとの通信 anchor.png Edit

  • 当たり前だが、このFDコントロールタスクは指令を出さなければずっと眠っていなくてはいけないもの。
    • どこか他のタスクが指令を出す。
    • 受け取った指令により、FDタスクが「独自に・独立して」処理を行う。
    • 終了後、結果を元のタスクに返す
  • こういう動作が必要になるな。
  • はりぼてWikiのページだと、
    # データリード: [1] [セクタ番号] [セクタ数] [番地] [FIFO32*] [データ]
    # データライト: [2] [セクタ番号] [セクタ数] [番地] [FIFO32*] [データ]
  • とある。なるほど。先頭の値をコマンド化して、後続のデータをパラメータ化したりするのか!?
  • たとえば、こういうことをしたほうが確実かなぁ??
    # データリード: [1] [セクタ番号] [セクタ数] [番地] [FIFO32*] [データ][コマンド終了コード]
    # データライト: [2] [セクタ番号] [セクタ数] [番地] [FIFO32*] [データ][コマンド終了コード]
  • それともう一つ。データの運搬というか受け渡し。
    • taskAから、セクタを読めと指令。
    • FDタスク。指令を受信。
    • FDタスク、指令が実行可能なら実行。セクタを読む。
    • FDタスク、指令を終了してtaskAに通知。かつ、読み取ったデータをtaskAに運搬
  • ・・・まあいいや。とりあえず、一番根幹たる、「指定セクタを読む」だけを、まず実装してみよう。
Page Top

セクタ単体読み出し関数(API予備軍?)の実装。 anchor.png Edit

    • 必要なパラメータは、「論理セクタ番号」「読んだデータの格納場所」と、「終了ステータス」だね。
    • じゃ、こんなのを妄想してみる。
int fd_read_sector(int r_sec,int *data)
{
   int cc,hh,ss;        /*物理セクタ格納用*/

   if( r_sec > 2879 ){
       return -1;
     }

   ss = r_sec % 18 +1;          /* 論理セクタを物理セクタに変換*/
   hh = (r_sec / 18) % 2;
   cc = (r_sec / 18) /2 / 80;

   /*データリード: [1] [セクタ番号] [セクタ数] [番地] [FIFO32*] [データ]*/
   io_cli();
   fifo32_put(fd_ctl_task->fifo,1);
   fifo32_put(fd_ctl_task->fifo,ss);
   fifo32_put(fd_ctl_task->fifo,hh);
   fifo32_put(fd_ctl_task->fifo,cc);
   fifo32_put(fd_ctl_task->fifo,data);
   io_sti();

   return;
}
  • さてここで問題発生。FDタスクのfifoに送信って、どうやったらいいかな?
  • とりあえずこのFDコントロールタスクは、task_fdctlの名前でHariMain編集から読んでいるから、こいつから送れないだろうか??
fifo32_put(task_fdctl.fifo_fd,1);
  • ・・・だめだ。これではHariMain編集はtask_fdctlを知っているが、呼び出したタスク(コンソールタスク)はこれを知らない。やっぱ、グローバル関数化かなぁ・・・

うーん。そうか。とにかくFDタスクに変数としてFIFOを渡さないといけないのかな??? FDタスクはタスクだから、とにかく一度でも動かないと初期化も定義もしないわけだし・・・

んんん? まてよ? こういうことかな???

  • まず、メインルーチンであるHariMain編集内であるFIFO(じゃ、FIFO_Aとする)を定義。
  • 同じくそれをHariMain編集内で初期化。HariMain編集内ではごく普通に扱えるFIFOが1個できる。
  • FDタスクを初期化。しかし、例の方法で「パラメータ」を渡せるタイプのタスクにする。(task_fd_main(int *FIFO)とか
  • FDタスクを走らせる(task_run)する前に、この*fifo を FIFO_Aに当て込む。(例のスタックを使うというおかしな方法で渡す)
  • HariMain編集側では、単にFIFO_Aにputすれば、それがFDタスクへの指令になる
  • fd_task内でもこのタスクを読みこんでループ動作から分岐して作業を行う

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