FDCドライバもどき・書きかけ

めも

advance/FDC

http://hrb.osask.jp/wiki/index.php?advance%2FFDC

必要なFIFOバッファ

  1. 「各タスクからfdc_taskにコマンドを送るため」と、「タイマー用」のFIFOバッファ
    • コマンド処理後にタイマーを発効する。
    • 新しいコマンドがきたら中断、来なかったらモーターOFF
  2. 割り込みを受け取るFIFOバッファ
    • コイツはちょっとトクベツだ。

セクタ番号からシリンダ・ヘッド・セクタを計算する

割り算の結果は、小数点以下切捨てで。

そーす

  1. INT06の割り込みがくるようにソース書き換え。
  2. bootpack.cの最初のほうに張る。
    /* <fdc.c> */
    
    struct FIFO32 *fdc_fifo;
    struct TASK *task_fdc;
    struct FDC_STAT {
        int motorman;
        int 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, 125);
            while (fifo32_status(&fifo) == 0) { task_sleep(task_fdc); }
            fifo32_get(&fifo);  // 空読み
            fdc_stat.motorman = 1;
        }
        return;
    }
    
    void fdc_sendcommand(int data)
    {
        /* FDCにコマンドを送る */
        while((io_in8(0x03f4) & 0xc0) != 0x80);
        io_out8(0x03f5, data);
        return;
    }
    
    int 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 = 1;
        } else if (i == 0x40) {
            /* 異常終了 */
            fdc_stat.result = 2;
        } else {
            /* OSのバグと見ていい */
            fdc_stat.result = 3;
        }
        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 h, int c)
    {
        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;
        int data[5], c, h, s;
        struct TIMER *timer;
        timer = timer_alloc();
        timer_init(timer, &task_fdc->fifo, 4);
    
        struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
        char str[30];
        // putfonts((unsigned int *)(binfo->vram), binfo->scrnx, 0, 0, 0xffffff, "@");
    
        for (;;) {
            io_cli();
            if (fifo32_status(&task_fdc->fifo) == 0) {
                if (fdc_stat.motorman == 1) {
                    /* 「モーターOFFしてもいいですか。」 */
                    timer_settime(timer, 300);  // 3秒待つ。
                }
                task_sleep(task_fdc);
                io_sti();
            } else {
                i = fifo32_get(&task_fdc->fifo);
                io_sti();
                if (i == 1) {
                    /* データリード */
                    /* 動いてるか知らんけどタイマーキャンセル */
                    timer_cancel(timer);
                    /* FIFOからコマンドを5個取得する */
                    for (j = 0; j < 5; j++) {
                        data[j] = fifo32_get(&task_fdc->fifo);
                    }
                    c = data[0] / 36;               // セクタ
                    h = (data[0] - c * 2) / 18;     // ヘッダ
                    s = data[0] - c - h + 1;        // セクタ
                    /* ここにDMACの設定 */
                    fdc_seek(h, c);
    j = fdc_stat.cylinder;
    sprintf(str, "r=%d c=%d", fdc_stat.result, fdc_stat.cylinder);
    putfonts((unsigned int *) (binfo->vram), binfo->scrnx, 280, j, 0xffffff, str);
                    /* コマンド送信アタタタタタ!!!
                    while((io_in8(0x03f4) & 0x11) != 0) { task_sleep(task_fdc); }   // 送信準備
                    fdc_sendcommand(0xE6);  // 読み込みコマンド
                    fdc_sendcommand(c);     // シリンダ
                    fdc_sendcommand(h);     // ヘッダ
                    fdc_sendcommand(s);     // セクタ
                    fdc_sendcommand(0x02);  // 以下おまじない
                    fdc_sendcommand(0x12);
                    fdc_sendcommand(0x01);
                    fdc_sendcommand(0xFF);  // 以上!
                    */
                }
                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);
        int fdc_fifobuf[32];
        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);   // コマンド・タイマー
        fifo32_init(fdc_fifo, 32, fdc_fifobuf, task_fdc);               // 割り込み
        fdc_stat.motorman = 0;
        return;
    }
    
    /* </fdc.c> */
  3. HariMainで、何かあいているキー(F12キーとか)を押したときに次のテストコードが実行されるようにしておく。
    io_cli();
    fifo32_put(&task_fdc->fifo, 1);//読み込みコマンドを送る合図1
    fifo32_put(&task_fdc->fifo, 1234);//これがセクタ番号
    fifo32_put(&task_fdc->fifo, 20);//以下、未実装に付き適当
    fifo32_put(&task_fdc->fifo, 1);
    fifo32_put(&task_fdc->fifo, 1);
    fifo32_put(&task_fdc->fifo, 1);//読み込みコマンド1ここまで
    fifo32_put(&task_fdc->fifo, 1);//読み込みコマンドを送る合図2
    fifo32_put(&task_fdc->fifo, 2345);//これがセクタ番号
    fifo32_put(&task_fdc->fifo, 20);//以下、未実装に付き適当
    fifo32_put(&task_fdc->fifo, 1);
    fifo32_put(&task_fdc->fifo, 1);
    fifo32_put(&task_fdc->fifo, 1);//読み込みコマンド2ここまで
    io_sti();

コメント欄

コメントはありません。 Comments/tmp/FDC?

お名前:

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