summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>2000-07-24 22:27:40 +0000
committergibbs <gibbs@FreeBSD.org>2000-07-24 22:27:40 +0000
commit60328e3aef4d63fcd77887e459f11eead2bf3b82 (patch)
tree4edc298bc7f68052ec7aa4ebe8a85235d7118664 /sys
parent6ac12ce11530d236bd7b7e9e14bceb08e046454b (diff)
downloadFreeBSD-src-60328e3aef4d63fcd77887e459f11eead2bf3b82.zip
FreeBSD-src-60328e3aef4d63fcd77887e459f11eead2bf3b82.tar.gz
aic7xxx.c:
Correct the BUILD_TCL macro. It was placing the target id in the wrong bits. This was only an issue for adapters that do not perform SCB paging (aha-3940AUW for instance). Don't bother inlining ahc_index_busy_tcl. It is never used in a performance critical path and is a bit chunky. Correct ahc_index_busy_tcl to deal with "busy target tables" embedded in the latter half of 64byte SCBs. Don't initialize the busy target table to its empty state until after we have finished extracting configuration information from chip SRAM. In the common case of using 16 bytes of chip SRAM to do untagged target lookups, we were trashing the last 8 targets configuration data. (actually only target 8 because of the bug in the BUILD_TCL macro). Cram the "bus reset delivered" message back under bootverbose. Fix the cleanup of the SCB busy target table when aborting commands. If the lun is wildcarded, we must loop through all possible luns. aic7xxx.h: Only bother supporting 64 luns right now. It doesn't seem like either this driver or any peripherals will be doing information unit transfers (where the lun number is a 32 bit integer) any time soon. aic7xxx.seq: Fix support for the aic7895. We must flush the data FIFO if performing a manual transfer that is not a multiple of 8 bytes. We were doing this quite regularly for embedded cdbs. Manaually flush the fifo on earlier adapters when dealing with embedded cdbs too. We were stuffing the FIFO with 16 bytes instead, but triggering the flush is more efficient and allows us to remove two instructions from the "copy_to_fifo" routine.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/aic7xxx/aic7xxx.c118
-rw-r--r--sys/dev/aic7xxx/aic7xxx.h7
-rw-r--r--sys/dev/aic7xxx/aic7xxx.seq16
3 files changed, 92 insertions, 49 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c
index 3859c19..8ac28db 100644
--- a/sys/dev/aic7xxx/aic7xxx.c
+++ b/sys/dev/aic7xxx/aic7xxx.c
@@ -168,8 +168,10 @@
(0x01 << (SCB_GET_TARGET_OFFSET(ahc, scb)))
#define TCL_TARGET_OFFSET(tcl) \
((((tcl) >> 4) & TID) >> 4)
+#define TCL_LUN(tcl) \
+ (tcl & (AHC_NUM_LUNS - 1))
#define BUILD_TCL(scsiid, lun) \
- ((lun) | (((scsiid) & TID) >> 4))
+ ((lun) | (((scsiid) & TID) << 4))
#define BUILD_SCSIID(ahc, sim, target_id, our_id) \
((((target_id) << TID_SHIFT) & TID) | (our_id) \
| (SIM_IS_SCSIBUS_B(ahc, sim) ? TWIN_CHNLB : 0))
@@ -394,8 +396,8 @@ static void ahc_queue_lstate_event(struct ahc_softc *ahc,
u_int event_arg);
static void ahc_send_lstate_events(struct ahc_softc *ahc,
struct tmode_lstate *lstate);
-static void restart_sequencer(struct ahc_softc *ahc);
-static __inline u_int ahc_index_busy_tcl(struct ahc_softc *ahc,
+static void restart_sequencer(struct ahc_softc *ahc);
+static u_int ahc_index_busy_tcl(struct ahc_softc *ahc,
u_int tcl, int unbusy);
static __inline void ahc_freeze_ccb(union ccb* ccb);
@@ -468,16 +470,29 @@ restart_sequencer(struct ahc_softc *ahc)
unpause_sequencer(ahc);
}
-static __inline u_int
+static u_int
ahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl, int unbusy)
{
u_int scbid;
u_int target_offset;
- target_offset = TCL_TARGET_OFFSET(tcl);
- scbid = ahc_inb(ahc, BUSY_TARGETS + target_offset);
- if (unbusy)
- ahc_outb(ahc, BUSY_TARGETS + target_offset, SCB_LIST_NULL);
+ if ((ahc->features & AHC_SCB_BTT) != 0) {
+ u_int saved_scbptr;
+
+ saved_scbptr = ahc_inb(ahc, SCBPTR);
+ ahc_outb(ahc, SCBPTR, TCL_LUN(tcl));
+ scbid = ahc_inb(ahc, SCB_64_BTT + TCL_TARGET_OFFSET(tcl));
+ if (unbusy)
+ ahc_outb(ahc, SCB_64_BTT + TCL_TARGET_OFFSET(tcl),
+ SCB_LIST_NULL);
+ ahc_outb(ahc, SCBPTR, saved_scbptr);
+ } else {
+ target_offset = TCL_TARGET_OFFSET(tcl);
+ scbid = ahc_inb(ahc, BUSY_TARGETS + target_offset);
+ if (unbusy)
+ ahc_outb(ahc, BUSY_TARGETS + target_offset,
+ SCB_LIST_NULL);
+ }
return (scbid);
}
@@ -1199,10 +1214,10 @@ ahc_reset(struct ahc_softc *ahc)
* not, STPWEN will be false (the value after a POST)
* and this action will be harmless.
*
- * We must actually always initialize STPWEN to 1
- * before we restore the saved value. STPWEN is
- * initialized to a tri-state condition which is
- * only be cleared by turning it on.
+ * We must always initialize STPWEN to 1 before we
+ * restore the saved value. STPWEN is initialized
+ * to a tri-state condition which is only be cleared
+ * by turning it on.
*/
ahc_outb(ahc, SXFRCTL1, sxfrctl1|STPWEN);
ahc_outb(ahc, SXFRCTL1, sxfrctl1);
@@ -4518,23 +4533,6 @@ ahc_init(struct ahc_softc *ahc)
if (ahcinitscbdata(ahc) != 0)
return (ENOMEM);
- /* There are no untagged SCBs active yet. */
- /* XXX will need to change for SCB ram approach */
- for (i = 0; i < 16; i++)
- ahc_index_busy_tcl(ahc, BUILD_TCL(i << 4, 0), /*unbusy*/TRUE);
-
- /* All of our queues are empty */
- for (i = 0; i < 256; i++)
- ahc->qoutfifo[i] = SCB_LIST_NULL;
-
- for (i = 0; i < 256; i++)
- ahc->qinfifo[i] = SCB_LIST_NULL;
-
- if ((ahc->features & AHC_MULTI_TID) != 0) {
- ahc_outb(ahc, TARGID, 0);
- ahc_outb(ahc, TARGID + 1, 0);
- }
-
/*
* Allocate a tstate to house information for our
* initiator presence on the bus as well as the user
@@ -4747,6 +4745,36 @@ ahc_init(struct ahc_softc *ahc)
ahc->user_discenable = discenable;
ahc->user_tagenable = tagenable;
+ /* There are no untagged SCBs active yet. */
+ for (i = 0; i < 16; i++) {
+ ahc_index_busy_tcl(ahc, BUILD_TCL(i << 4, 0), /*unbusy*/TRUE);
+ if ((ahc->features & AHC_SCB_BTT) != 0) {
+ int lun;
+
+ /*
+ * The SCB based BTT allows an entry per
+ * target and lun pair.
+ */
+ for (lun = 1; lun < AHC_NUM_LUNS; lun++) {
+ ahc_index_busy_tcl(ahc,
+ BUILD_TCL(i << 4, lun),
+ /*unbusy*/TRUE);
+ }
+ }
+ }
+
+ /* All of our queues are empty */
+ for (i = 0; i < 256; i++)
+ ahc->qoutfifo[i] = SCB_LIST_NULL;
+
+ for (i = 0; i < 256; i++)
+ ahc->qinfifo[i] = SCB_LIST_NULL;
+
+ if ((ahc->features & AHC_MULTI_TID) != 0) {
+ ahc_outb(ahc, TARGID, 0);
+ ahc_outb(ahc, TARGID + 1, 0);
+ }
+
/*
* Tell the sequencer where it can find our arrays in memory.
*/
@@ -5320,7 +5348,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
found = ahc_reset_channel(ahc, SIM_CHANNEL(ahc, sim),
/*initiate reset*/TRUE);
splx(s);
- if (1 || bootverbose) {
+ if (bootverbose) {
xpt_print_path(SIM_PATH(ahc, sim));
printf("SCSI bus reset delivered. "
"%d SCBs aborted.\n", found);
@@ -6577,14 +6605,36 @@ ahc_abort_scbs(struct ahc_softc *ahc, int target, char channel,
for (;i < maxtarget; i++) {
u_int scbid;
- /* XXX Will need lun loop for SCB ram version */
scbid = ahc_index_busy_tcl(ahc, BUILD_TCL(i << 4, 0),
/*unbusy*/FALSE);
scbp = &ahc->scb_data->scbarray[scbid];
if (scbid < ahc->scb_data->numscbs
- && ahc_match_scb(ahc, scbp, target, channel, lun, tag, role))
- ahc_index_busy_tcl(ahc, BUILD_TCL(i << 4, 0),
- /*unbusy*/TRUE);
+ && ahc_match_scb(ahc, scbp, target, channel, lun, tag, role)) {
+ u_int minlun;
+ u_int maxlun;
+
+ if (lun == CAM_LUN_WILDCARD) {
+
+ /*
+ * Unless we are using an SCB based
+ * busy targets table, there is only
+ * one table entry for all luns of
+ * a target.
+ */
+ minlun = 0;
+ maxlun = 1;
+ if ((ahc->flags & AHC_SCB_BTT) != 0)
+ maxlun = AHC_NUM_LUNS;
+ } else {
+ minlun = lun;
+ maxlun = lun + 1;
+ }
+ while (minlun < maxlun) {
+ ahc_index_busy_tcl(ahc, BUILD_TCL(i << 4,
+ minlun), /*unbusy*/TRUE);
+ minlun++;
+ }
+ }
}
/*
diff --git a/sys/dev/aic7xxx/aic7xxx.h b/sys/dev/aic7xxx/aic7xxx.h
index e491e22..6845299 100644
--- a/sys/dev/aic7xxx/aic7xxx.h
+++ b/sys/dev/aic7xxx/aic7xxx.h
@@ -56,12 +56,9 @@
/*
* The maximum number of supported luns.
- * Although the identify message only supports 64 luns in SPI3, you
- * can have 2^64 luns when information unit transfers are enabled.
- * The max we can do sanely given the 8bit nature of the RISC engine
- * on these chips is 256.
+ * The identify message supports up to 64 luns in SPI3.
*/
-#define AHC_NUM_LUNS 256
+#define AHC_NUM_LUNS 64
/*
* The maximum transfer per S/G segment.
diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq
index d2df34d..00b28b3 100644
--- a/sys/dev/aic7xxx/aic7xxx.seq
+++ b/sys/dev/aic7xxx/aic7xxx.seq
@@ -1112,13 +1112,13 @@ p_command_embedded:
}
if ((ahc->features & AHC_CMD_CHAN) != 0) {
bmov DFDAT, SCB_CDB_STORE, 12;
+ if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
+ or DFCNTRL, FIFOFLUSH;
+ }
} else {
- /*
- * At most 12 bytes, but we copy 16 to fill
- * the 64bit words in the FIFO
- */
- call copy_to_fifo_8;
- call copy_to_fifo_8;
+ call copy_to_fifo_6;
+ call copy_to_fifo_6;
+ or DFCNTRL, FIFOFLUSH;
}
p_command_loop:
test SSTAT0, SDONE jnz . + 2;
@@ -1849,10 +1849,6 @@ dfdat_in_2_continued:
mov DINDIR,DFDAT ret;
}
-copy_to_fifo_8:
- mov DFDAT,SINDIR;
-copy_to_fifo_7:
- mov DFDAT,SINDIR;
copy_to_fifo_6:
mov DFDAT,SINDIR;
copy_to_fifo_5:
OpenPOWER on IntegriCloud