summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2002-04-04 23:46:01 +0000
committermjacob <mjacob@FreeBSD.org>2002-04-04 23:46:01 +0000
commitf62deac6f06bab39d2dffeb95d82b8341445d5af (patch)
tree58b8cc455f67309f7a70758f449ddc01e0ded92b /sys
parent2be9f95449ddaa06d1bf21938e091ea7ecd27626 (diff)
downloadFreeBSD-src-f62deac6f06bab39d2dffeb95d82b8341445d5af.zip
FreeBSD-src-f62deac6f06bab39d2dffeb95d82b8341445d5af.tar.gz
Fix bus dma segment count to be based off of MAXPHYS, not BUS_SPACE_MAXSIZE.
Grumble. I've seen better documented architectures out of Redmond. Redo fabric evaluation to not use GET ALL NEXT (GA_NXT). Switches seem to be trying to wriggle out of supporting this well. Instead, use GID_FT to get a list of Port IDs and then use GPN_ID/GNN_ID to find the port and node wwn. This should make working on fabrics a bit cleaner and more stable. This also caused some cleanup of SNS subcommand canonicalization so that we can actually check for FS_ACC and FS_RJT, and if we get an FS_RJT, print out the reason and explanation codes. We'll keep the old GA_NXT method around if people want to uncomment a controlling definition in ispvar.h. This also had us clean up ISPASYNC_FABRICDEV to use a local lportdb argument and to have the caller explicitly say that a device is at the end of the fabric list. MFC after: 1 week
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/isp/isp.c451
-rw-r--r--sys/dev/isp/isp_freebsd.c102
-rw-r--r--sys/dev/isp/isp_freebsd.h2
-rw-r--r--sys/dev/isp/isp_inline.h127
-rw-r--r--sys/dev/isp/isp_pci.c15
-rw-r--r--sys/dev/isp/ispmbox.h120
-rw-r--r--sys/dev/isp/ispvar.h14
7 files changed, 675 insertions, 156 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index b6b9d4d..83af43e 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -96,6 +96,8 @@ static const char pskip[] =
"SCSI phase skipped for target %d.%d.%d";
static const char topology[] =
"Loop ID %d, AL_PA 0x%x, Port ID 0x%x, Loop State 0x%x, Topology '%s'";
+static const char swrej[] =
+ "Fabric Nameserver rejected %s (Reason=0x%x Expl=0x%x) for Port ID 0x%x";
static const char finmsg[] =
"(%d.%d.%d): FIN dl%d resid %d STS 0x%x SKEY %c XS_ERR=0x%x";
static const char sc0[] =
@@ -127,7 +129,8 @@ static int isp_fclink_test(struct ispsoftc *, int);
static char *isp2100_fw_statename(int);
static int isp_pdb_sync(struct ispsoftc *);
static int isp_scan_loop(struct ispsoftc *);
-static int isp_scan_fabric(struct ispsoftc *);
+static int isp_fabric_mbox_cmd(struct ispsoftc *, mbreg_t *);
+static int isp_scan_fabric(struct ispsoftc *, int);
static void isp_register_fc4_type(struct ispsoftc *);
static void isp_fw_state(struct ispsoftc *);
static void isp_mboxcmd_qnw(struct ispsoftc *, mbreg_t *, int);
@@ -2298,21 +2301,69 @@ isp_scan_loop(struct ispsoftc *isp)
return (0);
}
-#ifndef HICAP_MAX
-#define HICAP_MAX 256
-#endif
+
+static int
+isp_fabric_mbox_cmd(struct ispsoftc *isp, mbreg_t *mbp)
+{
+ isp_mboxcmd(isp, mbp, MBLOGNONE);
+ if (mbp->param[0] != MBOX_COMMAND_COMPLETE) {
+ if (FCPARAM(isp)->isp_loopstate == LOOP_SCANNING_FABRIC) {
+ FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
+ }
+ if (mbp->param[0] == MBOX_COMMAND_ERROR) {
+ char tbuf[16];
+ char *m;
+ switch (mbp->param[1]) {
+ case 1:
+ m = "No Loop";
+ break;
+ case 2:
+ m = "Failed to allocate IOCB buffer";
+ break;
+ case 3:
+ m = "Failed to allocate XCB buffer";
+ break;
+ case 4:
+ m = "timeout or transmit failed";
+ break;
+ case 5:
+ m = "no fabric loop";
+ break;
+ case 6:
+ m = "remote device not a target";
+ break;
+ default:
+ SNPRINTF(tbuf, sizeof tbuf, "%x",
+ mbp->param[1]);
+ m = tbuf;
+ break;
+ }
+ isp_prt(isp, ISP_LOGERR, "SNS Failed- %s", m);
+ }
+ return (-1);
+ }
+
+ if (FCPARAM(isp)->isp_fwstate != FW_READY ||
+ FCPARAM(isp)->isp_loopstate < LOOP_SCANNING_FABRIC) {
+ return (-1);
+ }
+ return(0);
+}
+
+#ifdef ISP_USE_GA_NXT
static int
-isp_scan_fabric(struct ispsoftc *isp)
+isp_scan_fabric(struct ispsoftc *isp, int ftype)
{
fcparam *fcp = isp->isp_param;
u_int32_t portid, first_portid, last_portid;
- int hicap, first_portid_seen, last_port_same;
+ int hicap, last_port_same;
if (fcp->isp_onfabric == 0) {
fcp->isp_loopstate = LOOP_FSCAN_DONE;
return (0);
}
+ FC_SCRATCH_ACQUIRE(isp);
/*
* Since Port IDs are 24 bits, we can check against having seen
@@ -2323,28 +2374,28 @@ isp_scan_fabric(struct ispsoftc *isp)
first_portid = portid = fcp->isp_portid;
fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
- for (first_portid_seen = hicap = 0; hicap < HICAP_MAX; hicap++) {
+ for (hicap = 0; hicap < GA_NXT_MAX; hicap++) {
mbreg_t mbs;
sns_screq_t *rq;
- sns_ganrsp_t *rs0, *rs1;
- u_int8_t sc[SNS_GAN_REQ_SIZE];
+ sns_ga_nxt_rsp_t *rs0, *rs1;
+ struct lportdb lcl;
+ u_int8_t sc[SNS_GA_NXT_RESP_SIZE];
rq = (sns_screq_t *)sc;
- MEMZERO((void *) rq, SNS_GAN_REQ_SIZE);
- rq->snscb_rblen = SNS_GAN_RESP_SIZE >> 1;
+ MEMZERO((void *) rq, SNS_GA_NXT_REQ_SIZE);
+ rq->snscb_rblen = SNS_GA_NXT_RESP_SIZE >> 1;
rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+0x100);
rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+0x100);
rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+0x100);
rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+0x100);
rq->snscb_sblen = 6;
- rq->snscb_data[0] = SNS_GAN;
+ rq->snscb_data[0] = SNS_GA_NXT;
rq->snscb_data[4] = portid & 0xffff;
rq->snscb_data[5] = (portid >> 16) & 0xff;
- FC_SCRATCH_ACQUIRE(isp);
isp_put_sns_request(isp, rq, (sns_screq_t *) fcp->isp_scratch);
- MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GAN_REQ_SIZE);
+ MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GA_NXT_REQ_SIZE);
mbs.param[0] = MBOX_SEND_SNS;
- mbs.param[1] = SNS_GAN_REQ_SIZE >> 1;
+ mbs.param[1] = SNS_GA_NXT_REQ_SIZE >> 1;
mbs.param[2] = DMA_WD1(fcp->isp_scdma);
mbs.param[3] = DMA_WD0(fcp->isp_scdma);
/*
@@ -2352,59 +2403,80 @@ isp_scan_fabric(struct ispsoftc *isp)
*/
mbs.param[6] = DMA_WD3(fcp->isp_scdma);
mbs.param[7] = DMA_WD2(fcp->isp_scdma);
- isp_mboxcmd(isp, &mbs, MBLOGNONE);
- if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
- if (fcp->isp_loopstate == LOOP_SCANNING_FABRIC) {
+ if (isp_fabric_mbox_cmd(isp, &mbs)) {
+ if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
fcp->isp_loopstate = LOOP_PDB_RCVD;
}
- if (mbs.param[0] == MBOX_COMMAND_ERROR) {
- char tbuf[16];
- char *m;
- switch (mbs.param[1]) {
- case 1:
- m = "No Loop";
- break;
- case 2:
- m = "Failed to allocate IOCB buffer";
- break;
- case 3:
- m = "Failed to allocate XCB buffer";
- break;
- case 4:
- m = "timeout or transmit failed";
- break;
- case 5:
- m = "no fabric loop";
- break;
- case 6:
- m = "remote device not a target";
- break;
- default:
- SNPRINTF(tbuf, sizeof tbuf, "%x",
- mbs.param[1]);
- m = tbuf;
- break;
- }
- isp_prt(isp, ISP_LOGERR, "SNS Failed- %s", m);
- }
+ FC_SCRATCH_RELEASE(isp);
return (-1);
}
- if (fcp->isp_fwstate != FW_READY ||
- fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
+ MEMORYBARRIER(isp, SYNC_SFORCPU, 0x100, SNS_GA_NXT_RESP_SIZE);
+ rs1 = (sns_ga_nxt_rsp_t *) sc;
+ rs0 = (sns_ga_nxt_rsp_t *) ((u_int8_t *)fcp->isp_scratch+0x100);
+ isp_get_ga_nxt_response(isp, rs0, rs1);
+ if (rs1->snscb_cthdr.ct_response != FS_ACC) {
+ isp_prt(isp, ISP_LOGWARN, swrej, "GA_NXT",
+ rs1->snscb_cthdr.ct_reason,
+ rs1->snscb_cthdr.ct_explanation, portid);
FC_SCRATCH_RELEASE(isp);
- return (-1);
+ fcp->isp_loopstate = LOOP_FSCAN_DONE;
+ return (0);
}
- MEMORYBARRIER(isp, SYNC_SFORCPU, 0x100, SNS_GAN_RESP_SIZE);
- rs1 = (sns_ganrsp_t *) fcp->isp_scratch;
- rs0 = (sns_ganrsp_t *) ((u_int8_t *)fcp->isp_scratch + 0x100);
- isp_get_gan_response(isp, rs0, rs1);
- FC_SCRATCH_RELEASE(isp);
- portid = (((u_int32_t) rs1->snscb_port_id[0]) << 16) |
+ portid =
+ (((u_int32_t) rs1->snscb_port_id[0]) << 16) |
(((u_int32_t) rs1->snscb_port_id[1]) << 8) |
(((u_int32_t) rs1->snscb_port_id[2]));
- (void) isp_async(isp, ISPASYNC_FABRIC_DEV, rs1);
+
+ /*
+ * Okay, we now have information about a fabric object.
+ * If it is the type we're interested in, tell the outer layers
+ * about it. The outer layer needs to know: Port ID, WWNN,
+ * WWPN, FC4 type, and port type.
+ *
+ * The lportdb structure is adequate for this.
+ */
+ MEMZERO(&lcl, sizeof (lcl));
+ lcl.port_type = rs1->snscb_port_type;
+ lcl.fc4_type = ftype;
+ lcl.portid = portid;
+ lcl.node_wwn =
+ (((u_int64_t)rs1->snscb_nodename[0]) << 56) |
+ (((u_int64_t)rs1->snscb_nodename[1]) << 48) |
+ (((u_int64_t)rs1->snscb_nodename[2]) << 40) |
+ (((u_int64_t)rs1->snscb_nodename[3]) << 32) |
+ (((u_int64_t)rs1->snscb_nodename[4]) << 24) |
+ (((u_int64_t)rs1->snscb_nodename[5]) << 16) |
+ (((u_int64_t)rs1->snscb_nodename[6]) << 8) |
+ (((u_int64_t)rs1->snscb_nodename[7]));
+ lcl.port_wwn =
+ (((u_int64_t)rs1->snscb_portname[0]) << 56) |
+ (((u_int64_t)rs1->snscb_portname[1]) << 48) |
+ (((u_int64_t)rs1->snscb_portname[2]) << 40) |
+ (((u_int64_t)rs1->snscb_portname[3]) << 32) |
+ (((u_int64_t)rs1->snscb_portname[4]) << 24) |
+ (((u_int64_t)rs1->snscb_portname[5]) << 16) |
+ (((u_int64_t)rs1->snscb_portname[6]) << 8) |
+ (((u_int64_t)rs1->snscb_portname[7]));
+
+ /*
+ * Does this fabric object support the type we want?
+ * If not, skip it.
+ */
+ if (rs1->snscb_fc4_types[ftype >> 5] & (1 << (ftype & 0x1f))) {
+ if (first_portid == portid) {
+ lcl.last_fabric_dev = 1;
+ } else {
+ lcl.last_fabric_dev = 0;
+ }
+ (void) isp_async(isp, ISPASYNC_FABRIC_DEV, &lcl);
+ } else {
+ isp_prt(isp, ISP_LOGDEBUG0,
+ "PortID 0x%x doesn't support FC4 type 0x%x",
+ portid, ftype);
+ }
if (first_portid == portid) {
fcp->isp_loopstate = LOOP_FSCAN_DONE;
+ FC_SCRATCH_RELEASE(isp);
return (0);
}
if (portid == last_portid) {
@@ -2414,47 +2486,285 @@ isp_scan_fabric(struct ispsoftc *isp)
break;
}
} else {
+ last_port_same = 0 ;
last_portid = portid;
}
}
+ FC_SCRATCH_RELEASE(isp);
+ if (hicap >= GA_NXT_MAX) {
+ isp_prt(isp, ISP_LOGWARN, "fabric too big (> %d)", GA_NXT_MAX);
+ }
+ fcp->isp_loopstate = LOOP_FSCAN_DONE;
+ return (0);
+}
+#else
+#define GIDLEN ((ISP2100_SCRLEN >> 1) + 16)
+#define NGENT ((GIDLEN - 16) >> 2)
+
+#define IGPOFF (ISP2100_SCRLEN - GIDLEN)
+#define GXOFF (256)
+
+static int
+isp_scan_fabric(struct ispsoftc *isp, int ftype)
+{
+ fcparam *fcp = FCPARAM(isp);
+ mbreg_t mbs;
+ u_int8_t sc[GIDLEN]; /* XXX USE ->tport */
+ int i;
+ sns_gid_ft_req_t *rq;
+ sns_gid_ft_rsp_t *rs0, *rs1;
+
+ if (fcp->isp_onfabric == 0) {
+ fcp->isp_loopstate = LOOP_FSCAN_DONE;
+ return (0);
+ }
+
+ FC_SCRATCH_ACQUIRE(isp);
+ fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
+
+ rq = (sns_gid_ft_req_t *)sc;
+ MEMZERO((void *) rq, SNS_GID_FT_REQ_SIZE);
+ rq->snscb_rblen = GIDLEN >> 1;
+ rq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+IGPOFF);
+ rq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+IGPOFF);
+ rq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+IGPOFF);
+ rq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+IGPOFF);
+ rq->snscb_sblen = 6;
+ rq->snscb_cmd = SNS_GID_FT;
+ rq->snscb_mword_div_2 = NGENT;
+ rq->snscb_fc4_type = ftype;
+ isp_put_gid_ft_request(isp, rq, (sns_gid_ft_req_t *) fcp->isp_scratch);
+ MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GID_FT_REQ_SIZE);
+ mbs.param[0] = MBOX_SEND_SNS;
+ mbs.param[1] = SNS_GID_FT_REQ_SIZE >> 1;
+ mbs.param[2] = DMA_WD1(fcp->isp_scdma);
+ mbs.param[3] = DMA_WD0(fcp->isp_scdma);
- if (hicap >= 65535) {
- isp_prt(isp, ISP_LOGWARN, "fabric too big (> 65535)");
+ /*
+ * Leave 4 and 5 alone
+ */
+ mbs.param[6] = DMA_WD3(fcp->isp_scdma);
+ mbs.param[7] = DMA_WD2(fcp->isp_scdma);
+ if (isp_fabric_mbox_cmd(isp, &mbs)) {
+ if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
+ fcp->isp_loopstate = LOOP_PDB_RCVD;
+ }
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN);
+ rs1 = (sns_gid_ft_rsp_t *) sc;
+ rs0 = (sns_gid_ft_rsp_t *) ((u_int8_t *)fcp->isp_scratch+IGPOFF);
+ isp_get_gid_ft_response(isp, rs0, rs1, NGENT);
+ if (rs1->snscb_cthdr.ct_response != FS_ACC) {
+ isp_prt(isp, ISP_LOGWARN, swrej, "GID_FT",
+ rs1->snscb_cthdr.ct_reason,
+ rs1->snscb_cthdr.ct_explanation, 0);
+ FC_SCRATCH_RELEASE(isp);
+ fcp->isp_loopstate = LOOP_FSCAN_DONE;
+ return (0);
}
/*
- * We either have a broken name server or a huge fabric if we get here.
+ * Okay, we now have a list of Port IDs for this class of device.
+ * Go through the list and for each one get the WWPN/WWNN for it
+ * and tell the outer layers about it. The outer layer needs to
+ * know: Port ID, WWNN, WWPN, FC4 type, and (possibly) port type.
+ *
+ * The lportdb structure is adequate for this.
*/
+ i = -1;
+ do {
+ sns_gxn_id_req_t grqbuf, *gq = &grqbuf;
+ sns_gxn_id_rsp_t *gs0, grsbuf, *gs1 = &grsbuf;
+ struct lportdb lcl;
+
+ i++;
+ MEMZERO(&lcl, sizeof (lcl));
+ lcl.fc4_type = ftype;
+ lcl.portid =
+ (((u_int32_t) rs1->snscb_ports[i].portid[0]) << 16) |
+ (((u_int32_t) rs1->snscb_ports[i].portid[1]) << 8) |
+ (((u_int32_t) rs1->snscb_ports[i].portid[2]));
+
+ MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t));
+ gq->snscb_rblen = SNS_GXN_ID_RESP_SIZE >> 1;
+ gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF);
+ gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF);
+ gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF);
+ gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF);
+ gq->snscb_sblen = 6;
+ gq->snscb_cmd = SNS_GPN_ID;
+ gq->snscb_portid = lcl.portid;
+ isp_put_gxn_id_request(isp, gq,
+ (sns_gxn_id_req_t *) fcp->isp_scratch);
+ MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE);
+ mbs.param[0] = MBOX_SEND_SNS;
+ mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1;
+ mbs.param[2] = DMA_WD1(fcp->isp_scdma);
+ mbs.param[3] = DMA_WD0(fcp->isp_scdma);
+ /*
+ * Leave 4 and 5 alone
+ */
+ mbs.param[6] = DMA_WD3(fcp->isp_scdma);
+ mbs.param[7] = DMA_WD2(fcp->isp_scdma);
+ if (isp_fabric_mbox_cmd(isp, &mbs)) {
+ if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
+ fcp->isp_loopstate = LOOP_PDB_RCVD;
+ }
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GXN_ID_RESP_SIZE);
+ gs0 = (sns_gxn_id_rsp_t *) ((u_int8_t *)fcp->isp_scratch+GXOFF);
+ isp_get_gxn_id_response(isp, gs0, gs1);
+ if (gs1->snscb_cthdr.ct_response != FS_ACC) {
+ isp_prt(isp, ISP_LOGWARN, swrej, "GPN_ID",
+ rs1->snscb_cthdr.ct_reason,
+ rs1->snscb_cthdr.ct_explanation, lcl.portid);
+ if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ continue;
+ }
+ lcl.port_wwn =
+ (((u_int64_t)gs1->snscb_wwn[0]) << 56) |
+ (((u_int64_t)gs1->snscb_wwn[1]) << 48) |
+ (((u_int64_t)gs1->snscb_wwn[2]) << 40) |
+ (((u_int64_t)gs1->snscb_wwn[3]) << 32) |
+ (((u_int64_t)gs1->snscb_wwn[4]) << 24) |
+ (((u_int64_t)gs1->snscb_wwn[5]) << 16) |
+ (((u_int64_t)gs1->snscb_wwn[6]) << 8) |
+ (((u_int64_t)gs1->snscb_wwn[7]));
+
+ MEMZERO((void *) gq, sizeof (sns_gxn_id_req_t));
+ gq->snscb_rblen = SNS_GXN_ID_RESP_SIZE >> 1;
+ gq->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma+GXOFF);
+ gq->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma+GXOFF);
+ gq->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma+GXOFF);
+ gq->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma+GXOFF);
+ gq->snscb_sblen = 6;
+ gq->snscb_cmd = SNS_GNN_ID;
+ gq->snscb_portid = lcl.portid;
+ isp_put_gxn_id_request(isp, gq,
+ (sns_gxn_id_req_t *) fcp->isp_scratch);
+ MEMORYBARRIER(isp, SYNC_SFORDEV, 0, SNS_GXN_ID_REQ_SIZE);
+ mbs.param[0] = MBOX_SEND_SNS;
+ mbs.param[1] = SNS_GXN_ID_REQ_SIZE >> 1;
+ mbs.param[2] = DMA_WD1(fcp->isp_scdma);
+ mbs.param[3] = DMA_WD0(fcp->isp_scdma);
+ /*
+ * Leave 4 and 5 alone
+ */
+ mbs.param[6] = DMA_WD3(fcp->isp_scdma);
+ mbs.param[7] = DMA_WD2(fcp->isp_scdma);
+ if (isp_fabric_mbox_cmd(isp, &mbs)) {
+ if (fcp->isp_loopstate >= LOOP_SCANNING_FABRIC) {
+ fcp->isp_loopstate = LOOP_PDB_RCVD;
+ }
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ MEMORYBARRIER(isp, SYNC_SFORCPU, GXOFF, SNS_GXN_ID_RESP_SIZE);
+ gs0 = (sns_gxn_id_rsp_t *) ((u_int8_t *)fcp->isp_scratch+GXOFF);
+ isp_get_gxn_id_response(isp, gs0, gs1);
+ if (gs1->snscb_cthdr.ct_response != FS_ACC) {
+ isp_prt(isp, ISP_LOGWARN, swrej, "GNN_ID",
+ rs1->snscb_cthdr.ct_reason,
+ rs1->snscb_cthdr.ct_explanation, lcl.portid);
+ if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
+ FC_SCRATCH_RELEASE(isp);
+ return (-1);
+ }
+ continue;
+ }
+ lcl.node_wwn =
+ (((u_int64_t)gs1->snscb_wwn[0]) << 56) |
+ (((u_int64_t)gs1->snscb_wwn[1]) << 48) |
+ (((u_int64_t)gs1->snscb_wwn[2]) << 40) |
+ (((u_int64_t)gs1->snscb_wwn[3]) << 32) |
+ (((u_int64_t)gs1->snscb_wwn[4]) << 24) |
+ (((u_int64_t)gs1->snscb_wwn[5]) << 16) |
+ (((u_int64_t)gs1->snscb_wwn[6]) << 8) |
+ (((u_int64_t)gs1->snscb_wwn[7]));
+
+ /*
+ * XXX: Argh! I saw some PDF which I now can't find that
+ * XXX: had proposed that the bottom nibble of CONTROL
+ * XXX: would have the SCSI-FCP role flags, which would
+ * XXX: be *awesome*.
+ *
+ lcl.roles = rs1->snscb_port[i].control & 0xf;
+ */
+
+ /*
+ * If we really want to know what kind of port type this is,
+ * we have to run another CT command. Otherwise, we'll leave
+ * it as undefined.
+ *
+ lcl.port_type = 0;
+ */
+ if (rs1->snscb_ports[i].control & 0x80) {
+ lcl.last_fabric_dev = 1;
+ } else {
+ lcl.last_fabric_dev = 0;
+ }
+ (void) isp_async(isp, ISPASYNC_FABRIC_DEV, &lcl);
+
+ } while ((rs1->snscb_ports[i].control & 0x80) == 0 && i < NGENT-1);
+
+ /*
+ * If we're not at the last entry, our list isn't big enough.
+ */
+ if ((rs1->snscb_ports[i].control & 0x80) == 0) {
+ isp_prt(isp, ISP_LOGWARN, "fabric too big for scratch area");
+ }
+
+ FC_SCRATCH_RELEASE(isp);
fcp->isp_loopstate = LOOP_FSCAN_DONE;
return (0);
}
+#endif
static void
isp_register_fc4_type(struct ispsoftc *isp)
{
fcparam *fcp = isp->isp_param;
- u_int8_t local[SNS_RFT_REQ_SIZE];
+ u_int8_t local[SNS_RFT_ID_REQ_SIZE];
sns_screq_t *reqp = (sns_screq_t *) local;
mbreg_t mbs;
- MEMZERO((void *) reqp, SNS_RFT_REQ_SIZE);
- reqp->snscb_rblen = SNS_RFT_RESP_SIZE >> 1;
+ MEMZERO((void *) reqp, SNS_RFT_ID_REQ_SIZE);
+ reqp->snscb_rblen = SNS_RFT_ID_RESP_SIZE >> 1;
reqp->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma + 0x100);
reqp->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma + 0x100);
reqp->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma + 0x100);
reqp->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma + 0x100);
reqp->snscb_sblen = 22;
- reqp->snscb_data[0] = SNS_RFT;
+ reqp->snscb_data[0] = SNS_RFT_ID;
reqp->snscb_data[4] = fcp->isp_portid & 0xffff;
reqp->snscb_data[5] = (fcp->isp_portid >> 16) & 0xff;
- reqp->snscb_data[6] = 0x100; /* SCS - FCP */
+ reqp->snscb_data[6] = (1 << FC4_SCSI);
#if 0
- reqp->snscb_data[6] |= 20; /* ISO/IEC 8802-2 LLC/SNAP */
+ reqp->snscb_data[6] |= (1 << FC4_IP); /* ISO/IEC 8802-2 LLC/SNAP */
#endif
FC_SCRATCH_ACQUIRE(isp);
isp_put_sns_request(isp, reqp, (sns_screq_t *) fcp->isp_scratch);
mbs.param[0] = MBOX_SEND_SNS;
- mbs.param[1] = SNS_RFT_REQ_SIZE >> 1;
+ mbs.param[1] = SNS_RFT_ID_REQ_SIZE >> 1;
mbs.param[2] = DMA_WD1(fcp->isp_scdma);
mbs.param[3] = DMA_WD0(fcp->isp_scdma);
/*
@@ -2652,7 +2962,7 @@ isp_start(XS_T *xs)
* out and try again later if this doesn't work.
*/
if (fcp->isp_loopstate == LOOP_PDB_RCVD && fcp->isp_onfabric) {
- if (isp_scan_fabric(isp)) {
+ if (isp_scan_fabric(isp, FC4_SCSI)) {
return (CMD_RQLATER);
}
if (fcp->isp_fwstate != FW_READY ||
@@ -2951,7 +3261,8 @@ isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg)
case ISPCTL_SCAN_FABRIC:
if (IS_FC(isp)) {
- return (isp_scan_fabric(isp));
+ int ftype = (arg)? *((int *) arg) : FC4_SCSI;
+ return (isp_scan_fabric(isp, ftype));
}
break;
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index 228669b..dda04a9 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -2734,43 +2734,13 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg)
break;
case ISPASYNC_FABRIC_DEV:
{
- int target, lrange;
+ int target, base, lim;
+ fcparam *fcp = isp->isp_param;
struct lportdb *lp = NULL;
+ struct lportdb *clp = (struct lportdb *) arg;
char *pt;
- sns_ganrsp_t *resp = (sns_ganrsp_t *) arg;
- u_int32_t portid;
- u_int64_t wwpn, wwnn;
- 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]));
-
- wwpn =
- (((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]));
-
- wwnn =
- (((u_int64_t)resp->snscb_nodename[0]) << 56) |
- (((u_int64_t)resp->snscb_nodename[1]) << 48) |
- (((u_int64_t)resp->snscb_nodename[2]) << 40) |
- (((u_int64_t)resp->snscb_nodename[3]) << 32) |
- (((u_int64_t)resp->snscb_nodename[4]) << 24) |
- (((u_int64_t)resp->snscb_nodename[5]) << 16) |
- (((u_int64_t)resp->snscb_nodename[6]) << 8) |
- (((u_int64_t)resp->snscb_nodename[7]));
- if (portid == 0 || wwpn == 0) {
- break;
- }
- switch (resp->snscb_port_type) {
+ switch (clp->port_type) {
case 1:
pt = " N_Port";
break;
@@ -2793,40 +2763,66 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg)
pt = " E_port";
break;
default:
- pt = "?";
+ pt = " ";
break;
}
+
isp_prt(isp, ISP_LOGINFO,
- "%s @ 0x%x, Node 0x%08x%08x Port %08x%08x",
- pt, portid, ((u_int32_t) (wwnn >> 32)), ((u_int32_t) wwnn),
- ((u_int32_t) (wwpn >> 32)), ((u_int32_t) wwpn));
+ "%s Fabric Device @ PortID 0x%x", pt, clp->portid);
+
+ /*
+ * If we don't have an initiator role we bail.
+ *
+ * We just use ISPASYNC_FABRIC_DEV for announcement purposes.
+ */
+
+ if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) {
+ break;
+ }
+
/*
- * We're only interested in SCSI_FCP types (for now)
+ * Is this entry for us? If so, we bail.
*/
- if ((resp->snscb_fc4_types[2] & 1) == 0) {
+
+ if (fcp->isp_portid == clp->portid) {
break;
}
- if (fcp->isp_topo != TOPO_F_PORT)
- lrange = FC_SNS_ID+1;
+
+ /*
+ * Else, the default policy is to find room for it in
+ * our local port database. Later, when we execute
+ * the call to isp_pdb_sync either this newly arrived
+ * or already logged in device will be (re)announced.
+ */
+
+ if (fcp->isp_topo == TOPO_FL_PORT)
+ base = FC_SNS_ID+1;
else
- lrange = 0;
+ base = 0;
+
+ if (fcp->isp_topo == TOPO_N_PORT)
+ lim = 1;
+ else
+ lim = MAX_FC_TARG;
+
/*
* Is it already in our list?
*/
- for (target = lrange; target < MAX_FC_TARG; target++) {
+ for (target = base; target < lim; target++) {
if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
continue;
}
lp = &fcp->portdb[target];
- if (lp->port_wwn == wwpn && lp->node_wwn == wwnn) {
+ if (lp->port_wwn == clp->port_wwn &&
+ lp->node_wwn == clp->node_wwn) {
lp->fabric_dev = 1;
break;
}
}
- if (target < MAX_FC_TARG) {
+ if (target < lim) {
break;
}
- for (target = lrange; target < MAX_FC_TARG; target++) {
+ for (target = base; target < lim; target++) {
if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
continue;
}
@@ -2835,14 +2831,16 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg)
break;
}
}
- if (target == MAX_FC_TARG) {
+ if (target == lim) {
isp_prt(isp, ISP_LOGWARN,
- "no more space for fabric devices");
+ "out of space for fabric devices");
break;
}
- lp->node_wwn = wwnn;
- lp->port_wwn = wwpn;
- lp->portid = portid;
+ lp->port_type = clp->port_type;
+ lp->fc4_type = clp->fc4_type;
+ lp->node_wwn = clp->node_wwn;
+ lp->port_wwn = clp->port_wwn;
+ lp->portid = clp->portid;
lp->fabric_dev = 1;
break;
}
diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h
index 38f0b36..5496b1a 100644
--- a/sys/dev/isp/isp_freebsd.h
+++ b/sys/dev/isp/isp_freebsd.h
@@ -156,7 +156,7 @@ struct isposinfo {
#define INLINE __inline
-#define ISP2100_SCRLEN 0x400
+#define ISP2100_SCRLEN 0x800
#define MEMZERO bzero
#define MEMCPY(dst, src, amt) bcopy((src), (dst), (amt))
diff --git a/sys/dev/isp/isp_inline.h b/sys/dev/isp/isp_inline.h
index f65c365..559cad0 100644
--- a/sys/dev/isp/isp_inline.h
+++ b/sys/dev/isp/isp_inline.h
@@ -275,11 +275,26 @@ isp_put_icb(struct ispsoftc *, isp_icb_t *, isp_icb_t *);
static INLINE void
isp_get_pdb(struct ispsoftc *, isp_pdb_t *, isp_pdb_t *);
static INLINE void
+isp_get_ct_hdr(struct ispsoftc *isp, ct_hdr_t *, ct_hdr_t *);
+static INLINE void
isp_put_sns_request(struct ispsoftc *, sns_screq_t *, sns_screq_t *);
static INLINE void
+isp_put_gid_ft_request(struct ispsoftc *, sns_gid_ft_req_t *,
+ sns_gid_ft_req_t *);
+static INLINE void
+isp_put_gxn_id_request(struct ispsoftc *, sns_gxn_id_req_t *,
+ sns_gxn_id_req_t *);
+static INLINE void
isp_get_sns_response(struct ispsoftc *, sns_scrsp_t *, sns_scrsp_t *, int);
static INLINE void
-isp_get_gan_response(struct ispsoftc *, sns_ganrsp_t *, sns_ganrsp_t *);
+isp_get_gid_ft_response(struct ispsoftc *, sns_gid_ft_rsp_t *,
+ sns_gid_ft_rsp_t *, int);
+static INLINE void
+isp_get_gxn_id_response(struct ispsoftc *, sns_gxn_id_rsp_t *,
+ sns_gxn_id_rsp_t *);
+static INLINE void
+isp_get_ga_nxt_response(struct ispsoftc *, sns_ga_nxt_rsp_t *,
+ sns_ga_nxt_rsp_t *);
#ifdef ISP_TARGET_MODE
#ifndef _ISP_TARGET_H
#include "isp_target.h"
@@ -673,6 +688,35 @@ isp_get_pdb(struct ispsoftc *isp, isp_pdb_t *src, isp_pdb_t *dst)
ISP_IOXGET_16(isp, &src->pdb_sl_ptr, dst->pdb_sl_ptr);
}
+
+/*
+ * CT_HDR canonicalization- only needed for SNS responses
+ */
+static INLINE void
+isp_get_ct_hdr(struct ispsoftc *isp, ct_hdr_t *src, ct_hdr_t *dst)
+{
+ ISP_IOXGET_8(isp, &src->ct_revision, dst->ct_revision);
+ ISP_IOXGET_8(isp, &src->ct_portid[0], dst->ct_portid[0]);
+ ISP_IOXGET_8(isp, &src->ct_portid[1], dst->ct_portid[1]);
+ ISP_IOXGET_8(isp, &src->ct_portid[2], dst->ct_portid[2]);
+ ISP_IOXGET_8(isp, &src->ct_fcs_type, dst->ct_fcs_type);
+ ISP_IOXGET_8(isp, &src->ct_fcs_subtype, dst->ct_fcs_subtype);
+ ISP_IOXGET_8(isp, &src->ct_options, dst->ct_options);
+ ISP_IOXGET_8(isp, &src->ct_res0, dst->ct_res0);
+ ISP_IOXGET_16(isp, &src->ct_response, dst->ct_response);
+ dst->ct_response = (dst->ct_response << 8) | (dst->ct_response >> 8);
+ ISP_IOXGET_16(isp, &src->ct_resid, dst->ct_resid);
+ dst->ct_resid = (dst->ct_resid << 8) | (dst->ct_resid >> 8);
+ ISP_IOXGET_8(isp, &src->ct_res1, dst->ct_res1);
+ ISP_IOXGET_8(isp, &src->ct_reason, dst->ct_reason);
+ ISP_IOXGET_8(isp, &src->ct_explanation, dst->ct_explanation);
+ ISP_IOXGET_8(isp, &src->ct_vunique, dst->ct_vunique);
+}
+
+/*
+ * Generic SNS request - not particularly useful since the per-command data
+ * isn't always 16 bit words.
+ */
static INLINE void
isp_put_sns_request(struct ispsoftc *isp, sns_screq_t *src, sns_screq_t *dst)
{
@@ -689,13 +733,51 @@ isp_put_sns_request(struct ispsoftc *isp, sns_screq_t *src, sns_screq_t *dst)
}
static INLINE void
+isp_put_gid_ft_request(struct ispsoftc *isp, sns_gid_ft_req_t *src,
+ sns_gid_ft_req_t *dst)
+{
+ ISP_IOXPUT_16(isp, src->snscb_rblen, &dst->snscb_rblen);
+ ISP_IOXPUT_16(isp, src->snscb_res0, &dst->snscb_res0);
+ ISP_IOXPUT_16(isp, src->snscb_addr[0], &dst->snscb_addr[0]);
+ ISP_IOXPUT_16(isp, src->snscb_addr[1], &dst->snscb_addr[1]);
+ ISP_IOXPUT_16(isp, src->snscb_addr[2], &dst->snscb_addr[2]);
+ ISP_IOXPUT_16(isp, src->snscb_addr[3], &dst->snscb_addr[3]);
+ ISP_IOXPUT_16(isp, src->snscb_sblen, &dst->snscb_sblen);
+ ISP_IOXPUT_16(isp, src->snscb_res1, &dst->snscb_res1);
+ ISP_IOXPUT_16(isp, src->snscb_cmd, &dst->snscb_cmd);
+ ISP_IOXPUT_16(isp, src->snscb_mword_div_2, &dst->snscb_mword_div_2);
+ ISP_IOXPUT_32(isp, src->snscb_res3, &dst->snscb_res3);
+ ISP_IOXPUT_16(isp, src->snscb_fc4_type, &dst->snscb_fc4_type);
+}
+
+static INLINE void
+isp_put_gxn_id_request(struct ispsoftc *isp, sns_gxn_id_req_t *src,
+ sns_gxn_id_req_t *dst)
+{
+ ISP_IOXPUT_16(isp, src->snscb_rblen, &dst->snscb_rblen);
+ ISP_IOXPUT_16(isp, src->snscb_res0, &dst->snscb_res0);
+ ISP_IOXPUT_16(isp, src->snscb_addr[0], &dst->snscb_addr[0]);
+ ISP_IOXPUT_16(isp, src->snscb_addr[1], &dst->snscb_addr[1]);
+ ISP_IOXPUT_16(isp, src->snscb_addr[2], &dst->snscb_addr[2]);
+ ISP_IOXPUT_16(isp, src->snscb_addr[3], &dst->snscb_addr[3]);
+ ISP_IOXPUT_16(isp, src->snscb_sblen, &dst->snscb_sblen);
+ ISP_IOXPUT_16(isp, src->snscb_res1, &dst->snscb_res1);
+ ISP_IOXPUT_16(isp, src->snscb_cmd, &dst->snscb_cmd);
+ ISP_IOXPUT_16(isp, src->snscb_res2, &dst->snscb_res2);
+ ISP_IOXPUT_32(isp, src->snscb_res3, &dst->snscb_res3);
+ ISP_IOXPUT_32(isp, src->snscb_portid, &dst->snscb_portid);
+}
+
+/*
+ * Generic SNS response - not particularly useful since the per-command data
+ * isn't always 16 bit words.
+ */
+static INLINE void
isp_get_sns_response(struct ispsoftc *isp, sns_scrsp_t *src,
sns_scrsp_t *dst, int nwords)
{
int i;
- for (i = 0; i < 16; i++) {
- ISP_IOXGET_8(isp, &src->snscb_cthdr[i], dst->snscb_cthdr[i]);
- }
+ isp_get_ct_hdr(isp, &src->snscb_cthdr, &dst->snscb_cthdr);
ISP_IOXGET_8(isp, &src->snscb_port_type, dst->snscb_port_type);
for (i = 0; i < 3; i++) {
ISP_IOXGET_8(isp, &src->snscb_port_id[i],
@@ -711,12 +793,43 @@ isp_get_sns_response(struct ispsoftc *isp, sns_scrsp_t *src,
}
static INLINE void
-isp_get_gan_response(struct ispsoftc *isp, sns_ganrsp_t *src, sns_ganrsp_t *dst)
+isp_get_gid_ft_response(struct ispsoftc *isp, sns_gid_ft_rsp_t *src,
+ sns_gid_ft_rsp_t *dst, int nwords)
{
int i;
- for (i = 0; i < 16; i++) {
- ISP_IOXGET_8(isp, &src->snscb_cthdr[i], dst->snscb_cthdr[i]);
+ isp_get_ct_hdr(isp, &src->snscb_cthdr, &dst->snscb_cthdr);
+ for (i = 0; i < nwords; i++) {
+ int j;
+ ISP_IOXGET_8(isp,
+ &src->snscb_ports[i].control,
+ dst->snscb_ports[i].control);
+ for (j = 0; j < 3; j++) {
+ ISP_IOXGET_8(isp,
+ &src->snscb_ports[i].portid[j],
+ dst->snscb_ports[i].portid[j]);
+ }
+ if (dst->snscb_ports[i].control & 0x80) {
+ break;
+ }
}
+}
+
+static INLINE void
+isp_get_gxn_id_response(struct ispsoftc *isp, sns_gxn_id_rsp_t *src,
+ sns_gxn_id_rsp_t *dst)
+{
+ int i;
+ isp_get_ct_hdr(isp, &src->snscb_cthdr, &dst->snscb_cthdr);
+ for (i = 0; i < 8; i++)
+ ISP_IOXGET_8(isp, &src->snscb_wwn[i], dst->snscb_wwn[i]);
+}
+
+static INLINE void
+isp_get_ga_nxt_response(struct ispsoftc *isp, sns_ga_nxt_rsp_t *src,
+ sns_ga_nxt_rsp_t *dst)
+{
+ int i;
+ isp_get_ct_hdr(isp, &src->snscb_cthdr, &dst->snscb_cthdr);
ISP_IOXGET_8(isp, &src->snscb_port_type, dst->snscb_port_type);
for (i = 0; i < 3; i++) {
ISP_IOXGET_8(isp, &src->snscb_port_id[i],
diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c
index 65aa923..66a9534 100644
--- a/sys/dev/isp/isp_pci.c
+++ b/sys/dev/isp/isp_pci.c
@@ -241,16 +241,6 @@ static struct ispmdvec mdvec_2300 = {
((PCI_PRODUCT_QLOGIC_ISP2312 << 16) | PCI_VENDOR_QLOGIC)
/*
- * I/O Mapping Stuff
- */
-#if _MACHINE_ARCH == SPARC64
-/* An IOMMU means that we only will ever need one descriptor. */
-#define ISP_NSEG 2
-#else
-#define ISP_NSEG ((MAXPHYS/PAGE_SIZE) + 1)
-#endif
-
-/*
* Odd case for some AMI raid cards... We need to *not* attach to this.
*/
#define AMI_RAID_SUBVENDOR_ID 0x101e
@@ -1031,7 +1021,10 @@ imc(void *arg, bus_dma_segment_t *segs, int nseg, int error)
}
}
-#define ISP_NSEGS ((BUS_SPACE_MAXSIZE / PAGE_SIZE) + 1)
+/*
+ * Should be BUS_SPACE_MAXSIZE, but MAXPHYS is larger than BUS_SPACE_MAXSIZE
+ */
+#define ISP_NSEGS ((MAXPHYS / PAGE_SIZE) + 1)
static int
isp_pci_mbxdma(struct ispsoftc *isp)
diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h
index ea62877..1bf7648 100644
--- a/sys/dev/isp/ispmbox.h
+++ b/sys/dev/isp/ispmbox.h
@@ -773,9 +773,39 @@ typedef struct {
#define SVC3_ROLE_MASK 0x30
#define SVC3_ROLE_SHIFT 4
-#define SNS_GAN 0x100
-#define SNS_GP3 0x171
-#define SNS_RFT 0x217
+/*
+ * CT definition
+ *
+ * This is as the QLogic f/w documentations defines it- which is just opposite,
+ * bit wise, from what the specification defines it as. Additionally, the
+ * ct_response and ct_resid (really from FC-GS-2) need to be byte swapped.
+ */
+
+typedef struct {
+ u_int8_t ct_revision;
+ u_int8_t ct_portid[3];
+ u_int8_t ct_fcs_type;
+ u_int8_t ct_fcs_subtype;
+ u_int8_t ct_options;
+ u_int8_t ct_res0;
+ u_int16_t ct_response;
+ u_int16_t ct_resid;
+ u_int8_t ct_res1;
+ u_int8_t ct_reason;
+ u_int8_t ct_explanation;
+ u_int8_t ct_vunique;
+} ct_hdr_t;
+#define FS_ACC 0x8002
+#define FS_RJT 0x8001
+
+#define FC4_IP 5 /* ISO/EEC 8802-2 LLC/SNAP "Out of Order Delivery" */
+#define FC4_SCSI 8 /* SCSI-3 via Fivre Channel Protocol (FCP) */
+
+#define SNS_GA_NXT 0x100
+#define SNS_GPN_ID 0x112
+#define SNS_GNN_ID 0x113
+#define SNS_GID_FT 0x171
+#define SNS_RFT_ID 0x217
typedef struct {
u_int16_t snscb_rblen; /* response buffer length (words) */
u_int16_t snscb_res0;
@@ -784,23 +814,70 @@ typedef struct {
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))))
-#define SNS_RFT_REQ_SIZE (sizeof (sns_screq_t)+(21*(sizeof (u_int16_t))))
typedef struct {
- u_int8_t snscb_cthdr[16];
+ 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_cmd;
+ u_int16_t snscb_res2;
+ u_int32_t snscb_res3;
+ u_int32_t snscb_port;
+} sns_ga_nxt_req_t;
+#define SNS_GA_NXT_REQ_SIZE (sizeof (sns_ga_nxt_req_t))
+
+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_cmd;
+ u_int16_t snscb_res2;
+ u_int32_t snscb_res3;
+ u_int32_t snscb_portid;
+} sns_gxn_id_req_t;
+#define SNS_GXN_ID_REQ_SIZE (sizeof (sns_gxn_id_req_t))
+
+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_cmd;
+ u_int16_t snscb_mword_div_2;
+ u_int32_t snscb_res3;
+ u_int32_t snscb_fc4_type;
+} sns_gid_ft_req_t;
+#define SNS_GID_FT_REQ_SIZE (sizeof (sns_gid_ft_req_t))
+
+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_cmd;
+ u_int16_t snscb_res2;
+ u_int32_t snscb_res3;
+ u_int32_t snscb_port;
+ u_int32_t snscb_fc4_types[8];
+} sns_rft_id_req_t;
+#define SNS_RFT_ID_REQ_SIZE (sizeof (sns_rft_id_req_t))
+
+typedef struct {
+ ct_hdr_t snscb_cthdr;
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 */
-#define SNS_RFT_RESP_SIZE 16
typedef struct {
- u_int8_t snscb_cthdr[16];
+ ct_hdr_t snscb_cthdr;
u_int8_t snscb_port_type;
u_int8_t snscb_port_id[3];
u_int8_t snscb_portname[8];
@@ -816,6 +893,25 @@ typedef struct {
u_int8_t snscb_fpname[8];
u_int8_t snscb_reserved;
u_int8_t snscb_hardaddr[3];
-} sns_ganrsp_t; /* Subcommand Response Structure */
+} sns_ga_nxt_rsp_t; /* Subcommand Response Structure */
+#define SNS_GA_NXT_RESP_SIZE (sizeof (sns_ga_nxt_rsp_t))
+
+typedef struct {
+ ct_hdr_t snscb_cthdr;
+ u_int8_t snscb_wwn[8];
+} sns_gxn_id_rsp_t;
+#define SNS_GXN_ID_RESP_SIZE (sizeof (sns_gxn_id_rsp_t))
+
+
+typedef struct {
+ ct_hdr_t snscb_cthdr;
+ struct {
+ u_int8_t control;
+ u_int8_t portid[3];
+ } snscb_ports[1];
+} sns_gid_ft_rsp_t;
+#define SNS_GID_FT_RESP_SIZE(x) ((sizeof (sns_gid_ft_rsp_t)) + ((x - 1) << 2))
+
+#define SNS_RFT_ID_RESP_SIZE (sizeof (ct_hdr_t))
#endif /* _ISPMBOX_H */
diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h
index 6ceab04..982bb2e 100644
--- a/sys/dev/isp/ispvar.h
+++ b/sys/dev/isp/ispvar.h
@@ -54,7 +54,7 @@
#endif
#define ISP_CORE_VERSION_MAJOR 2
-#define ISP_CORE_VERSION_MINOR 5
+#define ISP_CORE_VERSION_MINOR 6
/*
* Vector for bus specific code to provide specific services.
@@ -246,6 +246,11 @@ typedef struct {
#define FC_PORT_ID 0x7f /* Fabric Controller Special ID */
#define FC_SNS_ID 0x80 /* SNS Server Special ID */
+/* #define ISP_USE_GA_NXT 1 */ /* Use GA_NXT with switches */
+#ifndef GA_NXT_MAX
+#define GA_NXT_MAX 256
+#endif
+
typedef struct {
u_int32_t isp_fwoptions : 16,
isp_gbspeed : 2,
@@ -280,9 +285,12 @@ typedef struct {
* to move around.
*/
struct lportdb {
- u_int
+ u_int32_t
+ port_type : 8,
+ : 4,
+ fc4_type : 4,
loopid : 8,
- : 1,
+ last_fabric_dev : 1,
force_logout : 1,
was_fabric_dev : 1,
fabric_dev : 1,
OpenPOWER on IntegriCloud