summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1997-02-24 05:50:47 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1997-02-24 05:50:47 +0000
commita11eb1eb7b0965a8293a78473284e143df9e965e (patch)
treed9f248e91c423418b8f44b4aa57e98b65996cb6b
parent2601e59744bbe41ba3ab0aee5f7c3770382c3323 (diff)
We do NOT want interrupts when in polled mode. Fixes ATAPI boot
failures. THanks go to Angelos D. Keromytis for debugging this and devising the final fix. Also correct some diagnostic printfs. Do some KNF and unmap registers on probe failure. add a delay(10) to a busy-wait loop solely depending on CPU speed earlier.
-rw-r--r--sys/dev/isa/wdc.c61
1 files changed, 41 insertions, 20 deletions
diff --git a/sys/dev/isa/wdc.c b/sys/dev/isa/wdc.c
index e98d4faa610..7349321522d 100644
--- a/sys/dev/isa/wdc.c
+++ b/sys/dev/isa/wdc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wdc.c,v 1.17 1996/11/29 22:55:09 niklas Exp $ */
+/* $OpenBSD: wdc.c,v 1.18 1997/02/24 05:50:46 niklas Exp $ */
/* $NetBSD: wd.c,v 1.150 1996/05/12 23:54:03 mycroft Exp $ */
/*
@@ -144,7 +144,7 @@ wdcprobe(parent, match, aux)
wdc->sc_iot = iot = ia->ia_iot;
if (bus_space_map(iot, ia->ia_iobase, 8, 0, &ioh))
- return (0);
+ return 0;
wdc->sc_ioh = ioh;
/* Check if we have registers that work. */
@@ -163,14 +163,14 @@ wdcprobe(parent, match, aux)
bus_space_write_1(iot, ioh, wd_cyl_lo, 0xa5);
if (bus_space_read_1(iot, ioh, wd_error) == 0x5a ||
bus_space_read_1(iot, ioh, wd_cyl_lo) != 0xa5)
- return 0;
+ goto nomatch;
wdc->sc_flags |= WDCF_ONESLAVE;
}
if (wdcreset(wdc) != 0) {
delay(500000);
if (wdcreset(wdc) != 0)
- return 0;
+ goto nomatch;
}
/* Select drive 0 or ATAPI slave device */
@@ -181,18 +181,26 @@ wdcprobe(parent, match, aux)
/* Wait for controller to become ready. */
if (wait_for_unbusy(wdc) < 0)
- return 0;
+ goto nomatch;
/* Start drive diagnostics. */
bus_space_write_1(iot, ioh, wd_command, WDCC_DIAGNOSE);
/* Wait for command to complete. */
if (wait_for_unbusy(wdc) < 0)
- return 0;
+ goto nomatch;
ia->ia_iosize = 8;
ia->ia_msize = 0;
+#ifdef notyet
+ /* when we are ready for it... */
+ bus_space_unmap(iot, ioh, 8);
+#endif
return 1;
+
+nomatch:
+ bus_space_unmap(iot, ioh, 8);
+ return 0;
}
int
@@ -694,8 +702,8 @@ wdcintr(arg)
printf("wdcintr: inactive controller, "
"punting st=%02x er=%02x irr=%02x\n", s, e, i);
#else
- (void)bus_space_read_1(iot, ioh, wd_error);
- (void)bus_space_read_1(iot, ioh, wd_seccnt);
+ bus_space_read_1(iot, ioh, wd_error);
+ bus_space_read_1(iot, ioh, wd_seccnt);
#endif
if (s & WDCS_DRQ) {
@@ -703,10 +711,9 @@ wdcintr(arg)
wd_cyl_hi) +
bus_space_read_1(iot, ioh, wd_cyl_lo);
#ifdef ATAPI_DEBUG_WDC
- printf ("wdcintr: clearing up %d bytes\n",
- len);
+ printf("wdcintr: clearing up %d bytes\n", len);
#endif
- wdcbit_bucket (wdc, len);
+ wdcbit_bucket(wdc, len);
}
}
return 0;
@@ -717,7 +724,7 @@ wdcintr(arg)
wdc->sc_flags &= ~WDCF_IRQ_WAIT;
xfer = wdc->sc_xfer.tqh_first;
if (xfer->c_flags & C_ATAPI) {
- (void) wdc_atapi_intr(wdc, xfer);
+ (void)wdc_atapi_intr(wdc, xfer);
return 0;
} else {
return wdc_ata_intr(wdc, xfer);
@@ -747,7 +754,8 @@ wdc_ata_intr(wdc,xfer)
/* The drive is busy. Wait. */
return 1;
}
- WDDEBUG_PRINT(("wdc_ata_start from wdc_ata_intr(open) flags %d\n",
+ WDDEBUG_PRINT(
+ ("wdc_ata_start from wdc_ata_intr(open) flags %d\n",
wdc->sc_flags));
wdc_ata_start(wdc,xfer);
return 1;
@@ -1580,6 +1588,10 @@ wdc_atapi_send_command_packet(ab_link, acp)
}
}
+ /* Turn off interrupts. */
+ bus_space_write_1(iot, ioh, wd_ctlr, WDCTL_4BIT | WDCTL_IDS);
+ delay(1000);
+
if (wdccommand((struct wd_link*)ab_link,
ATAPI_PACKET_COMMAND, acp->drive, acp->data_size,
0, 0, 0) != 0) {
@@ -1591,7 +1603,8 @@ wdc_atapi_send_command_packet(ab_link, acp)
/* Wait for cmd i/o phase. */
phase = wait_for_phase(wdc, PHASE_CMDOUT);
if (phase != PHASE_CMDOUT)
- printf("wdc_atapi_intr: got wrong phase (0x%x)\n",
+ printf("wdc_atapi_send_command_packet: "
+ "got wrong phase (0x%x) wanted cmd I/O\n",
phase);
bus_space_write_raw_multi_2(iot, ioh, wd_data, acp->command,
@@ -1600,18 +1613,26 @@ wdc_atapi_send_command_packet(ab_link, acp)
/* Wait for data i/o phase. */
phase = wait_for_unphase(wdc, PHASE_CMDOUT);
if (phase == PHASE_CMDOUT)
- printf("wdc_atapi_intr: got wrong phase (0x%x)\n",
+ printf("wdc_atapi_send_command_packet: "
+ "got wrong phase (0x%x) wanted data I/O\n",
phase);
while (wdc_atapi_intr(wdc, xfer)) {
- for (i = 2000; i > 0; --i)
+ for (i = 2000; i > 0; --i) {
if ((bus_space_read_1(iot, ioh, wd_status) &
WDCS_DRQ) == 0)
break;
+ delay(10);
+ }
#ifdef ATAPI_DEBUG_WDC
- printf("wdc_atapi_intr: i = %d\n", i);
+ printf("wdc_atapi_send_command_packet: i = %d\n", i);
#endif
}
+
+ /* Turn on interrupts again. */
+ bus_space_write_1(iot, ioh, wd_ctlr, WDCTL_4BIT);
+ delay(1000);
+
wdc->sc_flags &= ~(WDCF_IRQ_WAIT | WDCF_SINGLE | WDCF_ERROR);
wdc->sc_errors = 0;
xfer->c_skip = 0;
@@ -1656,7 +1677,7 @@ wdcbit_bucket(wdc, size)
}
if (size % 2)
- (void)bus_space_read_1(iot, ioh, wd_data);
+ bus_space_read_1(iot, ioh, wd_data);
}
int
@@ -1705,6 +1726,7 @@ again:
{
int i;
char *c = (char *)acp->command;
+
printf("wdc_atapi_intr: cmd ");
for (i = 0; i < acp->command_size; i++)
printf("0x%x ", c[i]);
@@ -1760,8 +1782,7 @@ again:
printf("wdc_atapi_intr: warning: reading only "
"%d of %d bytes\n", xfer->c_bcount, len);
bus_space_read_raw_multi_2(iot, ioh, wd_data,
- xfer->databuf + xfer->c_skip,
- xfer->c_bcount);
+ xfer->databuf + xfer->c_skip, xfer->c_bcount);
wdcbit_bucket(wdc, len - xfer->c_bcount);
xfer->c_bcount = 0;
return 1;