diff options
| author | mjacob <mjacob@NetBSD.org> | 1999-07-05 20:31:35 +0000 |
|---|---|---|
| committer | mjacob <mjacob@NetBSD.org> | 1999-07-05 20:31:35 +0000 |
| commit | f428cf36fa402fef89c6bd1b2563f4acfbcc4a61 (patch) | |
| tree | 1a33edec8c103682140766f09862612bdc7e6a4e /sys/dev | |
| parent | 3bb408eb05a15ec2e65ede5ff8b0aed88644c396 (diff) | |
Change to approved NASA/Ames copyright. Add Fabric support. Fix SCCLUN support.
Add code that tries to track LoopID shifting.
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/ic/isp.c | 878 | ||||
| -rw-r--r-- | sys/dev/ic/isp_netbsd.c | 169 | ||||
| -rw-r--r-- | sys/dev/ic/isp_netbsd.h | 62 | ||||
| -rw-r--r-- | sys/dev/ic/ispmbox.h | 108 | ||||
| -rw-r--r-- | sys/dev/ic/ispreg.h | 43 | ||||
| -rw-r--r-- | sys/dev/ic/ispvar.h | 146 |
6 files changed, 1024 insertions, 382 deletions
diff --git a/sys/dev/ic/isp.c b/sys/dev/ic/isp.c index 970854e8587..1bb34aaf414 100644 --- a/sys/dev/ic/isp.c +++ b/sys/dev/ic/isp.c @@ -1,36 +1,35 @@ -/* $NetBSD: isp.c,v 1.36 1999/05/12 18:59:23 mjacob Exp $ */ -/* release_5_11_99 */ +/* $NetBSD: isp.c,v 1.37 1999/07/05 20:31:35 mjacob Exp $ */ +/* release_6_5_99 */ /* - * Machine and OS Independent (well, as best as possible) - * code for the Qlogic ISP SCSI adapters. - * - * Copyright (c) 1997, 1998 by Matthew Jacob - * NASA/Ames Research Center + * Copyright (C) 1997, 1998, 1999 National Aeronautics & Space Administration * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. + * derived from this software without specific prior written permission * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Machine and OS Independent (well, as best as possible) + * code for the Qlogic ISP SCSI adapters. + * Matthew Jacob <mjacob@nas.nasa.gov> */ /* @@ -113,7 +112,13 @@ static void isp_scsi_channel_init __P((struct ispsoftc *, int)); static void isp_fibre_init __P((struct ispsoftc *)); static void isp_mark_getpdb_all __P((struct ispsoftc *)); static int isp_getpdb __P((struct ispsoftc *, int, isp_pdb_t *)); +static u_int64_t isp_get_portname __P((struct ispsoftc *, int, int)); static int isp_fclink_test __P((struct ispsoftc *, int)); +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 *)); +#endif static void isp_fw_state __P((struct ispsoftc *)); static void isp_dumpregs __P((struct ispsoftc *, const char *)); static void isp_dumpxflist __P((struct ispsoftc *)); @@ -184,27 +189,32 @@ isp_reset(isp) DISABLE_INTS(isp); /* - * Put it into PAUSE mode. + * Put the board into PAUSE mode. */ ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); -#if 0 - /* - * Do a little register testing. - */ - ISP_WRITE(isp, CDMA_COUNT, 0); - ISP_WRITE(isp, CDMA_ADDR0, 0xdead); - ISP_WRITE(isp, CDMA_ADDR1, 0xbeef); - ISP_WRITE(isp, CDMA_ADDR2, 0xffff); - ISP_WRITE(isp, CDMA_ADDR3, 0x1111); - PRINTF("%s: (0,dead,beef,ffff,1111):\n", isp->isp_name); - PRINTF("0x%x 0x%x 0x%x 0x%x 0x%x\n", ISP_READ(isp, CDMA_COUNT), - ISP_READ(isp, CDMA_ADDR0), ISP_READ(isp, CDMA_ADDR1), - ISP_READ(isp, CDMA_ADDR2), ISP_READ(isp, CDMA_ADDR3)); -#endif - if (IS_FC(isp)) { - revname = "2100"; + revname = "2X00"; + switch (isp->isp_type) { + case ISP_HA_FC_2100: + revname[1] = '1'; + break; + case ISP_HA_FC_2200: + revname[1] = '2'; + /* + * Resident firmware for the 2200 appears to have + * SCCLUN enabled. + */ +#ifndef ISP2100_SCCLUN + if (isp->isp_mdvec->dv_fwlen == 0) { + PRINTF("%s: WARNING- using resident f/w without" + " SCCLUN support defined\n", isp->isp_name); + } +#endif + break; + default: + break; + } } else if (IS_12X0(isp)) { revname = "12X0"; isp->isp_clock = 60; @@ -494,7 +504,7 @@ again: return; } - if (isp->isp_type & ISP_HA_SCSI) { + if (IS_SCSI(isp)) { mbs.param[0] = MBOX_MAILBOX_REG_TEST; mbs.param[1] = 0xdead; mbs.param[2] = 0xbeef; @@ -960,7 +970,7 @@ isp_fibre_init(isp) fcparam *fcp; isp_icb_t *icbp; mbreg_t mbs; - int count, loopid; + int loopid; fcp = isp->isp_param; @@ -973,21 +983,11 @@ isp_fibre_init(isp) * best way to figure this out XXX */ #ifndef __i386__ - loopid = DEFAULT_LOOPID; + loopid = DEFAULT_LOOPID(isp); #else loopid = fcp->isp_loopid; #endif -#if defined(ISP2100_FABRIC) && defined(ISP2100_SCCLUN) - PRINTF("%s: Fabric Support, Expanded Lun Support\n", isp->isp_name); -#endif -#if defined(ISP2100_FABRIC) && !defined(ISP2100_SCCLUN) - PRINTF("%s: Fabric Support\n", isp->isp_name); -#endif -#if !defined(ISP2100_FABRIC) && defined(ISP2100_SCCLUN) - PRINTF("%s: Expanded Lun Support\n", isp->isp_name); -#endif - icbp = (isp_icb_t *) fcp->isp_scratch; MEMZERO(icbp, sizeof (*icbp)); @@ -997,18 +997,34 @@ isp_fibre_init(isp) #else fcp->isp_fwoptions = 0; #endif - fcp->isp_fwoptions |= ICBOPT_INI_ADISC|ICBOPT_FAIRNESS; + fcp->isp_fwoptions |= ICBOPT_FAIRNESS; fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE; fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS; -#ifndef ISP_NO_FASTPOST_FC - fcp->isp_fwoptions |= ICBOPT_FAST_POST; -#endif -#ifdef CHECKME - fcp->isp_fwoptions |= ICBOPT_USE_PORTNAME; -#endif #ifdef ISP2100_FABRIC +#if 0 + /* + * Do not use FULL LOGIN- it resets the loop too much. + */ fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN; #endif +#endif +#if 0 + /* + * Don't use this either + */ + fcp->isp_fwoptions |= ICBOPT_INI_ADISC; +#endif +#ifndef ISP_NO_FASTPOST_FC + fcp->isp_fwoptions |= ICBOPT_FAST_POST; +#endif + + if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX) + fcp->isp_fwoptions |= ICBOPT_FULL_DUPLEX; + + /* + * We don't set ICBOPT_PORTNAME because we want our + * Node Name && Port Names to be distinct. + */ icbp->icb_fwoptions = fcp->isp_fwoptions; icbp->icb_maxfrmlen = fcp->isp_maxfrmlen; @@ -1019,7 +1035,7 @@ isp_fibre_init(isp) icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN; } icbp->icb_maxalloc = fcp->isp_maxalloc; - if (icbp->icb_maxalloc < 16) { + if (icbp->icb_maxalloc < 1) { PRINTF("%s: bad maximum allocation (%d)- using 16\n", isp->isp_name, fcp->isp_maxalloc); icbp->icb_maxalloc = 16; @@ -1028,21 +1044,37 @@ isp_fibre_init(isp) if (icbp->icb_execthrottle < 1) { PRINTF("%s: bad execution throttle of %d- using 16\n", isp->isp_name, fcp->isp_execthrottle); - icbp->icb_execthrottle = 16; + icbp->icb_execthrottle = ICB_DFLT_THROTTLE; } icbp->icb_retry_delay = fcp->isp_retry_delay; icbp->icb_retry_count = fcp->isp_retry_count; icbp->icb_hardaddr = loopid; - if (fcp->isp_wwn) { - MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_wwn); - if (icbp->icb_fwoptions & ICBOPT_USE_PORTNAME) { - u_int64_t portname = fcp->isp_wwn | (2LL << 56); - MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, portname); + 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); } } else { fcp->isp_fwoptions &= ~(ICBOPT_USE_PORTNAME|ICBOPT_FULL_LOGIN); } + icbp->icb_rqstqlen = RQUEST_QUEUE_LEN; icbp->icb_rsltqlen = RESULT_QUEUE_LEN; icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_LSW(isp->isp_rquest_dma); @@ -1051,7 +1083,7 @@ isp_fibre_init(isp) icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_MSW(isp->isp_result_dma); MemoryBarrier(); - for (count = 0; count < 10; count++) { + for (;;) { mbs.param[0] = MBOX_INIT_FIRMWARE; mbs.param[1] = 0; mbs.param[2] = DMA_MSW(fcp->isp_scdma); @@ -1060,32 +1092,19 @@ isp_fibre_init(isp) mbs.param[5] = 0; mbs.param[6] = 0; mbs.param[7] = 0; - isp_mboxcmd(isp, &mbs); - - switch (mbs.param[0]) { - case MBOX_COMMAND_COMPLETE: - count = 10; - break; - case ASYNC_PDB_CHANGED: - isp_mark_getpdb_all(isp); - /* FALL THROUGH */ - case ASYNC_LIP_OCCURRED: - case ASYNC_LOOP_UP: - case ASYNC_LOOP_DOWN: - case ASYNC_LOOP_RESET: - case ASYNC_CHANGE_NOTIFY: - if (count > 9) { - PRINTF("%s: too many retries to get going- " - "giving up\n", isp->isp_name); - return; + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + PRINTF("%s: INIT FIRMWARE failed (code 0x%x)\n", + isp->isp_name, mbs.param[0]); + if (mbs.param[0] & 0xc000) { + SYS_DELAY(1000); + continue; } - break; - default: - PRINTF("%s: INIT FIRMWARE failed\n", isp->isp_name); return; } + break; } + isp->isp_reqidx = isp->isp_reqodx = 0; isp->isp_residx = 0; isp->isp_sendmarker = 1; @@ -1116,10 +1135,10 @@ static void isp_mark_getpdb_all(isp) struct ispsoftc *isp; { - isp_pdb_t *p; fcparam *fcp = (fcparam *) isp->isp_param; - for (p = &fcp->isp_pdb[0]; p < &fcp->isp_pdb[MAX_FC_TARG]; p++) { - p->pdb_options = INVALID_PDB_OPTIONS; + int i; + for (i = 0; i < MAX_FC_TARG; i++) { + fcp->portdb[i].valid = 0; } } @@ -1131,6 +1150,7 @@ isp_getpdb(isp, id, pdbp) { fcparam *fcp = (fcparam *) isp->isp_param; mbreg_t mbs; + mbs.param[0] = MBOX_GET_PORT_DB; mbs.param[1] = id << 8; mbs.param[2] = DMA_MSW(fcp->isp_scdma); @@ -1155,8 +1175,8 @@ isp_getpdb(isp, id, pdbp) return (-1); case MBOX_COMMAND_PARAM_ERROR: /* Not Logged In */ - IDPRINTF(3, ("%s: Comand Param Error on Get Port Database\n", - isp->isp_name)); + IDPRINTF(3, ("%s: Param Error on Get Port Database for id %d\n", + isp->isp_name, id)); return (-1); default: PRINTF("%s: error 0x%x getting port database for ID %d\n", @@ -1166,6 +1186,34 @@ isp_getpdb(isp, id, pdbp) return (0); } +static u_int64_t +isp_get_portname(isp, loopid, nodename) + struct ispsoftc *isp; + int loopid; + int nodename; +{ + u_int64_t wwn = 0; + mbreg_t mbs; + + mbs.param[0] = MBOX_GET_PORT_NAME; + mbs.param[1] = loopid << 8; + if (nodename) + mbs.param[1] |= 1; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { + wwn = + (((u_int64_t)(mbs.param[2] & 0xff)) << 56) | + (((u_int64_t)(mbs.param[2] >> 8)) << 48) | + (((u_int64_t)(mbs.param[3] & 0xff)) << 40) | + (((u_int64_t)(mbs.param[3] >> 8)) << 32) | + (((u_int64_t)(mbs.param[6] & 0xff)) << 24) | + (((u_int64_t)(mbs.param[6] >> 8)) << 16) | + (((u_int64_t)(mbs.param[7] & 0xff)) << 8) | + (((u_int64_t)(mbs.param[7] >> 8))); + } + return (wwn); +} + /* * Make sure we have good FC link and know our Loop ID. */ @@ -1179,7 +1227,9 @@ isp_fclink_test(isp, waitdelay) int count; u_int8_t lwfs; fcparam *fcp; - +#if defined(ISP2100_FABRIC) + isp_pdb_t pdb; +#endif fcp = isp->isp_param; /* @@ -1217,13 +1267,435 @@ isp_fclink_test(isp, waitdelay) return (-1); } fcp->isp_loopid = mbs.param[1]; + + /* + * 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) + if (isp_getpdb(isp, FL_PORT_ID, &pdb) == 0) { + fcp->isp_portid = mbs.param[2] | (((int)mbs.param[3]) << 16); + fcp->isp_onfabric = 1; + PRINTF("%s: Loop ID %d, AL_PA 0x%x, Port ID 0x%x\n", + isp->isp_name, fcp->isp_loopid, fcp->isp_alpa, + fcp->isp_portid); + + /* + * Make sure we're logged out of all fabric devices. + */ + 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); + } + } else +#endif PRINTF("%s: Loop ID %d, ALPA 0x%x\n", isp->isp_name, fcp->isp_loopid, fcp->isp_alpa); + fcp->loop_seen_once = 1; return (0); +} + +/* + * Compare two local port db entities and return 1 if they're the same, else 0. + */ + +static int +isp_same_lportdb(a, b) + struct lportdb *a, *b; +{ + /* + * We decide two lports are the same if they have non-zero and + * identical port WWNs and identical loop IDs. + */ + + if (a->port_wwn == 0 || a->port_wwn != b->port_wwn || + a->loopid != b->loopid) { + return (0); + } else { + return (1); + } +} + +/* + * Synchronize our soft copy of the port database with what the f/w thinks + * (with a view toward possibly for a specific target....) + */ + +static int +isp_pdb_sync(isp, target) + struct ispsoftc *isp; + int target; +{ + struct lportdb *lp, tport[FL_PORT_ID]; + fcparam *fcp = isp->isp_param; + isp_pdb_t pdb; + int loopid, lim; + +target = target; + +#ifdef ISP2100_FABRIC + /* + * XXX: If we do this *after* building up our local port database, + * XXX: the commands simply don't work. + */ + /* + * (Re)discover all fabric devices + */ + if (fcp->isp_onfabric) + (void) isp_scan_fabric(isp); +#endif + /* + * Run through the local loop ports and get port database info + * for each loop ID. + * + * There's a somewhat unexplained situation where the f/w passes back + * the wrong database entity- if that happens, just restart (up to + * FL_PORT_ID times). + */ + for (lim = loopid = 0; loopid < FL_PORT_ID; loopid++) { + /* + * make sure the temp port database is clean... + */ + lp = &tport[loopid]; + MEMZERO((void *) lp, sizeof (*lp)); + + lp->node_wwn = isp_get_portname(isp, loopid, 1); + if (lp->node_wwn == 0) + continue; + lp->port_wwn = isp_get_portname(isp, loopid, 0); + if (lp->port_wwn == 0) { + lp->node_wwn = 0; + continue; + } + /* + * Get an entry.... + */ + if (isp_getpdb(isp, loopid, &pdb) != 0) { + continue; + } + /* + * If the returned database element doesn't match what we + * asked for, restart the process entirely (up to a point...). + */ + if (pdb.pdb_loopid != loopid) { + IDPRINTF(0, ("%s: wankage (%d != %d)\n", + isp->isp_name, pdb.pdb_loopid, loopid)); + loopid = 0; + if (lim++ < FL_PORT_ID) { + continue; + } + PRINTF("%s: giving up on synchronizing the port " + "database\n", isp->isp_name); + return (-1); + } + /* + * Save the pertinent info locally. + */ + 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; + /* + * Do a quick check to see whether this matches the saved port + * database for the same loopid. We do this here to save + * searching later (if possible). Note that this fails over + * time as things shuffle on the loop- we get the current + * loop state (where loop id as an index matches loop id in + * use) and then compare it to our saved database which + * never shifts. + */ + if (isp_same_lportdb(lp, &fcp->portdb[target])) { + lp->valid = 1; + } + } + + /* + * If we get this far, we've settled our differences with the f/w + * and we can say that the loop state is ready. + */ + fcp->isp_loopstate = LOOP_READY; + + /* + * 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++) { + int i; + + /* + * While we're at it, clear the valid bit for the saved entry + * that coincidentally is at this same index. + */ + fcp->portdb[loopid].valid = 0; + + /* + * If we don't have a non-zero Port WWN, we're not here. + */ + if (tport[loopid].port_wwn == 0) { + continue; + } + + /* + * If we've already marked our tmp copy as valid, + * this means that we've decided that it's the + * same as our saved data base. This does not include + * the 'valid' marking though so we have to turn it + * back on. + */ + if (tport[loopid].valid) { +IDPRINTF(0, ("%s: loopid %d already valid\n", isp->isp_name, loopid)); + fcp->portdb[loopid].valid = 1; + continue; + } + + /* + * For the purposes of deciding whether this is the + * 'same' device or not, we only search for an identical + * Port WWN. Node WWNs may or may not be the same as + * the Port WWN, and there may be multiple different + * Port WWNs with the same Node WWN. It would be chaos + * to have multiple identical Port WWNs, so we don't + * allow that. + */ + + for (i = 0; i < FL_PORT_ID; i++) { + int j; + if (fcp->portdb[i].port_wwn == 0) + continue; + if (fcp->portdb[i].port_wwn != tport[loopid].port_wwn) + continue; + /* + * We found this WWN elsewhere- it's changed + * loopids then. We don't change it's actual + * position in our cached port database- we + * just change the actual loop ID we'd use. + */ + if (fcp->portdb[i].loopid != loopid) { + PRINTF("%s: Target ID %d (0x%x) was loopid 0x%x" + " and is now loopid 0x%x\n", isp->isp_name, + i, i, fcp->portdb[i].loopid, loopid); + } + fcp->portdb[i].loopid = loopid; + fcp->portdb[i].valid = 1; + + /* + * Now make sure this Port WWN doesn't exist elsewhere + * in the port database. + */ + for (j = i+1; j < FL_PORT_ID; j++) { + if (fcp->portdb[i].port_wwn != + fcp->portdb[j].port_wwn) { + continue; + } + PRINTF("%s: Target ID %d Duplicates Target ID " + "%d- killing off both\n", + isp->isp_name, j, i); + /* + * Invalidate the 'old' *and* 'new' ones. + * This is really harsh and not quite right, + * but if this happens, we really don't know + * who is what at this point. + */ + fcp->portdb[i].valid = 0; + fcp->portdb[j].valid = 0; + } + break; + } + + /* + * If we didn't traverse the entire port database, + * then we found (and remapped) an existing entry. + * No need to notify anyone- go for the next one. + */ + if (i < FL_PORT_ID) { + continue; + } + + /* + * We've not found this Port WWN anywhere. It's a new entry. + * See if we can leave it where it is (with target == loopid). + */ + if (fcp->portdb[loopid].port_wwn != 0) { + for (lim = 0; lim < FL_PORT_ID; lim++) { + if (fcp->portdb[lim].port_wwn == 0) + break; + } + /* "Cannot Happen" */ + if (lim == FL_PORT_ID) { + PRINTF("%s: remap overflow?\n", isp->isp_name); + continue; + } + i = lim; + } else { + i = loopid; + } + + /* + * NB: The actual loopid we use here is loopid- we may + * in fact be at a completely different index (target). + */ + fcp->portdb[i].loopid = loopid; + fcp->portdb[i].port_wwn = tport[loopid].port_wwn; + fcp->portdb[i].node_wwn = tport[loopid].node_wwn; + fcp->portdb[i].roles = tport[loopid].roles; + fcp->portdb[i].portid = tport[loopid].portid; + fcp->portdb[i].valid = 1; + + /* + * Tell the outside world we've arrived. + */ + (void) isp_async(isp, ISPASYNC_PDB_CHANGED, &i); + } + + /* + * 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++) { + if (lp->valid || lp->port_wwn == 0) + continue; + /* + * Tell the outside world we've gone away; + */ + loopid = lp - fcp->portdb; + (void) isp_async(isp, ISPASYNC_PDB_CHANGED, &loopid); + MEMZERO((void *) lp, sizeof (*lp)); + } + +#ifdef ISP2100_FABRIC + /* + * Now log in any fabric devices + */ + for (lp = &fcp->portdb[FC_SNS_ID+1]; + lp < &fcp->portdb[MAX_FC_TARG]; lp++) { + mbreg_t mbs; + + /* + * Nothing here? + */ + if (lp->port_wwn == 0) + continue; + /* + * Don't try to log into yourself. + */ + if (lp->portid == fcp->isp_portid) + continue; + + /* + * Force a logout. + */ + lp->loopid = lp - fcp->portdb; + mbs.param[0] = MBOX_FABRIC_LOGOUT; + mbs.param[1] = lp->loopid << 8; + mbs.param[2] = 0; + mbs.param[3] = 0; + isp_mboxcmd(isp, &mbs); + + /* + * And log in.... + */ + mbs.param[0] = MBOX_FABRIC_LOGIN; + mbs.param[1] = lp->loopid << 8; + mbs.param[2] = lp->portid >> 16; + mbs.param[3] = lp->portid & 0xffff; + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] == MBOX_COMMAND_COMPLETE) { + continue; + lp->valid = 1; + lp->fabdev = 1; + lp->roles = (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT); + } + } +#endif + return (0); } +#ifdef ISP2100_FABRIC +static int +isp_scan_fabric(isp) + struct ispsoftc *isp; +{ + fcparam *fcp = isp->isp_param; + u_int32_t portid, first_nz_portid; + sns_screq_t *reqp; + sns_scrsp_t *resp; + mbreg_t mbs; + int hicap; + + reqp = (sns_screq_t *) fcp->isp_scratch; + resp = (sns_scrsp_t *) (&((char *)fcp->isp_scratch)[0x100]); + first_nz_portid = portid = fcp->isp_portid; + + for (hicap = 0; hicap < 1024; hicap++) { + MEMZERO((void *) reqp, SNS_GAN_REQ_SIZE); + reqp->snscb_rblen = SNS_GAN_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 = 6; + reqp->snscb_data[0] = SNS_GAN; + reqp->snscb_data[4] = portid & 0xffff; + reqp->snscb_data[5] = (portid >> 16) & 0xff; + mbs.param[0] = MBOX_SEND_SNS; + mbs.param[1] = SNS_GAN_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; + MemoryBarrier(); + isp_mboxcmd(isp, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + return (-1); + } + portid = (((u_int32_t) resp->snscb_port_id[0]) << 16) | + (((u_int32_t) resp->snscb_port_id[1]) << 8) | + (((u_int32_t) resp->snscb_port_id[2])); + if (isp_async(isp, ISPASYNC_FABRIC_DEV, resp)) { + return (-1); + } + if (first_nz_portid == 0 && portid) { + first_nz_portid = portid; + } + if (first_nz_portid == portid) { + return (0); + } + } + /* + * We either have a broken name server or a huge fabric if we get here. + */ + return (0); +} +#endif /* * Start a command. Locking is assumed done in the caller. */ @@ -1241,7 +1713,7 @@ ispscsicmd(xs) #define reqp _u._reqp #define t2reqp _u._t2reqp #define UZSIZE max(sizeof (ispreq_t), sizeof (ispreqt2_t)) - int i, rqidx; + int target, i, rqidx; XS_INITERR(xs); isp = XS_ISP(xs); @@ -1268,29 +1740,89 @@ ispscsicmd(xs) * Check to see whether we have good firmware state still or * need to refresh our port database for this target. */ + target = XS_TGT(xs); if (IS_FC(isp)) { fcparam *fcp = isp->isp_param; - isp_pdb_t *pdbp = &fcp->isp_pdb[XS_TGT(xs)]; + struct lportdb *lp; + +#if defined(ISP2100_FABRIC) + if (target >= FL_PORT_ID) { + /* + * If we're not on a Fabric, we can't have a target + * above FL_PORT_ID-1. If we're on a fabric, we + * can't have a target less than FC_SNS_ID+1. + */ + if (fcp->isp_onfabric == 0 || target <= FC_SNS_ID) { + XS_SETERR(xs, HBA_SELTIMEOUT); + return (CMD_COMPLETE); + } + } +#endif /* - * Check for f/w being in ready state. Well, okay, - * our cached copy of it... + * Check for f/w being in ready state. If the f/w + * isn't in ready state, then we don't know our + * loop ID and the f/w hasn't completed logging + * into all targets on the loop. If this is the + * case, then bounce the command. We pretend this is + * a SELECTION TIMEOUT error if we've never gone to + * FW_READY state at all- in this case we may not + * be hooked to a loop at all and we shouldn't hang + * the machine for this. Otherwise, defer this command + * until later. */ if (fcp->isp_fwstate != FW_READY) { if (isp_fclink_test(isp, FC_FW_READY_DELAY)) { XS_SETERR(xs, HBA_SELTIMEOUT); - return (CMD_COMPLETE); + if (fcp->loop_seen_once) { + return (CMD_EAGAIN); + } else { + return (CMD_COMPLETE); + } } } + /* - * Refresh our port database if needed. + * If our loop state is such that we haven't yet received + * a "Port Database Changed" notification (after a LIP or + * a Loop Reset or firmware initialization), then defer + * sending commands for a little while. */ - if (pdbp->pdb_options == INVALID_PDB_OPTIONS) { - if (isp_getpdb(isp, XS_TGT(xs), pdbp) == 0) { - isp_async(isp, ISPASYNC_PDB_CHANGE_COMPLETE, - (void *) (long) XS_TGT(xs)); + if (fcp->isp_loopstate < LOOP_PDB_RCVD) { + XS_SETERR(xs, HBA_SELTIMEOUT); + return (CMD_EAGAIN); + } + + /* + * If our loop state is now such that we've just now + * received a Port Database Change notification, then + * we have to go off and (re)synchronize our + */ + if (fcp->isp_loopstate == LOOP_PDB_RCVD) { + if (isp_pdb_sync(isp, target)) { + XS_SETERR(xs, HBA_SELTIMEOUT); + return (CMD_COMPLETE); } } + + /* + * Now check whether we should even think about pursuing this. + */ + lp = &fcp->portdb[target]; +if ( target < 0x80) { + if (lp->valid == 0) { + XS_SETERR(xs, HBA_SELTIMEOUT); + return (CMD_COMPLETE); + } + if ((lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT)) == 0) { + XS_SETERR(xs, HBA_SELTIMEOUT); + return (CMD_COMPLETE); + } +} + /* + * Now turn target into what the actual loop ID is. + */ + target = lp->loopid; } /* @@ -1401,28 +1933,28 @@ ispscsicmd(xs) } } else { sdparam *sdp = (sdparam *)isp->isp_param; - if ((sdp->isp_devparam[XS_TGT(xs)].cur_dflags & DPARM_TQING) && + if ((sdp->isp_devparam[target].cur_dflags & DPARM_TQING) && XS_CANTAG(xs)) { reqp->req_flags = XS_KINDOF_TAG(xs); } else { reqp->req_flags = 0; } } - reqp->req_target = XS_TGT(xs) | (XS_CHANNEL(xs) << 7); + reqp->req_target = target | (XS_CHANNEL(xs) << 7); if (isp->isp_type & ISP_HA_SCSI) { reqp->req_lun_trn = XS_LUN(xs); reqp->req_cdblen = XS_CDBLEN(xs); } else { #ifdef ISP2100_SCCLUN - reqp->req_scclun = XS_LUN(xs); + t2reqp->req_scclun = XS_LUN(xs); #else - reqp->req_lun_trn = XS_LUN(xs); + t2reqp->req_lun_trn = XS_LUN(xs); #endif } MEMCPY(reqp->req_cdb, XS_CDBP(xs), XS_CDBLEN(xs)); IDPRINTF(5, ("%s(%d.%d.%d): START%d cmd 0x%x datalen %d\n", - isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), + isp->isp_name, XS_CHANNEL(xs), target, XS_LUN(xs), reqp->req_header.rqs_seqno, reqp->req_cdb[0], XS_XFRLEN(xs))); reqp->req_time = XS_TIME(xs) / 1000; @@ -2015,28 +2547,32 @@ isp_parse_async(isp, mbox) case ASYNC_LIP_OCCURRED: ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; + ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_LIP_RCVD; isp->isp_sendmarker = 1; isp_mark_getpdb_all(isp); PRINTF("%s: LIP occurred\n", isp->isp_name); break; case ASYNC_LOOP_UP: - ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; isp->isp_sendmarker = 1; + ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; + ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_LIP_RCVD; isp_mark_getpdb_all(isp); isp_async(isp, ISPASYNC_LOOP_UP, NULL); break; case ASYNC_LOOP_DOWN: - ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; isp->isp_sendmarker = 1; + ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; + ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_NIL; isp_mark_getpdb_all(isp); isp_async(isp, ISPASYNC_LOOP_DOWN, NULL); break; case ASYNC_LOOP_RESET: - ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; isp->isp_sendmarker = 1; + ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; + ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_NIL; isp_mark_getpdb_all(isp); PRINTF("%s: Loop RESET\n", isp->isp_name); #ifdef ISP_TARGET_MODE @@ -2046,8 +2582,9 @@ isp_parse_async(isp, mbox) case ASYNC_PDB_CHANGED: isp->isp_sendmarker = 1; + ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_PDB_RCVD; isp_mark_getpdb_all(isp); - PRINTF("%s: Port Database Changed\n", isp->isp_name); + IDPRINTF(3, ("%s: Port Database Changed\n", isp->isp_name)); break; case ASYNC_CHANGE_NOTIFY: @@ -2912,8 +3449,8 @@ isp_parse_status(isp, sp, xs) /* * It was there (maybe)- treat as a selection timeout. */ - PRINTF("%s: port logout for target %d\n", - isp->isp_name, XS_TGT(xs)); + IDPRINTF(2, ("%s: port logout for target %d\n", + isp->isp_name, XS_TGT(xs))); XS_SETERR(xs, HBA_SELTIMEOUT); return; @@ -3001,7 +3538,7 @@ static u_int8_t mbpcnt[] = { MAKNIB(2, 4), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */ MAKNIB(0, 0), /* 0x1e: */ MAKNIB(1, 3), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */ - MAKNIB(1, 3), /* 0x20: MBOX_GET_INIT_SCSI_ID, MBOX_GET_LOOP_ID */ + 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 */ @@ -3066,7 +3603,7 @@ static u_int8_t mbpcnt[] = { MAKNIB(0, 0), /* 0x5e: */ MAKNIB(0, 0), /* 0x5f: */ MAKNIB(8, 6), /* 0x60: MBOX_INIT_FIRMWARE */ - MAKNIB(0, 0), /* 0x60: MBOX_GET_INIT_CONTROL_BLOCK (FORMAT?) */ + 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 */ @@ -3079,10 +3616,10 @@ static u_int8_t mbpcnt[] = { MAKNIB(8, 1), /* 0x6b: MBOX_GET_LINK_STATUS */ MAKNIB(4, 4), /* 0x6c: MBOX_INIT_LIP_RESET */ MAKNIB(0, 0), /* 0x6d: */ - MAKNIB(0, 0), /* 0x6e: */ - MAKNIB(0, 0), /* 0x6f: */ - MAKNIB(0, 0), /* 0x70: */ - MAKNIB(0, 0), /* 0x71: */ + MAKNIB(8, 1), /* 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 NMBCOM (sizeof (mbpcnt) / sizeof (mbpcnt[0])) @@ -3389,8 +3926,9 @@ command_known: isp->isp_name, opcode); break; case MBOX_COMMAND_ERROR: - PRINTF("%s: mbox cmd %x failed with COMMAND_ERROR\n", - isp->isp_name, opcode); + if (opcode != MBOX_ABOUT_FIRMWARE) + PRINTF("%s: mbox cmd %x failed with COMMAND_ERROR\n", + isp->isp_name, opcode); break; case MBOX_COMMAND_PARAM_ERROR: switch (opcode) { @@ -3407,16 +3945,23 @@ command_known: /* * Be silent about these... */ + case ASYNC_PDB_CHANGED: + ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_PDB_RCVD; + break; - case ASYNC_LIP_OCCURRED: case ASYNC_LOOP_UP: + case ASYNC_LIP_OCCURRED: + ((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; - case ASYNC_PDB_CHANGED: - isp_mark_getpdb_all(isp); - break; default: /* @@ -3537,21 +4082,37 @@ again: mbs.param[0] = MBOX_GET_FW_STATE; isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + IDPRINTF(0, ("%s: isp_fw_state 0x%x\n", isp->isp_name, + mbs.param[0])); switch (mbs.param[0]) { case ASYNC_PDB_CHANGED: - isp_mark_getpdb_all(isp); - /* FALL THROUGH */ - case ASYNC_LIP_OCCURRED: + if (once++ < 10) { + goto again; + } + fcp->isp_fwstate = FW_CONFIG_WAIT; + fcp->isp_loopstate = LOOP_PDB_RCVD; + goto again; case ASYNC_LOOP_UP: - case ASYNC_LOOP_DOWN: + case ASYNC_LIP_OCCURRED: + fcp->isp_fwstate = FW_CONFIG_WAIT; + fcp->isp_loopstate = LOOP_LIP_RCVD; + if (once++ < 10) { + goto again; + } + break; case ASYNC_LOOP_RESET: + case ASYNC_LOOP_DOWN: + fcp->isp_fwstate = FW_CONFIG_WAIT; + fcp->isp_loopstate = LOOP_NIL; + /* FALLTHROUGH */ case ASYNC_CHANGE_NOTIFY: - if (once++ < 2) { + if (once++ < 10) { goto again; } break; } - isp_dumpregs(isp, "GET FIRMWARE STATE failed"); + PRINTF("%s: GET FIRMWARE STATE failed (0x%x)\n", + isp->isp_name, mbs.param[0]); return; } fcp->isp_fwstate = mbs.param[1]; @@ -3593,6 +4154,8 @@ isp_update_bus(isp, bus) int get; if (sdp->isp_devparam[tgt].dev_enable == 0) { + PRINTF("%s: skipping update of target %d on bus %d\n", + isp->isp_name, tgt, bus); continue; } @@ -3631,6 +4194,10 @@ isp_update_bus(isp, bus) sdp->isp_devparam[tgt].cur_dflags |= (sdp->isp_devparam[tgt].dev_flags & DPARM_TQING); sdp->isp_devparam[tgt].dev_refresh = 1; + IDPRINTF(3, ("%s: bus %d set tgt %d flags 0x%x off 0x%x" + " period 0x%x\n", isp->isp_name, bus, tgt, + mbs.param[2], mbs.param[3] >> 8, + mbs.param[3] & 0xff)); get = 0; } else if (sdp->isp_devparam[tgt].dev_refresh) { mbs.param[0] = MBOX_GET_TARGET_PARAMS; @@ -3678,24 +4245,26 @@ isp_setdfltparm(isp, channel) return; } fcp->isp_gotdparms = 1; - if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) { - if (isp_read_nvram(isp) == 0) { - return; - } - } fcp->isp_maxfrmlen = ICB_DFLT_FRMLEN; - fcp->isp_maxalloc = 256; - fcp->isp_execthrottle = 16; - fcp->isp_retry_delay = 5; - fcp->isp_retry_count = 3; - fcp->isp_loopid = DEFAULT_LOOPID; + fcp->isp_maxalloc = ICB_DFLT_ALLOC; + fcp->isp_execthrottle = ICB_DFLT_THROTTLE; + fcp->isp_retry_delay = ICB_DFLT_RDELAY; + fcp->isp_retry_count = ICB_DFLT_RCOUNT; + /* Platform specific.... */ + fcp->isp_loopid = DEFAULT_LOOPID(isp); + fcp->isp_nodewwn = DEFAULT_WWN(isp); + fcp->isp_portwwn = DEFAULT_WWN(isp); /* - * It would be nice to fake up a WWN in case we don't - * get one out of NVRAM. Solaris does this for SOCAL - * cards that don't have SBus properties- it sets up - * a WWN based upon the system MAC Address. + * Now try and read NVRAM */ - fcp->isp_wwn = 0; + if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) { + if (isp_read_nvram(isp)) { + PRINTF("%s: using default WWN 0x%08x%08x\n", + isp->isp_name, + (u_int32_t)(fcp->isp_portwwn >> 32), + (u_int32_t)(fcp->isp_portwwn & 0xffffffff)); + } + } return; } @@ -4235,7 +4804,20 @@ isp_read_nvram(isp) wwnstore.full64 = ISP2100_NVRAM_NODE_NAME(nvram_data); PRINTF("%s: Adapter WWN 0x%08x%08x\n", isp->isp_name, wwnstore.wds.hi32, wwnstore.wds.lo32); - fcp->isp_wwn = wwnstore.full64; + 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", diff --git a/sys/dev/ic/isp_netbsd.c b/sys/dev/ic/isp_netbsd.c index 1681730ba73..495a4d4f4d9 100644 --- a/sys/dev/ic/isp_netbsd.c +++ b/sys/dev/ic/isp_netbsd.c @@ -1,50 +1,34 @@ -/* $NetBSD: isp_netbsd.c,v 1.14 1999/05/12 18:59:24 mjacob Exp $ */ -/* release_5_11_99 */ +/* $NetBSD: isp_netbsd.c,v 1.15 1999/07/05 20:31:36 mjacob Exp $ */ +/* release_6_5_99 */ /* * Platform (NetBSD) dependent common attachment code for Qlogic adapters. - * - *--------------------------------------- - * Copyright (c) 1997, 1998 by Matthew Jacob - * NASA/Ames Research Center + * Matthew Jacob <mjacob@nas.nasa.gov> + */ +/* + * Copyright (C) 1997, 1998, 1999 National Aeronautics & Space Administration * All rights reserved. - *--------------------------------------- * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The author may be reached via electronic communications at - * - * mjacob@nas.nasa.gov - * mjacob@feral.com - * - * or, via United States Postal Address + * derived from this software without specific prior written permission * - * Matthew Jacob - * Feral Software - * 2339 3rd Street - * Suite 24 - * San Francisco, CA, 94107 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <dev/ic/isp_netbsd.h> @@ -78,7 +62,7 @@ isp_attach(isp) isp->isp_osinfo._link.adapter = &isp->isp_osinfo._adapter; TAILQ_INIT(&isp->isp_osinfo.waitq); - if (isp->isp_type & ISP_HA_FC) { + if (IS_FC(isp)) { /* * Give it another chance here to come alive... */ @@ -489,57 +473,86 @@ isp_async(isp, cmd, arg) timeout(isp_internal_restart, isp, 1); printf("%s: Loop UP\n", isp->isp_name); break; - case ISPASYNC_PDB_CHANGE_COMPLETE: - if (isp->isp_type & ISP_HA_FC) { - static char *roles[4] = { + case ISPASYNC_PDB_CHANGED: + if (IS_FC(isp)) { + const char *fmt = "%s: Target %d (Loop 0x%x) Port ID 0x%x " + "role %s %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x\n"; + const static char *roles[4] = { "No", "Target", "Initiator", "Target/Initiator" }; - long tgt = (long) arg; - isp_pdb_t *pdbp = &((fcparam *)isp->isp_param)->isp_pdb[tgt]; - printf("%s: Loop ID %d, %s role\n", - isp->isp_name, pdbp->pdb_loopid, - roles[(pdbp->pdb_prli_svc3 >> 4) & 0x3]); - printf(" Node Address 0x%x WWN 0x" - "%02x%02x%02x%02x%02x%02x%02x%02x\n", - BITS2WORD(pdbp->pdb_portid_bits), - pdbp->pdb_portname[0], pdbp->pdb_portname[1], - pdbp->pdb_portname[2], pdbp->pdb_portname[3], - pdbp->pdb_portname[4], pdbp->pdb_portname[5], - pdbp->pdb_portname[6], pdbp->pdb_portname[7]); - if (pdbp->pdb_options & PDB_OPTIONS_ADISC) - printf(" Hard Address 0x%x WWN 0x" - "%02x%02x%02x%02x%02x%02x%02x%02x\n", - BITS2WORD(pdbp->pdb_hardaddr_bits), - pdbp->pdb_nodename[0], - pdbp->pdb_nodename[1], - pdbp->pdb_nodename[2], - pdbp->pdb_nodename[3], - pdbp->pdb_nodename[4], - pdbp->pdb_nodename[5], - pdbp->pdb_nodename[6], - pdbp->pdb_nodename[7]); - switch (pdbp->pdb_prli_svc3 & SVC3_ROLE_MASK) { - case SVC3_TGT_ROLE|SVC3_INI_ROLE: - printf(" Master State=%s, Slave State=%s\n", - isp2100_pdb_statename(pdbp->pdb_mstate), - isp2100_pdb_statename(pdbp->pdb_sstate)); - break; - case SVC3_TGT_ROLE: - printf(" Master State=%s\n", - isp2100_pdb_statename(pdbp->pdb_mstate)); - break; - case SVC3_INI_ROLE: - printf(" Slave State=%s\n", - isp2100_pdb_statename(pdbp->pdb_sstate)); - break; - default: - break; + char *ptr; + fcparam *fcp = isp->isp_param; + int tgt = *((int *) arg); + struct lportdb *lp = &fcp->portdb[tgt]; + + if (lp->valid) { + ptr = "arrived"; + } else { + ptr = "disappeared"; } + printf(fmt, isp->isp_name, tgt, lp->loopid, lp->portid, + roles[lp->roles & 0x3], ptr, + (u_int32_t) (lp->port_wwn >> 32), + (u_int32_t) (lp->port_wwn & 0xffffffffLL), + (u_int32_t) (lp->node_wwn >> 32), + (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; + case ISPASYNC_FABRIC_DEV: + { + int target; + struct lportdb *lp; + sns_scrsp_t *resp = (sns_scrsp_t *) arg; + u_int32_t portid; + u_int64_t wwn; + fcparam *fcp = isp->isp_param; + + portid = + (((u_int32_t) resp->snscb_port_id[0]) << 16) | + (((u_int32_t) resp->snscb_port_id[1]) << 8) | + (((u_int32_t) resp->snscb_port_id[2])); + wwn = + (((u_int64_t)resp->snscb_portname[0]) << 56) | + (((u_int64_t)resp->snscb_portname[1]) << 48) | + (((u_int64_t)resp->snscb_portname[2]) << 40) | + (((u_int64_t)resp->snscb_portname[3]) << 32) | + (((u_int64_t)resp->snscb_portname[4]) << 24) | + (((u_int64_t)resp->snscb_portname[5]) << 16) | + (((u_int64_t)resp->snscb_portname[6]) << 8) | + (((u_int64_t)resp->snscb_portname[7])); + printf("%s: Fabric Device (Type 0x%x)@PortID 0x%x WWN " + "0x%08x%08x\n", isp->isp_name, resp->snscb_port_type, + portid, ((u_int32_t)(wwn >> 32)), + ((u_int32_t)(wwn & 0xffffffff))); + if (resp->snscb_port_type != 2) + break; + for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) { + lp = &fcp->portdb[target]; + if (lp->port_wwn == wwn) + break; + } + if (target < MAX_FC_TARG) { + break; + } + for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) { + lp = &fcp->portdb[target]; + if (lp->port_wwn == 0) + break; + } + if (target == MAX_FC_TARG) { + printf("%s: no more space for fabric devices\n", + isp->isp_name); + return (-1); + } + lp->port_wwn = lp->node_wwn = wwn; + lp->portid = portid; + break; + } +#endif default: break; } diff --git a/sys/dev/ic/isp_netbsd.h b/sys/dev/ic/isp_netbsd.h index 12a3a417a6f..f654ce5b0c5 100644 --- a/sys/dev/ic/isp_netbsd.h +++ b/sys/dev/ic/isp_netbsd.h @@ -1,40 +1,35 @@ -/* $NetBSD: isp_netbsd.h,v 1.14 1999/05/12 18:59:24 mjacob Exp $ */ -/* release_5_11_99 */ +/* $NetBSD: isp_netbsd.h,v 1.15 1999/07/05 20:31:36 mjacob Exp $ */ +/* release_6_5_99 */ /* * NetBSD Specific definitions for the Qlogic ISP Host Adapter - * - *--------------------------------------- - * Copyright (c) 1997, 1998 by Matthew Jacob - * NASA/Ames Research Center + * Matthew Jacob <mjacob@nas.nasa.gov> + */ +/* + * Copyright (C) 1997, 1998, 1999 National Aeronautics & Space Administration * All rights reserved. - *--------------------------------------- * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * derived from this software without specific prior written permission * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - #ifndef _ISP_NETBSD_H #define _ISP_NETBSD_H @@ -62,8 +57,10 @@ #include <vm/vm_param.h> #include <vm/pmap.h> +#include "opt_isp.h" + #define ISP_PLATFORM_VERSION_MAJOR 0 -#define ISP_PLATFORM_VERSION_MINOR 995 +#define ISP_PLATFORM_VERSION_MINOR 996 #define ISP_SCSI_XFER_T struct scsipi_xfer struct isposinfo { @@ -71,10 +68,16 @@ struct isposinfo { struct scsipi_link _link; struct scsipi_link _link_b; struct scsipi_adapter _adapter; + int seed; int blocked; TAILQ_HEAD(, scsipi_xfer) waitq; }; #define MAXISPREQUEST 256 +#ifdef ISP2100_FABRIC +#define ISP2100_SCRLEN 0x400 +#else +#define ISP2100_SCRLEN 0x100 +#endif #include <dev/ic/ispreg.h> #include <dev/ic/ispvar.h> @@ -172,6 +175,7 @@ struct isposinfo { #define isp_name isp_osinfo._dev.dv_xname +#define isp_unit isp_osinfo._dev.dv_unit #define SCSI_QFULL 0x28 @@ -181,6 +185,8 @@ struct isposinfo { #define WATCH_INTERVAL 30 #define FC_FW_READY_DELAY (12 * 1000000) +#define DEFAULT_LOOPID(x) 108 +#define DEFAULT_WWN(x) (0x1000beed00000000LL + (x)->isp_osinfo.seed) extern void isp_attach __P((struct ispsoftc *)); extern void isp_uninit __P((struct ispsoftc *)); @@ -263,12 +269,4 @@ static inline const char *isp2100_pdb_statename(int pdb_state) return buf; } } - -/* - * Keep these off for now... - */ - -#define ISP_NO_FASTPOST_SCSI 1 -#define ISP_NO_FASTPOST_FC 1 - #endif /* _ISP_NETBSD_H */ diff --git a/sys/dev/ic/ispmbox.h b/sys/dev/ic/ispmbox.h index a39ed6f33be..9b963cc8b51 100644 --- a/sys/dev/ic/ispmbox.h +++ b/sys/dev/ic/ispmbox.h @@ -1,38 +1,35 @@ -/* $NetBSD: ispmbox.h,v 1.17 1999/05/12 16:45:58 mjacob Exp $ */ -/* release_5_11_99 */ +/* $NetBSD: ispmbox.h,v 1.18 1999/07/05 20:31:36 mjacob Exp $ */ +/* release_6_5_99 */ /* - * Mailbox and Queue Entry Definitions for for Qlogic ISP SCSI adapters. - * - *--------------------------------------- - * Copyright (c) 1997, 1998 by Matthew Jacob - * NASA/Ames Research Center + * Copyright (C) 1997, 1998, 1999 National Aeronautics & Space Administration * All rights reserved. - *--------------------------------------- * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * derived from this software without specific prior written permission * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Mailbox and Queue Entry Definitions for for Qlogic ISP SCSI adapters. + * <mjacob@nas.nasa.gov> */ #ifndef _ISPMBOX_H #define _ISPMBOX_H @@ -130,6 +127,10 @@ #define MBOX_GET_PORT_NAME 0x6a #define MBOX_GET_LINK_STATUS 0x6b #define MBOX_INIT_LIP_RESET 0x6c +#define MBOX_SEND_SNS 0x6e +#define MBOX_FABRIC_LOGIN 0x6f +#define MBOX_SEND_CHANGE_REQUEST 0x70 +#define MBOX_FABRIC_LOGOUT 0x71 #define MBOX_INIT_LIP_LOGIN 0x72 #define ISP2100_SET_PCI_PARAM 0x00ff @@ -460,26 +461,31 @@ typedef struct { } isp_icb_t; #define ICB_VERSION1 1 -#define ICBOPT_HARD_ADDRESS (1<<0) -#define ICBOPT_FAIRNESS (1<<1) -#define ICBOPT_FULL_DUPLEX (1<<2) -#define ICBOPT_FAST_POST (1<<3) -#define ICBOPT_TGT_ENABLE (1<<4) -#define ICBOPT_INI_DISABLE (1<<5) -#define ICBOPT_INI_ADISC (1<<6) -#define ICBOPT_INI_TGTTYPE (1<<7) -#define ICBOPT_PDBCHANGE_AE (1<<8) -#define ICBOPT_NOLIP (1<<9) -#define ICBOPT_SRCHDOWN (1<<10) -#define ICBOPT_PREVLOOP (1<<11) -#define ICBOPT_STOP_ON_QFULL (1<<12) -#define ICBOPT_FULL_LOGIN (1<<13) -#define ICBOPT_USE_PORTNAME (1<<14) +#define ICBOPT_HARD_ADDRESS 0x0001 +#define ICBOPT_FAIRNESS 0x0002 +#define ICBOPT_FULL_DUPLEX 0x0004 +#define ICBOPT_FAST_POST 0x0008 +#define ICBOPT_TGT_ENABLE 0x0010 +#define ICBOPT_INI_DISABLE 0x0020 +#define ICBOPT_INI_ADISC 0x0040 +#define ICBOPT_INI_TGTTYPE 0x0080 +#define ICBOPT_PDBCHANGE_AE 0x0100 +#define ICBOPT_NOLIP 0x0200 +#define ICBOPT_SRCHDOWN 0x0400 +#define ICBOPT_PREVLOOP 0x0800 +#define ICBOPT_STOP_ON_QFULL 0x1000 +#define ICBOPT_FULL_LOGIN 0x2000 +#define ICBOPT_USE_PORTNAME 0x4000 #define ICB_MIN_FRMLEN 256 #define ICB_MAX_FRMLEN 2112 #define ICB_DFLT_FRMLEN 1024 +#define ICB_DFLT_ALLOC 256 +#define ICB_DFLT_THROTTLE 16 +#define ICB_DFLT_RDELAY 5 +#define ICB_DFLT_RCOUNT 3 + #define RQRSP_ADDR0015 0 #define RQRSP_ADDR1631 1 @@ -552,8 +558,6 @@ typedef struct { u_int16_t pdb_sl_ptr; } isp_pdb_t; -#define INVALID_PDB_OPTIONS 0xDEAD - #define PDB_OPTIONS_XMITTING (1<<11) #define PDB_OPTIONS_LNKXMIT (1<<10) #define PDB_OPTIONS_ABORTED (1<<9) @@ -575,6 +579,30 @@ typedef struct { #define SVC3_TGT_ROLE 0x10 #define SVC3_INI_ROLE 0x20 #define SVC3_ROLE_MASK 0x30 +#define SVC3_ROLE_SHIFT 4 + +#define SNS_GAN 0x100 +#define SNS_GP3 0x171 +typedef struct { + u_int16_t snscb_rblen; /* response buffer length (words) */ + u_int16_t snscb_res0; + u_int16_t snscb_addr[4]; /* response buffer address */ + u_int16_t snscb_sblen; /* subcommand buffer length (words) */ + u_int16_t snscb_res1; + u_int16_t snscb_data[1]; /* variable data */ +} sns_screq_t; /* Subcommand Request Structure */ +#define SNS_GAN_REQ_SIZE (sizeof (sns_screq_t)+(5*(sizeof (u_int16_t)))) +#define SNS_GP3_REQ_SIZE (sizeof (sns_screq_t)+(5*(sizeof (u_int16_t)))) + +typedef struct { + u_int8_t snscb_cthdr[16]; + u_int8_t snscb_port_type; + u_int8_t snscb_port_id[3]; + u_int8_t snscb_portname[8]; + u_int16_t snscb_data[1]; /* variable data */ +} sns_scrsp_t; /* Subcommand Response Structure */ +#define SNS_GAN_RESP_SIZE 608 /* Maximum response size (bytes) */ +#define SNS_GP3_RESP_SIZE 532 /* XXX: For 128 ports */ /* * Target Mode Structures diff --git a/sys/dev/ic/ispreg.h b/sys/dev/ic/ispreg.h index 9da89ed547c..48d87fdde9a 100644 --- a/sys/dev/ic/ispreg.h +++ b/sys/dev/ic/ispreg.h @@ -1,36 +1,37 @@ -/* $NetBSD: ispreg.h,v 1.15 1999/05/12 18:59:24 mjacob Exp $ */ -/* release_5_11_99 */ +/* $NetBSD: ispreg.h,v 1.16 1999/07/05 20:31:36 mjacob Exp $ */ +/* release_6_5_99 */ /* - * Machine Independent (well, as best as possible) register - * definitions for Qlogic ISP SCSI adapters. - * - * Copyright (c) 1997, 1998, 1999 by Matthew Jacob - * NASA/Ames Research Center + * Copyright (C) 1997, 1998, 1999 National Aeronautics & Space Administration * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Machine Independent (well, as best as possible) register + * definitions for Qlogic ISP SCSI adapters. + * + * Matthew Jacob <mjacob@nas.nasa.gov> * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. */ #ifndef _ISPREG_H #define _ISPREG_H diff --git a/sys/dev/ic/ispvar.h b/sys/dev/ic/ispvar.h index d7d7a1021e0..177a42c42d1 100644 --- a/sys/dev/ic/ispvar.h +++ b/sys/dev/ic/ispvar.h @@ -1,39 +1,36 @@ -/* $NetBSD: ispvar.h,v 1.22 1999/05/12 18:59:24 mjacob Exp $ */ -/* release_5_11_99 */ +/* $NetBSD: ispvar.h,v 1.23 1999/07/05 20:31:36 mjacob Exp $ */ +/* release_6_5_99 */ /* - * Soft Definitions for for Qlogic ISP SCSI adapters. - * - *--------------------------------------- - * Copyright (c) 1997, 1998 by Matthew Jacob - * NASA/Ames Research Center + * Copyright (C) XXXX National Aeronautics & Space Administration * All rights reserved. - *--------------------------------------- + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * derived from this software without specific prior written permission * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* + * Soft Definitions for for Qlogic ISP SCSI adapters. + * Matthew Jacob <mjacob@nas.nasa.gov> + */ #ifndef _ISPVAR_H #define _ISPVAR_H @@ -48,7 +45,7 @@ #endif #define ISP_CORE_VERSION_MAJOR 1 -#define ISP_CORE_VERSION_MINOR 8 +#define ISP_CORE_VERSION_MINOR 9 /* * Vector for bus specific code to provide specific services. @@ -82,7 +79,6 @@ struct ispmdvec { #else #define MAX_FC_TARG 126 #endif -#define DEFAULT_LOOPID 113 /* queue length must be a power of two */ #define QENTRY_LEN 64 @@ -161,40 +157,68 @@ typedef struct { * Fibre Channel Specifics */ typedef struct { - u_int8_t isp_gotdparms; - u_int8_t isp_reserved; + u_int isp_fwoptions : 16, + : 7, + loop_seen_once : 1, + isp_loopstate : 3, /* Current Loop State */ + isp_fwstate : 3, /* ISP F/W state */ + isp_gotdparms : 1, + isp_onfabric : 1; u_int8_t isp_loopid; /* hard loop id */ u_int8_t isp_alpa; /* ALPA */ + u_int32_t isp_portid; u_int8_t isp_execthrottle; u_int8_t isp_retry_delay; u_int8_t isp_retry_count; - u_int8_t isp_fwstate; /* ISP F/W state */ - u_int64_t isp_wwn; /* WWN of adapter */ u_int16_t isp_maxalloc; u_int16_t isp_maxfrmlen; - u_int16_t isp_fwoptions; + u_int64_t isp_nodewwn; + u_int64_t isp_portwwn; /* - * Port Data Base + * Port Data Base. This is indexed by 'target', which is invariate. + * However, elements within can move around due to loop changes, + * so the actual loop ID passed to the F/W is in this structure. + * The first time the loop is seen up, loopid will match the index + * (except for fabric nodes which are above mapped above FC_SNS_ID + * and are completely virtual), but subsequent LIPs can cause things + * to move around. */ - isp_pdb_t isp_pdb[MAX_FC_TARG]; + struct lportdb { + u_int + loopid : 8, + : 4, + fabdev : 1, + roles : 2, + valid : 1; + u_int32_t portid; + u_int64_t node_wwn; + u_int64_t port_wwn; + } portdb[MAX_FC_TARG]; /* * Scratch DMA mapped in area to fetch Port Database stuff, etc. */ - volatile caddr_t isp_scratch; + caddr_t isp_scratch; u_int32_t isp_scdma; } fcparam; -#define ISP2100_SCRLEN 0x100 +#define FW_CONFIG_WAIT 0 +#define FW_WAIT_AL_PA 1 +#define FW_WAIT_LOGIN 2 +#define FW_READY 3 +#define FW_LOSS_OF_SYNC 4 +#define FW_ERROR 5 +#define FW_REINIT 6 +#define FW_NON_PART 7 + +#define LOOP_NIL 0 +#define LOOP_LIP_RCVD 1 +#define LOOP_PDB_RCVD 2 +#define LOOP_READY 7 -#define FW_CONFIG_WAIT 0x0000 -#define FW_WAIT_AL_PA 0x0001 -#define FW_WAIT_LOGIN 0x0002 -#define FW_READY 0x0003 -#define FW_LOSS_OF_SYNC 0x0004 -#define FW_ERROR 0x0005 -#define FW_REINIT 0x0006 -#define FW_NON_PART 0x0007 +#define FL_PORT_ID 0x7e /* FL_Port Special ID */ +#define FC_PORT_ID 0x7f /* Fabric Controller Special ID */ +#define FC_SNS_ID 0x80 /* SNS Server Special ID */ #ifdef ISP_TARGET_MODE /* @@ -298,8 +322,8 @@ struct ispsoftc { /* * request/result queues and dma handles for them. */ - volatile caddr_t isp_rquest; - volatile caddr_t isp_result; + caddr_t isp_rquest; + caddr_t isp_result; u_int32_t isp_rquest_dma; u_int32_t isp_result_dma; @@ -339,6 +363,7 @@ struct ispsoftc { */ #define ISP_CFG_NORELOAD 0x80 /* don't download f/w */ #define ISP_CFG_NONVRAM 0x40 /* ignore NVRAM */ +#define ISP_CFG_FULL_DUPLEX 0x01 /* Fibre Channel Only */ #define ISP_FW_REV(maj, min, mic) ((maj << 24) | (min << 16) | mic) #define ISP_FW_REVX(xp) ((xp[0]<<24) | (xp[1] << 16) | xp[2]) @@ -365,6 +390,7 @@ struct ispsoftc { #define ISP_HA_SCSI_12X0 0xe #define ISP_HA_FC 0xf0 #define ISP_HA_FC_2100 0x10 +#define ISP_HA_FC_2200 0x20 #define IS_SCSI(isp) (isp->isp_type & ISP_HA_SCSI) #define IS_1080(isp) (isp->isp_type == ISP_HA_SCSI_1080) @@ -437,21 +463,15 @@ int32_t ispscsicmd __P((ISP_SCSI_XFER_T *)); /* * Platform Dependent to External to Internal Control Function * - * For: Aborting a running command - arg is an ISP_SCSI_XFER_T * - * Resetting a Device - arg is target to reset - * Resetting a BUS - arg is ignored - * Updating parameters - arg is ignored + * Assumes all locks are held and that no reentrancy issues need be dealt with. * - * First argument is this instance's softc pointer. - * Second argument is an index into xflist array. - * Assumes all locks must be held already. */ typedef enum { - ISPCTL_RESET_BUS, - ISPCTL_RESET_DEV, - ISPCTL_ABORT_CMD, - ISPCTL_UPDATE_PARAMS, - ISPCTL_FCLINK_TEST + ISPCTL_RESET_BUS, /* Reset Bus */ + ISPCTL_RESET_DEV, /* Reset Device */ + ISPCTL_ABORT_CMD, /* Abort Command */ + ISPCTL_UPDATE_PARAMS, /* Update Operating Parameters */ + ISPCTL_FCLINK_TEST /* Test FC Link Status */ } ispctl_t; int isp_control __P((struct ispsoftc *, ispctl_t, void *)); @@ -460,18 +480,18 @@ int isp_control __P((struct ispsoftc *, ispctl_t, void *)); * Platform Dependent to Internal to External Control Function * (each platform must provide such a function) * - * For: Announcing Target Paramter Changes (arg is target) + * Assumes all locks are held and that no reentrancy issues need be dealt with. * - * Assumes all locks are held. */ typedef enum { ISPASYNC_NEW_TGT_PARAMS, - ISPASYNC_BUS_RESET, /* Bus Reset */ - ISPASYNC_LOOP_DOWN, /* Obvious FC only */ - ISPASYNC_LOOP_UP, /* "" */ - ISPASYNC_PDB_CHANGE_COMPLETE, /* "" */ - ISPASYNC_CHANGE_NOTIFY /* "" */ + ISPASYNC_BUS_RESET, /* Bus Was Reset */ + ISPASYNC_LOOP_DOWN, /* FC Loop Down */ + ISPASYNC_LOOP_UP, /* FC Loop Up */ + ISPASYNC_PDB_CHANGED, /* FC Port Data Base Changed */ + ISPASYNC_CHANGE_NOTIFY, /* FC SNS Change Notification */ + ISPASYNC_FABRIC_DEV, /* FC New Fabric Device */ } ispasync_t; int isp_async __P((struct ispsoftc *, ispasync_t, void *)); |
