Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-1-4]: src/sys/dev/ata Pull up revision 1.19->1.20:
details: https://anonhg.NetBSD.org/src/rev/0f5b28fdc7f9
branches: netbsd-1-4
changeset: 469287:0f5b28fdc7f9
user: he <he%NetBSD.org@localhost>
date: Wed Aug 25 11:17:59 1999 +0000
description:
Pull up revision 1.19->1.20:
Add some debug printfs, change timeout handling to be more efficient
and less error-prone, and fix the "lockup after lost interrupt"
problem some users have been reporting. (bouyer)
diffstat:
sys/dev/ata/ata_wdc.c | 49 ++++++++++++++++++++++++++++++++++++-------------
1 files changed, 36 insertions(+), 13 deletions(-)
diffs (135 lines):
diff -r 04b1821ece43 -r 0f5b28fdc7f9 sys/dev/ata/ata_wdc.c
--- a/sys/dev/ata/ata_wdc.c Wed Aug 25 10:26:10 1999 +0000
+++ b/sys/dev/ata/ata_wdc.c Wed Aug 25 11:17:59 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ata_wdc.c,v 1.19 1999/04/01 21:46:28 bouyer Exp $ */
+/* $NetBSD: ata_wdc.c,v 1.19.2.1 1999/08/25 11:17:59 he Exp $ */
/*
* Copyright (c) 1998 Manuel Bouyer.
@@ -117,6 +117,7 @@
#define ATA_DELAY 10000 /* 10s for a drive I/O */
void wdc_ata_bio_start __P((struct channel_softc *,struct wdc_xfer *));
+void _wdc_ata_bio_start __P((struct channel_softc *,struct wdc_xfer *));
int wdc_ata_bio_intr __P((struct channel_softc *, struct wdc_xfer *, int));
void wdc_ata_bio_done __P((struct channel_softc *, struct wdc_xfer *));
int wdc_ata_ctrl_intr __P((struct channel_softc *, struct wdc_xfer *, int));
@@ -161,6 +162,22 @@
struct wdc_xfer *xfer;
{
struct ata_bio *ata_bio = xfer->cmd;
+ WDCDEBUG_PRINT(("wdc_ata_bio_start %s:%d:%d\n",
+ chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive),
+ DEBUG_XFERS);
+
+ /* start timeout machinery */
+ if ((ata_bio->flags & ATA_POLL) == 0)
+ timeout(wdctimeout, chp, ATA_DELAY / 1000 * hz);
+ _wdc_ata_bio_start(chp, xfer);
+}
+
+void
+_wdc_ata_bio_start(chp, xfer)
+ struct channel_softc *chp;
+ struct wdc_xfer *xfer;
+{
+ struct ata_bio *ata_bio = xfer->cmd;
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
u_int16_t cyl;
u_int8_t head, sect, cmd = 0;
@@ -168,10 +185,9 @@
int ata_delay;
int dma_flags = 0;
- WDCDEBUG_PRINT(("wdc_ata_bio_start %s:%d:%d\n",
+ WDCDEBUG_PRINT(("_wdc_ata_bio_start %s:%d:%d\n",
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive),
- DEBUG_XFERS);
-
+ DEBUG_INTR | DEBUG_XFERS);
/* Do control operations specially. */
if (drvp->state < READY) {
/*
@@ -181,10 +197,10 @@
*/
/* at this point, we should only be in RECAL state */
if (drvp->state != RECAL) {
- printf("%s:%d:%d: bad state %d in wdc_ata_bio_start\n",
+ printf("%s:%d:%d: bad state %d in _wdc_ata_bio_start\n",
chp->wdc->sc_dev.dv_xname, chp->channel,
xfer->drive, drvp->state);
- panic("wdc_ata_bio_start: bad state");
+ panic("_wdc_ata_bio_start: bad state");
}
xfer->c_intr = wdc_ata_ctrl_intr;
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
@@ -195,8 +211,6 @@
drvp->state = RECAL_WAIT;
if ((ata_bio->flags & ATA_POLL) == 0) {
chp->ch_flags |= WDCF_IRQ_WAIT;
- timeout(wdctimeout, chp,
- ATA_DELAY / 1000 * hz);
} else {
/* Wait for at last 400ns for status bit to be valid */
DELAY(1);
@@ -368,7 +382,6 @@
intr: /* Wait for IRQ (either real or polled) */
if ((ata_bio->flags & ATA_POLL) == 0) {
chp->ch_flags |= WDCF_IRQ_WAIT;
- timeout(wdctimeout, chp, ata_delay / 1000 * hz);
} else {
/* Wait for at last 400ns for status bit to be valid */
delay(1);
@@ -416,6 +429,16 @@
dma_flags |= (ata_bio->flags & ATA_POLL) ? WDC_DMA_POLL : 0;
}
+ /*
+ * if we missed an interrupt in a PIO transfer, reset and restart.
+ * Don't try to continue transfer, we may have missed cycles.
+ */
+ if ((xfer->c_flags & (C_TIMEOU | C_DMA)) == C_TIMEOU) {
+ ata_bio->error = TIMEOUT;
+ wdc_ata_bio_done(chp, xfer);
+ return 1;
+ }
+
/* Ack interrupt done by wait_for_unbusy */
if (wait_for_unbusy(chp,
(irq == 0) ? ATA_DELAY : 0) < 0) {
@@ -532,9 +555,9 @@
if (xfer->c_bcount > 0) {
if ((ata_bio->flags & ATA_POLL) == 0) {
/* Start the next operation */
- wdc_ata_bio_start(chp, xfer);
+ _wdc_ata_bio_start(chp, xfer);
} else {
- /* Let wdc_ata_bio_start do the loop */
+ /* Let _wdc_ata_bio_start do the loop */
return 1;
}
} else { /* Done with this transfer */
@@ -559,6 +582,7 @@
(u_int)xfer->c_flags),
DEBUG_XFERS);
+ untimeout(wdctimeout, chp);
if (ata_bio->error == NOERROR)
drvp->n_dmaerrs = 0;
else if (drvp->n_dmaerrs >= NERRS_MAX) {
@@ -696,13 +720,12 @@
* The drive is usable now
*/
xfer->c_intr = wdc_ata_bio_intr;
- wdc_ata_bio_start(chp, xfer);
+ _wdc_ata_bio_start(chp, xfer);
return 1;
}
if ((ata_bio->flags & ATA_POLL) == 0) {
chp->ch_flags |= WDCF_IRQ_WAIT;
- timeout(wdctimeout, chp, ATA_DELAY / 1000 * hz);
} else {
goto again;
}
Home |
Main Index |
Thread Index |
Old Index