summaryrefslogtreecommitdiffstats
path: root/sys/dev/aic7xxx/aic7xxx_osm.c
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>2000-10-09 01:46:01 +0000
committergibbs <gibbs@FreeBSD.org>2000-10-09 01:46:01 +0000
commit04442ea304505df9fd1948294deea8a6f3a91f4e (patch)
treebd1e277c6cb3a4d84cd88a1c62ce5663123b9720 /sys/dev/aic7xxx/aic7xxx_osm.c
parenta67a650294f41fc22f7c8412a6911bdc4372408f (diff)
downloadFreeBSD-src-04442ea304505df9fd1948294deea8a6f3a91f4e.zip
FreeBSD-src-04442ea304505df9fd1948294deea8a6f3a91f4e.tar.gz
Clean up error recovery code:
aic7xxx.c: In target mode, reset the TQINPOS on every restart of the sequencer. In the past we did this only during a bus reset, but there are other reasons the sequencer might be reset. In ahc_clear_critical_section(), disable pausing chip interrupts while we step the sequencer out of a critical section. This avoids the possibility of getting a pausing interrupt (unexpected bus free, bus reset, etc.) that would prevent the sequencer from stepping. Send the correct async notifications in the case of a BDR or bus reset. In ahc_loadseq(), correct the calculation of our critical sections. In some cases, the sections would be larger than needed. aic7xxx.h: Remove an unused SCB flag. aic7xxx.seq: MK_MESSAGE is cleared by the kernel, there is no need to waste a sequencer instruction clearing it. aic7xxx_freebsd.c: Go through the host message loop instead of issuing a single byte message directly in the ahc_timeout() case where we are currently on the bus to the device. The effect is the same, but this way we get a nice printf saying that an expected BDR was delivered instead of an unexpected bus free. If we are requeuing an SCB for an error recovery action, be sure to set the DISCONNECTED flag in the in-core version of the SCB. This ensures that, in the SCB-paging case, the sequencer will still recognize the reselection as valid even if the version of the SCB with this flag set was never previously paged out to system memory. In the non-paging case, set the MK_MESSAGE flag in SCB_CONTROL directly. aic7xxx_pci.c: Enable the Memeory Write and Invalidate bug workaround for all aic7880 chips with revs < 1. This bug is rarely triggered in FreeBSD as most transfers end on cache-aligned boundaries, but a recheck of my references indicates that these chips are affected.
Diffstat (limited to 'sys/dev/aic7xxx/aic7xxx_osm.c')
-rw-r--r--sys/dev/aic7xxx/aic7xxx_osm.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx_osm.c b/sys/dev/aic7xxx/aic7xxx_osm.c
index 988ebb4..04d83b9 100644
--- a/sys/dev/aic7xxx/aic7xxx_osm.c
+++ b/sys/dev/aic7xxx/aic7xxx_osm.c
@@ -1542,7 +1542,7 @@ bus_reset:
}
ahc_set_recoveryscb(ahc, active_scb);
- ahc_outb(ahc, MSG_OUT, MSG_BUS_DEV_RESET);
+ ahc_outb(ahc, MSG_OUT, HOST_MSG);
ahc_outb(ahc, SCSISIGO, last_phase|ATNO);
ahc_print_path(ahc, active_scb);
printf("BDR message in message buffer\n");
@@ -1581,19 +1581,25 @@ bus_reset:
ahc_set_recoveryscb(ahc, scb);
/*
- * Simply set the MK_MESSAGE control bit.
- */
- scb->hscb->control |= MK_MESSAGE;
- scb->flags |= SCB_QUEUED_MSG
- | SCB_DEVICE_RESET;
-
- /*
* Actually re-queue this SCB in an attempt
* to select the device before it reconnects.
* In either case (selection or reselection),
* we will now issue a target reset to the
* timed-out device.
*
+ * Set the MK_MESSAGE control bit indicating
+ * that we desire to send a message. We
+ * also set the disconnected flag since
+ * in the paging case there is no guarantee
+ * that our SCB control byte matches the
+ * version on the card. We don't want the
+ * sequencer to abort the command thinking
+ * an unsolicited reselection occurred.
+ */
+ scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
+ scb->flags |= SCB_DEVICE_RESET;
+
+ /*
* Remove any cached copy of this SCB in the
* disconnected list in preparation for the
* queuing of our abort SCB. We use the
@@ -1604,7 +1610,21 @@ bus_reset:
lun, scb->hscb->tag,
/*stop_on_first*/TRUE,
/*remove*/TRUE,
- /*save_state*/TRUE);
+ /*save_state*/FALSE);
+
+ /*
+ * In the non-paging case, the sequencer will
+ * never re-reference the in-core SCB.
+ * To make sure we are notified during
+ * reslection, set the MK_MESSAGE flag in
+ * the card's copy of the SCB.
+ */
+ if ((ahc->flags & AHC_PAGESCBS) != 0) {
+ ahc_outb(ahc, SCBPTR, scb->hscb->tag);
+ ahc_outb(ahc, SCB_CONTROL,
+ ahc_inb(ahc, SCB_CONTROL)
+ | MK_MESSAGE);
+ }
/*
* Clear out any entries in the QINFIFO first
@@ -1630,6 +1650,7 @@ bus_reset:
prev_tag);
}
ahc_qinfifo_requeue(ahc, prev_scb, scb);
+ ahc_outb(ahc, SCBPTR, active_scb_index);
scb->io_ctx->ccb_h.timeout_ch =
timeout(ahc_timeout, (caddr_t)scb, 2 * hz);
unpause_sequencer(ahc);
OpenPOWER on IntegriCloud