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