diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ic/isp.c | 1337 | ||||
-rw-r--r-- | sys/dev/ic/isp_inline.h | 75 | ||||
-rw-r--r-- | sys/dev/ic/isp_openbsd.c | 193 | ||||
-rw-r--r-- | sys/dev/ic/isp_openbsd.h | 71 | ||||
-rw-r--r-- | sys/dev/ic/isp_target.c | 74 | ||||
-rw-r--r-- | sys/dev/ic/isp_target.h | 11 | ||||
-rw-r--r-- | sys/dev/ic/isp_tpublic.h | 54 | ||||
-rw-r--r-- | sys/dev/ic/ispmbox.h | 5 | ||||
-rw-r--r-- | sys/dev/ic/ispreg.h | 57 | ||||
-rw-r--r-- | sys/dev/ic/ispvar.h | 35 |
10 files changed, 1071 insertions, 841 deletions
diff --git a/sys/dev/ic/isp.c b/sys/dev/ic/isp.c index e7daced056f..23e0c6af910 100644 --- a/sys/dev/ic/isp.c +++ b/sys/dev/ic/isp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: isp.c,v 1.15 2000/04/06 05:50:43 mjacob Exp $ */ +/* $OpenBSD: isp.c,v 1.16 2000/07/06 05:31:48 mjacob Exp $ */ /* * Machine and OS Independent (well, as best as possible) * code for the Qlogic ISP SCSI adapters. @@ -113,7 +113,7 @@ isp_reset(isp) struct ispsoftc *isp; { mbreg_t mbs; - int loops, i, dodnld = 1; + int loops, i, touched, dodnld = 1; char *revname; isp->isp_state = ISP_NILSTATE; @@ -138,7 +138,7 @@ isp_reset(isp) * case, we don't really use this yet, but we may in * the future. */ - if (isp->isp_touched == 0) { + if ((touched = isp->isp_touched) == 0) { /* * Just in case it was paused... */ @@ -576,6 +576,8 @@ again: else mbs.param[1] = 0x1000; isp_mboxcmd(isp, &mbs); + /* give it a chance to start */ + SYS_DELAY(500); if (IS_SCSI(isp)) { /* @@ -636,6 +638,46 @@ again: return; } isp->isp_state = ISP_RESETSTATE; + + /* + * Okay- now that we have new firmware running, we now (re)set our + * notion of how many luns we support. This is somewhat tricky because + * if we haven't loaded firmware, we don't have an easy way of telling + * how many luns we support. + * + * We'll make a simplifying assumption- if we loaded firmware, we + * are running with expanded lun firmware, otherwise not. + * + * Expanded lun firmware gives you 32 luns for SCSI cards and + * 65536 luns for Fibre Channel cards. + * + * Because the lun is in a a different position in the Request Queue + * Entry structure for Fibre Channel with expanded lun firmware, we + * can only support one lun (lun zero) when we don't know what kind + * of firmware we're running. + * + * Note that we only do this once (the first time thru isp_reset) + * because we may be called again after firmware has been loaded once + * and released. + */ + if (touched == 0) { + if (dodnld) { + if (IS_SCSI(isp)) { + isp->isp_maxluns = 32; + } else { + isp->isp_maxluns = 65536; + } + } else { + if (IS_SCSI(isp)) { + isp->isp_maxluns = 8; + } else { + PRINTF("%s: WARNING- cannot determine Expanded " + "LUN capability- limiting to one LUN\n", + isp->isp_name); + isp->isp_maxluns = 1; + } + } + } } /* @@ -861,11 +903,11 @@ isp_scsi_channel_init(isp, channel) * Set current per-target parameters to a safe minimum. */ for (tgt = 0; tgt < MAX_TARGETS; tgt++) { - int maxlun, lun; + int lun; u_int16_t sdf; if (sdp->isp_devparam[tgt].dev_enable == 0) { - IDPRINTF(1, ("%s: skipping target %d bus %d settings\n", + IDPRINTF(2, ("%s: skipping target %d bus %d settings\n", isp->isp_name, tgt, channel)); continue; } @@ -952,13 +994,7 @@ isp_scsi_channel_init(isp, channel) * seen yet. */ sdp->isp_devparam[tgt].cur_dflags &= ~DPARM_TQING; - if ((ISP_FW_REV(4, 55, 0) <= ISP_FW_REVX(isp->isp_fwrev) && - (ISP_FW_REV(5, 0, 0) > ISP_FW_REVX(isp->isp_fwrev))) || - (ISP_FW_REVX(isp->isp_fwrev) >= ISP_FW_REV(7, 55, 0))) - maxlun = 32; - else - maxlun = 8; - for (lun = 0; lun < maxlun; lun++) { + for (lun = 0; lun < isp->isp_maxluns; lun++) { mbs.param[0] = MBOX_SET_DEV_QUEUE_PARAMS; mbs.param[1] = (channel << 15) | (tgt << 8) | lun; mbs.param[2] = sdp->isp_max_queue_depth; @@ -1025,7 +1061,7 @@ isp_fibre_init(isp) /* * 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. + * a LIP- this is a known f/w bug for 2100 f/w less than 1.17.0. */ if (ISP_FW_REVX(isp->isp_fwrev) < ISP_FW_REV(1, 17, 0)) { fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN; @@ -1079,26 +1115,8 @@ isp_fibre_init(isp) icbp->icb_logintime = 60; /* 60 second login timeout */ if (fcp->isp_nodewwn) { - u_int64_t pn; MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_nodewwn); - if (fcp->isp_portwwn) { - pn = fcp->isp_portwwn; - } else { - pn = fcp->isp_nodewwn | - (((u_int64_t)(isp->isp_unit+1)) << 56); - } - /* - * If the top nibble is 2, we can construct a port name - * from the node name by setting a nonzero instance in - * bits 56..59. Otherwise, we need to make it identical - * to Node name... - */ - if ((fcp->isp_nodewwn >> 60) == 2) { - MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, pn); - } else { - MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, - fcp->isp_nodewwn); - } + MAKE_NODE_NAME_FROM_WWN(icbp->icb_portname, fcp->isp_portwwn); } else { fcp->isp_fwoptions &= ~(ICBOPT_USE_PORTNAME|ICBOPT_FULL_LOGIN); } @@ -1253,7 +1271,8 @@ isp_fclink_test(isp, waitdelay) "Private Loop", "FL Port", "N-Port to N-Port", - "F Port" + "F Port", + "F Port (no FLOGI_ACC response)" }; mbreg_t mbs; int count; @@ -1300,54 +1319,74 @@ isp_fclink_test(isp, waitdelay) } fcp->isp_loopid = mbs.param[1]; if (IS_2200(isp)) { - count = (int) mbs.param[6]; - if (count < TOPO_NL_PORT || count > TOPO_PTP_STUB) - count = TOPO_PTP_STUB; - fcp->isp_topo = count; + int topo = (int) mbs.param[6]; + if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB) + topo = TOPO_PTP_STUB; + fcp->isp_topo = topo; } else { fcp->isp_topo = TOPO_NL_PORT; } - - /* - * If we're not on a fabric, the low 8 bits will be our AL_PA. - * If we're on a fabric, the low 8 bits will still be our AL_PA. - */ fcp->isp_alpa = mbs.param[2]; + #if defined(ISP2100_FABRIC) fcp->isp_onfabric = 0; - if (isp_getpdb(isp, FL_PORT_ID, &pdb) == 0) { - - if (IS_2100(isp)) + if (fcp->isp_topo != TOPO_N_PORT && + isp_getpdb(isp, FL_PORT_ID, &pdb) == 0) { + struct lportdb *lp; + if (IS_2100(isp)) { fcp->isp_topo = TOPO_FL_PORT; - + } fcp->isp_portid = mbs.param[2] | (((int)mbs.param[3]) << 16); fcp->isp_onfabric = 1; - 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, - toponames[fcp->isp_topo]); /* - * Make sure we're logged out of all fabric devices. + * Save the Fabric controller's port database entry. */ - for (count = FC_SNS_ID+1; count < MAX_FC_TARG; count++) { - struct lportdb *lp = &fcp->portdb[count]; - if (lp->valid == 0 || lp->fabdev == 0) - continue; - PRINTF("%s: logging out target %d at Loop ID %d " - "(port id 0x%x)\n", isp->isp_name, count, - lp->loopid, lp->portid); - mbs.param[0] = MBOX_FABRIC_LOGOUT; - mbs.param[1] = lp->loopid << 8; - mbs.param[2] = 0; - mbs.param[3] = 0; - isp_mboxcmd(isp, &mbs); + lp = &fcp->portdb[FL_PORT_ID]; + 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])); + 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->loggedin = lp->valid = 1; +#if 0 + if (isp->isp_rfabric == 0) { + isp_i_register_fc4_type(isp); } +#endif } else #endif - 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, + { + fcp->isp_portid = mbs.param[2]; + fcp->isp_onfabric = 0; +#if 0 + isp->isp_rfabric = 0; +#endif + fcp->portdb[FL_PORT_ID].valid = 0; + } + + 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, toponames[fcp->isp_topo]); + return (0); } @@ -1365,7 +1404,7 @@ isp_same_lportdb(a, b) */ if (a->port_wwn == 0 || a->port_wwn != b->port_wwn || - a->loopid != b->loopid) { + a->loopid != b->loopid || a->roles != b->roles) { return (0); } else { return (1); @@ -1385,7 +1424,7 @@ isp_pdb_sync(isp, target) struct lportdb *lp, *tport; fcparam *fcp = isp->isp_param; isp_pdb_t pdb; - int loopid, lim; + int loopid, prange, lim; #ifdef ISP2100_FABRIC /* @@ -1400,6 +1439,19 @@ isp_pdb_sync(isp, target) #endif + switch (fcp->isp_topo) { + case TOPO_F_PORT: + case TOPO_PTP_STUB: + prange = 0; + break; + case TOPO_N_PORT: + prange = 2; + break; + default: + prange = FL_PORT_ID; + break; + } + /* * Run through the local loop ports and get port database info * for each loop ID. @@ -1414,12 +1466,17 @@ isp_pdb_sync(isp, target) * make sure the temp port database is clean... */ MEMZERO((void *) tport, sizeof (tport)); - for (lim = loopid = 0; loopid < FL_PORT_ID; loopid++) { + + for (lim = loopid = 0; loopid < prange; loopid++) { lp = &tport[loopid]; lp->node_wwn = isp_get_portname(isp, loopid, 1); + if (fcp->isp_loopstate < LOOP_PDB_RCVD) + return (-1); if (lp->node_wwn == 0) continue; lp->port_wwn = isp_get_portname(isp, loopid, 0); + if (fcp->isp_loopstate < LOOP_PDB_RCVD) + return (-1); if (lp->port_wwn == 0) { lp->node_wwn = 0; continue; @@ -1429,16 +1486,19 @@ isp_pdb_sync(isp, target) * Get an entry.... */ if (isp_getpdb(isp, loopid, &pdb) != 0) { + if (fcp->isp_loopstate < LOOP_PDB_RCVD) + return (-1); continue; } + if (fcp->isp_loopstate < LOOP_PDB_RCVD) + return (-1); + /* * If the returned database element doesn't match what we * asked for, restart the process entirely (up to a point...). */ if (pdb.pdb_loopid != loopid) { - IDPRINTF(1, ("%s: wankage (%d != %d)\n", - isp->isp_name, pdb.pdb_loopid, loopid)); loopid = 0; if (lim++ < FL_PORT_ID) { continue; @@ -1504,7 +1564,7 @@ isp_pdb_sync(isp, target) * Now merge our local copy of the port database into our saved copy. * Notify the outer layers of new devices arriving. */ - for (loopid = 0; loopid < FL_PORT_ID; loopid++) { + for (loopid = 0; loopid < prange; loopid++) { int i; /* @@ -1557,10 +1617,7 @@ isp_pdb_sync(isp, target) 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? - */ + fcp->portdb[i].roles = tport[loopid].roles; /* * Now make sure this Port WWN doesn't exist elsewhere @@ -1635,7 +1692,7 @@ isp_pdb_sync(isp, target) * Now find all previously used targets that are now invalid and * notify the outer layers that they're gone. */ - for (lp = fcp->portdb; lp < &fcp->portdb[FL_PORT_ID]; lp++) { + for (lp = fcp->portdb; lp < &fcp->portdb[prange]; lp++) { if (lp->valid || lp->port_wwn == 0) continue; @@ -1651,13 +1708,13 @@ isp_pdb_sync(isp, target) /* * Now log in any fabric devices */ - for (lim = FC_SNS_ID+1, lp = &fcp->portdb[FC_SNS_ID+1]; + for (lp = &fcp->portdb[FC_SNS_ID+1]; lp < &fcp->portdb[MAX_FC_TARG]; lp++) { u_int32_t portid; mbreg_t mbs; /* - * Nothing here? + * Anything here? */ if (lp->port_wwn == 0) continue; @@ -1668,16 +1725,61 @@ isp_pdb_sync(isp, target) if ((portid = lp->portid) == fcp->isp_portid) continue; + + /* + * If we'd been logged in- see if we still are and we haven't + * changed. If so, no need to log ourselves out, etc.. + */ + if (lp->loggedin && + isp_getpdb(isp, lp->loopid, &pdb) == 0) { + int nrole; + u_int64_t nwwnn, nwwpn; + nwwnn = + (((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])); + nwwpn = + (((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])); + nrole = (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> + SVC3_ROLE_SHIFT; + if (pdb.pdb_loopid == lp->loopid && lp->portid == + (u_int32_t) BITS2WORD(pdb.pdb_portid_bits) && + nwwnn == lp->node_wwn && nwwpn == lp->port_wwn && + lp->roles == nrole) { + lp->loggedin = lp->valid = 1; + IDPRINTF(1, ("%s: retained login of Target %d " + "(Loop 0x%x) Port ID 0x%x\n", + isp->isp_name, (int) (lp - fcp->portdb), + (int) lp->loopid, lp->portid)); + continue; + } + } + /* * Force a logout if we were logged in. */ - if (lp->valid) { + if (lp->loggedin) { mbs.param[0] = MBOX_FABRIC_LOGOUT; mbs.param[1] = lp->loopid << 8; mbs.param[2] = 0; mbs.param[3] = 0; isp_mboxcmd(isp, &mbs); - lp->valid = 0; + lp->loggedin = 0; + IDPRINTF(1, ("%s: Logging out target %d at Loop ID %d " + "(port id 0x%x)\n", isp->isp_name, + (int) (lp - fcp->portdb), lp->loopid, lp->portid)); } /* @@ -1685,16 +1787,15 @@ isp_pdb_sync(isp, target) */ loopid = lp - fcp->portdb; lp->loopid = 0; - lim = 0; do { mbs.param[0] = MBOX_FABRIC_LOGIN; mbs.param[1] = loopid << 8; + mbs.param[2] = portid >> 16; + mbs.param[3] = portid & 0xffff; if (IS_2200(isp)) { /* only issue a PLOGI if not logged in */ mbs.param[1] |= 0x1; } - mbs.param[2] = portid >> 16; - mbs.param[3] = portid & 0xffff; isp_mboxcmd(isp, &mbs); switch (mbs.param[0]) { case MBOX_LOOP_ID_USED: @@ -1706,49 +1807,71 @@ isp_pdb_sync(isp, target) case MBOX_PORT_ID_USED: /* * This port is already logged in. - * Snaffle the loop id it's using. + * Snaffle the loop id it's using if it's + * nonzero, otherwise we're hosed. */ - if ((loopid = mbs.param[1]) == 0) { - lim = -1; + if (mbs.param[1] != 0) { + loopid = mbs.param[1]; + IDPRINTF(1, ("%s: Retaining loopid 0x%x" + " for Target %d (port id 0x%x)\n", + isp->isp_name, loopid, + (int) (lp - fcp->portdb), + lp->portid)); + } else { + loopid = MAX_FC_TARG; + break; } /* FALLTHROUGH */ case MBOX_COMMAND_COMPLETE: + lp->loggedin = 1; lp->loopid = loopid; - lim = 1; break; case MBOX_COMMAND_ERROR: - PRINTF("%s: command error in PLOGI (0x%x)\n", - isp->isp_name, mbs.param[1]); + PRINTF("%s: command error in PLOGI for port " + " 0x%x (0x%x)\n", isp->isp_name, portid, + mbs.param[1]); /* FALLTHROUGH */ case MBOX_ALL_IDS_USED: /* We're outta IDs */ default: - lim = -1; + loopid = MAX_FC_TARG; break; } - } while (lim == 0 && loopid < MAX_FC_TARG); - if (lim < 0) + } while (lp->loopid == 0 && loopid < MAX_FC_TARG); + + /* + * If we get here and we haven't set a Loop ID, + * we failed to log into this device. + */ + + if (lp->loopid == 0) { continue; + } - lp->valid = 1; - lp->fabdev = 1; + /* + * Make sure we can get the approriate port information. + */ if (isp_getpdb(isp, lp->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); - continue; + PRINTF("%s: could not get PDB for device@port 0x%x\n", + isp->isp_name, lp->portid); + goto dump_em; } + 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); - continue; + PRINTF("%s: PDB loopid info for device@port 0x%x does " + "not match up (0x%x)\n", isp->isp_name, lp->portid, + pdb.pdb_loopid); + goto dump_em; } + + if (lp->portid != (u_int32_t) BITS2WORD(pdb.pdb_portid_bits)) { + PRINTF("%s: PDB port info for device@port 0x%x does " + "not match up (0x%x)\n", isp->isp_name, lp->portid, + BITS2WORD(pdb.pdb_portid_bits)); + goto dump_em; + } + lp->roles = (pdb.pdb_prli_svc3 & SVC3_ROLE_MASK) >> SVC3_ROLE_SHIFT; - lp->portid = BITS2WORD(pdb.pdb_portid_bits); lp->node_wwn = (((u_int64_t)pdb.pdb_nodename[0]) << 56) | (((u_int64_t)pdb.pdb_nodename[1]) << 48) | @@ -1771,13 +1894,15 @@ isp_pdb_sync(isp, target) * Check to make sure this all makes sense. */ if (lp->node_wwn && lp->port_wwn) { + lp->valid = 1; loopid = lp - fcp->portdb; (void) isp_async(isp, ISPASYNC_PDB_CHANGED, &loopid); continue; } - lp->fabdev = lp->valid = 0; - PRINTF("%s: Target %d (Loop 0x%x) Port ID 0x%x lost its WWN\n", - isp->isp_name, loopid, lp->loopid, lp->portid); +dump_em: + lp->valid = 0; + PRINTF("%s: Target %d (Loop 0x%x) Port ID 0x%x dumped after " + "login\n", isp->isp_name, loopid, lp->loopid, lp->portid); mbs.param[0] = MBOX_FABRIC_LOGOUT; mbs.param[1] = lp->loopid << 8; mbs.param[2] = 0; @@ -2011,7 +2136,7 @@ ispscsicmd(xs) } if (isp_getrqentry(isp, &iptr, &optr, (void **) &reqp)) { - IDPRINTF(1, ("%s: Request Queue Overflow\n", isp->isp_name)); + IDPRINTF(2, ("%s: Request Queue Overflow\n", isp->isp_name)); XS_SETERR(xs, HBA_BOTCH); return (CMD_EAGAIN); } @@ -2040,7 +2165,7 @@ ispscsicmd(xs) ISP_ADD_REQUEST(isp, iptr); if (isp_getrqentry(isp, &iptr, &optr, (void **)&reqp)) { - IDPRINTF(1, ("%s: Request Queue Overflow+\n", + IDPRINTF(2, ("%s: Request Queue Overflow+\n", isp->isp_name)); XS_SETERR(xs, HBA_BOTCH); return (CMD_EAGAIN); @@ -2091,11 +2216,10 @@ ispscsicmd(xs) reqp->req_lun_trn = XS_LUN(xs); reqp->req_cdblen = XS_CDBLEN(xs); } else { -#ifdef ISP2100_SCCLUN - t2reqp->req_scclun = XS_LUN(xs); -#else - t2reqp->req_lun_trn = XS_LUN(xs); -#endif + if (isp->isp_maxluns > 16) + t2reqp->req_scclun = XS_LUN(xs); + else + t2reqp->req_lun_trn = XS_LUN(xs); } MEMCPY(reqp->req_cdb, XS_CDBP(xs), XS_CDBLEN(xs)); @@ -2211,6 +2335,7 @@ isp_control(isp, ctl, arg) case ISPCTL_ABORT_CMD: xs = (ISP_SCSI_XFER_T *) arg; + tgt = XS_TGT(xs); handle = isp_find_handle(isp, xs); if (handle == 0) { PRINTF("%s: isp_control- cannot find command to abort " @@ -2220,14 +2345,14 @@ isp_control(isp, ctl, arg) bus = XS_CHANNEL(xs); mbs.param[0] = MBOX_ABORT; 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); -#endif + if (isp->isp_maxluns > 16) { + mbs.param[1] = tgt << 8; + mbs.param[4] = 0; + mbs.param[5] = 0; + mbs.param[6] = XS_LUN(xs); + } else { + mbs.param[1] = tgt << 8 | XS_LUN(xs); + } } else { mbs.param[1] = (bus << 15) | (XS_TGT(xs) << 8) | XS_LUN(xs); @@ -2235,13 +2360,19 @@ isp_control(isp, ctl, arg) mbs.param[3] = handle >> 16; mbs.param[2] = handle & 0xffff; isp_mboxcmd(isp, &mbs); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - PRINTF("%s: isp_control MBOX_ABORT failure (code %x)\n", - isp->isp_name, mbs.param[0]); + switch (mbs.param[0]) { + case MBOX_COMMAND_COMPLETE: + IDPRINTF(1, + ("%s: command (handle 0x%x) for %d.%d.%d aborted\n", + isp->isp_name, handle, bus, tgt, XS_LUN(xs))); + /* FALLTHROUGH */ + case MBOX_COMMAND_ERROR: + break; + default: + PRINTF("%s: command (handle 0x%x) abort failed (%x)\n", + isp->isp_name, handle, mbs.param[0]); break; } - PRINTF("%s: command for target %d lun %d was aborted\n", - isp->isp_name, XS_TGT(xs), XS_LUN(xs)); return (0); case ISPCTL_UPDATE_PARAMS: @@ -2249,10 +2380,16 @@ isp_control(isp, ctl, arg) return (0); case ISPCTL_FCLINK_TEST: - return (isp_fclink_test(isp, FC_FW_READY_DELAY)); + if (IS_FC(isp)) { + return (isp_fclink_test(isp, FC_FW_READY_DELAY)); + } + break; case ISPCTL_PDB_SYNC: - return (isp_pdb_sync(isp, -1)); + if (IS_FC(isp)) { + return (isp_pdb_sync(isp, -1)); + } + break; #ifdef ISP_TARGET_MODE case ISPCTL_TOGGLE_TMODE: @@ -2287,42 +2424,74 @@ isp_intr(arg) { ISP_SCSI_XFER_T *complist[RESULT_QUEUE_LEN], *xs; struct ispsoftc *isp = arg; - u_int16_t iptr, optr; - u_int16_t isr, isrb, sema; + u_int16_t iptr, optr, isr, sema, junk; 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. In any case, debounce isr reads. - */ - do { + if (IS_2100(isp)) { + i = 0; + do { + isr = ISP_READ(isp, BIU_ISR); + junk = ISP_READ(isp, BIU_ISR); + } while (isr != junk && ++i < 1000); + if (isr != junk) { + PRINTF("%s: isr unsteady (%x, %x)\n", + isp->isp_name, isr, junk); + } + i = 0; + do { + sema = ISP_READ(isp, BIU_SEMA); + junk = ISP_READ(isp, BIU_SEMA); + } while (sema != junk && ++i < 1000); + if (sema != junk) { + PRINTF("%s: sema unsteady (%x, %x)\n", + isp->isp_name, sema, junk); + } + } else { 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 (isr == 0) { - return (0); + sema = ISP_READ(isp, BIU_SEMA); } - if (!INT_PENDING(isp, isr)) { - IDPRINTF(4, ("%s: isp_intr isr=%x\n", isp->isp_name, isr)); + IDPRINTF(5, ("%s: isp_intr isr %x sem %x\n", isp->isp_name, isr, sema)); + isr &= INT_PENDING_MASK(isp); + sema &= BIU_SEMA_LOCK; + if (isr == 0 && sema == 0) { return (0); } - if (isp->isp_state != ISP_RUNSTATE) { - IDPRINTF(3, ("%s: interrupt (isr=%x,sema=%x) when not ready\n", - isp->isp_name, isr, sema)); - ISP_WRITE(isp, INMAILBOX5, ISP_READ(isp, OUTMAILBOX5)); - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - ISP_WRITE(isp, BIU_SEMA, 0); - ENABLE_INTS(isp); - return (1); - } if (sema) { - u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0); + u_int16_t mbox; + + if (IS_2100(isp)) { + i = 0; + do { + mbox = ISP_READ(isp, OUTMAILBOX0); + junk = ISP_READ(isp, OUTMAILBOX0);; + } while (junk != mbox && ++i < 1000); + if (mbox != junk) { + PRINTF("%s: mailbox0 unsteady (%x, %x)\n", + isp->isp_name, mbox, junk); + ISP_WRITE(isp, BIU_SEMA, 0); + ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); + return (1); + } + } else { + mbox = ISP_READ(isp, OUTMAILBOX0); + } if (mbox & 0x4000) { - IDPRINTF(4, ("%s: Command Mbox 0x%x\n", - isp->isp_name, mbox)); + int obits, i = 0; + if ((obits = isp->isp_mboxbsy) != 0) { + isp->isp_mboxtmp[i++] = mbox; + for (i = 1; i < 8; i++) { + if ((obits & (1 << i)) == 0) { + continue; + } + isp->isp_mboxtmp[i] = + ISP_READ(isp, MBOX_OFF(i)); + } + MBOX_NOTIFY_COMPLETE(isp); + } else { + PRINTF("%s: Command Mbox 0x%x\n", + isp->isp_name, mbox); + } } else { u_int32_t fhandle = isp_parse_async(isp, (int) mbox); IDPRINTF(4, ("%s: Async Mbox 0x%x\n", @@ -2331,9 +2500,22 @@ isp_intr(arg) isp_fastpost_complete(isp, fhandle); } } - ISP_WRITE(isp, BIU_SEMA, 0); + if (IS_FC(isp) || isp->isp_state != ISP_RUNSTATE) { + ISP_WRITE(isp, BIU_SEMA, 0); + ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); + return (1); + } + } + + /* + * We can't be getting this now. + */ + if (isp->isp_state != ISP_RUNSTATE) { + PRINTF("%s: interrupt (isr=%x, sema=%x) when not ready\n", + isp->isp_name, isr, sema); + ISP_WRITE(isp, INMAILBOX5, ISP_READ(isp, OUTMAILBOX5)); ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - ENABLE_INTS(isp); + ISP_WRITE(isp, BIU_SEMA, 0); return (1); } @@ -2341,11 +2523,41 @@ isp_intr(arg) * You *must* read OUTMAILBOX5 prior to clearing the RISC interrupt. */ optr = isp->isp_residx; - iptr = ISP_READ(isp, OUTMAILBOX5); + + if (IS_2100(isp)) { + i = 0; + do { + iptr = ISP_READ(isp, OUTMAILBOX5); + junk = ISP_READ(isp, OUTMAILBOX5); + } while (junk != iptr && ++i < 1000); + + if (iptr != junk) { + ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); + PRINTF("%s: mailbox5 unsteady (%x, %x)\n", + isp->isp_name, iptr, junk); + return (1); + } + } else { + iptr = ISP_READ(isp, OUTMAILBOX5); + } + + if (sema) { + ISP_WRITE(isp, BIU_SEMA, 0); + } ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - if (optr == iptr) { - IDPRINTF(4, ("why intr? isr %x iptr %x optr %x\n", - isr, optr, iptr)); + + if (optr == iptr && sema == 0) { + /* + * There are a lot of these- reasons unknown- mostly on + * faster Alpha machines. + * + * I tried delaying after writing HCCR_CMD_CLEAR_RISC_INT to + * make sure the old interrupt went away (to avoid 'ringing' + * effects), but that didn't stop this from occurring. + */ + junk = ISP_READ(isp, BIU_ISR); + IDPRINTF(2, ("%s: null intr- isr %x (%x) iptr %x optr %x\n", + isp->isp_name, isr, junk, iptr, optr)); } while (optr != iptr) { @@ -2460,8 +2672,9 @@ isp_intr(arg) XS_SNS_IS_VALID(xs); sp->req_state_flags |= RQSF_GOT_SENSE; } else if (XS_STS(xs) == SCSI_CHECK) { - IDPRINTF(1, ("%s: check condition with no sense" - " data\n", isp->isp_name)); + IDPRINTF(2, + ("%s: check condition with no sense data\n", + isp->isp_name)); } } if (XS_NOERR(xs) && XS_STS(xs) == SCSI_BUSY) { @@ -2503,24 +2716,6 @@ isp_intr(arg) if (XS_XFRLEN(xs)) { ISP_DMAFREE(isp, xs, sp->req_handle); } - /* - * Let the platforms cope. - */ -#if 0 - /* - * XXX: If we have a check condition, but no Sense Data, - * XXX: mark it as an error (ARQ failed). We need to - * XXX: to do a more distinct job because there may - * XXX: cases where ARQ is disabled. - */ - if (XS_STS(xs) == SCSI_CHECK && !(XS_IS_SNS_VALID(xs))) { - if (XS_NOERR(xs)) { - PRINTF("%s: ARQ failure for target %d lun %d\n", - isp->isp_name, XS_TGT(xs), XS_LUN(xs)); - XS_SETERR(xs, HBA_ARQFAIL); - } - } -#endif if ((isp->isp_dblev >= 5) || (isp->isp_dblev > 2 && !XS_NOERR(xs))) { PRINTF("%s(%d.%d): FIN dl%d resid%d STS %x", @@ -2549,6 +2744,7 @@ isp_intr(arg) ISP_WRITE(isp, INMAILBOX5, optr); isp->isp_reqodx = ISP_READ(isp, OUTMAILBOX4); } + isp->isp_residx = optr; for (i = 0; i < ndone; i++) { xs = complist[i]; @@ -2556,7 +2752,6 @@ isp_intr(arg) XS_CMD_DONE(xs); } } - ENABLE_INTS(isp); return (1); } @@ -2746,7 +2941,7 @@ isp_parse_async(isp, mbox) isp->isp_sendmarker = 1; ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_PDB_RCVD; isp_mark_getpdb_all(isp); - IDPRINTF(2, ("%s: Port Database Changed\n", isp->isp_name)); + IDPRINTF(1, ("%s: Port Database Changed\n", isp->isp_name)); break; case ASYNC_CHANGE_NOTIFY: @@ -2759,6 +2954,17 @@ isp_parse_async(isp, mbox) break; case ASYNC_PTPMODE: + if (((fcparam *) isp->isp_param)->isp_onfabric) + ((fcparam *) isp->isp_param)->isp_topo = TOPO_N_PORT; + else + ((fcparam *) isp->isp_param)->isp_topo = TOPO_F_PORT; + isp_mark_getpdb_all(isp); + isp->isp_sendmarker = 1; + ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; + ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_LIP_RCVD; +#ifdef ISP_TARGET_MODE + isp_target_async(isp, bus, mbox); +#endif PRINTF("%s: Point-to-Point mode\n", isp->isp_name); break; @@ -3013,7 +3219,7 @@ isp_parse_status(isp, sp, xs) case RQCS_ARQS_FAILED: PRINTF("%s: Auto Request Sense failed for %d.%d.%d\n", - isp->isp_name, XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs)); + isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); return; case RQCS_WIDE_FAILED: @@ -3117,309 +3323,279 @@ isp_fastpost_complete(isp, fph) isp->isp_nactive--; } -#define HINIB(x) ((x) >> 0x4) -#define LONIB(x) ((x) & 0xf) -#define MAKNIB(a, b) (((a) << 4) | (b)) -static u_int8_t mbpcnt[] = { - MAKNIB(1, 1), /* 0x00: MBOX_NO_OP */ - MAKNIB(5, 5), /* 0x01: MBOX_LOAD_RAM */ - MAKNIB(2, 0), /* 0x02: MBOX_EXEC_FIRMWARE */ - MAKNIB(5, 5), /* 0x03: MBOX_DUMP_RAM */ - MAKNIB(3, 3), /* 0x04: MBOX_WRITE_RAM_WORD */ - MAKNIB(2, 3), /* 0x05: MBOX_READ_RAM_WORD */ - MAKNIB(6, 6), /* 0x06: MBOX_MAILBOX_REG_TEST */ - MAKNIB(2, 3), /* 0x07: MBOX_VERIFY_CHECKSUM */ - MAKNIB(1, 4), /* 0x08: MBOX_ABOUT_FIRMWARE */ - MAKNIB(0, 0), /* 0x09: */ - MAKNIB(0, 0), /* 0x0a: */ - MAKNIB(0, 0), /* 0x0b: */ - MAKNIB(0, 0), /* 0x0c: */ - MAKNIB(0, 0), /* 0x0d: */ - MAKNIB(1, 2), /* 0x0e: MBOX_CHECK_FIRMWARE */ - MAKNIB(0, 0), /* 0x0f: */ - MAKNIB(5, 5), /* 0x10: MBOX_INIT_REQ_QUEUE */ - MAKNIB(6, 6), /* 0x11: MBOX_INIT_RES_QUEUE */ - MAKNIB(4, 4), /* 0x12: MBOX_EXECUTE_IOCB */ - MAKNIB(2, 2), /* 0x13: MBOX_WAKE_UP */ - MAKNIB(1, 6), /* 0x14: MBOX_STOP_FIRMWARE */ - MAKNIB(4, 4), /* 0x15: MBOX_ABORT */ - MAKNIB(2, 2), /* 0x16: MBOX_ABORT_DEVICE */ - MAKNIB(3, 3), /* 0x17: MBOX_ABORT_TARGET */ - MAKNIB(3, 1), /* 0x18: MBOX_BUS_RESET */ - MAKNIB(2, 3), /* 0x19: MBOX_STOP_QUEUE */ - MAKNIB(2, 3), /* 0x1a: MBOX_START_QUEUE */ - MAKNIB(2, 3), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */ - MAKNIB(2, 3), /* 0x1c: MBOX_ABORT_QUEUE */ - MAKNIB(2, 4), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */ - MAKNIB(0, 0), /* 0x1e: */ - MAKNIB(1, 3), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */ - MAKNIB(1, 4), /* 0x20: MBOX_GET_INIT_SCSI_ID, MBOX_GET_LOOP_ID */ - MAKNIB(1, 3), /* 0x21: MBOX_GET_SELECT_TIMEOUT */ - MAKNIB(1, 3), /* 0x22: MBOX_GET_RETRY_COUNT */ - MAKNIB(1, 2), /* 0x23: MBOX_GET_TAG_AGE_LIMIT */ - MAKNIB(1, 2), /* 0x24: MBOX_GET_CLOCK_RATE */ - MAKNIB(1, 2), /* 0x25: MBOX_GET_ACT_NEG_STATE */ - MAKNIB(1, 2), /* 0x26: MBOX_GET_ASYNC_DATA_SETUP_TIME */ - MAKNIB(1, 3), /* 0x27: MBOX_GET_PCI_PARAMS */ - MAKNIB(2, 4), /* 0x28: MBOX_GET_TARGET_PARAMS */ - MAKNIB(2, 4), /* 0x29: MBOX_GET_DEV_QUEUE_PARAMS */ - MAKNIB(1, 2), /* 0x2a: MBOX_GET_RESET_DELAY_PARAMS */ - MAKNIB(0, 0), /* 0x2b: */ - MAKNIB(0, 0), /* 0x2c: */ - MAKNIB(0, 0), /* 0x2d: */ - MAKNIB(0, 0), /* 0x2e: */ - MAKNIB(0, 0), /* 0x2f: */ - MAKNIB(2, 2), /* 0x30: MBOX_SET_INIT_SCSI_ID */ - MAKNIB(2, 3), /* 0x31: MBOX_SET_SELECT_TIMEOUT */ - MAKNIB(3, 3), /* 0x32: MBOX_SET_RETRY_COUNT */ - MAKNIB(2, 2), /* 0x33: MBOX_SET_TAG_AGE_LIMIT */ - MAKNIB(2, 2), /* 0x34: MBOX_SET_CLOCK_RATE */ - MAKNIB(2, 2), /* 0x35: MBOX_SET_ACT_NEG_STATE */ - MAKNIB(2, 2), /* 0x36: MBOX_SET_ASYNC_DATA_SETUP_TIME */ - MAKNIB(3, 3), /* 0x37: MBOX_SET_PCI_CONTROL_PARAMS */ - MAKNIB(4, 4), /* 0x38: MBOX_SET_TARGET_PARAMS */ - MAKNIB(4, 4), /* 0x39: MBOX_SET_DEV_QUEUE_PARAMS */ - MAKNIB(1, 2), /* 0x3a: MBOX_SET_RESET_DELAY_PARAMS */ - MAKNIB(0, 0), /* 0x3b: */ - MAKNIB(0, 0), /* 0x3c: */ - MAKNIB(0, 0), /* 0x3d: */ - MAKNIB(0, 0), /* 0x3e: */ - MAKNIB(0, 0), /* 0x3f: */ - MAKNIB(1, 2), /* 0x40: MBOX_RETURN_BIOS_BLOCK_ADDR */ - MAKNIB(6, 1), /* 0x41: MBOX_WRITE_FOUR_RAM_WORDS */ - MAKNIB(2, 3), /* 0x42: MBOX_EXEC_BIOS_IOCB */ - MAKNIB(0, 0), /* 0x43: */ - MAKNIB(0, 0), /* 0x44: */ - MAKNIB(0, 0), /* 0x45: */ - MAKNIB(0, 0), /* 0x46: */ - MAKNIB(0, 0), /* 0x47: */ - MAKNIB(0, 0), /* 0x48: */ - MAKNIB(0, 0), /* 0x49: */ - MAKNIB(2, 1), /* 0x4a: MBOX_SET_FIRMWARE_FEATURES */ - MAKNIB(1, 2), /* 0x4b: MBOX_GET_FIRMWARE_FEATURES */ - MAKNIB(0, 0), /* 0x4c: */ - MAKNIB(0, 0), /* 0x4d: */ - MAKNIB(0, 0), /* 0x4e: */ - MAKNIB(0, 0), /* 0x4f: */ - MAKNIB(0, 0), /* 0x50: */ - MAKNIB(0, 0), /* 0x51: */ - MAKNIB(0, 0), /* 0x52: */ - MAKNIB(0, 0), /* 0x53: */ - MAKNIB(8, 0), /* 0x54: MBOX_EXEC_COMMAND_IOCB_A64 */ - MAKNIB(2, 1), /* 0x55: MBOX_ENABLE_TARGET_MODE */ - MAKNIB(0, 0), /* 0x56: */ - MAKNIB(0, 0), /* 0x57: */ - MAKNIB(0, 0), /* 0x58: */ - MAKNIB(0, 0), /* 0x59: */ - MAKNIB(0, 0), /* 0x5a: */ - MAKNIB(0, 0), /* 0x5b: */ - MAKNIB(0, 0), /* 0x5c: */ - MAKNIB(0, 0), /* 0x5d: */ - MAKNIB(0, 0), /* 0x5e: */ - MAKNIB(0, 0), /* 0x5f: */ - MAKNIB(8, 6), /* 0x60: MBOX_INIT_FIRMWARE */ - MAKNIB(0, 0), /* 0x61: */ - MAKNIB(2, 1), /* 0x62: MBOX_INIT_LIP */ - MAKNIB(8, 1), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */ - MAKNIB(8, 1), /* 0x64: MBOX_GET_PORT_DB */ - MAKNIB(3, 1), /* 0x65: MBOX_CLEAR_ACA */ - MAKNIB(3, 1), /* 0x66: MBOX_TARGET_RESET */ - MAKNIB(3, 1), /* 0x67: MBOX_CLEAR_TASK_SET */ - MAKNIB(3, 1), /* 0x68: MBOX_ABORT_TASK_SET */ - MAKNIB(1, 2), /* 0x69: MBOX_GET_FW_STATE */ - MAKNIB(2, 8), /* 0x6a: MBOX_GET_PORT_NAME */ - MAKNIB(8, 1), /* 0x6b: MBOX_GET_LINK_STATUS */ - MAKNIB(4, 4), /* 0x6c: MBOX_INIT_LIP_RESET */ - MAKNIB(0, 0), /* 0x6d: */ - MAKNIB(8, 2), /* 0x6e: MBOX_SEND_SNS */ - MAKNIB(4, 3), /* 0x6f: MBOX_FABRIC_LOGIN */ - MAKNIB(2, 1), /* 0x70: MBOX_SEND_CHANGE_REQUEST */ - MAKNIB(2, 1), /* 0x71: MBOX_FABRIC_LOGOUT */ - MAKNIB(4, 1) /* 0x72: MBOX_INIT_LIP_LOGIN */ +#define HIBYT(x) ((x) >> 0x8) +#define LOBYT(x) ((x) & 0xff) +#define ISPOPMAP(a, b) (((a) << 8) | (b)) +static u_int16_t mbpscsi[] = { + ISPOPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */ + ISPOPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */ + ISPOPMAP(0x03, 0x01), /* 0x02: MBOX_EXEC_FIRMWARE */ + ISPOPMAP(0x1f, 0x01), /* 0x03: MBOX_DUMP_RAM */ + ISPOPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */ + ISPOPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */ + ISPOPMAP(0x3f, 0x3f), /* 0x06: MBOX_MAILBOX_REG_TEST */ + ISPOPMAP(0x03, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */ + ISPOPMAP(0x01, 0x0f), /* 0x08: MBOX_ABOUT_FIRMWARE */ + ISPOPMAP(0x00, 0x00), /* 0x09: */ + ISPOPMAP(0x00, 0x00), /* 0x0a: */ + ISPOPMAP(0x00, 0x00), /* 0x0b: */ + ISPOPMAP(0x00, 0x00), /* 0x0c: */ + ISPOPMAP(0x00, 0x00), /* 0x0d: */ + ISPOPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */ + ISPOPMAP(0x00, 0x00), /* 0x0f: */ + ISPOPMAP(0x1f, 0x1f), /* 0x10: MBOX_INIT_REQ_QUEUE */ + ISPOPMAP(0x3f, 0x3f), /* 0x11: MBOX_INIT_RES_QUEUE */ + ISPOPMAP(0x0f, 0x0f), /* 0x12: MBOX_EXECUTE_IOCB */ + ISPOPMAP(0x03, 0x03), /* 0x13: MBOX_WAKE_UP */ + ISPOPMAP(0x01, 0x3f), /* 0x14: MBOX_STOP_FIRMWARE */ + ISPOPMAP(0x0f, 0x0f), /* 0x15: MBOX_ABORT */ + ISPOPMAP(0x03, 0x03), /* 0x16: MBOX_ABORT_DEVICE */ + ISPOPMAP(0x07, 0x07), /* 0x17: MBOX_ABORT_TARGET */ + ISPOPMAP(0x07, 0x07), /* 0x18: MBOX_BUS_RESET */ + ISPOPMAP(0x03, 0x07), /* 0x19: MBOX_STOP_QUEUE */ + ISPOPMAP(0x03, 0x07), /* 0x1a: MBOX_START_QUEUE */ + ISPOPMAP(0x03, 0x07), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */ + ISPOPMAP(0x03, 0x07), /* 0x1c: MBOX_ABORT_QUEUE */ + ISPOPMAP(0x03, 0x4f), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */ + ISPOPMAP(0x00, 0x00), /* 0x1e: */ + ISPOPMAP(0x01, 0x07), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */ + ISPOPMAP(0x01, 0x07), /* 0x20: MBOX_GET_INIT_SCSI_ID */ + ISPOPMAP(0x01, 0x07), /* 0x21: MBOX_GET_SELECT_TIMEOUT */ + ISPOPMAP(0x01, 0xc7), /* 0x22: MBOX_GET_RETRY_COUNT */ + ISPOPMAP(0x01, 0x07), /* 0x23: MBOX_GET_TAG_AGE_LIMIT */ + ISPOPMAP(0x01, 0x03), /* 0x24: MBOX_GET_CLOCK_RATE */ + ISPOPMAP(0x01, 0x07), /* 0x25: MBOX_GET_ACT_NEG_STATE */ + ISPOPMAP(0x01, 0x07), /* 0x26: MBOX_GET_ASYNC_DATA_SETUP_TIME */ + ISPOPMAP(0x01, 0x07), /* 0x27: MBOX_GET_PCI_PARAMS */ + ISPOPMAP(0x03, 0x4f), /* 0x28: MBOX_GET_TARGET_PARAMS */ + ISPOPMAP(0x03, 0x0f), /* 0x29: MBOX_GET_DEV_QUEUE_PARAMS */ + ISPOPMAP(0x01, 0x07), /* 0x2a: MBOX_GET_RESET_DELAY_PARAMS */ + ISPOPMAP(0x00, 0x00), /* 0x2b: */ + ISPOPMAP(0x00, 0x00), /* 0x2c: */ + ISPOPMAP(0x00, 0x00), /* 0x2d: */ + ISPOPMAP(0x00, 0x00), /* 0x2e: */ + ISPOPMAP(0x00, 0x00), /* 0x2f: */ + ISPOPMAP(0x03, 0x03), /* 0x30: MBOX_SET_INIT_SCSI_ID */ + ISPOPMAP(0x07, 0x07), /* 0x31: MBOX_SET_SELECT_TIMEOUT */ + ISPOPMAP(0xc7, 0xc7), /* 0x32: MBOX_SET_RETRY_COUNT */ + ISPOPMAP(0x07, 0x07), /* 0x33: MBOX_SET_TAG_AGE_LIMIT */ + ISPOPMAP(0x03, 0x03), /* 0x34: MBOX_SET_CLOCK_RATE */ + ISPOPMAP(0x07, 0x07), /* 0x35: MBOX_SET_ACT_NEG_STATE */ + ISPOPMAP(0x07, 0x07), /* 0x36: MBOX_SET_ASYNC_DATA_SETUP_TIME */ + ISPOPMAP(0x07, 0x07), /* 0x37: MBOX_SET_PCI_CONTROL_PARAMS */ + ISPOPMAP(0x4f, 0x4f), /* 0x38: MBOX_SET_TARGET_PARAMS */ + ISPOPMAP(0x0f, 0x0f), /* 0x39: MBOX_SET_DEV_QUEUE_PARAMS */ + ISPOPMAP(0x07, 0x07), /* 0x3a: MBOX_SET_RESET_DELAY_PARAMS */ + ISPOPMAP(0x00, 0x00), /* 0x3b: */ + ISPOPMAP(0x00, 0x00), /* 0x3c: */ + ISPOPMAP(0x00, 0x00), /* 0x3d: */ + ISPOPMAP(0x00, 0x00), /* 0x3e: */ + ISPOPMAP(0x00, 0x00), /* 0x3f: */ + ISPOPMAP(0x01, 0x03), /* 0x40: MBOX_RETURN_BIOS_BLOCK_ADDR */ + ISPOPMAP(0x3f, 0x01), /* 0x41: MBOX_WRITE_FOUR_RAM_WORDS */ + ISPOPMAP(0x03, 0x07), /* 0x42: MBOX_EXEC_BIOS_IOCB */ + ISPOPMAP(0x00, 0x00), /* 0x43: */ + ISPOPMAP(0x00, 0x00), /* 0x44: */ + ISPOPMAP(0x03, 0x03), /* 0x45: SET SYSTEM PARAMETER */ + ISPOPMAP(0x01, 0x03), /* 0x46: GET SYSTEM PARAMETER */ + ISPOPMAP(0x00, 0x00), /* 0x47: */ + ISPOPMAP(0x01, 0xcf), /* 0x48: GET SCAM CONFIGURATION */ + ISPOPMAP(0xcf, 0xcf), /* 0x49: SET SCAM CONFIGURATION */ + ISPOPMAP(0x03, 0x03), /* 0x4a: MBOX_SET_FIRMWARE_FEATURES */ + ISPOPMAP(0x01, 0x03), /* 0x4b: MBOX_GET_FIRMWARE_FEATURES */ + ISPOPMAP(0x00, 0x00), /* 0x4c: */ + ISPOPMAP(0x00, 0x00), /* 0x4d: */ + ISPOPMAP(0x00, 0x00), /* 0x4e: */ + ISPOPMAP(0x00, 0x00), /* 0x4f: */ + ISPOPMAP(0xdf, 0xdf), /* 0x50: LOAD RAM A64 */ + ISPOPMAP(0xdf, 0xdf), /* 0x51: DUMP RAM A64 */ + ISPOPMAP(0xdf, 0xdf), /* 0x52: INITIALIZE REQUEST QUEUE A64 */ + ISPOPMAP(0xff, 0xff), /* 0x53: INITIALIZE RESPONSE QUEUE A64 */ + ISPOPMAP(0xcf, 0xff), /* 0x54: EXECUTE IOCB A64 */ + ISPOPMAP(0x03, 0x01), /* 0x55: ENABLE TARGET MODE */ + ISPOPMAP(0x00, 0x00), /* 0x56: */ + ISPOPMAP(0x00, 0x00), /* 0x57: */ + ISPOPMAP(0x00, 0x00), /* 0x58: */ + ISPOPMAP(0x00, 0x00), /* 0x59: */ + ISPOPMAP(0x03, 0x03), /* 0x5a: SET DATA OVERRUN RECOVERY MODE */ + ISPOPMAP(0x01, 0x03), /* 0x5b: GET DATA OVERRUN RECOVERY MODE */ + ISPOPMAP(0x0f, 0x0f), /* 0x5c: SET HOST DATA */ + ISPOPMAP(0x01, 0x01) /* 0x5d: GET NOST DATA */ +}; + +static u_int16_t mbpfc[] = { + ISPOPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */ + ISPOPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */ + ISPOPMAP(0x03, 0x01), /* 0x02: MBOX_EXEC_FIRMWARE */ + ISPOPMAP(0x1f, 0x01), /* 0x03: MBOX_DUMP_RAM */ + ISPOPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */ + ISPOPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */ + ISPOPMAP(0xff, 0xff), /* 0x06: MBOX_MAILBOX_REG_TEST */ + ISPOPMAP(0x03, 0x05), /* 0x07: MBOX_VERIFY_CHECKSUM */ + ISPOPMAP(0x01, 0x0f), /* 0x08: MBOX_ABOUT_FIRMWARE */ + ISPOPMAP(0xdf, 0x01), /* 0x09: LOAD RAM */ + ISPOPMAP(0xdf, 0x01), /* 0x0a: DUMP RAM */ + ISPOPMAP(0x00, 0x00), /* 0x0b: */ + ISPOPMAP(0x00, 0x00), /* 0x0c: */ + ISPOPMAP(0x00, 0x00), /* 0x0d: */ + ISPOPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */ + ISPOPMAP(0x00, 0x00), /* 0x0f: */ + ISPOPMAP(0x1f, 0x11), /* 0x10: MBOX_INIT_REQ_QUEUE */ + ISPOPMAP(0x2f, 0x21), /* 0x11: MBOX_INIT_RES_QUEUE */ + ISPOPMAP(0x0f, 0x01), /* 0x12: MBOX_EXECUTE_IOCB */ + ISPOPMAP(0x03, 0x03), /* 0x13: MBOX_WAKE_UP */ + ISPOPMAP(0x01, 0xff), /* 0x14: MBOX_STOP_FIRMWARE */ + ISPOPMAP(0x4f, 0x01), /* 0x15: MBOX_ABORT */ + ISPOPMAP(0x07, 0x01), /* 0x16: MBOX_ABORT_DEVICE */ + ISPOPMAP(0x07, 0x01), /* 0x17: MBOX_ABORT_TARGET */ + ISPOPMAP(0x03, 0x03), /* 0x18: MBOX_BUS_RESET */ + ISPOPMAP(0x07, 0x05), /* 0x19: MBOX_STOP_QUEUE */ + ISPOPMAP(0x07, 0x05), /* 0x1a: MBOX_START_QUEUE */ + ISPOPMAP(0x07, 0x05), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */ + ISPOPMAP(0x07, 0x05), /* 0x1c: MBOX_ABORT_QUEUE */ + ISPOPMAP(0x07, 0x03), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */ + ISPOPMAP(0x00, 0x00), /* 0x1e: */ + ISPOPMAP(0x01, 0x07), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */ + ISPOPMAP(0x01, 0x4f), /* 0x20: MBOX_GET_LOOP_ID */ + ISPOPMAP(0x00, 0x00), /* 0x21: */ + ISPOPMAP(0x01, 0x07), /* 0x22: MBOX_GET_RETRY_COUNT */ + ISPOPMAP(0x00, 0x00), /* 0x23: */ + ISPOPMAP(0x00, 0x00), /* 0x24: */ + ISPOPMAP(0x00, 0x00), /* 0x25: */ + ISPOPMAP(0x00, 0x00), /* 0x26: */ + ISPOPMAP(0x00, 0x00), /* 0x27: */ + ISPOPMAP(0x0f, 0x1), /* 0x28: MBOX_GET_FIRMWARE_OPTIONS */ + ISPOPMAP(0x03, 0x07), /* 0x29: MBOX_GET_PORT_QUEUE_PARAMS */ + ISPOPMAP(0x00, 0x00), /* 0x2a: */ + ISPOPMAP(0x00, 0x00), /* 0x2b: */ + ISPOPMAP(0x00, 0x00), /* 0x2c: */ + ISPOPMAP(0x00, 0x00), /* 0x2d: */ + ISPOPMAP(0x00, 0x00), /* 0x2e: */ + ISPOPMAP(0x00, 0x00), /* 0x2f: */ + ISPOPMAP(0x00, 0x00), /* 0x30: */ + ISPOPMAP(0x00, 0x00), /* 0x31: */ + ISPOPMAP(0x07, 0x07), /* 0x32: MBOX_SET_RETRY_COUNT */ + ISPOPMAP(0x00, 0x00), /* 0x33: */ + ISPOPMAP(0x00, 0x00), /* 0x34: */ + ISPOPMAP(0x00, 0x00), /* 0x35: */ + ISPOPMAP(0x00, 0x00), /* 0x36: */ + ISPOPMAP(0x00, 0x00), /* 0x37: */ + ISPOPMAP(0x0f, 0x01), /* 0x38: MBOX_SET_FIRMWARE_OPTIONS */ + ISPOPMAP(0x0f, 0x07), /* 0x39: MBOX_SET_PORT_QUEUE_PARAMS */ + ISPOPMAP(0x00, 0x00), /* 0x3a: */ + ISPOPMAP(0x00, 0x00), /* 0x3b: */ + ISPOPMAP(0x00, 0x00), /* 0x3c: */ + ISPOPMAP(0x00, 0x00), /* 0x3d: */ + ISPOPMAP(0x00, 0x00), /* 0x3e: */ + ISPOPMAP(0x00, 0x00), /* 0x3f: */ + ISPOPMAP(0x03, 0x01), /* 0x40: MBOX_LOOP_PORT_BYPASS */ + ISPOPMAP(0x03, 0x01), /* 0x41: MBOX_LOOP_PORT_ENABLE */ + ISPOPMAP(0x03, 0x07), /* 0x42: MBOX_GET_RESOURCE_COUNTS */ + ISPOPMAP(0x01, 0x01), /* 0x43: MBOX_REQUEST_NON_PARTICIPATING_MODE */ + ISPOPMAP(0x00, 0x00), /* 0x44: */ + ISPOPMAP(0x00, 0x00), /* 0x45: */ + ISPOPMAP(0x00, 0x00), /* 0x46: */ + ISPOPMAP(0xcf, 0x03), /* 0x47: GET PORT_DATABASE ENHANCED */ + ISPOPMAP(0x00, 0x00), /* 0x48: */ + ISPOPMAP(0x00, 0x00), /* 0x49: */ + ISPOPMAP(0x00, 0x00), /* 0x4a: */ + ISPOPMAP(0x00, 0x00), /* 0x4b: */ + ISPOPMAP(0x00, 0x00), /* 0x4c: */ + ISPOPMAP(0x00, 0x00), /* 0x4d: */ + ISPOPMAP(0x00, 0x00), /* 0x4e: */ + ISPOPMAP(0x00, 0x00), /* 0x4f: */ + ISPOPMAP(0x00, 0x00), /* 0x50: */ + ISPOPMAP(0x00, 0x00), /* 0x51: */ + ISPOPMAP(0x00, 0x00), /* 0x52: */ + ISPOPMAP(0x00, 0x00), /* 0x53: */ + ISPOPMAP(0xcf, 0x01), /* 0x54: EXECUTE IOCB A64 */ + ISPOPMAP(0x00, 0x00), /* 0x55: */ + ISPOPMAP(0x00, 0x00), /* 0x56: */ + ISPOPMAP(0x00, 0x00), /* 0x57: */ + ISPOPMAP(0x00, 0x00), /* 0x58: */ + ISPOPMAP(0x00, 0x00), /* 0x59: */ + ISPOPMAP(0x00, 0x00), /* 0x5a: */ + ISPOPMAP(0x00, 0x00), /* 0x5b: */ + ISPOPMAP(0x00, 0x00), /* 0x5c: */ + ISPOPMAP(0x00, 0x00), /* 0x5d: */ + ISPOPMAP(0x00, 0x00), /* 0x5e: */ + ISPOPMAP(0x00, 0x00), /* 0x5f: */ + ISPOPMAP(0xfd, 0x31), /* 0x60: MBOX_INIT_FIRMWARE */ + ISPOPMAP(0x00, 0x00), /* 0x61: */ + ISPOPMAP(0x01, 0x01), /* 0x62: MBOX_INIT_LIP */ + ISPOPMAP(0xcd, 0x03), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */ + ISPOPMAP(0xcf, 0x01), /* 0x64: MBOX_GET_PORT_DB */ + ISPOPMAP(0x07, 0x01), /* 0x65: MBOX_CLEAR_ACA */ + ISPOPMAP(0x07, 0x01), /* 0x66: MBOX_TARGET_RESET */ + ISPOPMAP(0x07, 0x01), /* 0x67: MBOX_CLEAR_TASK_SET */ + ISPOPMAP(0x07, 0x01), /* 0x68: MBOX_ABORT_TASK_SET */ + ISPOPMAP(0x01, 0x07), /* 0x69: MBOX_GET_FW_STATE */ + ISPOPMAP(0x03, 0xcf), /* 0x6a: MBOX_GET_PORT_NAME */ + ISPOPMAP(0xcf, 0x01), /* 0x6b: MBOX_GET_LINK_STATUS */ + ISPOPMAP(0x0f, 0x01), /* 0x6c: MBOX_INIT_LIP_RESET */ + ISPOPMAP(0x00, 0x00), /* 0x6d: */ + ISPOPMAP(0xcf, 0x03), /* 0x6e: MBOX_SEND_SNS */ + ISPOPMAP(0x0f, 0x07), /* 0x6f: MBOX_FABRIC_LOGIN */ + ISPOPMAP(0x03, 0x01), /* 0x70: MBOX_SEND_CHANGE_REQUEST */ + ISPOPMAP(0x03, 0x03), /* 0x71: MBOX_FABRIC_LOGOUT */ + ISPOPMAP(0x0f, 0x0f), /* 0x72: MBOX_INIT_LIP_LOGIN */ + ISPOPMAP(0x00, 0x00), /* 0x73: */ + ISPOPMAP(0x07, 0x01), /* 0x74: LOGIN LOOP PORT */ + ISPOPMAP(0xcf, 0x03), /* 0x75: GET PORT/NODE NAME LIST */ + ISPOPMAP(0x4f, 0x01), /* 0x76: SET VENDOR ID */ + ISPOPMAP(0xcd, 0x01), /* 0x77: INITIALIZE IP MAILBOX */ + ISPOPMAP(0x00, 0x00), /* 0x78: */ + ISPOPMAP(0x00, 0x00), /* 0x79: */ + ISPOPMAP(0x00, 0x00), /* 0x7a: */ + ISPOPMAP(0x00, 0x00), /* 0x7b: */ + ISPOPMAP(0x4f, 0x03), /* 0x7c: Get ID List */ + ISPOPMAP(0xcf, 0x01), /* 0x7d: SEND LFA */ + ISPOPMAP(0x07, 0x01) /* 0x7e: Lun RESET */ }; -#define NMBCOM (sizeof (mbpcnt) / sizeof (mbpcnt[0])) static void isp_mboxcmd(isp, mbp) struct ispsoftc *isp; mbreg_t *mbp; { - int outparam, inparam; - int loops, dld = 0; - u_int8_t opcode; - - if (mbp->param[0] == ISP2100_SET_PCI_PARAM) { - opcode = mbp->param[0] = MBOX_SET_PCI_PARAMETERS; - inparam = 4; - outparam = 4; - goto command_known; - } else if (mbp->param[0] > NMBCOM) { - PRINTF("%s: bad command %x\n", isp->isp_name, mbp->param[0]); - return; - } - - opcode = mbp->param[0]; - inparam = HINIB(mbpcnt[mbp->param[0]]); - outparam = LONIB(mbpcnt[mbp->param[0]]); + unsigned int lim, ibits, obits, box, opcode; + u_int16_t *mcp; - if (inparam == 0 && outparam == 0) { - PRINTF("%s: no parameters for %x\n", isp->isp_name, - mbp->param[0]); - return; - } - - - /* - * Check for variants - */ -#ifdef ISP2100_SCCLUN if (IS_FC(isp)) { - switch (mbp->param[0]) { - case MBOX_ABORT: - inparam = 7; - break; - case MBOX_ABORT_DEVICE: - case MBOX_START_QUEUE: - case MBOX_STOP_QUEUE: - case MBOX_SINGLE_STEP_QUEUE: - case MBOX_ABORT_QUEUE: - case MBOX_GET_DEV_QUEUE_STATUS: - inparam = 3; - break; - case MBOX_BUS_RESET: - inparam = 2; - break; - default: - break; - } + mcp = mbpfc; + lim = (sizeof (mbpfc) / sizeof (mbpfc[0])); + } else { + mcp = mbpscsi; + lim = (sizeof (mbpscsi) / sizeof (mbpscsi[0])); } -#endif - -command_known: - - /* - * Set semaphore on mailbox registers to win any races to acquire them. - */ - 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. - */ + if ((opcode = mbp->param[0]) >= lim) { + mbp->param[0] = MBOX_INVALID_COMMAND; + PRINTF("%s: unknown command 0x%x\n", isp->isp_name, opcode); + return; + } - /* - * Make sure we can send some words. - * Check to see if there's an async mbox event pending. - */ + ibits = HIBYT(mcp[opcode]) & NMBOX_BMASK(isp); + obits = LOBYT(mcp[opcode]) & NMBOX_BMASK(isp); - loops = MBOX_DELAY_COUNT; - while ((ISP_READ(isp, HCCR) & HCCR_HOST_INT) != 0) { - if (ISP_READ(isp, BIU_SEMA) & 1) { - int fph; - u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0); - /* - * We have a pending MBOX async event. - */ - 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) { - return; - } else if (fph > 0) { - isp_fastpost_complete(isp, fph); - } - SYS_DELAY(100); - goto command_known; - } - /* - * We have a pending MBOX completion? Might be - * from a previous command. We can't (sometimes) - * just clear HOST INTERRUPT, so we'll just silently - * 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; - } - } - SYS_DELAY(100); - if (--loops < 0) { - if (dld++ > 10) { - PRINTF("%s: isp_mboxcmd could not get command " - "started\n", isp->isp_name); - return; - } - ISP_WRITE(isp, BIU_SEMA, 0); - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - goto command_known; - } + if (ibits == 0 && obits == 0) { + mbp->param[0] = MBOX_COMMAND_PARAM_ERROR; + PRINTF("%s: no parameters for opcode 0x%x\n", isp->isp_name, + opcode); + return; } - /* - * Write input parameters. - * - * Special case some of the setups for the dual port SCSI cards. - * XXX Eventually will be fixed by converting register write/read - * XXX counts to bitmasks. - */ - if (IS_DUALBUS(isp)) { - switch (opcode) { - case MBOX_GET_RETRY_COUNT: - case MBOX_SET_RETRY_COUNT: - ISP_WRITE(isp, INMAILBOX7, mbp->param[7]); - mbp->param[7] = 0; - ISP_WRITE(isp, INMAILBOX6, mbp->param[6]); - mbp->param[6] = 0; - break; - case MBOX_SET_ASYNC_DATA_SETUP_TIME: - case MBOX_SET_ACT_NEG_STATE: - case MBOX_SET_TAG_AGE_LIMIT: - case MBOX_SET_SELECT_TIMEOUT: - ISP_WRITE(isp, INMAILBOX2, mbp->param[2]); - mbp->param[2] = 0; - break; + for (box = 0; box < MAX_MAILBOX; box++) { + if (ibits & (1 << box)) { + ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]); } - } - - switch (inparam) { - case 8: ISP_WRITE(isp, INMAILBOX7, mbp->param[7]); mbp->param[7] = 0; - case 7: ISP_WRITE(isp, INMAILBOX6, mbp->param[6]); mbp->param[6] = 0; - case 6: - /* - * The Qlogic 2100 cannot have registers 4 and 5 written to - * after initialization or BAD THINGS HAPPEN (tm). - */ - if (IS_SCSI(isp) || mbp->param[0] == MBOX_INIT_FIRMWARE) - ISP_WRITE(isp, INMAILBOX5, mbp->param[5]); - mbp->param[5] = 0; - case 5: - if (IS_SCSI(isp) || mbp->param[0] == MBOX_INIT_FIRMWARE) - ISP_WRITE(isp, INMAILBOX4, mbp->param[4]); - mbp->param[4] = 0; - case 4: ISP_WRITE(isp, INMAILBOX3, mbp->param[3]); mbp->param[3] = 0; - case 3: ISP_WRITE(isp, INMAILBOX2, mbp->param[2]); mbp->param[2] = 0; - case 2: ISP_WRITE(isp, INMAILBOX1, mbp->param[1]); mbp->param[1] = 0; - case 1: ISP_WRITE(isp, INMAILBOX0, mbp->param[0]); mbp->param[0] = 0; + isp->isp_mboxtmp[box] = mbp->param[box] = 0; } /* - * Clear RISC int condition. + * We assume that we can't overwrite a previous command. */ - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - - /* - * Clear semaphore on mailbox registers so that the Qlogic - * may update outgoing registers. - */ - ISP_WRITE(isp, BIU_SEMA, 0); + isp->isp_mboxbsy = obits; /* * Set Host Interrupt condition so that RISC will pick up mailbox regs. @@ -3427,121 +3603,25 @@ command_known: ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT); /* - * Wait until HOST INT has gone away (meaning that the Qlogic - * has picked up the mailbox command. Wait a long time. + * Give the f/w a chance to pick this up. */ - loops = MBOX_DELAY_COUNT * 5; - while ((ISP_READ(isp, HCCR) & HCCR_CMD_CLEAR_RISC_INT) != 0) { - SYS_DELAY(100); - if (--loops < 0) { - PRINTF("%s: isp_mboxcmd timeout #2\n", isp->isp_name); - return; - } - } + SYS_DELAY(250); - /* - * While the Semaphore registers isn't set, wait for the Qlogic - * to process the mailbox command. Again- wait a long time. - */ - loops = MBOX_DELAY_COUNT * 5; - while ((ISP_READ(isp, BIU_SEMA) & 1) == 0) { - SYS_DELAY(100); - /* - * Wierd- I've seen the case where the semaphore register - * isn't getting set- sort of a violation of the protocol.. - */ - if (ISP_READ(isp, OUTMAILBOX0) & 0x4000) - break; - if (--loops < 0) { - PRINTF("%s: isp_mboxcmd timeout #3\n", isp->isp_name); - return; - } - } /* - * Make sure that the MBOX_BUSY has gone away + * While we haven't finished the command, spin our wheels here. */ - loops = MBOX_DELAY_COUNT; - for (;;) { - u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0); - if (mbox == MBOX_BUSY) { - if (--loops < 0) { - PRINTF("%s: isp_mboxcmd timeout #4\n", - isp->isp_name); - return; - } - SYS_DELAY(100); - continue; - } - /* - * We have a pending MBOX async event. - */ - if (mbox & 0x8000) { - int fph = isp_parse_async(isp, (int) mbox); - ISP_WRITE(isp, BIU_SEMA, 0); - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - if (fph < 0) { - return; - } else if (fph > 0) { - isp_fastpost_complete(isp, fph); - } - SYS_DELAY(100); - continue; - } - break; - } + MBOX_WAIT_COMPLETE(isp); /* - * Pick up output parameters. Special case some of the readbacks - * for the dual port SCSI cards. + * Copy back output registers. */ - if (IS_DUALBUS(isp)) { - switch (opcode) { - case MBOX_GET_RETRY_COUNT: - case MBOX_SET_RETRY_COUNT: - mbp->param[7] = ISP_READ(isp, OUTMAILBOX7); - mbp->param[6] = ISP_READ(isp, OUTMAILBOX6); - break; - case MBOX_GET_TAG_AGE_LIMIT: - case MBOX_SET_TAG_AGE_LIMIT: - case MBOX_GET_ACT_NEG_STATE: - case MBOX_SET_ACT_NEG_STATE: - case MBOX_SET_ASYNC_DATA_SETUP_TIME: - case MBOX_GET_ASYNC_DATA_SETUP_TIME: - case MBOX_GET_RESET_DELAY_PARAMS: - case MBOX_SET_RESET_DELAY_PARAMS: - mbp->param[2] = ISP_READ(isp, OUTMAILBOX2); - break; - } - } - - if (IS_2200(isp)) { - if (opcode == MBOX_GET_LOOP_ID) { - mbp->param[6] = ISP_READ(isp, OUTMAILBOX6); + for (box = 0; box < MAX_MAILBOX; box++) { + if (obits & (1 << box)) { + mbp->param[box] = isp->isp_mboxtmp[box]; } } - switch (outparam) { - case 8: mbp->param[7] = ISP_READ(isp, OUTMAILBOX7); - case 7: mbp->param[6] = ISP_READ(isp, OUTMAILBOX6); - case 6: mbp->param[5] = ISP_READ(isp, OUTMAILBOX5); - case 5: mbp->param[4] = ISP_READ(isp, OUTMAILBOX4); - case 4: mbp->param[3] = ISP_READ(isp, OUTMAILBOX3); - case 3: mbp->param[2] = ISP_READ(isp, OUTMAILBOX2); - case 2: mbp->param[1] = ISP_READ(isp, OUTMAILBOX1); - case 1: mbp->param[0] = ISP_READ(isp, OUTMAILBOX0); - } - - /* - * Clear RISC int. - */ - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - - /* - * Release semaphore on mailbox registers - */ - ISP_WRITE(isp, BIU_SEMA, 0); - /* * Just to be chatty here... */ @@ -3582,30 +3662,6 @@ command_known: case MBOX_ALL_IDS_USED: break; - - /* - * Be silent about these... - */ - case ASYNC_PDB_CHANGED: - ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_PDB_RCVD; - break; - - 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; - - case ASYNC_LOOP_DOWN: - case ASYNC_LOOP_RESET: - ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; - ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_NIL; - /* FALLTHROUGH */ - case ASYNC_CHANGE_NOTIFY: - break; - default: /* * The expected return of EXEC_FIRMWARE is zero. @@ -3778,7 +3834,7 @@ isp_update_bus(isp, bus) int get; if (sdp->isp_devparam[tgt].dev_enable == 0) { - IDPRINTF(1, ("%s: skipping target %d bus %d update\n", + IDPRINTF(2, ("%s: skipping target %d bus %d update\n", isp->isp_name, tgt, bus)); continue; } @@ -3877,15 +3933,23 @@ isp_setdfltparm(isp, channel) /* Platform specific.... */ fcp->isp_loopid = DEFAULT_LOOPID(isp); fcp->isp_nodewwn = DEFAULT_WWN(isp); - fcp->isp_portwwn = 0; + if ((fcp->isp_nodewwn >> 60) == 2) { + fcp->isp_nodewwn &= ~((u_int64_t) 0xfff << 48); + fcp->isp_portwwn = fcp->isp_nodewwn | + (((u_int64_t)(isp->isp_unit+1)) << 48); + } else { + fcp->isp_portwwn = fcp->isp_nodewwn; + } /* * Now try and read NVRAM */ if ((isp->isp_confopts & (ISP_CFG_NONVRAM|ISP_CFG_OWNWWN)) || (isp_read_nvram(isp))) { - PRINTF("%s: using Node WWN 0x%08x%08x\n", - isp->isp_name, (u_int32_t)(fcp->isp_nodewwn >> 32), - (u_int32_t)(fcp->isp_nodewwn & 0xffffffff)); + PRINTF("%s: Node WWN 0x%08x%08x, Port WWN 0x%08x%08x\n", + isp->isp_name, (u_int32_t) (fcp->isp_nodewwn >> 32), + (u_int32_t) (fcp->isp_nodewwn & 0xffffffff), + (u_int32_t) (fcp->isp_portwwn >> 32), + (u_int32_t) (fcp->isp_portwwn & 0xffffffff)); } return; } @@ -3958,7 +4022,8 @@ isp_setdfltparm(isp, channel) isp->isp_type < ISP_HA_SCSI_1020A) || (isp->isp_bustype == ISP_BT_PCI && isp->isp_type < ISP_HA_SCSI_1040) || - (isp->isp_clock && isp->isp_clock < 60)) { + (isp->isp_clock && isp->isp_clock < 60) || + (sdp->isp_ultramode == 0)) { sdp->isp_devparam[tgt].sync_offset = ISP_10M_SYNCPARMS >> 8; sdp->isp_devparam[tgt].sync_period = @@ -4067,9 +4132,6 @@ isp_restart(isp) ISP_SCSI_XFER_T *xs; u_int32_t handle; -#if 0 - isp->isp_gotdparms = 0; -#endif isp_reset(isp); if (isp->isp_state == ISP_RESETSTATE) { isp_init(isp); @@ -4668,39 +4730,42 @@ isp_parse_nvram_2100(isp, nvram_data) u_int64_t full64; } wwnstore; - wwnstore.full64 = ISP2100_NVRAM_NODE_NAME(nvram_data); - /* - * Broken PTI cards with nothing in the top nibble. Pah. + * There is supposed to be WWNN storage as distinct + * from WWPN storage in NVRAM, but it doesn't appear + * to be used sanely. */ - 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 - * our unit number (plus one to make it nonzero) and - * putting it into bits 59..56. If the top nibble isn't - * 2, then we just set them identically. - */ - if ((fcp->isp_nodewwn >> 60) == 2) { - fcp->isp_portwwn = fcp->isp_nodewwn | - (((u_int64_t)(isp->isp_unit+1)) << 56); - } else { - fcp->isp_portwwn = fcp->isp_nodewwn; - } - 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.wd.hi32, wwnstore.wd.lo32); + wwnstore.full64 = ISP2100_NVRAM_PORT_NAME(nvram_data); + if (wwnstore.full64 != 0LL) { + switch ((int) (wwnstore.full64 >> 60)) { + case 0: + /* + * Broken cards with nothing in the top nibble. + * Pah. + */ + wwnstore.full64 |= (2LL << 60); + /* FALLTHROUGH */ + case 2: + fcp->isp_portwwn = wwnstore.full64; + fcp->isp_nodewwn = wwnstore.full64; + fcp->isp_nodewwn &= ~((0xfffLL) << 48); + if (fcp->isp_nodewwn == fcp->isp_portwwn) { + fcp->isp_portwwn |= + (((u_int64_t)(isp->isp_unit+1)) << 48); + } + break; + default: + fcp->isp_portwwn = wwnstore.full64; + fcp->isp_nodewwn = wwnstore.full64; + } } + CFGPRINTF("%s: Node WWN 0x%08x%08x, Port WWN 0x%08x%08x\n", + isp->isp_name, (u_int32_t) (fcp->isp_nodewwn >> 32), + (u_int32_t) (fcp->isp_nodewwn & 0xffffffff), + (u_int32_t) (fcp->isp_portwwn >> 32), + (u_int32_t) (fcp->isp_portwwn & 0xffffffff)); + fcp->isp_maxalloc = ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data); fcp->isp_maxfrmlen = diff --git a/sys/dev/ic/isp_inline.h b/sys/dev/ic/isp_inline.h index 9e45b7d443c..08dbbbbfc4b 100644 --- a/sys/dev/ic/isp_inline.h +++ b/sys/dev/ic/isp_inline.h @@ -1,4 +1,4 @@ -/* $OpenBSD: isp_inline.h,v 1.3 2000/02/20 21:22:41 mjacob Exp $ */ +/* $OpenBSD: isp_inline.h,v 1.4 2000/07/06 05:31:48 mjacob Exp $ */ /* * Qlogic Inline Functions * @@ -46,71 +46,54 @@ static INLINE void isp_prtstst(sp) ispstatusreq_t *sp; { - char buf[172], *p = buf; - sprintf(p, "states->"); + char buf[172]; + buf[0] = 0; + STRNCAT(buf, "states=>", sizeof buf); if (sp->req_state_flags & RQSF_GOT_BUS) { - p += strlen(p); - sprintf(p, "%s%s", buf, "GOT_BUS "); + STRNCAT(buf, " GOT_BUS", sizeof buf); } if (sp->req_state_flags & RQSF_GOT_TARGET) { - p += strlen(p); - sprintf(p, "%s%s", buf, "GOT_TGT "); + STRNCAT(buf, " GOT_TGT", sizeof buf); } if (sp->req_state_flags & RQSF_SENT_CDB) { - p += strlen(p); - sprintf(p, "%s%s", buf, "SENT_CDB "); + STRNCAT(buf, " SENT_CDB", sizeof buf); } if (sp->req_state_flags & RQSF_XFRD_DATA) { - p += strlen(p); - sprintf(p, "%s%s", buf, "XFRD_DATA "); + STRNCAT(buf, " XFRD_DATA", sizeof buf); } if (sp->req_state_flags & RQSF_GOT_STATUS) { - p += strlen(p); - sprintf(p, "%s%s", buf, "GOT_STS "); + STRNCAT(buf, " GOT_STS", sizeof buf); } if (sp->req_state_flags & RQSF_GOT_SENSE) { - p += strlen(p); - sprintf(p, "%s%s", buf, "GOT_SNS "); + STRNCAT(buf, " GOT_SNS", sizeof buf); } if (sp->req_state_flags & RQSF_XFER_COMPLETE) { - p += strlen(p); - sprintf(p, "%s%s", buf, "XFR_CMPLT "); + STRNCAT(buf, " XFR_CMPLT", sizeof buf); } - p += strlen(p); - sprintf(p, "%s%s", buf, "\n"); - p += strlen(p); - sprintf(p, "%s%s", buf, "status->"); + STRNCAT(buf, "\nstatus=>", sizeof buf); if (sp->req_status_flags & RQSTF_DISCONNECT) { - p += strlen(p); - sprintf(p, "%s%s", buf, "Disconnect "); + STRNCAT(buf, " Disconnect", sizeof buf); } if (sp->req_status_flags & RQSTF_SYNCHRONOUS) { - p += strlen(p); - sprintf(p, "%s%s", buf, "Sync_xfr "); + STRNCAT(buf, " Sync_xfr", sizeof buf); } if (sp->req_status_flags & RQSTF_PARITY_ERROR) { - p += strlen(p); - sprintf(p, "%s%s", buf, "Parity "); + STRNCAT(buf, " Parity", sizeof buf); } if (sp->req_status_flags & RQSTF_BUS_RESET) { - p += strlen(p); - sprintf(p, "%s%s", buf, "Bus_Reset "); + STRNCAT(buf, " Bus_Reset", sizeof buf); } if (sp->req_status_flags & RQSTF_DEVICE_RESET) { - p += strlen(p); - sprintf(p, "%s%s", buf, "Device_Reset "); + STRNCAT(buf, " Device_Reset", sizeof buf); } if (sp->req_status_flags & RQSTF_ABORTED) { - p += strlen(p); - sprintf(p, "%s%s", buf, "Aborted "); + STRNCAT(buf, " Aborted", sizeof buf); } if (sp->req_status_flags & RQSTF_TIMEOUT) { - p += strlen(p); - sprintf(p, "%s%s", buf, "Timeout "); + STRNCAT(buf, " Timeout", sizeof buf); } if (sp->req_status_flags & RQSTF_NEGOTIATION) { - p += strlen(p); - sprintf(p, "%s%s", buf, "Negotiation "); + STRNCAT(buf, " Negotiation", sizeof buf); } PRINTF(buf, "%s\n", buf); } @@ -173,6 +156,9 @@ isp_find_xs __P((struct ispsoftc *, u_int32_t)); static INLINE u_int32_t isp_find_handle __P((struct ispsoftc *, ISP_SCSI_XFER_T *)); +static INLINE int +isp_handle_index __P((u_int32_t)); + static INLINE void isp_destroy_handle __P((struct ispsoftc *, u_int32_t)); @@ -234,13 +220,20 @@ isp_find_handle(isp, xs) return (0); } +static INLINE int +isp_handle_index(handle) + u_int32_t handle; +{ + return (handle-1); +} + static INLINE void isp_destroy_handle(isp, handle) struct ispsoftc *isp; u_int32_t handle; { if (handle > 0 && handle <= (u_int32_t) isp->isp_maxcmds) { - isp->isp_xflist[handle - 1] = NULL; + isp->isp_xflist[isp_handle_index(handle)] = NULL; } } @@ -271,8 +264,10 @@ isp_getrqentry(isp, iptrp, optrp, resultp) if (iptr == optr) { return (1); } - *optrp = optr; - *iptrp = iptr; + if (optrp) + *optrp = optr; + if (iptrp) + *iptrp = iptr; return (0); } diff --git a/sys/dev/ic/isp_openbsd.c b/sys/dev/ic/isp_openbsd.c index 86c51cb323a..e882bb8ed01 100644 --- a/sys/dev/ic/isp_openbsd.c +++ b/sys/dev/ic/isp_openbsd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: isp_openbsd.c,v 1.9 2000/04/06 05:47:54 mjacob Exp $ */ +/* $OpenBSD: isp_openbsd.c,v 1.10 2000/07/06 05:31:48 mjacob Exp $ */ /* * Platform (OpenBSD) dependent common attachment code for Qlogic adapters. * @@ -55,10 +55,12 @@ static int32_t ispcmd __P((ISP_SCSI_XFER_T *)); static struct scsi_device isp_dev = { NULL, NULL, NULL, NULL }; static int isp_poll __P((struct ispsoftc *, ISP_SCSI_XFER_T *, int)); -static void isp_watch __P((void *)); -static void isp_command_requeue(void *); +static void isp_wdog __P((void *)); +static void isp_requeue(void *); static void isp_internal_restart(void *); +#define _XT(xs) ((((xs)->timeout + 999)/1000) + (2 * hz)) + struct cfdriver isp_cd = { NULL, "isp", DV_DULL }; @@ -145,7 +147,6 @@ isp_attach(isp) for (i = 0; i < 5; i++) { if (isp_control(isp, ISPCTL_FCLINK_TEST, NULL)) continue; -#ifdef ISP2100_FABRIC /* * Wait extra time to see if the f/w * eventually completed an FLOGI that @@ -156,7 +157,6 @@ isp_attach(isp) delay(1 * 1000000); continue; } -#endif break; } if (fcp->isp_fwstate == FW_READY && @@ -168,14 +168,6 @@ isp_attach(isp) } /* - * Start the watchdog. - * - * The watchdog will, ridiculously enough, also enable Sync negotiation. - */ - isp->isp_dogactive = 1; - timeout(isp_watch, isp, WATCH_INTERVAL * hz); - - /* * And attach children (if any). */ config_found((void *)isp, lptr, scsiprint); @@ -299,9 +291,15 @@ ispcmd(xs) int result; int s; - isp = xs->sc_link->adapter_softc; - s = splbio(); + /* + * Make sure that there's *some* kind of sane setting. + */ + timeout_set(&xs->stimeout, isp_wdog, isp); + timeout_del(&xs->stimeout); + isp = XS_ISP(xs); + + s = splbio(); if (isp->isp_state < ISP_RUNSTATE) { DISABLE_INTS(isp); isp_init(isp); @@ -335,21 +333,23 @@ ispcmd(xs) splx(s); return (SUCCESSFULLY_QUEUED); } - DISABLE_INTS(isp); result = ispscsicmd(xs); - ENABLE_INTS(isp); if ((xs->flags & SCSI_POLL) == 0) { switch (result) { case CMD_QUEUED: result = SUCCESSFULLY_QUEUED; + if (xs->timeout) { + timeout_add(&xs->stimeout, _XT(xs)); + } break; case CMD_EAGAIN: result = TRY_AGAIN_LATER; break; case CMD_RQLATER: result = SUCCESSFULLY_QUEUED; - timeout(isp_command_requeue, xs, hz); + timeout_set(&xs->stimeout, isp_requeue, xs); + timeout_add(&xs->stimeout, hz); break; case CMD_COMPLETE: result = COMPLETE; @@ -385,7 +385,7 @@ ispcmd(xs) * If no other error occurred but we didn't finish, * something bad happened. */ - if (XS_IS_CMD_DONE(xs) == 0) { + if (XS_CMD_DONE_P(xs) == 0) { if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) { isp_restart(isp); } @@ -400,6 +400,25 @@ ispcmd(xs) return (result); } +void +isp_done(xs) + ISP_SCSI_XFER_T *xs; +{ + XS_CMD_S_DONE(xs); + if (XS_CMD_WDOG_P(xs) == 0) { + if (xs->timeout) { + timeout_del(&xs->stimeout); + } + if (XS_CMD_GRACE_P(xs)) { + struct ispsoftc *isp = XS_ISP(xs); + PRINTF("%s: finished command on borrowed time\n", + isp->isp_name); + } + XS_CMD_S_CLEAR(xs); + scsi_done(xs); + } +} + static int isp_poll(isp, xs, mswait) struct ispsoftc *isp; @@ -412,7 +431,7 @@ isp_poll(isp, xs, mswait) (void)isp_intr((void *)isp); /* See if the xs is now done */ - if (XS_IS_CMD_DONE(xs)) { + if (XS_CMD_DONE_P(xs)) { return (0); } delay(1000); /* wait one millisecond */ @@ -423,48 +442,97 @@ isp_poll(isp, xs, mswait) static void -isp_watch(arg) +isp_wdog(arg) void *arg; { - int i; - struct ispsoftc *isp = arg; - struct scsi_xfer *xs; - int s; + ISP_SCSI_XFER_T *xs = arg; + struct ispsoftc *isp = XS_ISP(xs); + u_int32_t handle; + int s = splbio(); /* - * Look for completely dead commands (but not polled ones). + * We've decided this command is dead. Make sure we're not trying + * to kill a command that's already dead by getting it's handle and + * and seeing whether it's still alive. */ - s = splbio(); - for (i = 0; i < isp->isp_maxcmds; i++) { - if ((xs = (struct scsi_xfer *) isp->isp_xflist[i]) == NULL) { - continue; - } - if (xs->timeout == 0 || (xs->flags & SCSI_POLL)) { - continue; + handle = isp_find_handle(isp, xs); + if (handle) { + u_int16_t r, r1, i; + + if (XS_CMD_DONE_P(xs)) { + PRINTF("%s: watchdog found done cmd (handle 0x%x)\n", + isp->isp_name, handle); + (void) splx(s); + return; } - xs->timeout -= (WATCH_INTERVAL * 1000); - /* - * Avoid later thinking that this - * transaction is not being timed. - * Then give ourselves to watchdog - * periods of grace. - */ - if (xs->timeout == 0) { - xs->timeout = 1; - } else if (xs->timeout > -(2 * WATCH_INTERVAL * 1000)) { - continue; + if (XS_CMD_WDOG_P(xs)) { + PRINTF("%s: recursive watchdog (handle 0x%x)\n", + isp->isp_name, handle); + (void) splx(s); + return; } - if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) { - printf("%s: isp_watch failed to abort command\n", - isp->isp_name); - isp_restart(isp); - break; + + XS_CMD_S_WDOG(xs); + + i = 0; + do { + r = ISP_READ(isp, BIU_ISR); + SYS_DELAY(1); + r1 = ISP_READ(isp, BIU_ISR); + } while (r != r1 && ++i < 1000); + + if (INT_PENDING(isp, r) && isp_intr(isp) && XS_CMD_DONE_P(xs)) { + IDPRINTF(1, ("%s: watchdog cleanup (%x, %x)\n", + isp->isp_name, handle, r)); + XS_CMD_C_WDOG(xs); + isp_done(xs); + } else if (XS_CMD_GRACE_P(xs)) { + /* + * Make sure the command is *really* dead before we + * release the handle (and DMA resources) for reuse. + */ + (void) isp_control(isp, ISPCTL_ABORT_CMD, arg); + + /* + * After this point, the comamnd is really dead. + */ + if (XS_XFRLEN(xs)) { + ISP_DMAFREE(isp, xs, handle); + } + printf("%s: watchdog timeout (%x, %x)\n", + isp->isp_name, handle, r); + isp_destroy_handle(isp, handle); + XS_SETERR(xs, XS_TIMEOUT); + XS_CMD_S_CLEAR(xs); + isp_done(xs); + } else { + u_int16_t iptr, optr; + ispreq_t *mp; + + IDPRINTF(2, ("%s: possible command timeout (%x, %x)\n", + isp->isp_name, handle, r)); + + XS_CMD_C_WDOG(xs); + timeout_add(&xs->stimeout, _XT(xs)); + if (isp_getrqentry(isp, &iptr, &optr, (void **) &mp)) { + (void) splx(s); + return; + } + XS_CMD_S_GRACE(xs); + MEMZERO((void *) mp, sizeof (*mp)); + mp->req_header.rqs_entry_count = 1; + mp->req_header.rqs_entry_type = RQSTYPE_MARKER; + mp->req_modifier = SYNC_ALL; + mp->req_target = XS_CHANNEL(xs) << 7; + ISP_SWIZZLE_REQUEST(isp, mp); + MemoryBarrier(); + ISP_ADD_REQUEST(isp, iptr); } + } else if (isp->isp_dblev) { + PRINTF("%s: watchdog with no command\n", isp->isp_name); } - timeout(isp_watch, isp, WATCH_INTERVAL * hz); - isp->isp_dogactive = 1; - splx(s); + (void) splx(s); } /* @@ -484,14 +552,6 @@ isp_uninit(isp) */ DISABLE_INTS(isp); - /* - * Turn off the watchdog (if active). - */ - if (isp->isp_dogactive) { - untimeout(isp_watch, isp); - isp->isp_dogactive = 0; - } - splx(s); } @@ -499,7 +559,7 @@ isp_uninit(isp) * Restart function for a command to be requeued later. */ static void -isp_command_requeue(void *arg) +isp_requeue(void *arg) { struct scsi_xfer *xs = arg; struct ispsoftc *isp = XS_ISP(xs); @@ -508,6 +568,10 @@ isp_command_requeue(void *arg) case SUCCESSFULLY_QUEUED: printf("%s: isp_command_reque: queued %d.%d\n", isp->isp_name, XS_TGT(xs), XS_LUN(xs)); + if (xs->timeout) { + timeout_set(&xs->stimeout, isp_wdog, isp); + timeout_add(&xs->stimeout, _XT(xs)); + } break; case TRY_AGAIN_LATER: printf("%s: EAGAIN for %d.%d\n", @@ -548,6 +612,8 @@ isp_internal_restart(void *arg) if (XS_NOERR(xs)) XS_SETERR(xs, XS_DRIVER_STUFFUP); XS_CMD_DONE(xs); + } else if (xs->timeout) { + timeout_add(&xs->stimeout, _XT(xs)); } nrestarted++; } @@ -645,7 +711,8 @@ isp_async(isp, cmd, arg) break; case ISPASYNC_LOOP_UP: isp->isp_osinfo.blocked = 0; - timeout(isp_internal_restart, isp, 1); + timeout_set(&isp->isp_osinfo.rqt, isp_internal_restart, isp); + timeout_add(&isp->isp_osinfo.rqt, 1); printf("%s: Loop UP\n", isp->isp_name); break; case ISPASYNC_PDB_CHANGED: @@ -673,7 +740,6 @@ isp_async(isp, cmd, arg) (u_int32_t) (lp->node_wwn & 0xffffffffLL)); break; } -#ifdef ISP2100_FABRIC case ISPASYNC_CHANGE_NOTIFY: printf("%s: Name Server Database Changed\n", isp->isp_name); break; @@ -776,7 +842,6 @@ isp_async(isp, cmd, arg) lp->portid = portid; break; } -#endif default: break; } diff --git a/sys/dev/ic/isp_openbsd.h b/sys/dev/ic/isp_openbsd.h index fabd0857fe2..89f34fb2633 100644 --- a/sys/dev/ic/isp_openbsd.h +++ b/sys/dev/ic/isp_openbsd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: isp_openbsd.h,v 1.8 2000/03/05 22:20:09 mjacob Exp $ */ +/* $OpenBSD: isp_openbsd.h,v 1.9 2000/07/06 05:31:48 mjacob Exp $ */ /* * OpenBSD Specific definitions for the Qlogic ISP Host Adapter * @@ -63,7 +63,7 @@ #include <vm/pmap.h> #define ISP_PLATFORM_VERSION_MAJOR 0 -#define ISP_PLATFORM_VERSION_MINOR 9 +#define ISP_PLATFORM_VERSION_MINOR 10 #define ISP_SCSI_XFER_T struct scsi_xfer struct isposinfo { @@ -78,14 +78,28 @@ struct isposinfo { #define seed un._seed #define discovered un._discovered struct scsi_xfer *wqf, *wqt; + struct timeout rqt; }; +#define MBOX_WAIT_COMPLETE(isp) \ + { \ + int j; \ + for (j = 0; j < 60 * 2000; j++) { \ + if (isp_intr(isp) == 0) { \ + SYS_DELAY(500); \ + } \ + if (isp->isp_mboxbsy == 0) \ + break; \ + } \ + if (isp->isp_mboxbsy != 0) \ + printf("%s: mailbox timeout\n", isp->isp_name); \ + } + +#define MBOX_NOTIFY_COMPLETE(isp) isp->isp_mboxbsy = 0 + #define MAXISPREQUEST 256 -#ifdef ISP2100_FABRIC +#define ISP2100_FABRIC 1 #define ISP2100_SCRLEN 0x400 -#else -#define ISP2100_SCRLEN 0x100 -#endif #include <dev/ic/ispreg.h> #include <dev/ic/ispvar.h> @@ -160,13 +174,30 @@ struct isposinfo { #define XS_SNS_IS_VALID(xs) (xs)->error = XS_SENSE #define XS_IS_SNS_VALID(xs) ((xs)->error == XS_SENSE) -#define XS_INITERR(xs) (xs)->error = 0 +#define XS_PSTS_INWDOG 0x10000 +#define XS_PSTS_GRACE 0x20000 +#define XS_PSTS_ALL SCSI_PRIVATE + +#define XS_CMD_S_WDOG(xs) (xs)->flags |= XS_PSTS_INWDOG +#define XS_CMD_C_WDOG(xs) (xs)->flags &= ~XS_PSTS_INWDOG +#define XS_CMD_WDOG_P(xs) (((xs)->flags & XS_PSTS_INWDOG) != 0) + +#define XS_CMD_S_GRACE(xs) (xs)->flags |= XS_PSTS_GRACE +#define XS_CMD_C_GRACE(xs) (xs)->flags &= ~XS_PSTS_GRACE +#define XS_CMD_GRACE_P(xs) (((xs)->flags & XS_PSTS_GRACE) != 0) + +#define XS_CMD_S_DONE(xs) (xs)->flags |= ITSDONE +#define XS_CMD_C_DONE(xs) (xs)->flags &= ~ITSDONE +#define XS_CMD_DONE_P(xs) (((xs)->flags & ITSDONE) != 0) + +#define XS_CMD_S_CLEAR(xs) (xs)->flags &= ~XS_PSTS_ALL + +#define XS_INITERR(xs) (xs)->error = 0, XS_CMD_S_CLEAR(xs) #define XS_SETERR(xs, v) (xs)->error = v #define XS_ERR(xs) (xs)->error #define XS_NOERR(xs) (xs)->error == XS_NOERROR -#define XS_CMD_DONE(xs) (xs)->flags |= ITSDONE, scsi_done(xs) -#define XS_IS_CMD_DONE(xs) (((xs)->flags & ITSDONE) != 0) +#define XS_CMD_DONE isp_done /* * We use whether or not we're a polled command to decide about tagging. @@ -198,6 +229,7 @@ struct isposinfo { extern void isp_attach __P((struct ispsoftc *)); extern void isp_uninit __P((struct ispsoftc *)); +extern void isp_done __P((ISP_SCSI_XFER_T *)); #define ISP_UNSWIZZLE_AND_COPY_PDBP(isp, dest, src) \ @@ -218,6 +250,27 @@ extern void isp_uninit __P((struct ispsoftc *)); #define ISP_SWIZZLE_SNS_REQ(a, b) #define ISP_UNSWIZZLE_SNS_RSP(a, b, c) +#define STRNCAT strncat +static inline char *strncat(char *, const char *, size_t); +static inline char * +strncat(char *d, const char *s, size_t c) +{ + char *t = d; + + if (c) { + while (*d) + d++; + while ((*d++ = *s++)) { + if (--c == 0) { + *d = '\0'; + break; + } + } + } + return (t); +} + + #define INLINE inline #include <dev/ic/isp_inline.h> diff --git a/sys/dev/ic/isp_target.c b/sys/dev/ic/isp_target.c index bd7a4824e2b..d6b7fd14b9e 100644 --- a/sys/dev/ic/isp_target.c +++ b/sys/dev/ic/isp_target.c @@ -1,4 +1,4 @@ -/* $OpenBSD: isp_target.c,v 1.1 2000/02/20 21:22:40 mjacob Exp $ */ +/* $OpenBSD: isp_target.c,v 1.2 2000/07/06 05:31:48 mjacob Exp $ */ /* * Machine and OS Independent Target Mode Code for the Qlogic SCSI/FC adapters. * @@ -285,7 +285,7 @@ isp_lun_cmd(isp, cmd, bus, tgt, lun, opaque) el.le_in_count = DFLT_INOTIFY; if (cmd == RQSTYPE_ENABLE_LUN) { if (IS_SCSI(isp)) { - el.le_flags = LUN_TQAE; + el.le_flags = LUN_TQAE|LUN_DISAD; el.le_cdb6len = 12; el.le_cdb7len = 12; } @@ -305,10 +305,8 @@ isp_lun_cmd(isp, cmd, bus, tgt, lun, opaque) if (IS_SCSI(isp)) { el.le_tgt = tgt; el.le_lun = lun; -#ifndef ISP2100_SCCLUN - } else { + } else if (isp->isp_maxluns <= 16) { el.le_lun = lun; -#endif } if (isp_getrqentry(isp, &iptr, &optr, &outp)) { @@ -380,11 +378,11 @@ isp_target_put_atio(isp, iid, tgt, lun, ttype, tval) if (IS_FC(isp)) { atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2; atun._atio2.at_header.rqs_entry_count = 1; -#ifdef ISP2100_SCCLUN - atun._atio2.at_scclun = (uint16_t) lun; -#else - atun._atio2.at_lun = (uint8_t) lun; -#endif + if (isp->isp_maxluns > 16) { + atun._atio2.at_scclun = (u_int16_t) lun; + } else { + atun._atio2.at_lun = (u_int8_t) lun; + } atun._atio2.at_status = CT_OK; } else { atun._atio.at_header.rqs_entry_type = RQSTYPE_ATIO; @@ -436,9 +434,9 @@ isp_endcmd(struct ispsoftc *isp, void *arg, u_int32_t code, u_int32_t hdl) cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2; cto->ct_header.rqs_entry_count = 1; cto->ct_iid = aep->at_iid; -#ifndef ISP2100_SCCLUN - cto->ct_lun = aep->at_lun; -#endif + if (isp->isp_maxluns <= 16) { + cto->ct_lun = aep->at_lun; + } cto->ct_rxid = aep->at_rxid; cto->rsp.m1.ct_scsi_status = sts & 0xff; cto->ct_flags = CT2_SENDSTATUS | CT2_NO_DATA | CT2_FLAG_MODE1; @@ -596,11 +594,11 @@ isp_got_msg_fc(isp, bus, inp) MEMZERO(&msg, sizeof (msg)); msg.nt_bus = bus; msg.nt_iid = inp->in_iid; -#ifdef ISP2100_SCCLUN - msg.nt_lun = inp->in_scclun; -#else - msg.nt_lun = inp->in_lun; -#endif + if (isp->isp_maxluns > 16) { + msg.nt_lun = inp->in_scclun; + } else { + msg.nt_lun = inp->in_lun; + } msg.nt_tagval = inp->in_seqid; if (inp->in_task_flags & TASK_FLAGS_ABORT_TASK) { @@ -658,11 +656,11 @@ isp_notify_ack(isp, arg) in_fcentry_t *inp = arg; MEMCPY(storage, arg, sizeof (isphdr_t)); na->na_iid = inp->in_iid; -#ifdef ISP2100_SCCLUN - na->na_lun = inp->in_scclun; -#else - na->na_lun = inp->in_lun; -#endif + if (isp->isp_maxluns > 16) { + na->na_lun = inp->in_scclun; + } else { + na->na_lun = inp->in_lun; + } na->na_task_flags = inp->in_task_flags; na->na_seqid = inp->in_seqid; na->na_flags = NAFC_RCOUNT; @@ -672,6 +670,8 @@ isp_notify_ack(isp, arg) } else { na->na_flags = NAFC_RST_CLRD; } + na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; + na->na_header.rqs_entry_count = 1; ISP_SWIZ_NOT_ACK_FC(isp, outp, na); } else { na_entry_t *na = (na_entry_t *) storage; @@ -683,11 +683,13 @@ isp_notify_ack(isp, arg) na->na_tgt = inp->in_tgt; na->na_seqid = inp->in_seqid; if (inp->in_status == IN_RESET) { - na->na_flags = NA_RST_CLRD; + na->na_event = NA_RST_CLRD; } } else { - na->na_flags = NA_RST_CLRD; + na->na_event = NA_RST_CLRD; } + na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; + na->na_header.rqs_entry_count = 1; ISP_SWIZ_NOT_ACK(isp, outp, na); } ISP_TDQE(isp, "isp_notify_ack", (int) optr, storage); @@ -784,11 +786,13 @@ isp_handle_atio2(isp, aep) at2_entry_t *aep; { int lun; -#ifdef ISP2100_SCCLUN - lun = aep->at_scclun; -#else - lun = aep->at_lun; -#endif + + if (isp->isp_maxluns > 16) { + lun = aep->at_scclun; + } else { + lun = aep->at_lun; + } + /* * The firmware status (except for the QLTM_SVALID bit) indicates * why this ATIO was sent to us. @@ -892,12 +896,14 @@ isp_handle_ctio(isp, ct) * We sent status & command complete. */ - if ((ct->ct_flags & CT_DATAMASK) == CT_NO_DATA) { + if (ct->ct_flags & CT_SENDSTATUS) { + break; + } else if ((ct->ct_flags & CT_DATAMASK) == CT_NO_DATA) { /* * Nothing to do in this case. */ - IDPRINTF(pl, ("%s: CTIO- initiator disconnected OK\n", - isp->isp_name)); + IDPRINTF(pl, ("%s:CTIO- iid %d disconnected OK\n", + isp->isp_name, ct->ct_iid)); return; } break; @@ -1025,7 +1031,7 @@ isp_handle_ctio(isp, ct) * complete thread synchronization. */ IDPRINTF(pl, - ("%s: status CTIO complete\n", isp->isp_name)); + ("%s:status CTIO complete\n", isp->isp_name)); } else { /* * Final CTIO completed. Release DMA resources and diff --git a/sys/dev/ic/isp_target.h b/sys/dev/ic/isp_target.h index 7b86aa1de94..725a9dfb2e7 100644 --- a/sys/dev/ic/isp_target.h +++ b/sys/dev/ic/isp_target.h @@ -1,4 +1,4 @@ -/* $OpenBSD: isp_target.h,v 1.1 2000/02/20 21:22:40 mjacob Exp $ */ +/* $OpenBSD: isp_target.h,v 1.2 2000/07/06 05:31:48 mjacob Exp $ */ /* * Qlogic Target Mode Structure and Flag Definitions * @@ -71,6 +71,7 @@ typedef struct { */ #define LUN_TQAE 0x00000001 /* bit1 Tagged Queue Action Enable */ #define LUN_DSSM 0x01000000 /* bit24 Disable Sending SDP Message */ +#define LUN_DISAD 0x02000000 /* bit25 Disable autodisconnect */ #define LUN_DM 0x40000000 /* bit30 Disconnects Mandatory */ /* @@ -186,6 +187,8 @@ typedef struct { * Value for the na_event field */ #define NA_RST_CLRD 0x80 /* Clear an async event notification */ +#define NA_OK 0x01 /* Notify Acknowledge Succeeded */ +#define NA_INVALID 0x06 /* Invalid Notify Acknowledge */ #define NA2_RSVDLEN 21 typedef struct { @@ -623,7 +626,7 @@ int isp_target_notify __P((struct ispsoftc *, void *, u_int16_t *)); */ #define DFLT_CMD_CNT (RESULT_QUEUE_LEN >> 1) #define DFLT_INOTIFY (4) -int isp_lun_cmd __P((struct ispsoftc *isp, int, int, int, int, u_int32_t)); +int isp_lun_cmd __P((struct ispsoftc *, int, int, int, int, u_int32_t)); /* * General request queue 'put' routine for target mode entries. @@ -635,14 +638,14 @@ int isp_target_put_entry __P((struct ispsoftc *isp, void *)); * used for replenishing f/w resource counts. */ int -isp_target_put_atio __P((struct ispsoftc *isp, int, int, int, int, int)); +isp_target_put_atio __P((struct ispsoftc *, int, int, int, int, int)); /* * General routine to send a final CTIO for a command- used mostly for * local responses. */ int -isp_endcmd __P((struct ispsoftc *isp, void *, u_int32_t, u_int32_t)); +isp_endcmd __P((struct ispsoftc *, void *, u_int32_t, u_int32_t)); #define ECMD_SVALID 0x100 /* diff --git a/sys/dev/ic/isp_tpublic.h b/sys/dev/ic/isp_tpublic.h index a9ebe9589a8..34619b99df7 100644 --- a/sys/dev/ic/isp_tpublic.h +++ b/sys/dev/ic/isp_tpublic.h @@ -1,4 +1,4 @@ -/* $OpenBSD: isp_tpublic.h,v 1.1 2000/02/20 21:22:40 mjacob Exp $ */ +/* $OpenBSD: isp_tpublic.h,v 1.2 2000/07/06 05:31:48 mjacob Exp $ */ /* * Qlogic ISP Host Adapter Public Target Interface Structures && Routines *--------------------------------------- @@ -59,11 +59,26 @@ typedef struct { } tmd_event_t; /* - * Suggested software target mode command handling structure. + * Suggested Software Target Mode Command Handling structure. * - * The command structure is one suggested possible MD command structure, - * but since the handling of thbis is entirely in the MD layer, there - * is no requirement that it be used. + * A note about terminology: + * + * MD stands for "Machine Dependent". + * + * This driver is structured in three layers: Outer MD, core, and inner MD. + * The latter also is bus dependent (i.e., is cognizant of PCI bus issues + * as well as platform issues). + * + * + * "Outer Layer" means "Other Module" + * + * Some additional module that actually implements SCSI target command + * policy is the recipient of incoming commands and the source of the + * disposition for them. + * + * The command structure below is one suggested possible MD command structure, + * but since the handling of thbis is entirely in the MD layer, there is + * no explicit or implicit requirement that it be used. * * The cd_private tag should be used by the MD layer to keep a free list * of these structures. Code outside of this driver can then use this @@ -123,17 +138,16 @@ typedef struct { * layers must agree on the meaning of cd_data. * * The tag cd_totlen is the total data amount expected to be moved - * over the life of the command. It may be set by the MD layer, - * for example, from the datalen field of an FCP CMND IU unit. If - * it shows up in the outer layers set to zero and the CDB indicates - * data should be moved, the outer layer should set it to the amount - * expected to be moved. + * over the life of the command. It *may* be set by the MD layer, possibly + * from the datalen field of an FCP CMND IU unit. If it shows up in the outer + * layers set to zero and the CDB indicates data should be moved, the outer + * layer should set it to the amount expected to be moved. * * The tag cd_resid should be the total residual of data not transferred. * The outer layers need to set this at the begining of command processing * to equal cd_totlen. As data is successfully moved, this value is decreased. * At the end of a command, any nonzero residual indicates the number of bytes - * requested but not moved. + * requested but not moved. XXXXXXXXXXXXXXXXXXXXXXX TOO VAGUE!!! * * The tag cd_xfrlen is the length of the currently active data transfer. * This allows several interations between any outside software and the @@ -206,9 +220,10 @@ typedef struct tmd_cmd { } tmd_cmd_t; #define CDFL_BUSY 0x01 /* this command is not on a free list */ -#define CDFL_NODISC 0x02 /* disconnect not allowed */ +#define CDFL_NODISC 0x02 /* disconnects disabled */ #define CDFL_SENTSENSE 0x04 /* last action sent sense data */ -#define CDFL_ERROR 0x08 /* last action ended in error */ +#define CDFL_SENTSTATUS 0x08 /* last action sent status */ +#define CDFL_ERROR 0x10 /* last action ended in error */ #define CDFL_PRIVATE_0 0x80 /* private layer flags */ #define CDFH_SNSVALID 0x01 /* sense data valid */ @@ -238,6 +253,8 @@ typedef enum { */ typedef enum { QIN_HBA_REG=6, /* the argument is a pointer to a hba_register_t */ + QIN_ENABLE, /* the argument is a pointer to a tmd_cmd_t */ + QIN_DISABLE, /* the argument is a pointer to a tmd_cmd_t */ QIN_TMD_CONT, /* the argument is a pointer to a tmd_cmd_t */ QIN_TMD_FIN, /* the argument is a pointer to a done tmd_cmd_t */ QIN_HBA_UNREG /* the argument is a pointer to a hba_register_t */ @@ -267,6 +284,16 @@ typedef enum { * The graph looks like: * * QOUT_TMD_START -> [ QIN_TMD_CONT -> QOUT_TMD_DONE ] * -> QIN_TMD_FIN. + * + */ + +/* + * A word about ENABLE/DISABLE: the argument is a pointer to an tmd_cmd_t + * with cd_hba, cd_bus, cd_tgt and cd_lun filled out. If an error occurs + * in either enabling or disabling the described lun, cd_lflags is set + * with CDFL_ERROR. + * + * Logical unit zero must be the first enabled and the last disabled. */ /* @@ -297,5 +324,6 @@ typedef struct { char r_name[8]; int r_inst; int r_lunwidth; + int r_buswidth; void (*r_action) __P((int, void *)); } hba_register_t; diff --git a/sys/dev/ic/ispmbox.h b/sys/dev/ic/ispmbox.h index 51cc085b2b9..1d298dbd751 100644 --- a/sys/dev/ic/ispmbox.h +++ b/sys/dev/ic/ispmbox.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ispmbox.h,v 1.8 2000/02/20 21:22:41 mjacob Exp $ */ +/* $OpenBSD: ispmbox.h,v 1.9 2000/07/06 05:31:49 mjacob Exp $ */ /* * Mailbox and Queue Entry Definitions for for Qlogic ISP SCSI adapters. * @@ -118,6 +118,7 @@ /* These are for the ISP2100 FC cards */ #define MBOX_GET_LOOP_ID 0x20 +#define MBOX_GET_RESOURCE_COUNT 0x42 #define MBOX_EXEC_COMMAND_IOCB_A64 0x54 #define MBOX_INIT_FIRMWARE 0x60 #define MBOX_GET_INIT_CONTROL_BLOCK 0x61 @@ -564,7 +565,7 @@ typedef struct { u_int16_t pdb_options; u_int8_t pdb_mstate; u_int8_t pdb_sstate; -#define BITS2WORD(x) (x)[0] << 16 | (x)[3] << 8 | (x)[2] +#define BITS2WORD(x) ((x)[0] << 16 | (x)[3] << 8 | (x)[2]) u_int8_t pdb_hardaddr_bits[4]; u_int8_t pdb_portid_bits[4]; u_int8_t pdb_nodename[8]; diff --git a/sys/dev/ic/ispreg.h b/sys/dev/ic/ispreg.h index 0a7a1ae7ac2..bacf424cb8f 100644 --- a/sys/dev/ic/ispreg.h +++ b/sys/dev/ic/ispreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ispreg.h,v 1.7 2000/02/20 21:22:41 mjacob Exp $ */ +/* $OpenBSD: ispreg.h,v 1.8 2000/07/06 05:31:49 mjacob Exp $ */ /* * Machine Independent (well, as best as possible) register * definitions for Qlogic ISP SCSI adapters. @@ -225,6 +225,9 @@ #define INT_PENDING(isp, isr) (IS_FC(isp)? \ ((isr & BIU2100_ISR_RISC_INT) != 0) : ((isr & BIU_ISR_RISC_INT) != 0)) +#define INT_PENDING_MASK(isp) \ + (IS_FC(isp)? BIU2100_ISR_RISC_INT: BIU_ISR_RISC_INT) + /* BUS SEMAPHORE REGISTER */ #define BIU_SEMA_STATUS 0x0002 /* Semaphore Status Bit */ #define BIU_SEMA_LOCK 0x0001 /* Semaphore Lock Bit */ @@ -337,10 +340,15 @@ #define OUTMAILBOX6 (MBOX_BLOCK+0xC) #define OUTMAILBOX7 (MBOX_BLOCK+0xE) -#define OMBOX_OFFN(n) (MBOX_BLOCK + (n * 2)) +#define MBOX_OFF(n) (MBOX_BLOCK + ((n) << 1)) #define NMBOX(isp) \ (((((isp)->isp_type & ISP_HA_SCSI) >= ISP_HA_SCSI_1040A) || \ ((isp)->isp_type & ISP_HA_FC))? 8 : 6) +#define NMBOX_BMASK(isp) \ + (((((isp)->isp_type & ISP_HA_SCSI) >= ISP_HA_SCSI_1040A) || \ + ((isp)->isp_type & ISP_HA_FC))? 0xff : 0x3f) + +#define MAX_MAILBOX 8 /* * SXP Block Register Offsets @@ -699,26 +707,26 @@ /* Offset 5 */ /* - uint8_t bios_configuration_mode :2; - uint8_t bios_disable :1; - uint8_t selectable_scsi_boot_enable :1; - uint8_t cd_rom_boot_enable :1; - uint8_t disable_loading_risc_code :1; - uint8_t enable_64bit_addressing :1; - uint8_t unused_7 :1; + u_int8_t bios_configuration_mode :2; + u_int8_t bios_disable :1; + u_int8_t selectable_scsi_boot_enable :1; + u_int8_t cd_rom_boot_enable :1; + u_int8_t disable_loading_risc_code :1; + u_int8_t enable_64bit_addressing :1; + u_int8_t unused_7 :1; */ /* Offsets 6, 7 */ /* - uint8_t boot_lun_number :5; - uint8_t scsi_bus_number :1; - uint8_t unused_6 :1; - uint8_t unused_7 :1; - uint8_t boot_target_number :4; - uint8_t unused_12 :1; - uint8_t unused_13 :1; - uint8_t unused_14 :1; - uint8_t unused_15 :1; + u_int8_t boot_lun_number :5; + u_int8_t scsi_bus_number :1; + u_int8_t unused_6 :1; + u_int8_t unused_7 :1; + u_int8_t boot_target_number :4; + u_int8_t unused_12 :1; + u_int8_t unused_13 :1; + u_int8_t unused_14 :1; + u_int8_t unused_15 :1; */ #define ISP1080_NVRAM_HBA_ENABLE(c) ISPBSMX(c, 16, 3, 0x01) @@ -887,7 +895,7 @@ #define ISP2100_NVRAM_RETRY_COUNT(c) (c)[16] #define ISP2100_NVRAM_RETRY_DELAY(c) (c)[17] -#define ISP2100_NVRAM_NODE_NAME(c) (\ +#define ISP2100_NVRAM_PORT_NAME(c) (\ (((u_int64_t)(c)[18]) << 56) | \ (((u_int64_t)(c)[19]) << 48) | \ (((u_int64_t)(c)[20]) << 40) | \ @@ -896,8 +904,19 @@ (((u_int64_t)(c)[23]) << 16) | \ (((u_int64_t)(c)[24]) << 8) | \ (((u_int64_t)(c)[25]) << 0)) + #define ISP2100_NVRAM_HARDLOOPID(c) (c)[26] +#define ISP2100_NVRAM_NODE_NAME(c) (\ + (((u_int64_t)(c)[30]) << 56) | \ + (((u_int64_t)(c)[31]) << 48) | \ + (((u_int64_t)(c)[32]) << 40) | \ + (((u_int64_t)(c)[33]) << 32) | \ + (((u_int64_t)(c)[34]) << 24) | \ + (((u_int64_t)(c)[35]) << 16) | \ + (((u_int64_t)(c)[36]) << 8) | \ + (((u_int64_t)(c)[37]) << 0)) + #define ISP2100_NVRAM_HBA_OPTIONS(c) (c)[70] #define ISP2100_NVRAM_HBA_DISABLE(c) ISPBSMX(c, 70, 0, 0x01) #define ISP2100_NVRAM_BIOS_DISABLE(c) ISPBSMX(c, 70, 1, 0x01) diff --git a/sys/dev/ic/ispvar.h b/sys/dev/ic/ispvar.h index 09043ba3b11..b87c8e8d1e1 100644 --- a/sys/dev/ic/ispvar.h +++ b/sys/dev/ic/ispvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ispvar.h,v 1.10 2000/04/06 05:47:00 mjacob Exp $ */ +/* $OpenBSD: ispvar.h,v 1.11 2000/07/06 05:31:49 mjacob Exp $ */ /* * Soft Definitions for for Qlogic ISP SCSI adapters. * @@ -59,7 +59,7 @@ #endif #define ISP_CORE_VERSION_MAJOR 1 -#define ISP_CORE_VERSION_MINOR 13 +#define ISP_CORE_VERSION_MINOR 16 /* * Vector for bus specific code to provide specific services. @@ -76,7 +76,7 @@ struct ispmdvec { void (*dv_reset0) __P((struct ispsoftc *)); void (*dv_reset1) __P((struct ispsoftc *)); void (*dv_dregs) __P((struct ispsoftc *)); - const u_int16_t *dv_ispfw; /* ptr to f/w */ + const u_int16_t *dv_ispfw; /* ptr to f/w */ u_int16_t dv_fwlen; /* length of f/w */ u_int16_t dv_codeorg; /* code ORG for f/w */ u_int32_t dv_fwrev; /* f/w revision */ @@ -95,15 +95,7 @@ struct ispmdvec { #endif #define ISP_MAX_TARGETS(isp) (IS_FC(isp)? MAX_FC_TARG : MAX_TARGETS) -#ifdef ISP2100_SCCLUN -#define _ISP_FC_LUN(isp) 65536 -#else -#define _ISP_FC_LUN(isp) 16 -#endif -#define _ISP_SCSI_LUN(isp) \ - ((ISP_FW_REVX(isp->isp_fwrev) >= ISP_FW_REV(7, 55, 0))? 32 : 8) -#define ISP_MAX_LUNS(isp) \ - (IS_FC(isp)? _ISP_FC_LUN(isp) : _ISP_SCSI_LUN(isp)) +#define ISP_MAX_LUNS(isp) (isp)->isp_maxluns /* @@ -261,11 +253,11 @@ typedef struct { */ struct lportdb { u_int - loopid : 8, - : 4, - fabdev : 1, - roles : 2, - valid : 1; + loopid : 8, + : 4, + loggedin : 1, + roles : 2, + valid : 1; u_int32_t portid; u_int64_t node_wwn; u_int64_t port_wwn; @@ -323,12 +315,13 @@ struct ispsoftc { u_int16_t isp_maxcmds; /* max possible I/O cmds */ u_int8_t isp_type; /* HBA Chip Type */ u_int8_t isp_revision; /* HBA Chip H/W Revision */ + u_int32_t isp_maxluns; /* maximum luns supported */ u_int32_t : 4, isp_touched : 1, /* board ever seen? */ isp_fast_mttr : 1, /* fast sram */ isp_bustype : 1, /* SBus or PCI */ - isp_dogactive : 1, /* watchdog running */ + : 1, isp_dblev : 8, /* debug level */ isp_clock : 8, /* input clock */ isp_confopts : 8; /* config options */ @@ -337,16 +330,18 @@ struct ispsoftc { * Volatile state */ - volatile u_int32_t : 9, + volatile u_int32_t + isp_mboxbsy : 8, /* mailbox command active */ + : 1, isp_state : 3, isp_sendmarker : 2, /* send a marker entry */ isp_update : 2, /* update parameters */ isp_nactive : 16; /* how many commands active */ - volatile u_int16_t isp_reqodx; /* index of last ISP pickup */ volatile u_int16_t isp_reqidx; /* index of next request */ volatile u_int16_t isp_residx; /* index of next result */ volatile u_int16_t isp_lasthdls; /* last handle seed */ + volatile u_int16_t isp_mboxtmp[MAX_MAILBOX]; /* * Active commands are stored here, indexed by handle functions. |