aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/isp/isp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/isp/isp.c')
-rw-r--r--sys/dev/isp/isp.c451
1 files changed, 381 insertions, 70 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index b6b9d4d7b838e..83af43e7bec3f 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_scan_fabric(struct ispsoftc *isp)
+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, 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;