Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev Cancel active transfers on aic/wdc detach.



details:   https://anonhg.NetBSD.org/src/rev/11b462d963e4
branches:  trunk
changeset: 477543:11b462d963e4
user:      enami <enami%NetBSD.org@localhost>
date:      Wed Oct 20 15:22:24 1999 +0000

description:
Cancel active transfers on aic/wdc detach.
Also makes LS-120 drive works for me again.

diffstat:

 sys/dev/ata/ata_wdc.c        |  34 ++++++++++++++++++++++++++++-
 sys/dev/ata/atavar.h         |   3 +-
 sys/dev/ata/wd.c             |   7 +++++-
 sys/dev/ata/wdvar.h          |   3 +-
 sys/dev/ic/aic6360.c         |  23 ++++++++++++++++++-
 sys/dev/ic/aic6360var.h      |   6 ++--
 sys/dev/ic/wdc.c             |  30 +++++++++++++++++++++++--
 sys/dev/ic/wdcvar.h          |   5 +++-
 sys/dev/pcmcia/aic_pcmcia.c  |  51 +++++++++++++------------------------------
 sys/dev/pcmcia/wdc_pcmcia.c  |  25 +++++++++++----------
 sys/dev/scsipi/atapi_wdc.c   |  35 +++++++++++++++++++++++++++++-
 sys/dev/scsipi/atapiconf.c   |   3 +-
 sys/dev/scsipi/atapiconf.h   |   3 +-
 sys/dev/scsipi/scsi_base.c   |  20 ++++++++++++++++-
 sys/dev/scsipi/scsiconf.c    |   3 +-
 sys/dev/scsipi/scsiconf.h    |   3 +-
 sys/dev/scsipi/scsipi_base.c |  15 ++++++------
 sys/dev/scsipi/scsipiconf.h  |   3 +-
 18 files changed, 197 insertions(+), 75 deletions(-)

diffs (truncated from 680 to 300 lines):

diff -r 22252054c79d -r 11b462d963e4 sys/dev/ata/ata_wdc.c
--- a/sys/dev/ata/ata_wdc.c     Wed Oct 20 15:09:58 1999 +0000
+++ b/sys/dev/ata/ata_wdc.c     Wed Oct 20 15:22:24 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ata_wdc.c,v 1.21 1999/08/09 09:43:11 bouyer Exp $      */
+/*     $NetBSD: ata_wdc.c,v 1.22 1999/10/20 15:22:24 enami Exp $       */
 
 /*
  * Copyright (c) 1998 Manuel Bouyer.
@@ -119,6 +119,7 @@
 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_kill_xfer __P((struct channel_softc *,struct wdc_xfer *));
 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));
 int   wdc_ata_err __P((struct ata_drive_datas *, struct ata_bio *));
@@ -152,6 +153,7 @@
        xfer->c_bcount = ata_bio->bcount;
        xfer->c_start = wdc_ata_bio_start;
        xfer->c_intr = wdc_ata_bio_intr;
+       xfer->c_kill_xfer = wdc_ata_bio_kill_xfer;
        wdc_exec_xfer(chp, xfer);
        return (ata_bio->flags & ATA_ITSDONE) ? WDC_COMPLETE : WDC_QUEUED;
 }
@@ -568,6 +570,36 @@
 }
 
 void
+wdc_ata_kill_pending(drvp)
+       struct ata_drive_datas *drvp;
+{
+       struct channel_softc *chp = drvp->chnl_softc;
+
+       wdc_kill_pending(chp);
+}
+
+void
+wdc_ata_bio_kill_xfer(chp, xfer)
+       struct channel_softc *chp;
+       struct wdc_xfer *xfer;
+{
+       struct ata_bio *ata_bio = xfer->cmd;
+       int drive = xfer->drive;
+
+       untimeout(wdctimeout, chp);
+       /* remove this command from xfer queue */
+       wdc_free_xfer(chp, xfer);
+
+       ata_bio->flags |= ATA_ITSDONE;
+       ata_bio->error = ERR_NODEV;
+       ata_bio->r_error = WDCE_ABRT;
+       if ((ata_bio->flags & ATA_POLL) == 0) {
+               WDCDEBUG_PRINT(("wdc_ata_done: wddone\n"), DEBUG_XFERS);
+               wddone(chp->ch_drive[drive].drv_softc);
+       }
+}
+
+void
 wdc_ata_bio_done(chp, xfer)
        struct channel_softc *chp;
        struct wdc_xfer *xfer;
diff -r 22252054c79d -r 11b462d963e4 sys/dev/ata/atavar.h
--- a/sys/dev/ata/atavar.h      Wed Oct 20 15:09:58 1999 +0000
+++ b/sys/dev/ata/atavar.h      Wed Oct 20 15:22:24 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: atavar.h,v 1.13 1999/03/10 13:11:43 bouyer Exp $       */
+/*     $NetBSD: atavar.h,v 1.14 1999/10/20 15:22:25 enami Exp $        */
 
 /*
  * Copyright (c) 1998 Manuel Bouyer.
@@ -153,6 +153,7 @@
 
 int wdc_ata_addref __P((struct ata_drive_datas *));
 void wdc_ata_delref __P((struct ata_drive_datas *));
+void wdc_ata_kill_pending __P((struct ata_drive_datas *));
 
 struct ataparams;
 int ata_get_params __P((struct ata_drive_datas*, u_int8_t,
diff -r 22252054c79d -r 11b462d963e4 sys/dev/ata/wd.c
--- a/sys/dev/ata/wd.c  Wed Oct 20 15:09:58 1999 +0000
+++ b/sys/dev/ata/wd.c  Wed Oct 20 15:22:24 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wd.c,v 1.196 1999/09/23 11:04:29 enami Exp $ */
+/*     $NetBSD: wd.c,v 1.197 1999/10/20 15:22:25 enami Exp $ */
 
 /*
  * Copyright (c) 1998 Manuel Bouyer.  All rights reserved.
@@ -601,6 +601,11 @@
 noerror:       if ((wd->sc_wdc_bio.flags & ATA_CORR) || wd->retries > 0)
                        printf("%s: soft error (corrected)\n",
                            wd->sc_dev.dv_xname);
+               break;
+       case ERR_NODEV:
+               bp->b_flags |= B_ERROR;
+               bp->b_error = EIO;
+               break;
        }
        disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid));
 #if NRND > 0
diff -r 22252054c79d -r 11b462d963e4 sys/dev/ata/wdvar.h
--- a/sys/dev/ata/wdvar.h       Wed Oct 20 15:09:58 1999 +0000
+++ b/sys/dev/ata/wdvar.h       Wed Oct 20 15:22:24 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wdvar.h,v 1.3 1998/11/11 19:38:27 bouyer Exp $ */
+/*     $NetBSD: wdvar.h,v 1.4 1999/10/20 15:22:25 enami Exp $  */
 
 /*
  * Copyright (c) 1998 Manuel Bouyer.
@@ -57,6 +57,7 @@
 #define ERR_DF 2 /* Drive fault */
 #define ERR_DMA 3 /* DMA error */
 #define TIMEOUT 4 /* device timed out */
+#define ERR_NODEV 5 /* device has been gone */
     u_int8_t r_error; /* copy of error register */
     daddr_t badsect[127];    /* 126 plus trailing -1 marker */
 };
diff -r 22252054c79d -r 11b462d963e4 sys/dev/ic/aic6360.c
--- a/sys/dev/ic/aic6360.c      Wed Oct 20 15:09:58 1999 +0000
+++ b/sys/dev/ic/aic6360.c      Wed Oct 20 15:22:24 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: aic6360.c,v 1.63 1999/09/30 23:04:40 thorpej Exp $     */
+/*     $NetBSD: aic6360.c,v 1.64 1999/10/20 15:22:26 enami Exp $       */
 
 #include "opt_ddb.h"
 #ifdef DDB
@@ -311,8 +311,11 @@
                break;
 
        case DVACT_DEACTIVATE:
-               if (sc->sc_child != NULL)
+               if (sc->sc_child != NULL && !sc->sc_dying) {
                        rv = config_deactivate(sc->sc_child);
+                       if (rv == 0)
+                               sc->sc_dying = 1;
+               }
                break;
        }
        splx(s);
@@ -552,6 +555,16 @@
        AIC_CMDS(("[0x%x, %d]->%d ", (int)xs->cmd->opcode, xs->cmdlen,
            sc_link->scsipi_scsi.target));
 
+       if (sc->sc_dying) {
+               xs->xs_status |= XS_STS_DONE;
+               xs->error = XS_DRIVER_STUFFUP;
+               scsipi_done(xs);
+               if ((xs->xs_control & XS_CTL_POLL) == 0)
+                       return (SUCCESSFULLY_QUEUED);
+               else
+                       return (COMPLETE);
+       }
+
        flags = xs->xs_control;
        if ((acb = aic_get_acb(sc, flags)) == NULL) {
                xs->error = XS_DRIVER_STUFFUP;
@@ -790,6 +803,9 @@
        bus_space_tag_t iot = sc->sc_iot;
        bus_space_handle_t ioh = sc->sc_ioh;
 
+       if (sc->sc_dying)
+               return;
+
        /*
         * Find first acb in ready queue that is for a target/lunit pair that
         * is not busy.
@@ -1699,6 +1715,9 @@
        struct aic_tinfo *ti;
        int n;
 
+       if (sc->sc_dying)
+               return (0);
+
        /*
         * Clear INTEN.  We enable it again before returning.  This makes the
         * interrupt esssentially level-triggered.
diff -r 22252054c79d -r 11b462d963e4 sys/dev/ic/aic6360var.h
--- a/sys/dev/ic/aic6360var.h   Wed Oct 20 15:09:58 1999 +0000
+++ b/sys/dev/ic/aic6360var.h   Wed Oct 20 15:22:24 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: aic6360var.h,v 1.4 1999/09/26 08:14:57 enami Exp $     */
+/*     $NetBSD: aic6360var.h,v 1.5 1999/10/20 15:22:26 enami Exp $     */
 
 /*
  * Copyright (c) 1994, 1995, 1996 Charles M. Hannum.  All rights reserved.
@@ -148,6 +148,8 @@
 #define        AIC_ABORTING    0x02    /* Bailing out */
 #define AIC_DOINGDMA   0x04    /* The FIFO data path is active! */
        u_char  sc_selid;       /* Reselection ID */
+       struct device *sc_child;/* Our child */
+       u_char  sc_dying;       /* true if device is going */
 
        /* Message stuff */
        u_char  sc_msgpriq;     /* Messages we want to send */
@@ -173,8 +175,6 @@
        int     sc_freq;                /* Clock frequency in MHz */
        int     sc_minsync;             /* Minimum sync period / 4 */
        int     sc_maxsync;             /* Maximum sync period / 4 */
-
-       struct device *sc_child;        /* Our child */
 };
 
 #if AIC_DEBUG
diff -r 22252054c79d -r 11b462d963e4 sys/dev/ic/wdc.c
--- a/sys/dev/ic/wdc.c  Wed Oct 20 15:09:58 1999 +0000
+++ b/sys/dev/ic/wdc.c  Wed Oct 20 15:22:24 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wdc.c,v 1.74 1999/09/23 11:04:32 enami Exp $ */
+/*     $NetBSD: wdc.c,v 1.75 1999/10/20 15:22:26 enami Exp $ */
 
 
 /*
@@ -120,6 +120,7 @@
 void  __wdccommand_start __P((struct channel_softc *, struct wdc_xfer *));     
 int   __wdccommand_intr __P((struct channel_softc *, struct wdc_xfer *, int));
 int   wdprint __P((void *, const char *));
+void   wdc_kill_pending __P((struct channel_softc *));
 
 
 #define DEBUG_INTR   0x01
@@ -473,6 +474,8 @@
                break;
 
        case DVACT_DEACTIVATE:
+               if (wdc->sc_dying != 0)
+                       goto out;
                for (i = 0; i < wdc->nchannels; i++) {
                        chp = wdc->channels[i];
 
@@ -503,6 +506,7 @@
                                }
                        }
                }
+               wdc->sc_dying = 1;
                break;
        }
 
@@ -557,6 +561,8 @@
                                        goto out;
                        }
                }
+
+               wdc_kill_pending(chp);
        }
 
 out:
@@ -1169,6 +1175,7 @@
        xfer->cmd = wdc_c;
        xfer->c_start = __wdccommand_start;
        xfer->c_intr = __wdccommand_intr;
+       xfer->c_kill_xfer = __wdccommand_done;
 
        s = splbio();
        wdc_exec_xfer(chp, xfer);
@@ -1292,8 +1299,8 @@
                wdc_c->r_error = chp->ch_error;
        }
        wdc_c->flags |= AT_DONE;
-       if (wdc_c->flags & AT_READREG && (wdc_c->flags & (AT_ERROR | AT_DF))
-                                                               == 0) {
+       if ((wdc_c->flags & AT_READREG) != 0 && chp->wdc->sc_dying != 0 &&
+           (wdc_c->flags & (AT_ERROR | AT_DF)) == 0) {
                wdc_c->r_head = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
                                                 wd_sdh);
                wdc_c->r_cyl = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
@@ -1434,6 +1441,23 @@
        splx(s);
 }
 
+/*
+ * Kill off all pending xfers for a channel_softc.
+ *
+ * Must be called at splbio().
+ */
+void
+wdc_kill_pending(chp)
+       struct channel_softc *chp;
+{
+       struct wdc_xfer *xfer;
+
+       while ((xfer = TAILQ_FIRST(&chp->ch_queue->sc_xfer)) != NULL) {
+               chp = xfer->chp;
+               (*xfer->c_kill_xfer)(chp, xfer);
+       }
+}
+
 static void
 __wdcerror(chp, msg) 
        struct channel_softc *chp;
diff -r 22252054c79d -r 11b462d963e4 sys/dev/ic/wdcvar.h
--- a/sys/dev/ic/wdcvar.h       Wed Oct 20 15:09:58 1999 +0000
+++ b/sys/dev/ic/wdcvar.h       Wed Oct 20 15:22:24 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wdcvar.h,v 1.19 1999/09/23 11:04:32 enami Exp $        */
+/*     $NetBSD: wdcvar.h,v 1.20 1999/10/20 15:22:26 enami Exp $        */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -103,6 +103,7 @@
         * The reference count here is used for both IDE and ATAPI devices.



Home | Main Index | Thread Index | Old Index