/* <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 FIFO32 fifo;
    int fifobuf[32];
    struct TIMER *timer;
    fifo32_init(&fifo, 32, fifobuf, 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;
}

unsigned 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, k, errcnt = 0;
    unsigned int data[5], result[7];
    char now_c, now_h, now_s;
    int addr;
    int fdc_fifobuf[32];
    struct TIMER *timer;

    /* for Debug. */
    struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
    int newline = 0;
    char s[50];
    // putfonts((unsigned int *)(binfo->vram), binfo->scrnx, 0, 0, 0xffffff, "@");

    /* 割り込み */
    fifo32_init(fdc_fifo, 32, fdc_fifobuf, task_fdc);
    /* タイマー */
    timer = timer_alloc();
    timer_init(timer, &task_fdc->fifo, 4);
    /* DMACの初期設定 */
    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);            /* モーターOFFを阻止 */
                for (j = 0; j < 5; j++) {
                    /* FIFOからコマンドを5個取得する */
                    data[j] = fifo32_get(&task_fdc->fifo);
                }
sprintf(s, "DATA: [0]%d [1]%d [2]%02x [3]%d [4]%d", data[0], data[1], data[2], data[3], data[4]);
putfonts((unsigned int *) (binfo->vram), binfo->scrnx, 0, newline, 0xffffff, s);
newline+=16;
                /* 読み込みmain */
                now_c =  data[0] / 36;          /* セクタ */
                now_h = (data[0] / 18) % 2;     /* ヘッダ */
                now_s = 1 + data[0] % 18;       /* セクタ */
                addr  = data[2];                /* DMACに渡すアドレス */
sprintf(s, "SET: C=%d H=%d S=%d", now_c, now_h, now_s);
putfonts((unsigned int *) (binfo->vram), binfo->scrnx, 0, newline, 0xffffff, s);
newline+=16;
                fdc_seek(now_c, now_h);
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;
                for (k = 0; k < data[1]; k++) {
                    /* DMACの設定 */
                    io_out8(0x000b, 0x06);                  /* モード設定:デマンド,アドレス増加方向,メモリへ書き込み,ch2 */
                    io_out8(0x0005, 0xff);                  /* バイト数の設定(1セクタずつ) */
                    io_out8(0x0005, 1);
                    io_out8(0x0004, addr & 0xff);           /* メモリ番地の設定 */
                    io_out8(0x0004, (addr >> 8) & 0xff);
                    io_out8(0x0081, (addr >> 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);
//wait1
                    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をマスク */
//wait2

                    if ((result[0] & 0xc0) != 0x00) {
                        /* 異常終了 */
                        /* とりあえず今のところはループカウントから1を引いてやり直し */
                        errcnt++;
sprintf(s, "Result: [0]%02x [1]%02x [2]%02x %02x %02x %02x %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);
sprintf(s, "        C=%d H=%d S=%d", now_c, now_h, now_s);
putfonts((unsigned int *) (binfo->vram), binfo->scrnx, 0, newline+16, 0xffffff, s);
newline+=32;
                        if (errcnt == 3) {
                            fdc_seek0();
                            fdc_seek(now_c, now_h);
                            k--;
                            continue;
                        } else if (errcnt == 6) {
                            errcnt = 0;
                        } else {
                            k--;
                            continue;
                        }
                    }
                    errcnt = 0;
                    addr += 512;
                    now_s++;
                    if (now_s == 19) {
                        now_h++;
                        now_s = 1;
                        if (now_h == 2) {
                            now_c++;
                            now_h = 0;
                            fdc_seek(now_c, now_h);
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;
                        }
sprintf(s, "SET: C=%d H=%d S=%d", now_c, now_h, now_s);
putfonts((unsigned int *) (binfo->vram), binfo->scrnx, 0, newline, 0xffffff, s);
newline+=16;
                    }
if (592 <= newline) {
    boxfill((unsigned int *) (binfo->vram), binfo->scrnx, 0x3a6ea5, 0, 0, 400, 600);
    newline=0;
}
                }

sprintf(s, "%x %x", *((unsigned char *) 0x00400000), *((unsigned char *) 0x00400001));
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);
    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]