Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/ic Handle better the status codes.
details: https://anonhg.NetBSD.org/src/rev/b0141ff44828
branches: trunk
changeset: 486176:b0141ff44828
user: dante <dante%NetBSD.org@localhost>
date: Sun May 14 18:25:49 2000 +0000
description:
Handle better the status codes.
Add a way to instruct the upper layer to don't bother w/ new requests if/when a device queue is full/busy or the device is unavailabale at that time
Use scsipi_inquiry_data instead of its own inquiry structure
diffstat:
sys/dev/ic/adw.c | 251 ++++++++++++++++++++++++++++++++-------------------
sys/dev/ic/adwlib.c | 30 ++---
sys/dev/ic/adwlib.h | 68 ++-----------
3 files changed, 184 insertions(+), 165 deletions(-)
diffs (truncated from 552 to 300 lines):
diff -r c9bf032622e3 -r b0141ff44828 sys/dev/ic/adw.c
--- a/sys/dev/ic/adw.c Sun May 14 18:22:13 2000 +0000
+++ b/sys/dev/ic/adw.c Sun May 14 18:25:49 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: adw.c,v 1.20 2000/05/10 21:22:34 dante Exp $ */
+/* $NetBSD: adw.c,v 1.21 2000/05/14 18:25:49 dante Exp $ */
/*
* Generic driver for the Advanced Systems Inc. SCSI controllers
@@ -92,6 +92,7 @@
static int adw_poll __P((ADW_SOFTC *, struct scsipi_xfer *, int));
static void adw_timeout __P((void *));
+static void adw_reset_bus __P((ADW_SOFTC *, struct scsipi_xfer *));
/******************************************************************************/
@@ -566,6 +567,10 @@
sc->sc_dev.dv_xname, i, ADW_MAX_CARRIER);
}
+ /*
+ * Zero's the freeze_device status
+ */
+ bzero(sc->sc_freeze_dev, sizeof(sc->sc_freeze_dev));
/*
* Initialize the adapter
@@ -691,10 +696,20 @@
* called with the first queue entry as our argument.
*/
if (xs == TAILQ_FIRST(&sc->sc_queue)) {
+ if(sc->sc_freeze_dev[xs->sc_link->scsipi_scsi.target]) {
+ splx(s);
+ return (TRY_AGAIN_LATER);
+ }
+
TAILQ_REMOVE(&sc->sc_queue, xs, adapter_q);
fromqueue = 1;
nowait = 1;
} else {
+ if(sc->sc_freeze_dev[xs->sc_link->scsipi_scsi.target]) {
+ splx(s);
+ xs->error = XS_DRIVER_STUFFUP;
+ return (TRY_AGAIN_LATER);
+ }
/* Polled requests can't be queued for later. */
dontqueue = xs->xs_control & XS_CTL_POLL;
@@ -835,9 +850,7 @@
scsiqp->vsense_addr = &ccb->scsi_sense;
scsiqp->sense_addr = sc->sc_dmamap_control->dm_segs[0].ds_addr +
ADW_CCB_OFF(ccb) + offsetof(struct adw_ccb, scsi_sense);
-/* scsiqp->sense_addr = ccb->hashkey +
- offsetof(struct adw_ccb, scsi_sense);
-*/ scsiqp->sense_len = sizeof(struct scsipi_sense_data);
+ scsiqp->sense_len = sizeof(struct scsipi_sense_data);
/*
* Build ADW_SCSI_REQ_Q for a scatter-gather buffer command.
@@ -1023,17 +1036,8 @@
* reinitialize the host adapter.
*/
callout_stop(&xs->xs_callout);
-
printf(" AGAIN. Resetting SCSI Bus\n");
- AdvResetSCSIBus(sc);
-
- while((ccb = TAILQ_LAST(&sc->sc_pending_ccb,
- adw_pending_ccb)) != NULL) {
- callout_stop(&ccb->xs->xs_callout);
- TAILQ_REMOVE(&sc->sc_pending_ccb, ccb, chain);
- TAILQ_INSERT_HEAD(&sc->sc_waiting_ccb, ccb, chain);
- }
- adw_queue_ccb(sc, TAILQ_FIRST(&sc->sc_waiting_ccb), 1);
+ adw_reset_bus(sc, xs);
splx(s);
return;
} else if (ccb->flags & CCB_ABORTING) {
@@ -1108,6 +1112,27 @@
}
+static void
+adw_reset_bus(sc, xs)
+ ADW_SOFTC *sc;
+ struct scsipi_xfer *xs;
+{
+ ADW_CCB *ccb;
+ int s;
+
+ s = splbio();
+ AdvResetSCSIBus(sc);
+ while((ccb = TAILQ_LAST(&sc->sc_pending_ccb,
+ adw_pending_ccb)) != NULL) {
+ callout_stop(&ccb->xs->xs_callout);
+ TAILQ_REMOVE(&sc->sc_pending_ccb, ccb, chain);
+ TAILQ_INSERT_HEAD(&sc->sc_waiting_ccb, ccb, chain);
+ }
+ adw_queue_ccb(sc, TAILQ_FIRST(&sc->sc_waiting_ccb), 1);
+ splx(s);
+}
+
+
/******************************************************************************/
/* Host Adapter and Peripherals Information Routines */
/******************************************************************************/
@@ -1237,89 +1262,137 @@
* 'host_status' conatins the host adapter status.
* 'scsi_status' contains the scsi peripheral status.
*/
- switch (scsiq->done_status) {
- case QD_NO_ERROR:
- xs->error = XS_NOERROR;
- xs->resid = scsiq->data_cnt;
-#ifdef ADW_DEBUG
- /* Check for an underrun condition. */
- if ((xs->datalen != 0) && (scsiq->data_cnt != 0) &&
- (scsiq->data_cnt <= xs->datalen)) {
- printf("%s: underrun condition %d bytes\n",
- sc->sc_dev.dv_xname, scsiq->data_cnt);
+ if ((scsiq->host_status == QHSTA_NO_ERROR) &&
+ ((scsiq->done_status == QD_NO_ERROR) ||
+ (scsiq->done_status == QD_WITH_ERROR))) {
+ switch (scsiq->host_status) {
+ case SCSI_STATUS_GOOD:
+ if ((scsiq->cdb[0] == INQUIRY) &&
+ (scsiq->target_lun == 0)) {
+ adw_print_info(sc, scsiq->target_id);
+ }
+ xs->error = XS_NOERROR;
+ xs->resid = scsiq->data_cnt;
+ sc->sc_freeze_dev[scsiq->target_id] = 0;
+ break;
+
+ case SCSI_STATUS_CHECK_CONDITION:
+ case SCSI_STATUS_CMD_TERMINATED:
+ s1 = &ccb->scsi_sense;
+ s2 = &xs->sense.scsi_sense;
+ *s2 = *s1;
+ xs->error = XS_SENSE;
+ sc->sc_freeze_dev[scsiq->target_id] = 1;
+ break;
+
+ default:
+ xs->error = XS_BUSY;
+ sc->sc_freeze_dev[scsiq->target_id] = 1;
+ break;
}
-#endif
- if ((scsiq->cdb[0] == INQUIRY) && (scsiq->target_lun == 0)) {
- adw_print_info(sc, scsiq->target_id);
- }
- break;
-
- case QD_WITH_ERROR:
+ } else if (scsiq->done_status == QD_ABORTED_BY_HOST) {
+ xs->error = XS_DRIVER_STUFFUP;
+ } else {
switch (scsiq->host_status) {
- case QHSTA_NO_ERROR:
- switch(scsiq->scsi_status) {
- case SS_CHK_CONDITION:
- s1 = &ccb->scsi_sense;
- s2 = &xs->sense.scsi_sense;
- *s2 = *s1;
- xs->error = XS_SENSE;
- break;
+ case QHSTA_M_SEL_TIMEOUT:
+ xs->error = XS_SELTIMEOUT;
+ break;
+
+ case QHSTA_M_SXFR_OFF_UFLW:
+ case QHSTA_M_SXFR_OFF_OFLW:
+ case QHSTA_M_DATA_OVER_RUN:
+ printf("%s: Overrun/Overflow/Underflow condition\n",
+ sc->sc_dev.dv_xname);
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
- default:
- xs->error = XS_DRIVER_STUFFUP;
-#ifdef ADW_DEBUG
- printf("%s: Command %d completed with error."
- " SCSI Status = %d\n",
- sc->sc_dev.dv_xname, scsiq->cdb[0],
- scsiq->scsi_status);
-#endif
- break;
- }
+ case QHSTA_M_SXFR_DESELECTED:
+ case QHSTA_M_UNEXPECTED_BUS_FREE:
+ printf("%s: Unexpected BUS free\n",sc->sc_dev.dv_xname);
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
+
+ case QHSTA_M_SCSI_BUS_RESET:
+ case QHSTA_M_SCSI_BUS_RESET_UNSOL:
+ printf("%s: BUS Reset\n", sc->sc_dev.dv_xname);
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
+
+ case QHSTA_M_BUS_DEVICE_RESET:
+ printf("%s: Device Reset\n", sc->sc_dev.dv_xname);
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
+
+ case QHSTA_M_QUEUE_ABORTED:
+ printf("%s: Queue Aborted\n", sc->sc_dev.dv_xname);
+ xs->error = XS_DRIVER_STUFFUP;
break;
case QHSTA_M_SXFR_SDMA_ERR:
+ case QHSTA_M_SXFR_SXFR_PERR:
+ case QHSTA_M_RDMA_PERR:
/*
- * SCSI DMA Error. This should *NEVER* happen!
+ * DMA Error. This should *NEVER* happen!
*
* Lets try resetting the bus and reinitialize
* the host adapter.
*/
- AdvResetSCSIBus(sc);
- while((ccb = TAILQ_LAST(&sc->sc_pending_ccb,
- adw_pending_ccb)) != NULL) {
- callout_stop(&ccb->xs->xs_callout);
- TAILQ_REMOVE(&sc->sc_pending_ccb, ccb, chain);
- TAILQ_INSERT_HEAD(&sc->sc_waiting_ccb, ccb, chain);
- }
- adw_queue_ccb(sc, TAILQ_FIRST(&sc->sc_waiting_ccb), 1);
- return;
+ printf("%s: DMA Error. Reseting bus\n",
+ sc->sc_dev.dv_xname);
+ adw_reset_bus(sc, xs);
+ xs->error = XS_BUSY;
+ break;
+
+ case QHSTA_M_WTM_TIMEOUT:
+ case QHSTA_M_SXFR_WD_TMO:
+ /* The SCSI bus hung in a phase */
+ printf("%s: Watch Dog timer expired. Reseting bus\n",
+ sc->sc_dev.dv_xname);
+ adw_reset_bus(sc, xs);
+ xs->error = XS_BUSY;
+ break;
+
+ case QHSTA_M_SXFR_XFR_PH_ERR:
+ printf("%s: Transfer Error\n", sc->sc_dev.dv_xname);
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
+
+ case QHSTA_M_BAD_CMPL_STATUS_IN:
+ /* No command complete after a status message */
+ printf("%s: Bad Completion Status\n",
+ sc->sc_dev.dv_xname);
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
+
+ case QHSTA_M_AUTO_REQ_SENSE_FAIL:
+ printf("%s: Auto Sense Failed\n", sc->sc_dev.dv_xname);
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
+
+ case QHSTA_M_INVALID_DEVICE:
+ printf("%s: Invalid Device\n", sc->sc_dev.dv_xname);
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
+
+ case QHSTA_M_NO_AUTO_REQ_SENSE:
+ /*
+ * User didn't request sense, but we got a
+ * check condition.
+ */
+ printf("%s: Unexpected Check Condition\n",
+ sc->sc_dev.dv_xname);
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
+
+ case QHSTA_M_SXFR_UNKNOWN_ERROR:
+ printf("%s: Unknown Error\n", sc->sc_dev.dv_xname);
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
default:
- xs->error = XS_DRIVER_STUFFUP;
-#ifdef ADW_DEBUG
- printf("%s: Command %d completed with error."
- " Host Status = %d\n",
- sc->sc_dev.dv_xname, scsiq->cdb[0],
- scsiq->host_status);
-#endif
- break;
+ panic("%s: Unhandled Host Status Error %x",
+ sc->sc_dev.dv_xname, scsiq->host_status);
}
- break;
-
- case QD_ABORTED_BY_HOST:
- xs->error = XS_DRIVER_STUFFUP;
- printf("%s: Command aborted by host.\n", sc->sc_dev.dv_xname);
Home |
Main Index |
Thread Index |
Old Index