/* <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> */