summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authormjacob <mjacob@NetBSD.org>1999-07-05 20:31:35 +0000
committermjacob <mjacob@NetBSD.org>1999-07-05 20:31:35 +0000
commitf428cf36fa402fef89c6bd1b2563f4acfbcc4a61 (patch)
tree1a33edec8c103682140766f09862612bdc7e6a4e /sys/dev
parent3bb408eb05a15ec2e65ede5ff8b0aed88644c396 (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.c878
-rw-r--r--sys/dev/ic/isp_netbsd.c169
-rw-r--r--sys/dev/ic/isp_netbsd.h62
-rw-r--r--sys/dev/ic/ispmbox.h108
-rw-r--r--sys/dev/ic/ispreg.h43
-rw-r--r--sys/dev/ic/ispvar.h146
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 *));