summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>1999-10-17 18:58:22 +0000
committermjacob <mjacob@FreeBSD.org>1999-10-17 18:58:22 +0000
commit3cefde7f1c334a697bd9f77171e1d3bd1b44b898 (patch)
treeffcc20c5dfb51b3299c394c93b0cd70390c30043
parent0e371d52dc7b8f526fcc434027f5c1386325c349 (diff)
downloadFreeBSD-src-3cefde7f1c334a697bd9f77171e1d3bd1b44b898.zip
FreeBSD-src-3cefde7f1c334a697bd9f77171e1d3bd1b44b898.tar.gz
Remove some target mode stuff. It will get re-introduced in a different
file later. Do some pencil-sharpening types of minor changes. Change how active commands are remembered (using new inline functions to get handles, etc..). Now do a GET FIRMWARE STATUS after firing up the f/w as outgoing mailbox 2 will tell you the f/w's notion of the max commands that can be supported. Attempt to retrieve loop topology. Add in the appropriate SWIZZLE/UNSWIZZLE macros calls (this is a no-op on Little Endian machines but is needed for sparc (on other platforms)). Move the temp port database we use to find out where things have moved to after a LIP to the softc and off the kernel stack. Follow Qlogic's hint and don't bother setting a tag for commands that don't have this enabled (presumably the f/w will do it's own selection then). Use an INT_PENDING macro to check for an interrupt. The call to ISP_DMAFREE now just takes the handle- not the 'handle-1' which was a layering violation. Use CFGPRINTF in a couple of places to make things less chatty if not booting verbose, or CAMDEBUG compiles, etc..
-rw-r--r--sys/dev/isp/isp.c981
1 files changed, 166 insertions, 815 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index 377632e..586b75b 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -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 *));
@@ -468,13 +434,6 @@ again:
*/
ISP_RESET1(isp);
-#if 0
- /*
- * Enable interrupts
- */
- ENABLE_INTS(isp);
-#endif
-
/*
* Wait for everything to finish firing up...
*/
@@ -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.
*/
@@ -1074,8 +1043,7 @@ isp_fibre_init(isp)
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.
@@ -1084,6 +1052,7 @@ isp_fibre_init(isp)
fcp->isp_fwstate = FW_CONFIG_WAIT;
fcp->isp_loopstate = LOOP_NIL;
+ MemoryBarrier();
for (;;) {
mbs.param[0] = MBOX_INIT_FIRMWARE;
mbs.param[1] = 0;
@@ -1166,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);
@@ -1221,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)
@@ -1265,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.
@@ -1276,9 +1265,9 @@ isp_fclink_test(isp, waitdelay)
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.
@@ -1298,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);
}
@@ -1335,7 +1325,7 @@ 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;
@@ -1361,6 +1351,7 @@ isp_pdb_sync(isp, 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++) {
/*
@@ -1709,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);
@@ -1720,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]));
@@ -1756,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);
@@ -1903,9 +1896,8 @@ ispscsicmd(xs)
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.
@@ -1934,26 +1926,7 @@ ispscsicmd(xs)
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(0, ("%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;
- }
-
+ reqp->req_header.rqs_seqno = 0;
if (IS_FC(isp)) {
/*
* See comment in isp_intr
@@ -1961,24 +1934,17 @@ ispscsicmd(xs)
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);
@@ -1994,10 +1960,6 @@ ispscsicmd(xs)
}
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;
@@ -2006,15 +1968,21 @@ ispscsicmd(xs)
* 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.
@@ -2022,7 +1990,9 @@ ispscsicmd(xs)
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;
@@ -2047,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:
@@ -2090,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",
@@ -2100,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;
-#ifdef ISP2100_SCCLUN
if (IS_FC(isp)) {
+#ifdef ISP2100_SCCLUN
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",
@@ -2167,7 +2134,7 @@ isp_intr(arg)
/*
* Well, if we've disabled interrupts, we may get a case where
- * isr isn't set, but sema is. In any case, debounce Isr reads.
+ * isr isn't set, but sema is. In any case, debounce isr reads.
*/
do {
isr = ISP_READ(isp, BIU_ISR);
@@ -2175,22 +2142,12 @@ isp_intr(arg)
} 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)) {
- if (isr == 0 || (isr & BIU2100_ISR_RISC_INT) == 0) {
- if (isr) {
- IDPRINTF(4, ("%s: isp_intr isr=%x\n",
- isp->isp_name, isr));
- }
- return (0);
- }
- } else {
- if (isr == 0 || (isr & BIU_ISR_RISC_INT) == 0) {
- if (isr) {
- IDPRINTF(4, ("%s: isp_intr isr=%x\n",
- isp->isp_name, isr));
- }
- return (0);
- }
+ if (isr == 0) {
+ return (0);
+ }
+ if (!INT_PENDING(isp, isr)) {
+ IDPRINTF(4, ("%s: isp_intr isr=%x\n", isp->isp_name, isr));
+ return (0);
}
if (isp->isp_state != ISP_RUNSTATE) {
IDPRINTF(3, ("%s: interrupt (isr=%x,sema=%x) when not ready\n",
@@ -2212,21 +2169,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);
@@ -2256,7 +2199,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);
@@ -2310,22 +2257,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));
}
@@ -2395,7 +2340,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,
@@ -2412,10 +2357,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))) {
@@ -2589,6 +2533,8 @@ isp_parse_async(isp, mbox)
break;
case ASYNC_LIP_OCCURRED:
+ ((fcparam *) isp->isp_param)->isp_lipseq =
+ ISP_READ(isp, OUTMAILBOX1);
((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT;
((fcparam *) isp->isp_param)->isp_loopstate = LOOP_LIP_RCVD;
isp->isp_sendmarker = 1;
@@ -2652,620 +2598,29 @@ 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 (IS_FC(isp)) {
- 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 (IS_FC(isp)) {
- 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 (IS_SCSI(isp)) {
- 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 (IS_FC(isp)) {
- 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)
struct ispsoftc *isp;
ispstatusreq_t *sp;
@@ -3525,19 +2880,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
@@ -3546,9 +2903,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)
@@ -3757,6 +3116,8 @@ command_known:
*/
if (mbox & 0x8000) {
fph = isp_parse_async(isp, (int) mbox);
+ IDPRINTF(5, ("%s: line %d, fph %d\n",
+ isp->isp_name, __LINE__, fph));
ISP_WRITE(isp, BIU_SEMA, 0);
ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
if (fph < 0) {
@@ -3774,11 +3135,15 @@ command_known:
* eat this here.
*/
if (mbox & 0x4000) {
+ IDPRINTF(5, ("%s: line %d, mbox 0x%x\n",
+ isp->isp_name, __LINE__, mbox));
ISP_WRITE(isp, BIU_SEMA, 0);
ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
SYS_DELAY(100);
goto command_known;
}
+ PRINTF("%s: isp_mboxcmd sees mailbox int with 0x%x in "
+ "mbox0\n", isp->isp_name, mbox);
}
SYS_DELAY(100);
if (--loops < 0) {
@@ -3814,6 +3179,7 @@ command_known:
case MBOX_SET_TAG_AGE_LIMIT:
case MBOX_SET_SELECT_TIMEOUT:
ISP_WRITE(isp, INMAILBOX2, mbp->param[2]);
+ mbp->param[2] = 0;
break;
}
}
@@ -4007,8 +3373,10 @@ command_known:
((fcparam *) isp->isp_param)->isp_loopstate = LOOP_PDB_RCVD;
break;
- case ASYNC_LOOP_UP:
case ASYNC_LIP_OCCURRED:
+ ((fcparam *) isp->isp_param)->isp_lipseq = mbp->param[1];
+ /* FALLTHROUGH */
+ case ASYNC_LOOP_UP:
((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT;
((fcparam *) isp->isp_param)->isp_loopstate = LOOP_LIP_RCVD;
break;
@@ -4108,27 +3476,6 @@ 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;
{
@@ -4150,8 +3497,10 @@ again:
fcp->isp_fwstate = FW_CONFIG_WAIT;
fcp->isp_loopstate = LOOP_PDB_RCVD;
goto again;
- case ASYNC_LOOP_UP:
case ASYNC_LIP_OCCURRED:
+ fcp->isp_lipseq = mbs.param[1];
+ /* FALLTHROUGH */
+ case ASYNC_LOOP_UP:
fcp->isp_fwstate = FW_CONFIG_WAIT;
fcp->isp_loopstate = LOOP_LIP_RCVD;
if (once++ < 10) {
@@ -4478,7 +3827,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.
*/
@@ -4487,13 +3837,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
@@ -4507,15 +3853,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);
}
@@ -4865,10 +4216,10 @@ isp_read_nvram(isp)
*/
if ((wwnstore.wd.hi32 >> 28) == 0) {
wwnstore.wd.hi32 |= (2 << 28);
- PRINTF("%s: (corrected) Adapter WWN 0x%08x%08x\n",
+ CFGPRINTF("%s: (corrected) Adapter WWN 0x%08x%08x\n",
isp->isp_name, wwnstore.wd.hi32, wwnstore.wd.lo32);
} else {
- PRINTF("%s: Adapter WWN 0x%08x%08x\n", isp->isp_name,
+ CFGPRINTF("%s: Adapter WWN 0x%08x%08x\n", isp->isp_name,
wwnstore.wd.hi32, wwnstore.wd.lo32);
}
fcp->isp_nodewwn = wwnstore.full64;
OpenPOWER on IntegriCloud