From 3b18fa22dba8c7eb2142e175986d94e2ba76edae Mon Sep 17 00:00:00 2001 From: mjacob Date: Tue, 9 Jan 2001 03:26:19 +0000 Subject: Make some strings constant (from Bill Sommerfeld @ NetBSD). Clean up some wwn handling. Do a Register FC4 Type (so that we can work with McData switches). Allow F-port topologies to use the target range 0..125 for logging in fabric devices. We changed ISPASYNC_PDB_CHANGED to ISPASYNC_LOGGED_INOUT and now use ISPASYNC_CHANGE_NOTIFY for both loop && fabric events. --- sys/dev/ic/isp.c | 213 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 142 insertions(+), 71 deletions(-) diff --git a/sys/dev/ic/isp.c b/sys/dev/ic/isp.c index ef4c101a4dd..727e1d6e654 100644 --- a/sys/dev/ic/isp.c +++ b/sys/dev/ic/isp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: isp.c,v 1.18 2000/12/06 01:07:21 mjacob Exp $ */ +/* $OpenBSD: isp.c,v 1.19 2001/01/09 03:26:18 mjacob Exp $ */ /* * Machine and OS Independent (well, as best as possible) * code for the Qlogic ISP SCSI adapters. @@ -64,43 +64,43 @@ /* * Local static data */ -static char *warnlun = +static const char warnlun[] = "WARNING- cannot determine Expanded LUN capability- limiting to one LUN"; -static char *portshift = +static const char portshift[] = "Target %d Loop ID 0x%x (Port 0x%x) => Loop 0x%x (Port 0x%x)"; -static char *portdup = +static const char portdup[] = "Target %d duplicates Target %d- killing off both"; -static char *retained = +static const char retained[] = "Retaining Loop ID 0x%x for Target %d (Port 0x%x)"; #ifdef ISP2100_FABRIC -static char *lretained = +static const char lretained[] = "Retained login of Target %d (Loop ID 0x%x) Port 0x%x"; -static char *plogout = +static const char plogout[] = "Logging out Target %d at Loop ID 0x%x (Port 0x%x)"; -static char *plogierr = +static const char plogierr[] = "Command Error in PLOGI for Port 0x%x (0x%x)"; -static char *nopdb = +static const char nopdb[] = "Could not get PDB for Device @ Port 0x%x"; -static char *pdbmfail1 = +static const char pdbmfail1[] = "PDB Loop ID info for Device @ Port 0x%x does not match up (0x%x)"; -static char *pdbmfail2 = +static const char pdbmfail2[] = "PDB Port info for Device @ Port 0x%x does not match up (0x%x)"; -static char *ldumped = +static const char ldumped[] = "Target %d (Loop ID 0x%x) Port 0x%x dumped after login info mismatch"; #endif -static char *notresp = +static const char notresp[] = "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d"; -static char *xact1 = +static const char xact1[] = "HBA attempted queued transaction with disconnect not set for %d.%d.%d"; -static char *xact2 = +static const char xact2[] = "HBA attempted queued transaction to target routine %d on target %d bus %d"; -static char *xact3 = +static const char xact3[] = "HBA attempted queued cmd for %d.%d.%d when queueing disabled"; -static char *pskip = +static const char pskip[] = "SCSI phase skipped for target %d.%d.%d"; -static char *topology = +static const char topology[] = "Loop ID %d, AL_PA 0x%x, Port ID 0x%x, Loop State 0x%x, Topology '%s'"; -static char *finmsg = +static const char finmsg[] = "(%d.%d.%d): FIN dl%d resid%d STS 0x%x SKEY %c XS_ERR=0x%x"; /* * Local function prototypes. @@ -123,6 +123,7 @@ static int isp_same_lportdb __P((struct lportdb *, struct lportdb *)); static int isp_pdb_sync __P((struct ispsoftc *, int)); #ifdef ISP2100_FABRIC static int isp_scan_fabric __P((struct ispsoftc *)); +static void isp_register_fc4_type __P((struct ispsoftc *)); #endif static void isp_fw_state __P((struct ispsoftc *)); static void isp_mboxcmd __P((struct ispsoftc *, mbreg_t *, int)); @@ -150,7 +151,7 @@ isp_reset(isp) { mbreg_t mbs; int loops, i, touched, dodnld = 1; - char *revname; + char *revname = "????"; isp->isp_state = ISP_NILSTATE; @@ -186,7 +187,7 @@ isp_reset(isp) */ ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); mbs.param[0] = MBOX_ABOUT_FIRMWARE; - isp_mboxcmd(isp, &mbs, MBLOGNONE); + isp_mboxcmd(isp, &mbs, MBOX_COMMAND_ERROR); /* * This *shouldn't* fail..... */ @@ -207,13 +208,12 @@ isp_reset(isp) ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); if (IS_FC(isp)) { - revname = "2X00"; switch (isp->isp_type) { case ISP_HA_FC_2100: - revname[1] = '1'; + revname = "2100"; break; case ISP_HA_FC_2200: - revname[1] = '2'; + revname = "2200"; break; default: break; @@ -229,7 +229,7 @@ isp_reset(isp) * XXX: Should probably do some bus sensing. */ } else if (IS_ULTRA2(isp)) { - static char *m = "bus %d is in %s Mode"; + static const char m[] = "bus %d is in %s Mode"; u_int16_t l; sdparam *sdp = isp->isp_param; @@ -729,10 +729,12 @@ isp_init(isp) if (IS_DUALBUS(isp)) { isp_setdfltparm(isp, 1); } - if (IS_FC(isp)) { - isp_fibre_init(isp); - } else { - isp_scsi_init(isp); + if ((isp->isp_confopts & ISP_CFG_NOINIT) == 0) { + if (IS_FC(isp)) { + isp_fibre_init(isp); + } else { + isp_scsi_init(isp); + } } } @@ -1288,16 +1290,16 @@ isp_fclink_test(isp, usdelay) */ enano = NANOTIME_SUB(&hrb, &hra); + isp_prt(isp, ISP_LOGDEBUG3, "usec%d: 0x%lx->0x%lx enano %lu", + count, (long) GET_NANOSEC(&hra), (long) GET_NANOSEC(&hrb), + (enano > ((u_int64_t)0xffffffff))? 0xffffffff : + (unsigned long) (enano & 0xffffffff)); + /* * If the elapsed time is less than 1 millisecond, * delay a period of time up to that millisecond of * waiting. - */ - isp_prt(isp, ISP_LOGDEBUG3, "usec%d: 0x%lx->0x%lx enano %u", - count, (long) GET_NANOSEC(&hra), (long) GET_NANOSEC(&hrb), - enano); - - /* + * * This peculiar code is an attempt to try and avoid * invoking u_int64_t math support functions for some * platforms where linkage is a problem. @@ -1385,19 +1387,12 @@ isp_fclink_test(isp, usdelay) 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 + isp_register_fc4_type(isp); } else #endif { fcp->isp_portid = mbs.param[2]; fcp->isp_onfabric = 0; -#if 0 - isp->isp_rfabric = 0; -#endif fcp->portdb[FL_PORT_ID].valid = 0; } @@ -1454,7 +1449,7 @@ isp_pdb_sync(isp, target) struct lportdb *lp, *tport; fcparam *fcp = isp->isp_param; isp_pdb_t pdb; - int loopid, prange, lim; + int loopid, frange, prange, lim; #ifdef ISP2100_FABRIC /* @@ -1472,12 +1467,13 @@ isp_pdb_sync(isp, target) switch (fcp->isp_topo) { case TOPO_F_PORT: case TOPO_PTP_STUB: - prange = 0; + frange = prange = 0; break; case TOPO_N_PORT: prange = 2; break; default: + frange = FC_SNS_ID+1; prange = FL_PORT_ID; break; } @@ -1712,7 +1708,7 @@ isp_pdb_sync(isp, target) /* * Tell the outside world we've arrived. */ - (void) isp_async(isp, ISPASYNC_PDB_CHANGED, &i); + (void) isp_async(isp, ISPASYNC_LOGGED_INOUT, &i); } /* @@ -1727,7 +1723,7 @@ isp_pdb_sync(isp, target) * Tell the outside world we've gone away. */ loopid = lp - fcp->portdb; - (void) isp_async(isp, ISPASYNC_PDB_CHANGED, &loopid); + (void) isp_async(isp, ISPASYNC_LOGGED_INOUT, &loopid); MEMZERO((void *) lp, sizeof (*lp)); } @@ -1735,27 +1731,39 @@ isp_pdb_sync(isp, target) /* * Now log in any fabric devices */ - for (lp = &fcp->portdb[FC_SNS_ID+1]; + for (lp = &fcp->portdb[frange]; lp < &fcp->portdb[MAX_FC_TARG]; lp++) { u_int32_t portid; mbreg_t mbs; + loopid = lp - fcp->portdb; + if (loopid >= FL_PORT_ID && loopid <= FC_SNS_ID) { + continue; + } + /* * Anything here? */ - if (lp->port_wwn == 0) + if (lp->port_wwn == 0) { continue; + } /* * Don't try to log into yourself. */ - if ((portid = lp->portid) == fcp->isp_portid) + 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.. + * + * Unfortunately, our charming Qlogic f/w has decided to + * return a valid port database entry for a fabric device + * that has, in fact, gone away. And it hangs trying to + * log it out. */ if (lp->loggedin && isp_getpdb(isp, lp->loopid, &pdb) == 0) { @@ -1916,7 +1924,7 @@ isp_pdb_sync(isp, target) if (lp->node_wwn && lp->port_wwn) { lp->valid = 1; loopid = lp - fcp->portdb; - (void) isp_async(isp, ISPASYNC_PDB_CHANGED, &loopid); + (void) isp_async(isp, ISPASYNC_LOGGED_INOUT, &loopid); continue; } dump_em: @@ -1996,6 +2004,39 @@ isp_scan_fabric(isp) */ return (0); } + +static void +isp_register_fc4_type(struct ispsoftc *isp) +{ + fcparam *fcp = isp->isp_param; + sns_screq_t *reqp; + mbreg_t mbs; + + reqp = (sns_screq_t *) fcp->isp_scratch; + MEMZERO((void *) reqp, SNS_RFT_REQ_SIZE); + reqp->snscb_rblen = SNS_RFT_RESP_SIZE >> 1; + reqp->snscb_addr[RQRSP_ADDR0015] = DMA_LSW(fcp->isp_scdma + 0x100); + reqp->snscb_addr[RQRSP_ADDR1631] = DMA_MSW(fcp->isp_scdma + 0x100); + reqp->snscb_sblen = 22; + reqp->snscb_data[0] = SNS_RFT; + reqp->snscb_data[4] = fcp->isp_portid & 0xffff; + reqp->snscb_data[5] = (fcp->isp_portid >> 16) & 0xff; + reqp->snscb_data[6] = 0x100; /* SCS - FCP */ +#if 0 + reqp->snscb_data[6] |= 20; /* ISO/IEC 8802-2 LLC/SNAP */ +#endif + ISP_SWIZZLE_SNS_REQ(isp, reqp); + mbs.param[0] = MBOX_SEND_SNS; + mbs.param[1] = SNS_RFT_REQ_SIZE >> 1; + mbs.param[2] = DMA_MSW(fcp->isp_scdma); + mbs.param[3] = DMA_LSW(fcp->isp_scdma); + mbs.param[6] = 0; + mbs.param[7] = 0; + isp_mboxcmd(isp, &mbs, MBLOGALL); + if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { + isp_prt(isp, ISP_LOGINFO, "Register FC4 types succeeded"); + } +} #endif /* * Start a command. Locking is assumed done in the caller. @@ -2051,9 +2092,13 @@ isp_start(xs) #if defined(ISP2100_FABRIC) /* * If we're not on a Fabric, we can't have a target - * above FL_PORT_ID-1. If we're on a fabric and - * connected as an F-port, we can't have a target - * less than FC_SNS_ID+1. + * above FL_PORT_ID-1. + * + * If we're on a fabric and *not* connected as an F-port, + * we can't have a target less than FC_SNS_ID+1. This + * keeps us from having to sort out the difference between + * local public loop devices and those which we might get + * from a switch's database. */ if (fcp->isp_onfabric == 0) { if (target >= FL_PORT_ID) { @@ -2065,7 +2110,7 @@ isp_start(xs) XS_SETERR(xs, HBA_SELTIMEOUT); return (CMD_COMPLETE); } - if (fcp->isp_topo == TOPO_F_PORT && + if (fcp->isp_topo != TOPO_F_PORT && target < FL_PORT_ID) { XS_SETERR(xs, HBA_SELTIMEOUT); return (CMD_COMPLETE); @@ -2442,10 +2487,11 @@ isp_control(isp, ctl, arg) break; } isp_init(isp); - if (isp->isp_state != ISP_INITSTATE) { - break; + if ((isp->isp_confopts & ISP_CFG_NOINIT) == 0) { + if (isp->isp_state == ISP_INITSTATE) { + isp->isp_state = ISP_RUNSTATE; + } } - isp->isp_state = ISP_RUNSTATE; } return (0); } @@ -2531,7 +2577,7 @@ isp_intr(arg) int obits, i = 0; if ((obits = isp->isp_mboxbsy) != 0) { isp->isp_mboxtmp[i++] = mbox; - for (i = 1; i < 8; i++) { + for (i = 1; i < MAX_MAILBOX; i++) { if ((obits & (1 << i)) == 0) { continue; } @@ -3036,16 +3082,16 @@ isp_parse_async(isp, mbox) isp->isp_sendmarker = 1; FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD; isp_mark_getpdb_all(isp); - isp_prt(isp, ISP_LOGINFO, "Port Database Changed"); + isp_async(isp, ISPASYNC_CHANGE_NOTIFY, (void *) 0); break; case ASYNC_CHANGE_NOTIFY: - isp_mark_getpdb_all(isp); /* * Not correct, but it will force us to rescan the loop. */ FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD; - isp_async(isp, ISPASYNC_CHANGE_NOTIFY, NULL); + isp_mark_getpdb_all(isp); + isp_async(isp, ISPASYNC_CHANGE_NOTIFY, (void *) 1); break; case ASYNC_PTPMODE: @@ -4263,6 +4309,8 @@ isp_setdfltparm(isp, channel) if (IS_FC(isp)) { fcparam *fcp = (fcparam *) isp->isp_param; + int nvfail; + fcp += channel; if (fcp->isp_gotdparms) { return; @@ -4294,16 +4342,39 @@ isp_setdfltparm(isp, channel) fcp->isp_fwoptions &= ~ICBOPT_EXTENDED; /* - * Now try and read NVRAM + * Now try and read NVRAM unless told to not do so. + * This will set fcparam's isp_nodewwn && isp_portwwn. */ - if ((isp->isp_confopts & (ISP_CFG_NONVRAM|ISP_CFG_OWNWWN)) || - (isp_read_nvram(isp))) { - isp_prt(isp, ISP_LOGINFO, - "Node WWN 0x%08x%08x, Port WWN 0x%08x%08x", - (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)); + if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) { + nvfail = isp_read_nvram(isp); + if (nvfail) + isp->isp_confopts |= ISP_CFG_NONVRAM; + } else { + nvfail = 1; + } + /* + * Set node && port to override platform set defaults + * unless the nvram read failed (or none was done), + * or the platform code wants to use what had been + * set in the defaults. + */ + if (nvfail || (isp->isp_confopts & ISP_CFG_OWNWWN)) { + isp_prt(isp, ISP_LOGCONFIG, + "Using Node WWN 0x%08x%08x, Port WWN 0x%08x%08x", + (u_int32_t) (DEFAULT_NODEWWN(isp) >> 32), + (u_int32_t) (DEFAULT_NODEWWN(isp) & 0xffffffff), + (u_int32_t) (DEFAULT_PORTWWN(isp) >> 32), + (u_int32_t) (DEFAULT_PORTWWN(isp) & 0xffffffff)); + isp->isp_confopts |= ISP_CFG_OWNWWN; + ISP_NODEWWN(isp) = DEFAULT_NODEWWN(isp); + ISP_PORTWWN(isp) = DEFAULT_PORTWWN(isp); + } else { + /* + * We always start out with values derived + * from NVRAM or our platform default. + */ + ISP_NODEWWN(isp) = fcp->isp_nodewwn; + ISP_PORTWWN(isp) = fcp->isp_portwwn; } return; } -- cgit v1.2.3