/* <fdc.c> */
 
 struct FIFO32 *fdc_fifo;
 struct TASK *task_fdc;
 struct FDC_STAT {
     char motorman;
     char result, cylinder;
 } fdc_stat;
 
 void inthandler26(int *esp)
 /* FDCからの割り込み */
 {
     io_in8(0x03f4); /* から読み:IRQにCPUが気づいたことをFDCへ教えてあげる */
     io_out8(PIC0_OCW2, 0x66);   /* IRQ-06を終了 */
     fifo32_put(fdc_fifo, 3);
     return;
 }
 
 void motor_on(void)
 {
     struct TIMER *timer;
     struct FIFO32 fifo;
     int fifo_buf[32];
     fifo32_init(&fifo, 32, fifo_buf, task_fdc);
     timer = timer_alloc();
     timer_init(timer, &fifo, 1);
 
     if (fdc_stat.motorman == 0) {
         /* モーターON */
         io_out8(0x03f2, 0x1c);
         timer_settime(timer, 150);
         while (fifo32_status(&fifo) == 0) { task_sleep(task_fdc); }
         fifo32_get(&fifo);  // 空読み
         fdc_stat.motorman = 1;
     }
     return;
 }
 
 void fdc_sendcommand(char data)
 {
     /* FDCにコマンドを送る */
     while((io_in8(0x03f4) & 0xc0) != 0x80);
     io_out8(0x03f5, data);
     return;
 }
 
 char fdc_receivedata(void)
 {
     while((io_in8(0x03f4) & 0xc0) != 0xc0);
     return io_in8(0x03f5);
 }
 
 void fdc_getstatus(void)
 {
     int i;
     while((io_in8(0x03f4) & 0x10) != 0) { task_sleep(task_fdc); }   // コマンド送信準備
     fdc_sendcommand(0x08);
     i = fdc_receivedata() & 0xc0;
     if (i == 0x00) {
         /* 正常終了 */
         fdc_stat.result = 0;
     } else {
         /* 異常終了 */
         fdc_stat.result = 1;
     }
     fdc_stat.cylinder = fdc_receivedata();
     return;
 }
 
 void fdc_seek0(void)
 {
     motor_on();
     while((io_in8(0x03f4) & 0x11) != 0) { task_sleep(task_fdc); }   // 送信準備
     fdc_sendcommand(0x07);
     fdc_sendcommand(0x00);
     while (fifo32_status(fdc_fifo) == 0) { task_sleep(task_fdc); }  // 割り込み待ち
     fifo32_get(fdc_fifo);
     fdc_getstatus();
     return;
 }
 
 void fdc_seek(int c, int h)
 {
     motor_on();
     while((io_in8(0x03f4) & 0x11) != 0) { task_sleep(task_fdc); }   // 送信準備
     fdc_sendcommand(0x0f);
     fdc_sendcommand(h<<2);
     fdc_sendcommand(c);
     while (fifo32_status(fdc_fifo) == 0) { task_sleep(task_fdc); }  // 割り込み待ち
     fifo32_get(fdc_fifo);
     fdc_getstatus();
     return;
 }
 
 void fdc_task(void)
 {
     int i, j, newline = 0;
     char cylinder, head, sector, now_c, now_h, now_s;
     unsigned int data[5], result[7];
     int fdc_fifobuf[32];
     struct TIMER *timer;
 
     fifo32_init(fdc_fifo, 32, fdc_fifobuf, task_fdc);               // 割り込み
 
     timer = timer_alloc();
     timer_init(timer, &task_fdc->fifo, 4);
 
     struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
     char s[50];
     // putfonts((unsigned int *)(binfo->vram), binfo->scrnx, 0, 0, 0xffffff, "@");
 
     io_out8(0x00d6, 0xc0);  /* マスタのch0をカスケードモードに */
     io_out8(0x00c0, 0x00);  /* スレーブのDMAを許可 */
     io_out8(0x000a, 0x06);  /* マスタのch2のDMAをマスク */
 
     for (;;) {
         io_cli();
         if (fifo32_status(&task_fdc->fifo) == 0) {
             if (fdc_stat.motorman == 1) {
                 /* 「モーターOFFしてもいいですか。」 */
                 timer_settime(timer, 300);
             }
             task_sleep(task_fdc);
             io_sti();
         } else {
             i = fifo32_get(&task_fdc->fifo);
             io_sti();
             if (i == 1) {
                 /* データリード */
                 timer_cancel(timer);        /* 動いてるか知らんけどタイマーキャンセル */
                 for (j = 0; j < 5; j++) {
                     data[j] = fifo32_get(&task_fdc->fifo);  /* FIFOからコマンドを5個取得する */
                 }
                 cylinder =  data[0] / 36;                   /* セクタ */
                 head     = (data[0] / 18) % 2;              /* ヘッダ */
                 sector   = 1 + data[0] % 18;                /* セクタ */
 sprintf(s, "SET: C=%d H=%d S=%d", cylinder, head, sector);
 putfonts((unsigned int *) (binfo->vram), binfo->scrnx, 0, newline, 0xffffff, s);
 newline+=16;
                 fdc_seek(cylinder, head);
 sprintf(s, "SEEK: Result=%d C=%d", fdc_stat.result, fdc_stat.cylinder);
 putfonts((unsigned int *) (binfo->vram), binfo->scrnx, 0, newline, 0xffffff, s);
 newline+=16; 
                 /* 読み込みmain */
                 now_c = cylinder;
                 now_h = head;
                 now_s = sector;
                 do {
                     /* DMACの設定 */
                     io_out8(0x000b, 0x06);                      /* モード設定:デマンド・アドレス増加方向・メモリへの書き込み・ch2 */
                     io_out8(0x0005, 0xff);                      /* バイト数の設定 */
                     io_out8(0x0005, data[1] * 2 - 1);
                     io_out8(0x0004, data[2] & 0xff);
                     io_out8(0x0004, (data[2] >> 8) & 0xff);
                     io_out8(0x0081, (data[2] >> 16) & 0xff);    /* メモリ番地の設定 */
                     io_out8(0x000a, 0x02);                      /* マスタのch2のDMAをマスク解除 */
                     /* コマンド送信アタタタタタ!!!*/
                     while((io_in8(0x03f4) & 0x11) != 0) { task_sleep(task_fdc); }   // 送信準備
                     fdc_sendcommand(0xE6);      /* 読み込みコマンド */
                     fdc_sendcommand(now_h<<2);  /* ヘッダ<<2 */
                     fdc_sendcommand(now_c);     /* シリンダ */
                     fdc_sendcommand(now_h);     /* ヘッダ */
                     fdc_sendcommand(now_s);     /* セクタ */
                     fdc_sendcommand(0x02);      /* 以下おまじない */
                     fdc_sendcommand(0x12);
                     fdc_sendcommand(0x01);
                     fdc_sendcommand(0xFF);
                     while (fifo32_status(fdc_fifo) == 0) { task_sleep(task_fdc); }  // 割り込み待ち
                     fifo32_get(fdc_fifo);
                     for (j = 0; j < 7; j++) {
                         result[j] = fdc_receivedata();
                     }
                     io_out8(0x000a, 0x06);      /* マスタのch2のDMAをマスク */
 sprintf(s, "Result: [0]%02x [1]%02x [2]%02x [3]%d [4]%d [5]%d [6]%02x", 
     result[0], result[1], result[2], result[3], result[4], result[5], result[6]);
 putfonts((unsigned int *) (binfo->vram), binfo->scrnx, 0, newline, 0xffffff, s);
 newline+=16;
                     result[0] &= 0xc0;
                     if (result[0] != 0x00) {
                         /* 異常終了 */
                         /* とりあえず今のところは100%成功している想定で */
                         j = 1;
                     }
                     if (now_c != result[3] || now_h != result[4]) {
                         /* 次はC=result[3],H=result[4]にシーク */
                         fdc_seek(result[3], result[4]);
                         now_c = result[3];
                         now_h = result[4];
 sprintf(s, "New: C=%d H=%d -> SEEK: Result=%d C=%d", result[3], result[4], fdc_stat.result, fdc_stat.cylinder);
 putfonts((unsigned int *) (binfo->vram), binfo->scrnx, 0, newline, 0xffffff, s);
 newline+=16;
                     }
                     now_s = result[5];
                     j = result[3] * 36 + result[4] * 18 + (result[5] - 1);
                 } while (j <= data[0] + data[1]);
 
 sprintf(s, "%x", *((unsigned int *) 0x00400002));
 putfonts((unsigned int *) (binfo->vram), binfo->scrnx, 0, newline, 0xffffff, s);
 newline+=16;
             }
             if (i == 2) {
                 /* データライト */
                 /* 動いてるか知らんけどタイマーキャンセル */
                 timer_cancel(timer);
             }
             if (i == 4) {
                 /* FDDモーターOFF */
                 io_out8(0x03f2, 0x0c);
                 fdc_stat.motorman = 0;
             }
         }
     }
 }
 
 void fdc_init(struct MEMMAN *memman)
 {
     int *fdc_taskfifobuf = (int *) memman_alloc_4k(memman, 128 * 4);
     task_fdc = task_alloc();
     task_fdc->tss.esp = memman_alloc_4k(memman, 64 * 1024) + 64 * 1024;
     task_fdc->tss.eip = (int) &fdc_task;
     task_fdc->tss.es = 1 * 8;
     task_fdc->tss.cs = 2 * 8;
     task_fdc->tss.ss = 1 * 8;
     task_fdc->tss.ds = 1 * 8;
     task_fdc->tss.fs = 1 * 8;
     task_fdc->tss.gs = 1 * 8;
     task_run(task_fdc, 2, 2);
     fifo32_init(&task_fdc->fifo, 128, fdc_taskfifobuf, task_fdc);   // コマンド・タイマー
     fdc_stat.motorman = 0;
     return;
 }
 
 /* </fdc.c> */



Wikiの [ 一覧一覧 最終更新最終更新 ヘルプヘルプ   RSSRSS]