summaryrefslogtreecommitdiff
path: root/sys/dev/ic/isp.c
diff options
context:
space:
mode:
authormjacob <mjacob@NetBSD.org>1999-10-14 02:27:12 +0000
committermjacob <mjacob@NetBSD.org>1999-10-14 02:27:12 +0000
commit2b760bfd7b8a7eac756c6744fd3c8e24ef1b1b70 (patch)
tree7165dae162d40206025eee451b3894bd88d0806a /sys/dev/ic/isp.c
parent74f3840c1baab976d7116124d4c17a6ee1ffc9bf (diff)
remove most target mode stuff. Change the arguments to the
isp_fastpost_complete function to include a handle. Do some isr register debouncing. Use new inline functions for xflist handle storage. Remove isp_dumpxflist function. Do some fixups of NVRAM from some broken cards. Use Full Login after LIP option for FC cards if f/w < 1.17 - there's a f/w bug that causes the port database to not be actually refreshed for local loop devices! Do the appropriate endian swizzling for the ICB. Ditto for SNS structures (these are no-ops until UltraSparc PCI needs them).
Diffstat (limited to 'sys/dev/ic/isp.c')
-rw-r--r--sys/dev/ic/isp.c1207
1 files changed, 311 insertions, 896 deletions
diff --git a/sys/dev/ic/isp.c b/sys/dev/ic/isp.c
index 1bb34aaf414..1a3f2dc1784 100644
--- a/sys/dev/ic/isp.c
+++ b/sys/dev/ic/isp.c
@@ -1,5 +1,4 @@
-/* $NetBSD: isp.c,v 1.37 1999/07/05 20:31:35 mjacob Exp $ */
-/* release_6_5_99 */
+/* $NetBSD: isp.c,v 1.38 1999/10/14 02:27:12 mjacob Exp $ */
/*
* Copyright (C) 1997, 1998, 1999 National Aeronautics & Space Administration
* All rights reserved.
@@ -26,6 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
/*
* Machine and OS Independent (well, as best as possible)
* code for the Qlogic ISP SCSI adapters.
@@ -64,31 +64,6 @@
/*
* Local static data
*/
-#ifdef ISP_TARGET_MODE
-static const char tgtiqd[36] = {
- 0x03, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0x51, 0x4C, 0x4F, 0x47, 0x49, 0x43, 0x20, 0x20,
-#ifdef __NetBSD__
- 0x4E, 0x45, 0x54, 0x42, 0x53, 0x44, 0x20, 0x20,
-#else
-# ifdef __FreeBSD__
- 0x46, 0x52, 0x45, 0x45, 0x42, 0x52, 0x44, 0x20,
-# else
-# ifdef __OpenBSD__
- 0x4F, 0x50, 0x45, 0x4E, 0x42, 0x52, 0x44, 0x20,
-# else
-# ifdef linux
- 0x4C, 0x49, 0x4E, 0x55, 0x58, 0x20, 0x20, 0x20,
-# else
-# endif
-# endif
-# endif
-#endif
- 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x20, 0x20,
- 0x20, 0x20, 0x20, 0x31
-};
-#endif
-
/*
* Local function prototypes.
@@ -96,17 +71,9 @@ static const char tgtiqd[36] = {
static int isp_parse_async __P((struct ispsoftc *, int));
static int isp_handle_other_response
__P((struct ispsoftc *, ispstatusreq_t *, u_int8_t *));
-#ifdef ISP_TARGET_MODE
-static int isp_modify_lun __P((struct ispsoftc *, int, int, int));
-static void isp_notify_ack __P((struct ispsoftc *, void *));
-static void isp_handle_atio __P((struct ispsoftc *, void *));
-static void isp_handle_atio2 __P((struct ispsoftc *, void *));
-static void isp_handle_ctio __P((struct ispsoftc *, void *));
-static void isp_handle_ctio2 __P((struct ispsoftc *, void *));
-#endif
static void isp_parse_status
__P((struct ispsoftc *, ispstatusreq_t *, ISP_SCSI_XFER_T *));
-static void isp_fastpost_complete __P((struct ispsoftc *, int));
+static void isp_fastpost_complete __P((struct ispsoftc *, u_int32_t));
static void isp_scsi_init __P((struct ispsoftc *));
static void isp_scsi_channel_init __P((struct ispsoftc *, int));
static void isp_fibre_init __P((struct ispsoftc *));
@@ -121,7 +88,6 @@ static int isp_scan_fabric __P((struct ispsoftc *));
#endif
static void isp_fw_state __P((struct ispsoftc *));
static void isp_dumpregs __P((struct ispsoftc *, const char *));
-static void isp_dumpxflist __P((struct ispsoftc *));
static void isp_mboxcmd __P((struct ispsoftc *, mbreg_t *));
static void isp_update __P((struct ispsoftc *));
@@ -202,8 +168,8 @@ isp_reset(isp)
case ISP_HA_FC_2200:
revname[1] = '2';
/*
- * Resident firmware for the 2200 appears to have
- * SCCLUN enabled.
+ * Resident firmware for the 2200 appears
+ * to have SCCLUN enabled.
*/
#ifndef ISP2100_SCCLUN
if (isp->isp_mdvec->dv_fwlen == 0) {
@@ -392,7 +358,7 @@ again:
*/
loops = MBOX_DELAY_COUNT;
for (;;) {
- if (isp->isp_type & ISP_HA_SCSI) {
+ if (IS_SCSI(isp)) {
if (!(ISP_READ(isp, BIU_ICR) & BIU_ICR_SOFT_RESET))
break;
} else {
@@ -468,13 +434,6 @@ again:
*/
ISP_RESET1(isp);
-#if 0
- /*
- * Enable interrupts
- */
- ENABLE_INTS(isp);
-#endif
-
/*
* Wait for everything to finish firing up...
*/
@@ -582,7 +541,7 @@ again:
mbs.param[1] = 0x1000;
isp_mboxcmd(isp, &mbs);
- if (isp->isp_type & ISP_HA_SCSI) {
+ if (IS_SCSI(isp)) {
/*
* Set CLOCK RATE, but only if asked to.
*/
@@ -591,38 +550,48 @@ again:
mbs.param[1] = isp->isp_clock;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- isp_dumpregs(isp, "failed to set CLOCKRATE");
+ PRINTF("failed to set clockrate (0x%x)\n",
+ mbs.param[0]);
/* but continue */
- } else {
- IDPRINTF(3, ("%s: setting input clock to %d\n",
- isp->isp_name, isp->isp_clock));
}
}
}
mbs.param[0] = MBOX_ABOUT_FIRMWARE;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- isp_dumpregs(isp, "ABOUT FIRMWARE command failed");
+ PRINTF("could not get f/w started (0x%x)\n", mbs.param[0]);
return;
}
- PRINTF("%s: Board Revision %s, %s F/W Revision %d.%d.%d\n",
- isp->isp_name, revname, dodnld? "loaded" : "resident",
- mbs.param[1], mbs.param[2], mbs.param[3]);
+ CFGPRINTF("%s: Board Revision %s, %s F/W Revision %d.%d.%d\n",
+ isp->isp_name, revname, dodnld? "loaded" : "resident",
+ mbs.param[1], mbs.param[2], mbs.param[3]);
if (IS_FC(isp)) {
if (ISP_READ(isp, BIU2100_CSR) & BIU2100_PCI64) {
- PRINTF("%s: in 64-Bit PCI slot\n", isp->isp_name);
+ CFGPRINTF("%s: in 64-Bit PCI slot\n", isp->isp_name);
}
}
+
isp->isp_fwrev[0] = mbs.param[1];
isp->isp_fwrev[1] = mbs.param[2];
isp->isp_fwrev[2] = mbs.param[3];
if (isp->isp_romfw_rev[0] || isp->isp_romfw_rev[1] ||
isp->isp_romfw_rev[2]) {
- PRINTF("%s: Last F/W revision was %d.%d.%d\n", isp->isp_name,
+ CFGPRINTF("%s: Last F/W revision was %d.%d.%d\n", isp->isp_name,
isp->isp_romfw_rev[0], isp->isp_romfw_rev[1],
isp->isp_romfw_rev[2]);
}
+
+ mbs.param[0] = MBOX_GET_FIRMWARE_STATUS;
+ isp_mboxcmd(isp, &mbs);
+ if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ PRINTF("%s: could not GET FIRMWARE STATUS\n", isp->isp_name);
+ return;
+ }
+ isp->isp_maxcmds = mbs.param[2];
+ CFGPRINTF("%s: %d max I/O commands supported\n",
+ isp->isp_name, mbs.param[2]);
isp_fw_state(isp);
+
/*
* Set up DMA for the request and result mailboxes.
*/
@@ -856,8 +825,8 @@ isp_scsi_channel_init(isp, channel)
u_int16_t sdf;
if (sdp->isp_devparam[tgt].dev_enable == 0) {
- PRINTF("%s: skipping settings for target %d bus %d\n",
- isp->isp_name, tgt, channel);
+ IDPRINTF(1, ("%s: skipping target %d bus %d settings\n",
+ isp->isp_name, tgt, channel));
continue;
}
@@ -993,31 +962,24 @@ isp_fibre_init(isp)
icbp->icb_version = ICB_VERSION1;
#ifdef ISP_TARGET_MODE
- fcp->isp_fwoptions = ICBOPT_TGT_ENABLE|ICBOPT_INI_TGTTYPE;
+ fcp->isp_fwoptions = ICBOPT_TGT_ENABLE;
#else
fcp->isp_fwoptions = 0;
#endif
fcp->isp_fwoptions |= ICBOPT_FAIRNESS;
fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE;
fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS;
-#ifdef ISP2100_FABRIC
-#if 0
- /*
- * Do not use FULL LOGIN- it resets the loop too much.
- */
- fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN;
-#endif
-#endif
-#if 0
/*
- * Don't use this either
+ * We have to use FULL LOGIN even though it resets the loop too much
+ * because otherwise port database entries don't get updated after
+ * a LIP- this is a known f/w bug.
*/
- fcp->isp_fwoptions |= ICBOPT_INI_ADISC;
-#endif
+ if (ISP_FW_REVX(isp->isp_fwrev) < ISP_FW_REV(1, 17, 0)) {
+ fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN;
+ }
#ifndef ISP_NO_FASTPOST_FC
fcp->isp_fwoptions |= ICBOPT_FAST_POST;
#endif
-
if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX)
fcp->isp_fwoptions |= ICBOPT_FULL_DUPLEX;
@@ -1049,6 +1011,7 @@ isp_fibre_init(isp)
icbp->icb_retry_delay = fcp->isp_retry_delay;
icbp->icb_retry_count = fcp->isp_retry_count;
icbp->icb_hardaddr = loopid;
+ icbp->icb_logintime = 30; /* 30 second login timeout */
if (fcp->isp_nodewwn) {
u_int64_t pn;
@@ -1074,15 +1037,22 @@ isp_fibre_init(isp)
} else {
fcp->isp_fwoptions &= ~(ICBOPT_USE_PORTNAME|ICBOPT_FULL_LOGIN);
}
-
icbp->icb_rqstqlen = RQUEST_QUEUE_LEN;
icbp->icb_rsltqlen = RESULT_QUEUE_LEN;
icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_LSW(isp->isp_rquest_dma);
icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_MSW(isp->isp_rquest_dma);
icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_LSW(isp->isp_result_dma);
icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_MSW(isp->isp_result_dma);
- MemoryBarrier();
+ ISP_SWIZZLE_ICB(isp, icbp);
+
+ /*
+ * Do this *before* initializing the firmware.
+ */
+ isp_mark_getpdb_all(isp);
+ fcp->isp_fwstate = FW_CONFIG_WAIT;
+ fcp->isp_loopstate = LOOP_NIL;
+ MemoryBarrier();
for (;;) {
mbs.param[0] = MBOX_INIT_FIRMWARE;
mbs.param[1] = 0;
@@ -1096,7 +1066,7 @@ isp_fibre_init(isp)
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
PRINTF("%s: INIT FIRMWARE failed (code 0x%x)\n",
isp->isp_name, mbs.param[0]);
- if (mbs.param[0] & 0xc000) {
+ if (mbs.param[0] & 0x8000) {
SYS_DELAY(1000);
continue;
}
@@ -1113,9 +1083,6 @@ isp_fibre_init(isp)
* Whatever happens, we're now committed to being here.
*/
isp->isp_state = ISP_INITSTATE;
- fcp->isp_fwstate = FW_CONFIG_WAIT;
-
- isp_mark_getpdb_all(isp);
#ifdef ISP_TARGET_MODE
if (isp_modify_lun(isp, 0, 1, 1)) {
@@ -1168,7 +1135,7 @@ isp_getpdb(isp, id, pdbp)
switch (mbs.param[0]) {
case MBOX_COMMAND_COMPLETE:
MemoryBarrier();
- MEMCPY(pdbp, fcp->isp_scratch, sizeof (isp_pdb_t));
+ ISP_UNSWIZZLE_AND_COPY_PDBP(isp, pdbp, fcp->isp_scratch);
break;
case MBOX_HOST_INTERFACE_ERROR:
PRINTF("%s: DMA error getting port database\n", isp->isp_name);
@@ -1223,8 +1190,15 @@ isp_fclink_test(isp, waitdelay)
struct ispsoftc *isp;
int waitdelay;
{
+ static char *toponames[] = {
+ "Private Loop",
+ "FL Port",
+ "N-Port to N-Port",
+ "F Port"
+ };
+ char *tname;
mbreg_t mbs;
- int count;
+ int count, topo = -1;
u_int8_t lwfs;
fcparam *fcp;
#if defined(ISP2100_FABRIC)
@@ -1267,6 +1241,19 @@ isp_fclink_test(isp, waitdelay)
return (-1);
}
fcp->isp_loopid = mbs.param[1];
+ if (isp->isp_type == ISP_HA_FC_2100) {
+ if (ISP_FW_REVX(isp->isp_fwrev) >= ISP_FW_REV(2, 0, 14)) {
+ topo = (int) mbs.param[6];
+ }
+ } else if (isp->isp_type == ISP_HA_FC_2100) {
+ if (ISP_FW_REVX(isp->isp_fwrev) >= ISP_FW_REV(1, 17, 26)) {
+ topo = (int) mbs.param[6];
+ }
+ }
+ if (topo < 0 || topo > 3)
+ tname = "unknown";
+ else
+ tname = toponames[topo];
/*
* If we're not on a fabric, the low 8 bits will be our AL_PA.
@@ -1274,12 +1261,13 @@ isp_fclink_test(isp, waitdelay)
*/
fcp->isp_alpa = mbs.param[2];
#if defined(ISP2100_FABRIC)
+ fcp->isp_onfabric = 0;
if (isp_getpdb(isp, FL_PORT_ID, &pdb) == 0) {
fcp->isp_portid = mbs.param[2] | (((int)mbs.param[3]) << 16);
fcp->isp_onfabric = 1;
- PRINTF("%s: Loop ID %d, AL_PA 0x%x, Port ID 0x%x\n",
- isp->isp_name, fcp->isp_loopid, fcp->isp_alpa,
- fcp->isp_portid);
+ CFGPRINTF("%s: Loop ID %d, AL_PA 0x%x, Port ID 0x%x Loop State "
+ "0x%x topology %s\n", isp->isp_name, fcp->isp_loopid,
+ fcp->isp_alpa, fcp->isp_portid, fcp->isp_loopstate, tname);
/*
* Make sure we're logged out of all fabric devices.
@@ -1299,8 +1287,9 @@ isp_fclink_test(isp, waitdelay)
}
} else
#endif
- PRINTF("%s: Loop ID %d, ALPA 0x%x\n", isp->isp_name,
- fcp->isp_loopid, fcp->isp_alpa);
+ CFGPRINTF("%s: Loop ID %d, ALPA 0x%x Loop State 0x%x topology %s\n",
+ isp->isp_name, fcp->isp_loopid, fcp->isp_alpa, fcp->isp_loopstate,
+ tname);
fcp->loop_seen_once = 1;
return (0);
}
@@ -1336,13 +1325,11 @@ isp_pdb_sync(isp, target)
struct ispsoftc *isp;
int target;
{
- struct lportdb *lp, tport[FL_PORT_ID];
+ struct lportdb *lp, *tport;
fcparam *fcp = isp->isp_param;
isp_pdb_t pdb;
int loopid, lim;
-target = target;
-
#ifdef ISP2100_FABRIC
/*
* XXX: If we do this *after* building up our local port database,
@@ -1354,6 +1341,8 @@ target = target;
if (fcp->isp_onfabric)
(void) isp_scan_fabric(isp);
#endif
+
+
/*
* Run through the local loop ports and get port database info
* for each loop ID.
@@ -1362,13 +1351,13 @@ target = target;
* the wrong database entity- if that happens, just restart (up to
* FL_PORT_ID times).
*/
+ tport = fcp->tport;
+ MEMZERO((void *) tport, sizeof (tport));
for (lim = loopid = 0; loopid < FL_PORT_ID; loopid++) {
/*
* make sure the temp port database is clean...
*/
lp = &tport[loopid];
- MEMZERO((void *) lp, sizeof (*lp));
-
lp->node_wwn = isp_get_portname(isp, loopid, 1);
if (lp->node_wwn == 0)
continue;
@@ -1377,12 +1366,14 @@ target = target;
lp->node_wwn = 0;
continue;
}
+
/*
* Get an entry....
*/
if (isp_getpdb(isp, loopid, &pdb) != 0) {
continue;
}
+
/*
* If the returned database element doesn't match what we
* asked for, restart the process entirely (up to a point...).
@@ -1398,6 +1389,7 @@ target = target;
"database\n", isp->isp_name);
return (-1);
}
+
/*
* Save the pertinent info locally.
*/
@@ -1444,6 +1436,13 @@ target = target;
fcp->isp_loopstate = LOOP_READY;
/*
+ * Mark all of the permanent local loop database entries as invalid.
+ */
+ for (loopid = 0; loopid < FL_PORT_ID; loopid++) {
+ fcp->portdb[loopid].valid = 0;
+ }
+
+ /*
* Now merge our local copy of the port database into our saved copy.
* Notify the outer layers of new devices arriving.
*/
@@ -1451,12 +1450,6 @@ target = target;
int i;
/*
- * While we're at it, clear the valid bit for the saved entry
- * that coincidentally is at this same index.
- */
- fcp->portdb[loopid].valid = 0;
-
- /*
* If we don't have a non-zero Port WWN, we're not here.
*/
if (tport[loopid].port_wwn == 0) {
@@ -1466,12 +1459,10 @@ target = target;
/*
* If we've already marked our tmp copy as valid,
* this means that we've decided that it's the
- * same as our saved data base. This does not include
- * the 'valid' marking though so we have to turn it
- * back on.
+ * same as our saved data base. This didn't include
+ * the 'valid' marking so we have set that here.
*/
if (tport[loopid].valid) {
-IDPRINTF(0, ("%s: loopid %d already valid\n", isp->isp_name, loopid));
fcp->portdb[loopid].valid = 1;
continue;
}
@@ -1499,12 +1490,19 @@ IDPRINTF(0, ("%s: loopid %d already valid\n", isp->isp_name, loopid));
* just change the actual loop ID we'd use.
*/
if (fcp->portdb[i].loopid != loopid) {
- PRINTF("%s: Target ID %d (0x%x) was loopid 0x%x"
- " and is now loopid 0x%x\n", isp->isp_name,
- i, i, fcp->portdb[i].loopid, loopid);
+ PRINTF("%s: Target ID %d Loop 0x%x (Port 0x%x) "
+ "=> Loop 0x%x (Port 0x%x) \n",
+ isp->isp_name, i, fcp->portdb[i].loopid,
+ fcp->portdb[i].portid, loopid,
+ tport[loopid].portid);
}
+ fcp->portdb[i].portid = tport[loopid].portid;
fcp->portdb[i].loopid = loopid;
fcp->portdb[i].valid = 1;
+ /*
+ * XXX: Should we also propagate roles in case they
+ * XXX: changed?
+ */
/*
* Now make sure this Port WWN doesn't exist elsewhere
@@ -1613,7 +1611,7 @@ IDPRINTF(0, ("%s: loopid %d already valid\n", isp->isp_name, loopid));
/*
* Force a logout.
*/
- lp->loopid = lp - fcp->portdb;
+ lp->loopid = loopid = lp - fcp->portdb;
mbs.param[0] = MBOX_FABRIC_LOGOUT;
mbs.param[1] = lp->loopid << 8;
mbs.param[2] = 0;
@@ -1629,10 +1627,46 @@ IDPRINTF(0, ("%s: loopid %d already valid\n", isp->isp_name, loopid));
mbs.param[3] = lp->portid & 0xffff;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
- continue;
lp->valid = 1;
lp->fabdev = 1;
- lp->roles = (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT);
+ if (isp_getpdb(isp, loopid, &pdb) != 0) {
+ /*
+ * Be kind...
+ */
+ lp->roles = (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT);
+ PRINTF("%s: Faked PortID 0x%x into LoopID %d\n",
+ isp->isp_name, lp->portid, lp->loopid);
+ } else if (pdb.pdb_loopid != lp->loopid) {
+ lp->roles = (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT);
+ PRINTF("%s: Wanked PortID 0x%x to LoopID %d\n",
+ isp->isp_name, lp->portid, lp->loopid);
+ } else {
+ lp->roles =
+ (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >>
+ SVC3_ROLE_SHIFT;
+ lp->portid = BITS2WORD(pdb.pdb_portid_bits);
+ lp->loopid = pdb.pdb_loopid;
+ lp->node_wwn =
+ (((u_int64_t)pdb.pdb_nodename[0]) << 56) |
+ (((u_int64_t)pdb.pdb_nodename[1]) << 48) |
+ (((u_int64_t)pdb.pdb_nodename[2]) << 40) |
+ (((u_int64_t)pdb.pdb_nodename[3]) << 32) |
+ (((u_int64_t)pdb.pdb_nodename[4]) << 24) |
+ (((u_int64_t)pdb.pdb_nodename[5]) << 16) |
+ (((u_int64_t)pdb.pdb_nodename[6]) << 8) |
+ (((u_int64_t)pdb.pdb_nodename[7]));
+ lp->port_wwn =
+ (((u_int64_t)pdb.pdb_portname[0]) << 56) |
+ (((u_int64_t)pdb.pdb_portname[1]) << 48) |
+ (((u_int64_t)pdb.pdb_portname[2]) << 40) |
+ (((u_int64_t)pdb.pdb_portname[3]) << 32) |
+ (((u_int64_t)pdb.pdb_portname[4]) << 24) |
+ (((u_int64_t)pdb.pdb_portname[5]) << 16) |
+ (((u_int64_t)pdb.pdb_portname[6]) << 8) |
+ (((u_int64_t)pdb.pdb_portname[7]));
+ (void) isp_async(isp, ISPASYNC_PDB_CHANGED,
+ &loopid);
+ }
}
}
#endif
@@ -1666,6 +1700,7 @@ isp_scan_fabric(isp)
reqp->snscb_data[0] = SNS_GAN;
reqp->snscb_data[4] = portid & 0xffff;
reqp->snscb_data[5] = (portid >> 16) & 0xff;
+ ISP_SWIZZLE_SNS_REQ(isp, reqp);
mbs.param[0] = MBOX_SEND_SNS;
mbs.param[1] = SNS_GAN_REQ_SIZE >> 1;
mbs.param[2] = DMA_MSW(fcp->isp_scdma);
@@ -1677,6 +1712,7 @@ isp_scan_fabric(isp)
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return (-1);
}
+ ISP_UNSWIZZLE_SNS_RSP(isp, resp, SNS_GAN_RESP_SIZE >> 1);
portid = (((u_int32_t) resp->snscb_port_id[0]) << 16) |
(((u_int32_t) resp->snscb_port_id[1]) << 8) |
(((u_int32_t) resp->snscb_port_id[2]));
@@ -1713,7 +1749,7 @@ ispscsicmd(xs)
#define reqp _u._reqp
#define t2reqp _u._t2reqp
#define UZSIZE max(sizeof (ispreq_t), sizeof (ispreqt2_t))
- int target, i, rqidx;
+ int target, i;
XS_INITERR(xs);
isp = XS_ISP(xs);
@@ -1744,7 +1780,6 @@ ispscsicmd(xs)
if (IS_FC(isp)) {
fcparam *fcp = isp->isp_param;
struct lportdb *lp;
-
#if defined(ISP2100_FABRIC)
if (target >= FL_PORT_ID) {
/*
@@ -1758,7 +1793,6 @@ ispscsicmd(xs)
}
}
#endif
-
/*
* Check for f/w being in ready state. If the f/w
* isn't in ready state, then we don't know our
@@ -1775,7 +1809,7 @@ ispscsicmd(xs)
if (isp_fclink_test(isp, FC_FW_READY_DELAY)) {
XS_SETERR(xs, HBA_SELTIMEOUT);
if (fcp->loop_seen_once) {
- return (CMD_EAGAIN);
+ return (CMD_RQLATER);
} else {
return (CMD_COMPLETE);
}
@@ -1790,7 +1824,7 @@ ispscsicmd(xs)
*/
if (fcp->isp_loopstate < LOOP_PDB_RCVD) {
XS_SETERR(xs, HBA_SELTIMEOUT);
- return (CMD_EAGAIN);
+ return (CMD_RQLATER);
}
/*
@@ -1809,16 +1843,16 @@ ispscsicmd(xs)
* Now check whether we should even think about pursuing this.
*/
lp = &fcp->portdb[target];
-if ( target < 0x80) {
if (lp->valid == 0) {
XS_SETERR(xs, HBA_SELTIMEOUT);
return (CMD_COMPLETE);
}
if ((lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT)) == 0) {
+ IDPRINTF(3, ("%s: target %d is not a target\n",
+ isp->isp_name, target));
XS_SETERR(xs, HBA_SELTIMEOUT);
return (CMD_COMPLETE);
}
-}
/*
* Now turn target into what the actual loop ID is.
*/
@@ -1839,7 +1873,7 @@ if ( target < 0x80) {
reqp = (ispreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, iptr);
iptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN);
if (iptr == optr) {
- IDPRINTF(2, ("%s: Request Queue Overflow\n", isp->isp_name));
+ IDPRINTF(0, ("%s: Request Queue Overflow\n", isp->isp_name));
XS_SETERR(xs, HBA_BOTCH);
return (CMD_EAGAIN);
}
@@ -1862,9 +1896,8 @@ if ( target < 0x80) {
reqp->req_header.rqs_entry_count = 1;
reqp->req_header.rqs_entry_type = RQSTYPE_MARKER;
reqp->req_modifier = SYNC_ALL;
- ISP_SBUSIFY_ISPHDR(isp, &reqp->req_header);
- reqp->req_target = i << 7;
- ISP_SBUSIFY_ISPREQ(isp, reqp);
+ reqp->req_target = i << 7; /* insert bus number */
+ ISP_SWIZZLE_REQUEST(isp, reqp);
/*
* Unconditionally update the input pointer anyway.
@@ -1874,7 +1907,7 @@ if ( target < 0x80) {
niptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN);
if (niptr == optr) {
- IDPRINTF(2, ("%s: Request Queue Overflow+\n",
+ IDPRINTF(0, ("%s: Request Queue Overflow+\n",
isp->isp_name));
XS_SETERR(xs, HBA_BOTCH);
return (CMD_EAGAIN);
@@ -1887,61 +1920,35 @@ if ( target < 0x80) {
MEMZERO((void *) reqp, UZSIZE);
reqp->req_header.rqs_entry_count = 1;
- if (isp->isp_type & ISP_HA_FC) {
+ if (IS_FC(isp)) {
reqp->req_header.rqs_entry_type = RQSTYPE_T2RQS;
} else {
reqp->req_header.rqs_entry_type = RQSTYPE_REQUEST;
}
reqp->req_header.rqs_flags = 0;
- reqp->req_header.rqs_seqno = isp->isp_seqno++;
- ISP_SBUSIFY_ISPHDR(isp, &reqp->req_header);
-
- for (rqidx = 0; rqidx < RQUEST_QUEUE_LEN; rqidx++) {
- if (isp->isp_xflist[rqidx] == NULL)
- break;
- }
- if (rqidx == RQUEST_QUEUE_LEN) {
- IDPRINTF(2, ("%s: out of xflist pointers\n", isp->isp_name));
- XS_SETERR(xs, HBA_BOTCH);
- return (CMD_EAGAIN);
- } else {
- /*
- * Never have a handle that is zero, so
- * set req_handle off by one.
- */
- isp->isp_xflist[rqidx] = xs;
- reqp->req_handle = rqidx+1;
- }
-
- if (isp->isp_type & ISP_HA_FC) {
+ reqp->req_header.rqs_seqno = 0;
+ if (IS_FC(isp)) {
/*
* See comment in isp_intr
*/
XS_RESID(xs) = 0;
/*
- * Fibre Channel always requires some kind of tag.
- * If we're marked as "Can't Tag", just do simple
- * instead of ordered tags. It's pretty clear to me
- * that we shouldn't do head of queue tagging in
- * this case.
+ * Fibre Channel always requires some kind of tag, but
+ * the firmware seems to be happy if we don't use a tag.
*/
if (XS_CANTAG(xs)) {
t2reqp->req_flags = XS_KINDOF_TAG(xs);
- } else {
- t2reqp->req_flags = REQFLAG_STAG;
}
} else {
sdparam *sdp = (sdparam *)isp->isp_param;
if ((sdp->isp_devparam[target].cur_dflags & DPARM_TQING) &&
XS_CANTAG(xs)) {
reqp->req_flags = XS_KINDOF_TAG(xs);
- } else {
- reqp->req_flags = 0;
}
}
reqp->req_target = target | (XS_CHANNEL(xs) << 7);
- if (isp->isp_type & ISP_HA_SCSI) {
+ if (IS_SCSI(isp)) {
reqp->req_lun_trn = XS_LUN(xs);
reqp->req_cdblen = XS_CDBLEN(xs);
} else {
@@ -1953,10 +1960,6 @@ if ( target < 0x80) {
}
MEMCPY(reqp->req_cdb, XS_CDBP(xs), XS_CDBLEN(xs));
- IDPRINTF(5, ("%s(%d.%d.%d): START%d cmd 0x%x datalen %d\n",
- isp->isp_name, XS_CHANNEL(xs), target, XS_LUN(xs),
- reqp->req_header.rqs_seqno, reqp->req_cdb[0], XS_XFRLEN(xs)));
-
reqp->req_time = XS_TIME(xs) / 1000;
if (reqp->req_time == 0 && XS_TIME(xs))
reqp->req_time = 1;
@@ -1965,15 +1968,21 @@ if ( target < 0x80) {
* Always give a bit more leeway to commands after a bus reset.
* XXX: DOES NOT DISTINGUISH WHICH PORT MAY HAVE BEEN SYNCED
*/
- if (isp->isp_sendmarker && reqp->req_time < 5)
+ if (isp->isp_sendmarker && reqp->req_time < 5) {
reqp->req_time = 5;
-
+ }
+ if (isp_save_xs(isp, xs, &reqp->req_handle)) {
+ IDPRINTF(2, ("%s: out of xflist pointers\n", isp->isp_name));
+ XS_SETERR(xs, HBA_BOTCH);
+ return (CMD_EAGAIN);
+ }
+ /*
+ * Set up DMA and/or do any bus swizzling of the request entry
+ * so that the Qlogic F/W understands what is being asked of it.
+ */
i = ISP_DMASETUP(isp, xs, reqp, &iptr, optr);
if (i != CMD_QUEUED) {
- /*
- * Take memory of it away...
- */
- isp->isp_xflist[rqidx] = NULL;
+ isp_destroy_handle(isp, reqp->req_handle);
/*
* dmasetup sets actual error in packet, and
* return what we were given to return.
@@ -1981,7 +1990,9 @@ if ( target < 0x80) {
return (i);
}
XS_SETERR(xs, HBA_NOERROR);
- ISP_SBUSIFY_ISPREQ(isp, reqp);
+ IDPRINTF(5, ("%s(%d.%d.%d): START cmd 0x%x datalen %d\n",
+ isp->isp_name, XS_CHANNEL(xs), target, XS_LUN(xs),
+ reqp->req_cdb[0], XS_XFRLEN(xs)));
MemoryBarrier();
ISP_WRITE(isp, INMAILBOX4, iptr);
isp->isp_reqidx = iptr;
@@ -2006,7 +2017,8 @@ isp_control(isp, ctl, arg)
{
ISP_SCSI_XFER_T *xs;
mbreg_t mbs;
- int i, bus, tgt;
+ int bus, tgt;
+ u_int32_t handle;
switch (ctl) {
default:
@@ -2019,19 +2031,18 @@ isp_control(isp, ctl, arg)
* Issue a bus reset.
*/
mbs.param[0] = MBOX_BUS_RESET;
- if (isp->isp_type & ISP_HA_SCSI) {
+ if (IS_SCSI(isp)) {
mbs.param[1] =
((sdparam *) isp->isp_param)->isp_bus_reset_delay;
if (mbs.param[1] < 2)
mbs.param[1] = 2;
+ bus = *((int *) arg);
+ mbs.param[2] = bus;
} else {
- /*
- * Unparameterized.
- */
- mbs.param[1] = 5;
+ /* Unparameterized. */
+ mbs.param[1] = 10;
+ bus = 0;
}
- bus = *((int *) arg);
- mbs.param[2] = bus;
isp->isp_sendmarker = 1 << bus;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
@@ -2050,7 +2061,8 @@ isp_control(isp, ctl, arg)
mbs.param[2] = 3; /* 'delay', in seconds */
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- isp_dumpregs(isp, "Target Reset Failed");
+ PRINTF("%s: isp_control MBOX_RESET_DEV failure (code "
+ "%x)\n", isp->isp_name, mbs.param[0]);
break;
}
PRINTF("%s: Target %d on Bus %d Reset Succeeded\n",
@@ -2060,34 +2072,29 @@ isp_control(isp, ctl, arg)
case ISPCTL_ABORT_CMD:
xs = (ISP_SCSI_XFER_T *) arg;
- for (i = 0; i < RQUEST_QUEUE_LEN; i++) {
- if (xs == isp->isp_xflist[i]) {
- break;
- }
- }
- if (i == RQUEST_QUEUE_LEN) {
+ handle = isp_find_handle(isp, xs);
+ if (handle == 0) {
PRINTF("%s: isp_control- cannot find command to abort "
"in active list\n", isp->isp_name);
break;
}
+ bus = XS_CHANNEL(xs);
mbs.param[0] = MBOX_ABORT;
+ if (IS_FC(isp)) {
#ifdef ISP2100_SCCLUN
- if (isp->isp_type & ISP_HA_FC) {
mbs.param[1] = XS_TGT(xs) << 8;
mbs.param[4] = 0;
mbs.param[5] = 0;
mbs.param[6] = XS_LUN(xs);
- } else {
- mbs.param[1] = XS_TGT(xs) << 8 | XS_LUN(xs);
- }
#else
- mbs.param[1] = XS_TGT(xs) << 8 | XS_LUN(xs);
+ mbs.param[1] = XS_TGT(xs) << 8 | XS_LUN(xs);
#endif
- /*
- * XXX: WHICH BUS?
- */
- mbs.param[2] = (i+1) >> 16;
- mbs.param[3] = (i+1) & 0xffff;
+ } else {
+ mbs.param[1] =
+ (bus << 15) | (XS_TGT(xs) << 8) | XS_LUN(xs);
+ }
+ mbs.param[2] = handle >> 16;
+ mbs.param[3] = handle & 0xffff;
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
PRINTF("%s: isp_control MBOX_ABORT failure (code %x)\n",
@@ -2122,14 +2129,17 @@ isp_intr(arg)
ISP_SCSI_XFER_T *complist[RESULT_QUEUE_LEN], *xs;
struct ispsoftc *isp = arg;
u_int8_t iptr, optr;
- u_int16_t isr, sema;
+ u_int16_t isr, isrb, sema;
int i, nlooked = 0, ndone = 0;
/*
* Well, if we've disabled interrupts, we may get a case where
- * isr isn't set, but sema is.
+ * isr isn't set, but sema is. In any case, debounce isr reads.
*/
- isr = ISP_READ(isp, BIU_ISR);
+ do {
+ isr = ISP_READ(isp, BIU_ISR);
+ isrb = ISP_READ(isp, BIU_ISR);
+ } while (isr != isrb);
sema = ISP_READ(isp, BIU_SEMA) & 0x1;
IDPRINTF(5, ("%s: isp_intr isr %x sem %x\n", isp->isp_name, isr, sema));
if (IS_FC(isp)) {
@@ -2169,21 +2179,7 @@ isp_intr(arg)
IDPRINTF(3, ("%s: Async Mbox 0x%x\n",
isp->isp_name, mbox));
if (fhandle > 0) {
- xs = (void *)isp->isp_xflist[fhandle - 1];
- isp->isp_xflist[fhandle - 1] = NULL;
- /*
- * Since we don't have a result queue entry
- * item, we must believe that SCSI status is
- * zero and that all data transferred.
- */
- XS_RESID(xs) = 0;
- XS_STS(xs) = 0;
- if (XS_XFRLEN(xs)) {
- ISP_DMAFREE(isp, xs, fhandle - 1);
- }
- if (isp->isp_nactive > 0)
- isp->isp_nactive--;
- XS_CMD_DONE(xs);
+ isp_fastpost_complete(isp, fhandle);
}
}
ISP_WRITE(isp, BIU_SEMA, 0);
@@ -2213,7 +2209,11 @@ isp_intr(arg)
optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN);
nlooked++;
MemoryBarrier();
- ISP_SBUSIFY_ISPHDR(isp, &sp->req_header);
+ /*
+ * Do any appropriate unswizzling of what the Qlogic f/w has
+ * written into memory so it makes sense to us.
+ */
+ ISP_UNSWIZZLE_RESPONSE(isp, sp);
if (sp->req_header.rqs_entry_type != RQSTYPE_RESPONSE) {
if (isp_handle_other_response(isp, sp, &optr) == 0) {
ISP_WRITE(isp, INMAILBOX5, optr);
@@ -2267,22 +2267,20 @@ isp_intr(arg)
}
#undef _RQS_OFLAGS
}
-
- if (sp->req_handle > RQUEST_QUEUE_LEN || sp->req_handle < 1) {
+ if (sp->req_handle > isp->isp_maxcmds || sp->req_handle < 1) {
PRINTF("%s: bad request handle %d\n", isp->isp_name,
- sp->req_handle);
+ sp->req_handle);
ISP_WRITE(isp, INMAILBOX5, optr);
continue;
}
- xs = (void *) isp->isp_xflist[sp->req_handle - 1];
+ xs = isp_find_xs(isp, sp->req_handle);
if (xs == NULL) {
- PRINTF("%s: NULL xs in xflist (handle %x)\n",
+ PRINTF("%s: NULL xs in xflist (handle 0x%x)\n",
isp->isp_name, sp->req_handle);
- isp_dumpxflist(isp);
ISP_WRITE(isp, INMAILBOX5, optr);
continue;
}
- isp->isp_xflist[sp->req_handle - 1] = NULL;
+ isp_destroy_handle(isp, sp->req_handle);
if (sp->req_status_flags & RQSTF_BUS_RESET) {
isp->isp_sendmarker |= (1 << XS_CHANNEL(xs));
}
@@ -2344,7 +2342,7 @@ isp_intr(arg)
XS_SETERR(xs, HBA_BOTCH);
}
}
- if (isp->isp_type & ISP_HA_SCSI) {
+ if (IS_SCSI(isp)) {
XS_RESID(xs) = sp->req_resid;
} else if (sp->req_scsi_status & RQCS_RU) {
XS_RESID(xs) = sp->req_resid;
@@ -2352,7 +2350,7 @@ isp_intr(arg)
XS_XFRLEN(xs), sp->req_resid));
}
if (XS_XFRLEN(xs)) {
- ISP_DMAFREE(isp, xs, sp->req_handle - 1);
+ ISP_DMAFREE(isp, xs, sp->req_handle);
}
/*
* XXX: If we have a check condition, but no Sense Data,
@@ -2369,10 +2367,9 @@ isp_intr(arg)
}
if ((isp->isp_dblev >= 5) ||
(isp->isp_dblev > 2 && !XS_NOERR(xs))) {
- PRINTF("%s(%d.%d): FIN%d dl%d resid%d STS %x",
+ PRINTF("%s(%d.%d): FIN dl%d resid%d STS %x",
isp->isp_name, XS_TGT(xs), XS_LUN(xs),
- sp->req_header.rqs_seqno, XS_XFRLEN(xs),
- XS_RESID(xs), XS_STS(xs));
+ XS_XFRLEN(xs), XS_RESID(xs), XS_STS(xs));
if (sp->req_state_flags & RQSF_GOT_SENSE) {
PRINTF(" Skey: %x", XS_SNSKEY(xs));
if (!(XS_IS_SNS_VALID(xs))) {
@@ -2550,7 +2547,7 @@ isp_parse_async(isp, mbox)
((fcparam *) isp->isp_param)->isp_loopstate = LOOP_LIP_RCVD;
isp->isp_sendmarker = 1;
isp_mark_getpdb_all(isp);
- PRINTF("%s: LIP occurred\n", isp->isp_name);
+ IDPRINTF(1, ("%s: LIP occurred\n", isp->isp_name));
break;
case ASYNC_LOOP_UP:
@@ -2584,10 +2581,16 @@ isp_parse_async(isp, mbox)
isp->isp_sendmarker = 1;
((fcparam *) isp->isp_param)->isp_loopstate = LOOP_PDB_RCVD;
isp_mark_getpdb_all(isp);
- IDPRINTF(3, ("%s: Port Database Changed\n", isp->isp_name));
+ IDPRINTF(2, ("%s: Port Database Changed\n", isp->isp_name));
break;
case ASYNC_CHANGE_NOTIFY:
+ isp_mark_getpdb_all(isp);
+ /*
+ * Not correct, but it will force us to rescan the loop.
+ */
+ ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_PDB_RCVD;
+ isp_async(isp, ISPASYNC_CHANGE_NOTIFY, NULL);
break;
default:
@@ -2603,618 +2606,27 @@ isp_handle_other_response(isp, sp, optrp)
ispstatusreq_t *sp;
u_int8_t *optrp;
{
- u_int8_t iptr, optr;
- int reqsize = 0;
- void *ireqp = NULL;
-#ifdef ISP_TARGET_MODE
- union {
- at_entry_t *atio;
- at2_entry_t *at2io;
- ct_entry_t *ctio;
- ct2_entry_t *ct2io;
- lun_entry_t *lunen;
- in_entry_t *inot;
- in_fcentry_t *inot_fc;
- na_entry_t *nack;
- na_fcentry_t *nack_fc;
- void *voidp;
-#define atio un.atio
-#define at2io un.at2io
-#define ctio un.ctio
-#define ct2io un.ct2io
-#define lunen un.lunen
-#define inot un.inot
-#define inot_fc un.inot_fc
-#define nack un.nack
-#define nack_fc un.nack_fc
- } un;
-
- un.voidp = sp;
-#endif
-
-
switch (sp->req_header.rqs_entry_type) {
- case RQSTYPE_REQUEST:
- return (-1);
-#ifdef ISP_TARGET_MODE
- case RQSTYPE_NOTIFY_ACK:
- {
- static const char *f =
- "%s: Notify Ack Status 0x%x Sequence Id 0x%x\n"
- /*
- * The ISP is acknowleding our ack of an Immediate Notify.
- */
- if (isp->isp_type & ISP_HA_FC) {
- PRINTF(f, isp->isp_name,
- nack_fc->na-status, nack_fc->na_seqid);
- } else {
- PRINTF(f, isp->isp_name,
- nack->na_status, nack->na_seqid);
- }
- break;
- }
- case RQSTYPE_NOTIFY:
- {
- u_int16_t seqid, status;
-
- /*
- * Either the ISP received a SCSI message it cannot handle
- * or some other out of band condition (e.g., Port Logout)
- * or it is returning an Immediate Notify entry we sent.
- */
- if (isp->isp_type & ISP_HA_FC) {
- status = inot_fc->status;
- seqid = inot_fc->in_seqid;
- } else {
- status = inot->status;
- seqid = inot->seqid & 0xff;
- }
- PRINTF("%s: Immediate Notify Status 0x%x Sequence Id 0x%x\n",
- isp->isp_name, status, seqid);
-
- switch (status) {
- case IN_MSG_RECEIVED:
- case IN_IDE_RECEIVED:
- ptisp_got_msg(ptp, &inot);
- break;
- case IN_RSRC_UNAVAIL:
- PRINTF("%s: Firmware out of ATIOs\n", isp->isp_name);
- break;
- case IN_ABORT_TASK:
- PRINTF("%s: Abort Task iid %d rx_id 0x%x\n",
- inot_fc->in_iid, seqid);
- break;
- case IN_PORT_LOGOUT:
- PRINTF("%s: Port Logout for Initiator %d\n",
- isp->isp_name, inot_fc->in_iid);
- break;
- default:
- PRINTF("%s: bad status (0x%x) in Immediate Notify\n",
- isp->isp_name, status);
- break;
-
- }
- isp_notify_ack(isp, un.voidp);
- reqsize = 0;
- break;
- }
+ case RQSTYPE_ATIO:
+ case RQSTYPE_CTIO0:
case RQSTYPE_ENABLE_LUN:
case RQSTYPE_MODIFY_LUN:
- if (lunen->req_status != 1) {
- PRINTF("%s: ENABLE/MODIFY LUN returned status 0x%x\n",
- isp->isp_name, lunen->req_status);
- }
- break;
+ case RQSTYPE_NOTIFY:
+ case RQSTYPE_NOTIFY_ACK:
+ case RQSTYPE_CTIO1:
case RQSTYPE_ATIO2:
- {
- fcparam *fcp = isp->isp_param;
- ispctiot2_t local, *ct2 = NULL;
- ispatiot2_t *at2 = (ispatiot2_t *) sp;
- int s, lun;
-
-#ifdef ISP2100_SCCLUN
- lun = at2->req_scclun;
-#else
- lun = at2->req_lun;
-#endif
- PRINTF("%s: atio2 loopid %d for lun %d rxid 0x%x flags0x%x "
- "tflags0x%x ecodes0x%x rqstatus0x%x\n", isp->isp_name,
- at2->req_initiator, lun, at2->req_rxid,
- at2->req_flags, at2->req_taskflags, at2->req_execodes,
- at2->req_status);
-
- switch (at2->req_status & ~ATIO_SENSEVALID) {
- case ATIO_PATH_INVALID:
- PRINTF("%s: ATIO2 Path Invalid\n", isp->isp_name);
- break;
- case ATIO_NOCAP:
- PRINTF("%s: ATIO2 No Cap\n", isp->isp_name);
- break;
- case ATIO_BDR_MSG:
- PRINTF("%s: ATIO2 BDR Received\n", isp->isp_name);
- break;
- case ATIO_CDB_RECEIVED:
- ct2 = &local;
- break;
- default:
- PRINTF("%s: unknown req_status 0x%x\n", isp->isp_name,
- at2->req_status);
- break;
- }
- if (ct2 == NULL) {
- /*
- * Just do an ACCEPT on this fellow.
- */
- at2->req_header.rqs_entry_type = RQSTYPE_ATIO2;
- at2->req_header.rqs_flags = 0;
- at2->req_flags = 1;
- ireqp = at2;
- reqsize = sizeof (*at2);
- break;
- }
- PRINTF("%s: datalen %d cdb0=0x%x\n", isp->isp_name,
- at2->req_datalen, at2->req_cdb[0]);
- MEMZERO((void *) ct2, sizeof (*ct2));
- ct2->req_header.rqs_entry_type = RQSTYPE_CTIO2;
- ct2->req_header.rqs_entry_count = 1;
- ct2->req_header.rqs_flags = 0;
- ct2->req_header.rqs_seqno = isp->isp_seqno++;
- ct2->req_handle = (at2->req_initiator << 16) | lun;
-#ifndef ISP2100_SCCLUN
- ct2->req_lun = lun;
-#endif
- ct2->req_initiator = at2->req_initiator;
- ct2->req_rxid = at2->req_rxid;
-
- ct2->req_flags = CTIO_SEND_STATUS;
- switch (at2->req_cdb[0]) {
- case 0x0: /* TUR */
- ct2->req_flags |= CTIO_NODATA | CTIO2_SMODE0;
- ct2->req_m.mode0.req_scsi_status = CTIO2_STATUS_VALID;
- break;
-
- case 0x3: /* REQUEST SENSE */
- case 0x12: /* INQUIRE */
- ct2->req_flags |= CTIO_SEND_DATA | CTIO2_SMODE0;
- ct2->req_m.mode0.req_scsi_status = CTIO2_STATUS_VALID;
- ct2->req_seg_count = 1;
- if (at2->req_cdb[0] == 0x12) {
- s = sizeof (tgtiqd);
- MEMCPY(fcp->isp_scratch, tgtiqd, s);
- } else {
- s = at2->req_datalen;
- MEMZERO(fcp->isp_scratch, s);
- }
- ct2->req_m.mode0.req_dataseg[0].ds_base =
- fcp->isp_scdma;
- ct2->req_m.mode0.req_dataseg[0].ds_count = s;
- ct2->req_m.mode0.req_datalen = s;
-#if 1
- if (at2->req_datalen < s) {
- ct2->req_m.mode1.req_scsi_status |=
- CTIO2_RESP_VALID|CTIO2_RSPOVERUN;
- } else if (at2->req_datalen > s) {
- ct2->req_m.mode1.req_scsi_status |=
- CTIO2_RESP_VALID|CTIO2_RSPUNDERUN;
- }
-#endif
- break;
-
- default: /* ALL OTHERS */
- ct2->req_flags |= CTIO_NODATA | CTIO2_SMODE1;
- ct2->req_m.mode1.req_scsi_status = 0;
-#if 1
- if (at2->req_datalen) {
- ct2->req_m.mode1.req_scsi_status |=
- CTIO2_RSPUNDERUN;
- ct2->req_resid[0] = at2->req_datalen & 0xff;
- ct2->req_resid[1] =
- (at2->req_datalen >> 8) & 0xff;
- ct2->req_resid[2] =
- (at2->req_datalen >> 16) & 0xff;
- ct2->req_resid[3] =
- (at2->req_datalen >> 24) & 0xff;
- }
-#endif
- if ((at2->req_status & ATIO_SENSEVALID) == 0) {
- ct2->req_m.mode1.req_sense_len = 18;
- ct2->req_m.mode1.req_scsi_status |= 2;
- ct2->req_m.mode1.req_response[0] = 0x70;
- ct2->req_m.mode1.req_response[2] = 0x2;
- } else {
- ct2->req_m.mode1.req_sense_len = 18;
- ct2->req_m.mode1.req_scsi_status |=
- at2->req_scsi_status;
- MEMCPY(ct2->req_m.mode1.req_response,
- at2->req_sense, sizeof (at2->req_sense));
- }
- break;
- }
- reqsize = sizeof (*ct2);
- ireqp = ct2;
- break;
- }
case RQSTYPE_CTIO2:
- {
- ispatiot2_t *at2;
- ispctiot2_t *ct2 = (ispctiot2_t *) sp;
- PRINTF("%s: CTIO2 returned status 0x%x\n", isp->isp_name,
- ct2->req_status);
- /*
- * Return the ATIO to the board.
- */
- at2 = (ispatiot2_t *) sp;
- at2->req_header.rqs_entry_type = RQSTYPE_ATIO2;
- at2->req_header.rqs_entry_count = 1;
- at2->req_header.rqs_flags = 0;
- at2->req_header.rqs_seqno = isp->isp_seqno++;
- at2->req_status = 1;
- reqsize = sizeof (*at2);
- ireqp = at2;
- break;
- }
-#undef atio
-#undef at2io
-#undef ctio
-#undef ct2io
-#undef lunen
-#undef inot
-#undef inot_fc
-#undef nack
-#undef nack_fc
+ case RQSTYPE_CTIO3:
+#ifdef ISP_TARGET_MODE
+ return(isp_target_notify(isp, sp, optrp));
+#else
+ /* FALLTHROUGH */
#endif
+ case RQSTYPE_REQUEST:
default:
- PRINTF("%s: other response type %x\n", isp->isp_name,
- sp->req_header.rqs_entry_type);
- break;
- }
- if (reqsize) {
- void *reqp;
- optr = isp->isp_reqodx = ISP_READ(isp, OUTMAILBOX4);
- iptr = isp->isp_reqidx;
- reqp = (void *) ISP_QUEUE_ENTRY(isp->isp_rquest, iptr);
- iptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN);
- if (iptr == optr) {
- PRINTF("%s: Request Queue Overflow other response\n",
- isp->isp_name);
- } else {
- MEMCPY(reqp, ireqp, reqsize);
- ISP_WRITE(isp, INMAILBOX4, iptr);
- isp->isp_reqidx = iptr;
- }
- }
- return (0);
-}
-
-#ifdef ISP_TARGET_MODE
-
-static void isp_tmd_newcmd_dflt __P((void *, tmd_cmd_t *));
-static void isp_tmd_event_dflt __P((void *, int));
-static void isp_tmd_notify_dflt __P((void *, tmd_notify_t *));
-
-static void isp_tgt_data_xfer __P ((tmd_cmd_t *));
-static void isp_tgt_endcmd __P ((tmd_cmd_t *, u_int8_t));
-static void isp_tgt_done __P ((tmd_cmd_t *));
-
-static void
-isp_tmd_newcmd_dflt(arg0, cmdp)
- void *arg0;
- tmd_cmd_t *cmdp;
-{
-}
-
-static void
-isp_tmd_event_dflt(arg0, event)
- void *arg0;
- int event;
-{
-}
-
-static void
-isp_tmd_notify_dflt(arg0, npt)
- void *arg0;
- tmd_notify_t *npt;
-{
-}
-
-/*
- * Locks held, and ints disabled (if FC).
- *
- * XXX: SETUP ONLY FOR INITIAL ENABLING RIGHT NOW
- */
-static int
-isp_modify_lun(isp, lun, icnt, ccnt)
- struct ispsoftc *isp;
- int lun; /* logical unit to enable, modify, or disable */
- int icnt; /* immediate notify count */
- int ccnt; /* command count */
-{
- isplun_t *ip = NULL;
- u_int8_t iptr, optr;
-
- optr = isp->isp_reqodx = ISP_READ(isp, OUTMAILBOX4);
- iptr = isp->isp_reqidx;
- ip = (isplun_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, iptr);
- iptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN);
- if (iptr == optr) {
- PRINTF("%s: Request Queue Overflow in isp_modify_lun\n",
- isp->isp_name);
return (-1);
}
-
- MEMZERO((void *) ip, sizeof (*ip));
- ip->req_header.rqs_entry_type = RQSTYPE_ENABLE_LUN;
- ip->req_header.rqs_entry_count = 1;
- ip->req_header.rqs_seqno = isp->isp_seqno++;
- ip->req_handle = RQSTYPE_ENABLE_LUN;
- if (isp->isp_type & ISP_HA_SCSI) {
- ip->req_lun = lun;
- }
- ip->req_cmdcount = ccnt;
- ip->req_imcount = icnt;
- ip->req_timeout = 0; /* default 30 seconds */
- ISP_WRITE(isp, INMAILBOX4, iptr);
- isp->isp_reqidx = iptr;
- return (0);
-}
-
-static void
-isp_notify_ack(isp, ptrp)
- struct ispsoftc *isp;
- void *ptrp;
-{
- void *reqp;
- u_int8_t iptr, optr;
- union {
- na_fcentry_t _naf;
- na_entry_t _nas;
- } un;
-
- MEMZERO((caddr_t)&un, sizeof (un));
- un._nas.na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
- un._nas.na_header.rqs_entry_count = 1;
-
- if (isp->isp_type & ISP_HA_FC) {
- na_fcentry_t *na = &un._nas;
- if (ptrp) {
- in_fcentry_t *inp = ptrp;
- na->na_iid = inp->in_iid;
- na->na_lun = inp->in_lun;
- na->na_task_flags = inp->in_task_flags;
- na->na_seqid = inp->in_seqid;
- na->na_status = inp->in_status;
- } else {
- na->na_flags = NAFC_RST_CLRD;
- }
- } else {
- na_entry_t *na = &un._nas;
- if (ptrp) {
- in_entry_t *inp = ptrp;
- na->na_iid = inp->in_iid;
- na->na_lun = inp->in_lun;
- na->na_tgt = inp->in_tgt;
- na->na_seqid = inp->in_seqid;
- } else {
- na->na_flags = NA_RST_CLRD;
- }
- }
- optr = isp->isp_reqodx = ISP_READ(isp, OUTMAILBOX4);
- iptr = isp->isp_reqidx;
- reqp = (void *) ISP_QUEUE_ENTRY(isp->isp_rquest, iptr);
- iptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN);
- if (iptr == optr) {
- PRINTF("%s: Request Queue Overflow For isp_notify_ack\n",
- isp->isp_name);
- } else {
- MEMCPY(reqp, ireqp, sizeof (un));
- ISP_WRITE(isp, INMAILBOX4, iptr);
- isp->isp_reqidx = iptr;
- }
-}
-
-/*
- * These are dummy stubs for now until the outside framework is plugged in.
- */
-
-static void
-isp_handle_atio (isp, aep)
- struct ispsoftc *isp;
- at_entry_t *aep;
-{
- int status, connected;
- tmd_cmd_t local, *cdp = &local;
-
- /*
- * Get the ATIO status and see if we're still connected.
- */
- status = aep->at_status;
- connected = ((aep->at_flags & AT_NODISC) != 0);
-
- PRINTF("%s: ATIO status=0x%x, connected=%d\n", isp->isp_name,
- status, connected);
-
- /*
- * The firmware status (except for the SenseValid bit) indicates
- * why this ATIO was sent to us.
- * If SenseValid is set, the firware has recommended Sense Data.
- * If the Disconnects Disabled bit is set in the flags field,
- * we're still connected on the SCSI bus - i.e. the initiator
- * did not set DiscPriv in the identify message. We don't care
- * about this so it's ignored.
- */
- switch (status & ~TGTSVALID) {
- case AT_PATH_INVALID:
- /*
- * ATIO rejected by the firmware due to disabled lun.
- */
- PRINTF("%s: Firmware rejected ATIO for disabled lun %d\n",
- isp->isp_name, aep->at_lun);
- break;
-
- case AT_PHASE_ERROR:
- /*
- * Bus Pase Sequence error.
- *
- * The firmware should have filled in the correct
- * sense data.
- */
-
-
- if (status & TGTSVALID) {
- MEMCPY(&cdp->cd_sensedata, aep->at_sense,
- sizeof (cdp->cd_sensedata));
- PRINTF("%s: Bus Phase Sequence error key 0x%x\n",
- isp->isp_name, cdp->cd_sensedata[2] & 0xf);
- } else {
- PRINTF("%s: Bus Phase Sequence With No Sense\n",
- isp->isp_name);
- }
- (*isp->isp_tmd_newcmd)(isp, cdp);
- break;
-
- case AT_NOCAP:
- /*
- * Requested Capability not available
- * We sent an ATIO that overflowed the firmware's
- * command resource count.
- */
- PRINTF("%s: Firmware rejected ATIO, command count overflow\n",
- isp->isp_name);
- break;
-
- case AT_BDR_MSG:
- /*
- * If we send an ATIO to the firmware to increment
- * its command resource count, and the firmware is
- * recovering from a Bus Device Reset, it returns
- * the ATIO with this status.
- */
- PRINTF("%s: ATIO returned with BDR received\n", isp->isp_name);
- break;
-
- case AT_CDB:
- /*
- * New CDB
- */
- cdp->cd_hba = isp;
- cdp->cd_iid = aep->at_iid;
- cdp->cd_tgt = aep->at_tgt;
- cdp->cd_lun = aep->at_lun;
- cdp->cd_tagtype = aep->at_tag_type;
- cdp->cd_tagval = aep->at_tag_val;
- MEMCPY(cdp->cd_cdb, aep->at_cdb, 16);
- PRINTF("%s: CDB 0x%x itl %d/%d/%d\n", isp->isp_name,
- cdp->cd_cdb[0], cdp->cd_iid, cdp->cd_tgt, cdp->cd_lun);
- (*isp->isp_tmd_newcmd)(isp, cdp);
- break;
-
- default:
- PRINTF("%s: Unknown status (0x%x) in ATIO\n",
- isp->isp_name, status);
- cdp->cd_hba = isp;
- cdp->cd_iid = aep->at_iid;
- cdp->cd_tgt = aep->at_tgt;
- cdp->cd_lun = aep->at_lun;
- cdp->cd_tagtype = aep->at_tag_type;
- cdp->cd_tagval = aep->at_tag_val;
- isp_tgtcmd_done(cdp);
- break;
- }
-}
-
-static void
-isp_handle_atio2(isp, aep)
- struct ispsoftc *isp;
- at2_entry_t *aep;
-{
- int status;
- tmd_cmd_t local, *cdp = &local;
-
- /*
- * Get the ATIO2 status.
- */
- status = aep->at_status;
- PRINTD("%s: ATIO2 status=0x%x\n", status);
-
- /*
- * The firmware status (except for the SenseValid bit) indicates
- * why this ATIO was sent to us.
- * If SenseValid is set, the firware has recommended Sense Data.
- */
- switch (status & ~TGTSVALID) {
- case AT_PATH_INVALID:
- /*
- * ATIO rejected by the firmware due to disabled lun.
- */
- PRINTF("%s: Firmware rejected ATIO2 for disabled lun %d\n",
- isp->isp_name, aep->at_lun);
- break;
-
- case AT_NOCAP:
- /*
- * Requested Capability not available
- * We sent an ATIO that overflowed the firmware's
- * command resource count.
- */
- PRINTF("%s: Firmware rejected ATIO2, command count overflow\n",
- isp->isp_name);
- break;
-
- case AT_BDR_MSG:
- /*
- * If we send an ATIO to the firmware to increment
- * its command resource count, and the firmware is
- * recovering from a Bus Device Reset, it returns
- * the ATIO with this status.
- */
- PRINTF("%s: ATIO2 returned with BDR rcvd\n", isp->isp_name);
- break;
-
- case AT_CDB:
- /*
- * New CDB
- */
- cdp->cd_hba = isp;
- cdp->cd_iid = aep->at_iid;
- cdp->cd_tgt = 0;
- cdp->cd_lun = aep->at_lun;
- MEMCPY(cdp->cd_cdb, aep->at_cdb, 16);
- cdp->cd_rxid = aep->at_rxid;
- cdp->cp_origdlen = aep->at_datalen;
- cdp->cp_totbytes = 0;
- PRINTF("%s: CDB 0x%x rx_id 0x%x itl %d/%d/%d dlen %d\n",
- isp->isp_name, cdp->cd_cdb[0], cdp->cd_tagval, cdp->cd_iid,
- cdp->cd_tgt, cdp->cd_lun, aep->at_datalen);
- (*isp->isp_tmd_newcmd)(isp, cdp);
- break;
-
- default:
- PRINTF("%s: Unknown status (0x%x) in ATIO2\n",
- isp->isp_name, status);
- cdp->cd_hba = isp;
- cdp->cd_iid = aep->at_iid;
- cdp->cd_tgt = aep->at_tgt;
- cdp->cd_lun = aep->at_lun;
- cdp->cp_rxid = aep->at_rxid;
- isp_tgtcmd_done(cdp);
- break;
- }
-}
-
-static void
-isp_handle_ctio(isp, cep)
- struct ispsoftc *isp;
- ct_entry_t *aep;
-{
-}
-
-static void
-isp_handle_ctio2(isp, cep)
- struct ispsoftc *isp;
- at2_entry_t *aep;
-{
}
-#endif
static void
isp_parse_status(isp, sp, xs)
@@ -3276,7 +2688,7 @@ isp_parse_status(isp, sp, xs)
return;
case RQCS_DATA_OVERRUN:
- if (isp->isp_type & ISP_HA_FC) {
+ if (IS_FC(isp)) {
XS_RESID(xs) = sp->req_resid;
break;
}
@@ -3351,7 +2763,7 @@ isp_parse_status(isp, sp, xs)
break;
case RQCS_DATA_UNDERRUN:
- if (isp->isp_type & ISP_HA_FC) {
+ if (IS_FC(isp)) {
XS_RESID(xs) = sp->req_resid;
/* an UNDERRUN is not a botch ??? */
}
@@ -3476,19 +2888,21 @@ isp_parse_status(isp, sp, xs)
static void
isp_fastpost_complete(isp, fph)
struct ispsoftc *isp;
- int fph;
+ u_int32_t fph;
{
ISP_SCSI_XFER_T *xs;
- if (fph < 1)
+ if (fph < 1) {
return;
- xs = (ISP_SCSI_XFER_T *) isp->isp_xflist[fph - 1];
- isp->isp_xflist[fph - 1] = NULL;
+ }
+ xs = isp_find_xs(isp, fph);
if (xs == NULL) {
- PRINTF("%s: fast posting handle 0x%x not found\n",
- isp->isp_name, fph - 1);
+ PRINTF("%s: command for fast posting handle 0x%x not found\n",
+ isp->isp_name, fph);
return;
}
+ isp_destroy_handle(isp, fph);
+
/*
* Since we don't have a result queue entry item,
* we must believe that SCSI status is zero and
@@ -3497,9 +2911,11 @@ isp_fastpost_complete(isp, fph)
XS_RESID(xs) = 0;
XS_STS(xs) = 0;
if (XS_XFRLEN(xs)) {
- ISP_DMAFREE(isp, xs, fph - 1);
+ ISP_DMAFREE(isp, xs, fph);
}
XS_CMD_DONE(xs);
+ if (isp->isp_nactive)
+ isp->isp_nactive--;
}
#define HINIB(x) ((x) >> 0x4)
@@ -3658,7 +3074,7 @@ isp_mboxcmd(isp, mbp)
* Check for variants
*/
#ifdef ISP2100_SCCLUN
- if (isp->isp_type & ISP_HA_FC) {
+ if (IS_FC(isp)) {
switch (mbp->param[0]) {
case MBOX_ABORT:
inparam = 7;
@@ -3671,6 +3087,9 @@ isp_mboxcmd(isp, mbp)
case MBOX_GET_DEV_QUEUE_STATUS:
inparam = 3;
break;
+ case MBOX_BUS_RESET:
+ inparam = 2;
+ break;
default:
break;
}
@@ -3685,6 +3104,12 @@ command_known:
ISP_WRITE(isp, BIU_SEMA, 1);
/*
+ * Qlogic Errata for the ISP2100 says that there is a necessary
+ * debounce between between writing the semaphore register
+ * and reading a mailbox register. I believe we're okay here.
+ */
+
+ /*
* Make sure we can send some words.
* Check to see if there's an async mbox event pending.
*/
@@ -3864,7 +3289,7 @@ command_known:
/*
* Pick up output parameters. Special case some of the readbacks
- * for the dual port SCSI cards.
+ * for the dual port SCSI cards or FC Cards...
*/
if (IS_12X0(isp)) {
switch (opcode) {
@@ -3884,6 +3309,14 @@ command_known:
mbp->param[2] = ISP_READ(isp, OUTMAILBOX2);
break;
}
+ } else if (IS_FC(isp)) {
+ switch (opcode) {
+ case MBOX_GET_LOOP_ID:
+ mbp->param[6] = ISP_READ(isp, OUTMAILBOX6);
+ break;
+ default:
+ break;
+ }
}
switch (outparam) {
@@ -3914,32 +3347,24 @@ command_known:
case MBOX_COMMAND_COMPLETE:
break;
case MBOX_INVALID_COMMAND:
- IDPRINTF(2, ("%s: mbox cmd %x failed with INVALID_COMMAND\n",
+ IDPRINTF(2, ("%s: mbox cmd %x fails with INVALID_COMMAND\n",
isp->isp_name, opcode));
break;
case MBOX_HOST_INTERFACE_ERROR:
- PRINTF("%s: mbox cmd %x failed with HOST_INTERFACE_ERROR\n",
- isp->isp_name, opcode);
+ IDPRINTF(2, ("%s: mbox cmd %x fails with HOST_INTERFACE_ERR\n",
+ isp->isp_name, opcode));
break;
case MBOX_TEST_FAILED:
- PRINTF("%s: mbox cmd %x failed with TEST_FAILED\n",
- isp->isp_name, opcode);
+ IDPRINTF(2, ("%s: mbox cmd %x fails with TEST_FAILED\n",
+ isp->isp_name, opcode));
break;
case MBOX_COMMAND_ERROR:
- if (opcode != MBOX_ABOUT_FIRMWARE)
- PRINTF("%s: mbox cmd %x failed with COMMAND_ERROR\n",
- isp->isp_name, opcode);
+ IDPRINTF(2, ("%s: mbox cmd %x fails with COMMAND_ERROR\n",
+ isp->isp_name, opcode));
break;
case MBOX_COMMAND_PARAM_ERROR:
- switch (opcode) {
- case MBOX_GET_PORT_DB:
- case MBOX_GET_PORT_NAME:
- case MBOX_GET_DEV_QUEUE_PARAMS:
- break;
- default:
- PRINTF("%s: mbox cmd %x failed with "
- "COMMAND_PARAM_ERROR\n", isp->isp_name, opcode);
- }
+ IDPRINTF(2, ("%s: mbox cmd %x fails with COMMAND_PARAM_ERROR\n",
+ isp->isp_name, opcode));
break;
/*
@@ -4019,7 +3444,7 @@ isp_dumpregs(isp, msg)
const char *msg;
{
PRINTF("%s: %s\n", isp->isp_name, msg);
- if (isp->isp_type & ISP_HA_SCSI)
+ if (IS_SCSI(isp))
PRINTF(" biu_conf1=%x", ISP_READ(isp, BIU_CONF1));
else
PRINTF(" biu_csr=%x", ISP_READ(isp, BIU2100_CSR));
@@ -4028,7 +3453,7 @@ isp_dumpregs(isp, msg)
PRINTF("risc_hccr=%x\n", ISP_READ(isp, HCCR));
- if (isp->isp_type & ISP_HA_SCSI) {
+ if (IS_SCSI(isp)) {
ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE);
PRINTF(" cdma_conf=%x cdma_sts=%x cdma_fifostat=%x\n",
ISP_READ(isp, CDMA_CONF), ISP_READ(isp, CDMA_STATUS),
@@ -4050,32 +3475,11 @@ isp_dumpregs(isp, msg)
}
static void
-isp_dumpxflist(isp)
- struct ispsoftc *isp;
-{
- volatile ISP_SCSI_XFER_T *xs;
- int i, hdp;
-
- for (hdp = i = 0; i < RQUEST_QUEUE_LEN; i++) {
- xs = isp->isp_xflist[i];
- if (xs == NULL) {
- continue;
- }
- if (hdp == 0) {
- PRINTF("%s: active requests\n", isp->isp_name);
- hdp++;
- }
- PRINTF(" Active Handle %d: tgt %d lun %d dlen %d\n",
- i+1, XS_TGT(xs), XS_LUN(xs), XS_XFRLEN(xs));
- }
-}
-
-static void
isp_fw_state(isp)
struct ispsoftc *isp;
{
mbreg_t mbs;
- if (isp->isp_type & ISP_HA_FC) {
+ if (IS_FC(isp)) {
int once = 0;
fcparam *fcp = isp->isp_param;
again:
@@ -4142,7 +3546,7 @@ isp_update_bus(isp, bus)
mbreg_t mbs;
sdparam *sdp;
- if (isp->isp_type & ISP_HA_FC) {
+ if (IS_FC(isp)) {
return;
}
@@ -4154,8 +3558,8 @@ isp_update_bus(isp, bus)
int get;
if (sdp->isp_devparam[tgt].dev_enable == 0) {
- PRINTF("%s: skipping update of target %d on bus %d\n",
- isp->isp_name, tgt, bus);
+ IDPRINTF(1, ("%s: skipping target %d bus %d update\n",
+ isp->isp_name, tgt, bus));
continue;
}
@@ -4420,7 +3824,8 @@ isp_setdfltparm(isp, channel)
/*
* Re-initialize the ISP and complete all orphaned commands
- * with a 'botched' notice.
+ * with a 'botched' notice. The reset/init routines should
+ * not disturb an already active list of commands.
*
* Locks held prior to coming here.
*/
@@ -4429,13 +3834,9 @@ void
isp_restart(isp)
struct ispsoftc *isp;
{
- ISP_SCSI_XFER_T *tlist[RQUEST_QUEUE_LEN], *xs;
- int i;
+ ISP_SCSI_XFER_T *xs;
+ u_int32_t handle;
- for (i = 0; i < RQUEST_QUEUE_LEN; i++) {
- tlist[i] = (ISP_SCSI_XFER_T *) isp->isp_xflist[i];
- isp->isp_xflist[i] = NULL;
- }
#if 0
isp->isp_gotdparms = 0;
#endif
@@ -4449,15 +3850,20 @@ isp_restart(isp)
if (isp->isp_state != ISP_RUNSTATE) {
PRINTF("%s: isp_restart cannot restart ISP\n", isp->isp_name);
}
+ isp->isp_nactive = 0;
- for (i = 0; i < RQUEST_QUEUE_LEN; i++) {
- xs = tlist[i];
- if (XS_NULL(xs)) {
+ for (handle = 1; handle <= (int) isp->isp_maxcmds; handle++) {
+ xs = isp_find_xs(isp, handle);
+ if (xs == NULL) {
continue;
}
- if (isp->isp_nactive > 0)
- isp->isp_nactive--;
- XS_RESID(xs) = XS_XFRLEN(xs);
+ isp_destroy_handle(isp, handle);
+ if (XS_XFRLEN(xs)) {
+ ISP_DMAFREE(isp, xs, handle);
+ XS_RESID(xs) = XS_XFRLEN(xs);
+ } else {
+ XS_RESID(xs) = 0;
+ }
XS_SETERR(xs, HBA_BUSRESET);
XS_CMD_DONE(xs);
}
@@ -4797,14 +4203,24 @@ isp_read_nvram(isp)
u_int32_t lo32;
u_int32_t hi32;
#endif
- } wds;
+ } wd;
u_int64_t full64;
} wwnstore;
wwnstore.full64 = ISP2100_NVRAM_NODE_NAME(nvram_data);
- PRINTF("%s: Adapter WWN 0x%08x%08x\n", isp->isp_name,
- wwnstore.wds.hi32, wwnstore.wds.lo32);
+ /*
+ * Broken PTI cards with nothing in the top nibble. Pah.
+ */
+ if ((wwnstore.wd.hi32 >> 28) == 0) {
+ wwnstore.wd.hi32 |= (2 << 28);
+ CFGPRINTF("%s: (corrected) Adapter WWN 0x%08x%08x\n",
+ isp->isp_name, wwnstore.wd.hi32, wwnstore.wd.lo32);
+ } else {
+ CFGPRINTF("%s: Adapter WWN 0x%08x%08x\n", isp->isp_name,
+ wwnstore.wd.hi32, wwnstore.wd.lo32);
+ }
fcp->isp_nodewwn = wwnstore.full64;
+
/*
* If the Node WWN has 2 in the top nibble, we can
* authoritatively construct a Port WWN by adding
@@ -4821,8 +4237,7 @@ isp_read_nvram(isp)
wwnstore.full64 = ISP2100_NVRAM_BOOT_NODE_NAME(nvram_data);
if (wwnstore.full64 != 0) {
PRINTF("%s: BOOT DEVICE WWN 0x%08x%08x\n",
- isp->isp_name, wwnstore.wds.hi32,
- wwnstore.wds.lo32);
+ isp->isp_name, wwnstore.wd.hi32, wwnstore.wd.lo32);
}
fcp->isp_maxalloc =
ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data);