aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2013-03-02 21:26:54 -0500
committerKevin O'Connor <kevin@koconnor.net>2013-03-03 15:45:01 -0500
commit1f711d2ae89a9753b48c67373936d46a2b75578a (patch)
tree96a590d3a98139fa80c6d0465fe7c46d9bec59a0
parent6e529bdae4922f48c0d7eaa31613b7a9230e8f95 (diff)
downloadseabios-1f711d2ae89a9753b48c67373936d46a2b75578a.tar.gz
floppy: Clean up Check Interrupt Status code.
Don't run the Check Interrupt Status command from the floppy hardware interrupt handler. Instead, run it where it is needed - after controller startup and after a recalibration command. Also, use floppy_pio() to issue the command instead of open coding it. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
-rw-r--r--src/floppy.c105
1 files changed, 61 insertions, 44 deletions
diff --git a/src/floppy.c b/src/floppy.c
index ddefdc6..f3dba38 100644
--- a/src/floppy.c
+++ b/src/floppy.c
@@ -191,34 +191,6 @@ floppy_wait_irq(void)
return DISK_RET_SUCCESS;
}
-static int
-floppy_enable_controller(void)
-{
- outb(inb(PORT_FD_DOR) | 0x04, PORT_FD_DOR);
- return floppy_wait_irq();
-}
-
-static int
-floppy_select_drive(u8 floppyid)
-{
- // reset the disk motor timeout value of INT 08
- SET_BDA(floppy_motor_counter, FLOPPY_MOTOR_TICKS);
-
- // Enable controller if it isn't running.
- u8 dor = inb(PORT_FD_DOR);
- if (!(dor & 0x04)) {
- int ret = floppy_enable_controller();
- if (ret)
- return ret;
- }
-
- // Turn on motor of selected drive, DMA & int enabled, normal operation
- dor = (floppyid ? 0x20 : 0x10) | 0x0c | floppyid;
- outb(dor, PORT_FD_DOR);
-
- return DISK_RET_SUCCESS;
-}
-
struct floppy_pio_s {
u8 cmdlen;
u8 resplen;
@@ -229,10 +201,6 @@ struct floppy_pio_s {
static int
floppy_pio(struct floppy_pio_s *pio)
{
- int ret = floppy_select_drive(pio->data[1] & 1);
- if (ret)
- return ret;
-
// wait for drive readiness
while ((inb(PORT_FD_STATUS) & 0xc0) != 0x80)
;
@@ -262,6 +230,43 @@ floppy_pio(struct floppy_pio_s *pio)
return DISK_RET_SUCCESS;
}
+static int
+floppy_enable_controller(void)
+{
+ outb(inb(PORT_FD_DOR) | 0x04, PORT_FD_DOR);
+ int ret = floppy_wait_irq();
+ if (ret)
+ return ret;
+
+ struct floppy_pio_s pio;
+ pio.cmdlen = 1;
+ pio.resplen = 2;
+ pio.waitirq = 0;
+ pio.data[0] = 0x08; // 08: Check Interrupt Status
+ return floppy_pio(&pio);
+}
+
+static int
+floppy_select_drive(u8 floppyid)
+{
+ // reset the disk motor timeout value of INT 08
+ SET_BDA(floppy_motor_counter, FLOPPY_MOTOR_TICKS);
+
+ // Enable controller if it isn't running.
+ u8 dor = inb(PORT_FD_DOR);
+ if (!(dor & 0x04)) {
+ int ret = floppy_enable_controller();
+ if (ret)
+ return ret;
+ }
+
+ // Turn on motor of selected drive, DMA & int enabled, normal operation
+ dor = (floppyid ? 0x20 : 0x10) | 0x0c | floppyid;
+ outb(dor, PORT_FD_DOR);
+
+ return DISK_RET_SUCCESS;
+}
+
// Perform a floppy transfer command (setup DMA and issue PIO).
static int
floppy_cmd(struct disk_op_s *op, int count, struct floppy_pio_s *pio)
@@ -298,9 +303,12 @@ floppy_cmd(struct disk_op_s *op, int count, struct floppy_pio_s *pio)
outb(0x02, PORT_DMA1_MASK_REG); // unmask channel 2
+ int ret = floppy_select_drive(pio->data[1] & 1);
+ if (ret)
+ return ret;
pio->resplen = 7;
pio->waitirq = 1;
- int ret = floppy_pio(pio);
+ ret = floppy_pio(pio);
if (ret)
return ret;
@@ -323,9 +331,13 @@ set_diskette_current_cyl(u8 floppyid, u8 cyl)
SET_BDA(floppy_track[floppyid], cyl);
}
-static void
+static int
floppy_drive_recal(u8 floppyid)
{
+ int ret = floppy_select_drive(floppyid);
+ if (ret)
+ return ret;
+
// send Recalibrate command (2 bytes) to controller
struct floppy_pio_s pio;
pio.cmdlen = 2;
@@ -333,11 +345,22 @@ floppy_drive_recal(u8 floppyid)
pio.waitirq = 1;
pio.data[0] = 0x07; // 07: Recalibrate
pio.data[1] = floppyid; // 0=drive0, 1=drive1
- floppy_pio(&pio);
+ ret = floppy_pio(&pio);
+ if (ret)
+ return ret;
+
+ pio.cmdlen = 1;
+ pio.resplen = 2;
+ pio.waitirq = 0;
+ pio.data[0] = 0x08; // 08: Check Interrupt Status
+ ret = floppy_pio(&pio);
+ if (ret)
+ return ret;
u8 frs = GET_BDA(floppy_recalibration_status);
SET_BDA(floppy_recalibration_status, frs | (1<<floppyid));
set_diskette_current_cyl(floppyid, 0);
+ return DISK_RET_SUCCESS;
}
static int
@@ -392,7 +415,9 @@ check_recal_drive(struct drive_s *drive_g)
return DISK_RET_SUCCESS;
// Recalibrate drive.
- floppy_drive_recal(floppyid);
+ int ret = floppy_drive_recal(floppyid);
+ if (ret)
+ return ret;
// Sense media.
return floppy_media_sense(drive_g);
@@ -607,14 +632,6 @@ handle_0e(void)
return;
debug_isr(DEBUG_ISR_0e);
- if ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0) {
- outb(0x08, PORT_FD_DATA); // sense interrupt status
- while ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0)
- ;
- do {
- inb(PORT_FD_DATA);
- } while ((inb(PORT_FD_STATUS) & 0xc0) == 0xc0);
- }
// diskette interrupt has occurred
u8 frs = GET_BDA(floppy_recalibration_status);
SET_BDA(floppy_recalibration_status, frs | FRS_IRQ);