From: David Given Date: Wed, 18 Apr 2018 21:49:23 +0000 (+0200) Subject: Add motor spindown and multisector transfer support (although we only ever seem X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=a4572107666b2d21be0260571d9b3d3f062e92e7;p=FUZIX.git Add motor spindown and multisector transfer support (although we only ever seem to be asked for a single sector at a time). Fix so, so many bugs. --- diff --git a/Kernel/platform-nc200/devfd.c b/Kernel/platform-nc200/devfd.c index b5e12752..1822ab38 100644 --- a/Kernel/platform-nc200/devfd.c +++ b/Kernel/platform-nc200/devfd.c @@ -1,20 +1,12 @@ -/* - * Amstrad PCW8256 Floppy Driver - */ - #include #include #include #include #include #include +#include -bool fd765_ready; - -static uint8_t motorct; -static int8_t devsel = -1; - -__sfr __at 0xe0 fd_st; +static timer_t spindown_timer = 0; void devfd_init(void) { @@ -22,29 +14,28 @@ void devfd_init(void) if (!blk) return; + fd765_do_nudge_tc(); fd765_track = 0xff; /* not on a known track */ blk->transfer = devfd_transfer; blk->drive_lba_count = 1440; /* 512-byte sectors */ blkdev_scan(blk, 0); } -void devfd_spindown(void) -{ -} - -static void motor_on(int minor) +static void nudge_timer(void) { - minor; - mod_control(0x00, 0x20); /* motor on (active low) */ - fd765_ready = false; - mod_irqen(0x20, 0x00); /* enable FDC IRQ */ + di(); + spindown_timer = set_timer_sec(2); + ei(); } -static void motor_off(void) +/* (called from interrupt context) */ +void devfd_spindown(void) { - mod_control(0x20, 0x00); /* motor off (active low( */ - mod_irqen(0x00, 0x20); /* disable FDC IRQ */ - devsel = -1; + if (spindown_timer && timer_expired(spindown_timer)) + { + mod_control(0x20, 0x00); /* motor off (active low) */ + spindown_timer = 0; + } } /* Seek to track 0. */ @@ -56,31 +47,31 @@ static void fd_recalibrate(void) for (;;) { + nudge_timer(); fd765_do_recalibrate(); if (((fd765_status[0] & 0xf8) == 0x20) && !fd765_status[1]) break; } - fd765_track = 0; + /* Forget which track we've saught to */ + fd765_track = 0xff; } /* Set up the controller for a given block, seek, and wait for spinup. */ -static void fd_seek(void) +static void fd_seek(uint16_t lba) { - uint16_t block = blk_op.lba; - uint8_t track2 = block / 9; + uint8_t track2 = lba / 9; uint8_t newtrack = track2 >> 1; - fd765_sector = (block % 9) + 1; + fd765_sector = (lba % 9) + 1; fd765_head = track2 & 1; if (newtrack != fd765_track) { - fd765_track = newtrack; - for (;;) { - fd765_do_nudge_tc(); + fd765_track = newtrack; + nudge_timer(); fd765_do_seek(); if ((fd765_status[0] & 0xf8) == 0x20) break; @@ -93,33 +84,40 @@ static void fd_seek(void) /* Select a drive and ensure the motor is on. */ static void fd_select(int minor) { - if (devsel == minor) - return; - motor_on(minor); + (void)minor; + + mod_control(0x00, 0x20); /* motor on (active low) */ + nudge_timer(); } -/* - * Block transfer - */ uint8_t devfd_transfer(void) { int ct = 0; int tries; + int blocks = blk_op.nblock; + uint16_t lba = blk_op.lba; - fd_select(0); /* Select, motor on */ + fd_select(0); fd765_is_user = blk_op.is_user; - while (ct < blk_op.nblock) { /* For each block */ - for (tries = 0; tries < 3; tries ++) { /* Try 3 times */ + fd765_buffer = blk_op.addr; + + while (blocks != 0) + { + for (tries = 0; tries < 3; tries ++) + { + nudge_timer(); if (tries != 0) fd_recalibrate(); - fd_seek(); + fd_seek(lba); - fd765_buffer = blk_op.addr; - if (blk_op.is_read) { + fd765_sectors = 10 - fd765_sector; + if (fd765_sectors > blocks) + fd765_sectors = blocks; + + if (blk_op.is_read) fd765_do_read(); - } else { + else fd765_do_write(); - } /* Did it work ? */ if ((fd765_status[0] & 0xc0) == 0) @@ -127,13 +125,14 @@ uint8_t devfd_transfer(void) } if (tries == 3) { - kprintf("fd%d: I/O error %d:%d\n", blk_op.is_read, blk_op.lba); + kprintf("fd%d: I/O error %d:%d\n", blk_op.is_read, lba); udata.u_error = EIO; break; } - udata.u_block++; - ct++; - blk_op.addr += 512; + lba += fd765_sectors; + blocks -= fd765_sectors; + ct += fd765_sectors; } + return ct; } \ No newline at end of file diff --git a/Kernel/platform-nc200/devfd.h b/Kernel/platform-nc200/devfd.h index f41426b5..2c59a93c 100644 --- a/Kernel/platform-nc200/devfd.h +++ b/Kernel/platform-nc200/devfd.h @@ -18,6 +18,7 @@ extern uint8_t fd765_head; extern uint8_t fd765_sector; extern uint8_t fd765_status[8]; extern uint8_t* fd765_buffer; +extern uint8_t fd765_sectors; extern bool fd765_is_user; #endif /* __DEVRD_DOT_H__ */ diff --git a/Kernel/platform-nc200/fdc765.s b/Kernel/platform-nc200/fdc765.s index 85056ae7..60eeee6b 100644 --- a/Kernel/platform-nc200/fdc765.s +++ b/Kernel/platform-nc200/fdc765.s @@ -22,6 +22,7 @@ .globl _fd765_status .globl _fd765_buffer .globl _fd765_is_user + .globl _fd765_sectors .area _COMMONMEM @@ -131,7 +132,9 @@ _fd765_do_read: ld hl, (_fd765_buffer) ld c, #FD_DT ld b, #0 - ld e, #2 + ld a, (_fd765_sectors) + add a + ld e, a read_loop: in a, (FD_ST) rla ; RQM... @@ -144,6 +147,7 @@ read_loop: dec e jr nz, read_loop ; outer loop: 2 iterations read_finished: + ld (_fd765_buffer), hl call _fd765_do_nudge_tc ; Tell FDC we've finished call fd765_read_status ei @@ -165,7 +169,9 @@ _fd765_do_write: ld hl, (_fd765_buffer) ld c, #FD_DT ld b, #0 - ld e, #2 + ld a, (_fd765_sectors) + add a + ld e, a write_loop: in a, (FD_ST) rla ; RQM... @@ -178,6 +184,7 @@ write_loop: dec e jr nz, write_loop ; outer loop: 2 iterations write_finished: + ld (_fd765_buffer), hl call _fd765_do_nudge_tc ; Tell FDC we've finished call fd765_read_status ei @@ -201,7 +208,9 @@ setup_read_or_write: call fd765_tx ld a, #2 ; 5: bytes per sector: 512 call fd765_tx - ld a, b ; 6: last sector (same as start sector) + ld a, (_fd765_sectors) + add b ; add first sector + dec a ; 6: last sector (*inclusive*) call fd765_tx ld a, #27 ; 7: Gap 3 length (27 is standard for 3.5" drives) call fd765_tx @@ -213,6 +222,8 @@ _fd765_buffer: .dw 0 _fd765_is_user: .db 0 +_fd765_sectors: + .db 0 ; Read the next sector ID off the disk. ; (Only used for debugging.)