summaryrefslogtreecommitdiffstats
path: root/sys/dev/aic7xxx/aic7xxx_inline.h
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>2000-10-05 04:24:14 +0000
committergibbs <gibbs@FreeBSD.org>2000-10-05 04:24:14 +0000
commit53b245ea4d63e5de1d1046e01869c44196fa5e7d (patch)
tree0cf8ec6adc0bc1fdf748acaefd18fbfaa74c0348 /sys/dev/aic7xxx/aic7xxx_inline.h
parentabbeb4eb790e7fad36e1d81705b63cf6d631b7ee (diff)
downloadFreeBSD-src-53b245ea4d63e5de1d1046e01869c44196fa5e7d.zip
FreeBSD-src-53b245ea4d63e5de1d1046e01869c44196fa5e7d.tar.gz
Convert the driver to use a single DMA for fetching new commands instead
of two (one to access the circular input fifo, the other to get the SCB). This costs us a command slot so the driver can now only queue 254 simultaneous commands. Have the kernel driver honor critical sections in sequencer code. When prefetching S/G segments only pull a cacheline's worth but never less than two elements. This reduces the impact of the prefetch on the main data transfer when compared to the 128 byte fetches the driver used to do. Add "bootverbose" logging for transfer negotiations. Correct a bug in ahc_set_syncrate() that would prevent an update of the sync parameters if only the ppr_options had changed. Correct locking for calls to ahc_free_scb(). ahc_free_scb() is no longer protected internally to simplify ports to other platforms. Make sure we unfreeze our SIMQ if a resource shortage has occurred and an SCB is been freed. ahc_pci.c: Turn on cacheline streaming for all controllers that support it. Clarify diagnostic messages about PCI interrupts.
Diffstat (limited to 'sys/dev/aic7xxx/aic7xxx_inline.h')
-rw-r--r--sys/dev/aic7xxx/aic7xxx_inline.h72
1 files changed, 54 insertions, 18 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx_inline.h b/sys/dev/aic7xxx/aic7xxx_inline.h
index 7bf63de..8f6d2ba 100644
--- a/sys/dev/aic7xxx/aic7xxx_inline.h
+++ b/sys/dev/aic7xxx/aic7xxx_inline.h
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx_inline.h#3 $
+ * $Id: //depot/src/aic7xxx/aic7xxx_inline.h#5 $
*
* $FreeBSD$
*/
@@ -242,18 +242,16 @@ ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id,
static __inline struct scb *
ahc_get_scb(struct ahc_softc *ahc)
{
- struct scb *scbp;
+ struct scb *scb;
- if ((scbp = SLIST_FIRST(&ahc->scb_data->free_scbs))) {
- SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links.sle);
- } else {
+ if ((scb = SLIST_FIRST(&ahc->scb_data->free_scbs)) == NULL) {
ahc_alloc_scbs(ahc);
- scbp = SLIST_FIRST(&ahc->scb_data->free_scbs);
- if (scbp != NULL)
- SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links.sle);
+ scb = SLIST_FIRST(&ahc->scb_data->free_scbs);
+ if (scb == NULL)
+ return (NULL);
}
-
- return (scbp);
+ SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links.sle);
+ return (scb);
}
/*
@@ -265,19 +263,22 @@ ahc_free_scb(struct ahc_softc *ahc, struct scb *scb)
struct hardware_scb *hscb;
hscb = scb->hscb;
-#if 0
- /* What do we do to generically handle driver resource shortages??? */
- if ((ahc->flags & AHC_RESOURCE_SHORTAGE) != 0
- && (scb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
- scb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
- ahc->flags &= ~AHC_RESOURCE_SHORTAGE;
- }
-#endif
/* Clean up for the next user */
+ ahc->scb_data->scbindex[hscb->tag] = NULL;
scb->flags = SCB_FREE;
hscb->control = 0;
SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle);
+
+ /* Notify the OSM that a resource is now available. */
+ ahc_platform_scb_free(ahc, scb);
+}
+
+static __inline struct scb *
+ahc_lookup_scb(struct ahc_softc *ahc, u_int tag)
+{
+ return (ahc->scb_data->scbindex[tag]);
+
}
/*
@@ -286,6 +287,41 @@ ahc_free_scb(struct ahc_softc *ahc, struct scb *scb)
static __inline void
ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb)
{
+ struct hardware_scb *q_hscb;
+ u_int saved_tag;
+
+ /*
+ * Our queuing method is a bit tricky. The card
+ * knows in advance which HSCB to download, and we
+ * can't disappoint it. To achieve this, the next
+ * SCB to download is saved off in ahc->next_queued_scb.
+ * When we are called to queue "an arbitrary scb",
+ * we copy the contents of the incoming HSCB to the one
+ * the sequencer knows about, swap HSCB pointers and
+ * finally assigne the SCB to the tag indexed location
+ * in the scb_array. This makes sure that we can still
+ * locate the correct SCB by SCB_TAG.
+ *
+ * Start by copying the payload without perterbing
+ * the tag number. Also set the hscb id for the next
+ * SCB to download.
+ */
+ q_hscb = ahc->next_queued_scb->hscb;
+ saved_tag = q_hscb->tag;
+ memcpy(q_hscb, scb->hscb, 32);
+ q_hscb->tag = saved_tag;
+ q_hscb->next = scb->hscb->tag;
+
+ /* Now swap HSCB pointers. */
+ ahc->next_queued_scb->hscb = scb->hscb;
+ scb->hscb = q_hscb;
+
+ /* Now define the mapping from tag to SCB in the scbindex */
+ ahc->scb_data->scbindex[scb->hscb->tag] = scb;
+
+ /*
+ * Keep a history of SCBs we've downloaded in the qinfifo.
+ */
ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag;
if ((ahc->features & AHC_QUEUE_REGS) != 0) {
ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext);
OpenPOWER on IntegriCloud