- 追加された行はこの色です。
- 削除された行はこの色です。
/* <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> */