#include <printf.h>
#include <devfdc765.h>
#include <timer.h>
-#include <fdc765_platform.h>
+#include <platform_fdc765.h>
static timer_t spindown_timer, recal_timer;
+static uint8_t lastdrive;
+static uint8_t trackpos[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
+
int devfd_open(uint8_t minor, uint16_t flag)
{
flag;
- if(minor != 0) {
+ if(minor > FDC765_MAX_FLOPPY) {
udata.u_error = ENODEV;
return -1;
}
+
fd765_do_nudge_tc();
- fd765_track = 0xff; /* not on a known track */
+
+ trackpos[minor] = 0xFF;
+ if (minor == lastdrive)
+ fd765_track = 0xff; /* not on a known track */
return 0;
}
return 1;
}
-/* Set up the controller for a given block, seek, and wait for spinup. */
-static void fd_seek(uint16_t lba)
+/* Set up the controller for a given block, seek, and wait for it.
+ By the time we are called the motor is assumed to be at speed */
+
+static uint8_t fd_seek(uint16_t lba)
{
+ uint8_t i = 0;
+ /* Hack for the moment until we introduce the proper floppy ioctls
+ here and in the platform code */
+#ifdef CONFIG_FDC765_DS
uint8_t track2 = lba / 9;
uint8_t newtrack = track2 >> 1;
fd765_sector = (lba % 9) + 1;
fd765_head = track2 & 1;
+#else
+ uint8_t newtrack = lba / 9;
+ fd765_sector = (lba % 9) + 1;
+ fd765_head = 0;
+#endif
if (newtrack != fd765_track)
{
- for (;;)
- {
+ while (i++ < 5) {
fd765_track = newtrack;
nudge_timer();
fd765_do_seek();
if ((fd765_status[0] & 0xf8) == 0x20)
- break;
-
- fd_recalibrate();
+ return 0;
+ if (i != 5)
+ fd_recalibrate();
}
+ return 1;
}
+ return 0;
}
/* Select a drive and ensure the motor is on. */
static void fd_select(int minor)
{
- (void)minor;
-
+ if (lastdrive != minor) {
+ trackpos[lastdrive] = fd765_track;
+ fd765_track = trackpos[minor];
+ lastdrive = minor;
+ }
+ fd765_drive = minor;
fd765_motor_on();
nudge_timer();
}
-static int devfd_transfer(bool is_read, uint8_t is_raw)
+static int devfd_transfer(uint8_t minor, bool is_read, uint8_t is_raw)
{
int ct = 0;
int tries;
// if (!is_read)
// return blocks << BLKSHIFT;
- fd_select(0);
+ fd_select(minor);
fd765_is_user = is_raw;
fd765_buffer = udata.u_dptr;
if (fd_recalibrate())
continue;
}
- fd_seek(lba);
+ /* Seek failed - no point trying the I/O again */
+ if (fd_seek(lba))
+ continue;
/* Not all machines can make the timing for this, or have
real controllers that can do it */
if (tries == 3)
{
/* FIXME: will be the drive num once we fix that */
- kprintf("fd%d: I/O error %d:%d - %d\n", 0, is_read, lba, fd765_status[0]);
+ kprintf("fd%d: I/O error %d:%d - %d:%d\n", minor , is_read, lba,
+ fd765_status[0], fd765_status[1]);
udata.u_error = EIO;
break;
}
int devfd_read(uint8_t minor, uint8_t is_raw, uint8_t flag)
{
flag;minor;
- return devfd_transfer(true, is_raw);
+ return devfd_transfer(minor, true, is_raw);
}
int devfd_write(uint8_t minor, uint8_t is_raw, uint8_t flag)
{
flag;minor;
- return devfd_transfer(false, is_raw);
+ return devfd_transfer(minor, false, is_raw);
}
.globl _fd765_buffer
.globl _fd765_is_user
.globl _fd765_sectors
- .globl _fd765_disc
+ .globl _fd765_drive
- .globl _vborder
+ .globl _vtborder
.globl diskmotor
.ds 8 ; 8 bytes of status data
; Sends the head/drive byte of a command.
-; (Drive #0 is always used.)
-; FIXME: add drive 1 support
send_head:
- ld a, (_fd765_head)
+ ld hl, (_fd765_head) ; l = head h = drive)
+ ld a, l
add a
add a
+ add h
jr fd765_tx
; Performs a RECALIBRATE command.
_fd765_do_recalibrate:
ld a, #0x07 ; RECALIBRATE
call fd765_tx
- ld a, #0x00 ; drive #0 FIXME
+ ld a, (_fd765_drive) ; drive #
call fd765_tx
jr wait_for_seek_ending
jr wait_for_seek_ending
_fd765_track:
.db 0
-_fd765_head:
- .db 0
_fd765_sector:
.db 0
-_fd765_disc:
+;
+; These two must remain adjacent see send_head
+;
+_fd765_head:
+ .db 0
+_fd765_drive:
.db 0
; Waits for a SEEK or RECALIBRATE command to finish by polling SENSE INTERRUPT STATUS.
dec a
jr nz, wait_ms_loop
pop bc
- ld a,(_vborder)
+ ld a,(_vtborder)
out (0xFE),a
ret
call fd765_read_status
call tc_fix
- ld a,(_vborder)
+ ld a,(_vtborder)
out (0xFE),a
pop af
call fd765_read_status
call tc_fix
- ld a,(_vborder)
+ ld a,(_vtborder)
out (0xFE),a
pop af