diff options
Diffstat (limited to 'sys/dev/isp/isp.c')
-rw-r--r-- | sys/dev/isp/isp.c | 981 |
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; |