- 追加された行はこの色です。
- 削除された行はこの色です。
*FDCドライバもどき・書きかけ
-眺めるだけですよ。実行は超危険です。FDDのモーターが壊れるかもしれません。
-実行はちょっと危険です。
-うちの環境ではまぁ動きますが、もしFDDのモーターが壊れたりしても責任は負いかねます。
**めも
***必要なFIFOバッファ
+「各タスクからfdc_taskにコマンドを送るため」と、「タイマー用」のFIFOバッファ
--コマンド処理後にタイマーを発効する。
--新しいコマンドがきたら中断、来なかったらモーターOFF
+割り込みを受け取るFIFOバッファ
--コイツはちょっとトクベツだ。
***セクタ番号からシリンダ・ヘッド・セクタを計算する
割り算の結果は、小数点以下切捨てで。
-シリンダ
C = セクタ番号 / 36
-ヘッド
H = (セクタ番号 - C * 2) / 18
-セクタ
S = セクタ番号 - C - H + 1
**そーす
+INT06の割り込みがくるようにソース書き換え。
+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(&task_fdc->fifo, 3);
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();
io_cli();
fifo32_put(&task_fdc->fifo, 1);
fifo32_put(&task_fdc->fifo, 0x07);
fifo32_put(&task_fdc->fifo, 0x00);
io_sti();
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();
io_cli();
fifo32_put(&task_fdc->fifo, 1);
fifo32_put(&task_fdc->fifo, 0x0f);
fifo32_put(&task_fdc->fifo, h<<2);
fifo32_put(&task_fdc->fifo, c);
io_sti();
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;
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, "@");
char s[30];
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();
#if 0
if (fdc_stat.motorman == 1) {
/* モーターOFF */
timer_settime(timer, 300);
while (fifo32_status(&task_fdc->fifo) == 0) { task_sleep(task_fdc); }
i = fifo32_get(&task_fdc->fifo);
if (i == 4) {
/* タイマーがキタ */
io_out8(0x03f2, 0x0c);
fdc_stat.motorman = 0;
} else {
/* ちょ、これ次のコマンドwww */
timer_cancel(timer);
goto skip;
}
}
#endif
} else {
i = fifo32_get(&task_fdc->fifo);
io_sti();
if (i == 1) {
/* データリード */
while((io_in8(0x03f4) & 0x11) != 0) { task_sleep(task_fdc); } // 0になるまで待つ
j = fifo32_status(&task_fdc->fifo);
for (k = 0; k < j; k++) {
/* 送信アタタタタタ!!! */
while((io_in8(0x03f4) & 0xc0) != 0x80);
io_out8(0x03f5, fifo32_get(&task_fdc->fifo));
/* 動いてるか知らんけどタイマーキャンセル */
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 == 3) {
/* コマンド08 */
while((io_in8(0x03f4) & 0x10) != 0) { task_sleep(task_fdc); } // 0になるまで待つ
while((io_in8(0x03f4) & 0xc0) != 0x80);
io_out8(0x03f5, 0x08);
while((io_in8(0x03f4) & 0xc0) != 0xc0);
j = io_in8(0x03f5) & 0xc0;
if (j == 0x00) {
/* 正常終了 */
fdc_stat.result = 1;
} else if (j == 0x40) {
/* 異常終了 */
fdc_stat.result = 2;
} else {
/* OSのバグと見ていい */
fdc_stat.result = 3;
}
while((io_in8(0x03f4) & 0xc0) != 0xc0) { }
fdc_stat.cylinder = io_in8(0x03f5);
sprintf(s, "r=%02x c=%d", j, fdc_stat.cylinder);
putfonts((unsigned int *)(binfo->vram), binfo->scrnx, 0, 0, 0xffffff, s);
if (i == 4) {
/* FDDモーターOFF */
io_out8(0x03f2, 0x0c);
fdc_stat.motorman = 0;
}
}
}
}
void fdc_init(struct MEMMAN *memman)
{
int *fdc_fifo = (int *) memman_alloc_4k(memman, 128 * 4);
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_fifo, task_fdc);
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> */
+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();
-注意点
++PCがおかしくなってもあっきぃは責任は負わない。
++テストコードは激しく連続実行するとFDDが弱るのでやってはいけない。せいぜい1.5秒間隔で。
++モーター自動ON/OFFがイイカンジ。
++素敵なデバッグ表示つき。
*コメント欄
#pcomment