aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/isp
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2017-07-03 15:56:45 +0000
committerAlexander Motin <mav@FreeBSD.org>2017-07-03 15:56:45 +0000
commita94fab67bb9c07d5837c9e2ad25d48b9b701643a (patch)
tree73126e2c342a7b144676bcb54ca8bd52832cd6b2 /sys/dev/isp
parentbe9e8bfaea0093d7612b7ee5b357c5f70f1b7463 (diff)
downloadsrc-a94fab67bb9c07d5837c9e2ad25d48b9b701643a.tar.gz
src-a94fab67bb9c07d5837c9e2ad25d48b9b701643a.zip
Switch fabric scans from GID_FT to GID_PT+GFF_ID/GFT_ID.
Instead of using GID_FT SNS request to get list of registered FCP ports, use GID_PT to get list of all Nx_Ports, and then use GFF_ID and/or GFT_ID requests to find whether they are FCP and target capable. The problem with old approach is that GID_FT does not report ports without FC-4 type registered. In particular it was impossible to boot OS from FreeBSD FC target using QLogic FC BIOS, since one does not register FC-4 type even on new cards and so ignored by old code as incompatible. As a side bonus this allows initiator to skip pointless logins to other initiators by fetching that information from SNS instead. In case some switches do not implement GFF_ID/GFT_ID correctly, add sysctls to disable that functionality. I handled broken GFF_ID of my Brocade 200E, but there may be other switches with different bugs. Linux also uses GID_PT, but GFF_ID is disabled by default there, and GFT_ID is not supported. Sponsored by: iXsystems, Inc.
Notes
Notes: svn path=/head/; revision=320604
Diffstat (limited to 'sys/dev/isp')
-rw-r--r--sys/dev/isp/isp.c194
-rw-r--r--sys/dev/isp/isp_freebsd.c9
-rw-r--r--sys/dev/isp/isp_library.c105
-rw-r--r--sys/dev/isp/isp_library.h8
-rw-r--r--sys/dev/isp/ispmbox.h38
-rw-r--r--sys/dev/isp/ispvar.h3
6 files changed, 281 insertions, 76 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index 1a5898c39461..71c059977fd9 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2009-2017 Alexander Motin <mav@FreeBSD.org>
* Copyright (c) 1997-2009 by Matthew Jacob
* All rights reserved.
*
@@ -117,7 +118,7 @@ static uint64_t isp_get_wwn(ispsoftc_t *, int, int, int);
static int isp_fclink_test(ispsoftc_t *, int, int);
static int isp_pdb_sync(ispsoftc_t *, int);
static int isp_scan_loop(ispsoftc_t *, int);
-static int isp_gid_ft(ispsoftc_t *, int);
+static int isp_gid_pt(ispsoftc_t *, int);
static int isp_scan_fabric(ispsoftc_t *, int);
static int isp_login_device(ispsoftc_t *, int, uint32_t, isp_pdb_t *, uint16_t *);
static int isp_send_change_request(ispsoftc_t *, int);
@@ -3496,7 +3497,7 @@ isp_ct_passthru(ispsoftc_t *isp, int chan, uint32_t cmd_bcnt, uint32_t rsp_bcnt)
isp_get_ct_pt(isp, (isp_ct_pt_t *)resp, &pt);
if (pt.ctp_status && pt.ctp_status != RQCS_DATA_UNDERRUN) {
isp_prt(isp, ISP_LOGWARN,
- "Chan %d GID_FT CT Passthrough returned 0x%x",
+ "Chan %d CT pass-through returned 0x%x",
chan, pt.ctp_status);
return (-1);
}
@@ -3510,7 +3511,8 @@ isp_ct_passthru(ispsoftc_t *isp, int chan, uint32_t cmd_bcnt, uint32_t rsp_bcnt)
/*
* Scan the fabric for devices and add them to our port database.
*
- * Use the GID_FT command to get all Port IDs for FC4 SCSI devices it knows.
+ * Use the GID_PT command to get list of all Nx_Port IDs SNS knows.
+ * Use GFF_ID and GFT_ID to check port type (FCP) and features (target).
*
* For 2100-23XX cards, we use the SNS mailbox command to pass simple name
* server commands to the switch management server via the QLogic f/w.
@@ -3521,15 +3523,14 @@ isp_ct_passthru(ispsoftc_t *isp, int chan, uint32_t cmd_bcnt, uint32_t rsp_bcnt)
#define NGENT ((GIDLEN - 16) >> 2)
static int
-isp_gid_ft(ispsoftc_t *isp, int chan)
+isp_gid_pt(ispsoftc_t *isp, int chan)
{
fcparam *fcp = FCPARAM(isp, chan);
ct_hdr_t ct;
- sns_gid_ft_req_t rq;
- uint32_t *rp;
+ sns_gid_pt_req_t rq;
uint8_t *scp = fcp->isp_scratch;
- isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GID_FT", chan);
+ isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GID_PT", chan);
if (FC_SCRATCH_ACQUIRE(isp, chan)) {
isp_prt(isp, ISP_LOGERR, sacq);
return (-1);
@@ -3541,11 +3542,13 @@ isp_gid_ft(ispsoftc_t *isp, int chan)
ct.ct_revision = CT_REVISION;
ct.ct_fcs_type = CT_FC_TYPE_FC;
ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
- ct.ct_cmd_resp = SNS_GID_FT;
+ ct.ct_cmd_resp = SNS_GID_PT;
ct.ct_bcnt_resid = (GIDLEN - 16) >> 2;
isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
- rp = (uint32_t *) &scp[sizeof(ct)];
- ISP_IOZPUT_32(isp, FC4_SCSI, rp);
+ scp[sizeof(ct)] = 0x7f; /* Port Type = Nx_Port */
+ scp[sizeof(ct)+1] = 0; /* Domain_ID = any */
+ scp[sizeof(ct)+2] = 0; /* Area_ID = any */
+ scp[sizeof(ct)+3] = 0; /* Flags = no Area_ID */
if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t), GIDLEN)) {
FC_SCRATCH_RELEASE(isp, chan);
@@ -3553,17 +3556,20 @@ isp_gid_ft(ispsoftc_t *isp, int chan)
}
} else {
/* Build the SNS request and execute via firmware. */
- ISP_MEMZERO(&rq, SNS_GID_FT_REQ_SIZE);
+ ISP_MEMZERO(&rq, SNS_GID_PT_REQ_SIZE);
rq.snscb_rblen = GIDLEN >> 1;
rq.snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma);
rq.snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma);
rq.snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma);
rq.snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma);
rq.snscb_sblen = 6;
- rq.snscb_cmd = SNS_GID_FT;
+ rq.snscb_cmd = SNS_GID_PT;
rq.snscb_mword_div_2 = NGENT;
- rq.snscb_fc4_type = FC4_SCSI;
- isp_put_gid_ft_request(isp, &rq, (sns_gid_ft_req_t *)scp);
+ rq.snscb_port_type = 0x7f; /* Port Type = Nx_Port */
+ rq.snscb_domain = 0; /* Domain_ID = any */
+ rq.snscb_area = 0; /* Area_ID = any */
+ rq.snscb_flags = 0; /* Flags = no Area_ID */
+ isp_put_gid_pt_request(isp, &rq, (sns_gid_pt_req_t *)scp);
if (isp_ct_sns(isp, chan, sizeof(rq), NGENT)) {
FC_SCRATCH_RELEASE(isp, chan);
@@ -3571,13 +3577,147 @@ isp_gid_ft(ispsoftc_t *isp, int chan)
}
}
- isp_get_gid_ft_response(isp, (sns_gid_ft_rsp_t *)scp,
- (sns_gid_ft_rsp_t *)fcp->isp_scanscratch, NGENT);
+ isp_get_gid_xx_response(isp, (sns_gid_xx_rsp_t *)scp,
+ (sns_gid_xx_rsp_t *)fcp->isp_scanscratch, NGENT);
FC_SCRATCH_RELEASE(isp, chan);
return (0);
}
static int
+isp_gff_id(ispsoftc_t *isp, int chan, uint32_t portid)
+{
+ fcparam *fcp = FCPARAM(isp, chan);
+ ct_hdr_t ct;
+ uint32_t *rp;
+ uint8_t *scp = fcp->isp_scratch;
+ sns_gff_id_rsp_t rsp;
+ int i, res = -1;
+
+ if (!fcp->isp_use_gff_id) /* User may block GFF_ID use. */
+ return (res);
+
+ if (!IS_24XX(isp)) /* Old chips can't request GFF_ID. */
+ return (res);
+
+ isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GFF_ID", chan);
+ if (FC_SCRATCH_ACQUIRE(isp, chan)) {
+ isp_prt(isp, ISP_LOGERR, sacq);
+ return (res);
+ }
+
+ /* Build the CT command and execute via pass-through. */
+ ISP_MEMZERO(&ct, sizeof (ct));
+ ct.ct_revision = CT_REVISION;
+ ct.ct_fcs_type = CT_FC_TYPE_FC;
+ ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
+ ct.ct_cmd_resp = SNS_GFF_ID;
+ ct.ct_bcnt_resid = (SNS_GFF_ID_RESP_SIZE - sizeof(ct)) / 4;
+ isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
+ rp = (uint32_t *) &scp[sizeof(ct)];
+ ISP_IOZPUT_32(isp, portid, rp);
+
+ if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t),
+ SNS_GFF_ID_RESP_SIZE)) {
+ FC_SCRATCH_RELEASE(isp, chan);
+ return (res);
+ }
+
+ isp_get_gff_id_response(isp, (sns_gff_id_rsp_t *)scp, &rsp);
+ if (rsp.snscb_cthdr.ct_cmd_resp == LS_ACC) {
+ for (i = 0; i < 32; i++) {
+ if (rsp.snscb_fc4_features[i] != 0) {
+ res = 0;
+ break;
+ }
+ }
+ if (((rsp.snscb_fc4_features[FC4_SCSI / 8] >>
+ ((FC4_SCSI % 8) * 4)) & 0x01) != 0)
+ res = 1;
+ /* Workaround for broken Brocade firmware. */
+ if (((ISP_SWAP32(isp, rsp.snscb_fc4_features[FC4_SCSI / 8]) >>
+ ((FC4_SCSI % 8) * 4)) & 0x01) != 0)
+ res = 1;
+ }
+ FC_SCRATCH_RELEASE(isp, chan);
+ isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFF_ID result is %d", chan, res);
+ return (res);
+}
+
+static int
+isp_gft_id(ispsoftc_t *isp, int chan, uint32_t portid)
+{
+ fcparam *fcp = FCPARAM(isp, chan);
+ ct_hdr_t ct;
+ sns_gxx_id_req_t rq;
+ uint32_t *rp;
+ uint8_t *scp = fcp->isp_scratch;
+ sns_gft_id_rsp_t rsp;
+ int i, res = -1;
+
+ if (!fcp->isp_use_gft_id) /* User may block GFT_ID use. */
+ return (res);
+
+ isp_prt(isp, ISP_LOGDEBUG0, "Chan %d requesting GFT_ID", chan);
+ if (FC_SCRATCH_ACQUIRE(isp, chan)) {
+ isp_prt(isp, ISP_LOGERR, sacq);
+ return (res);
+ }
+
+ if (IS_24XX(isp)) {
+ /* Build the CT command and execute via pass-through. */
+ ISP_MEMZERO(&ct, sizeof (ct));
+ ct.ct_revision = CT_REVISION;
+ ct.ct_fcs_type = CT_FC_TYPE_FC;
+ ct.ct_fcs_subtype = CT_FC_SUBTYPE_NS;
+ ct.ct_cmd_resp = SNS_GFT_ID;
+ ct.ct_bcnt_resid = (SNS_GFT_ID_RESP_SIZE - sizeof(ct)) / 4;
+ isp_put_ct_hdr(isp, &ct, (ct_hdr_t *)scp);
+ rp = (uint32_t *) &scp[sizeof(ct)];
+ ISP_IOZPUT_32(isp, portid, rp);
+
+ if (isp_ct_passthru(isp, chan, sizeof(ct) + sizeof(uint32_t),
+ SNS_GFT_ID_RESP_SIZE)) {
+ FC_SCRATCH_RELEASE(isp, chan);
+ return (res);
+ }
+ } else {
+ /* Build the SNS request and execute via firmware. */
+ ISP_MEMZERO(&rq, SNS_GXX_ID_REQ_SIZE);
+ rq.snscb_rblen = SNS_GFT_ID_RESP_SIZE >> 1;
+ rq.snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma);
+ rq.snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma);
+ rq.snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma);
+ rq.snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma);
+ rq.snscb_sblen = 6;
+ rq.snscb_cmd = SNS_GFT_ID;
+ rq.snscb_mword_div_2 = (SNS_GFT_ID_RESP_SIZE - sizeof(ct)) / 4;
+ rq.snscb_portid = portid;
+ isp_put_gxx_id_request(isp, &rq, (sns_gxx_id_req_t *)scp);
+
+ if (isp_ct_sns(isp, chan, sizeof(rq), SNS_GFT_ID_RESP_SIZE)) {
+ FC_SCRATCH_RELEASE(isp, chan);
+ return (res);
+ }
+ }
+
+ isp_get_gft_id_response(isp, (sns_gft_id_rsp_t *)scp, &rsp);
+ if (rsp.snscb_cthdr.ct_cmd_resp == LS_ACC) {
+ for (i = 0; i < 8; i++) {
+ if (rsp.snscb_fc4_types[i] != 0) {
+ res = 0;
+ break;
+ }
+ }
+ if (((rsp.snscb_fc4_types[FC4_SCSI / 32] >>
+ (FC4_SCSI % 32)) & 0x01) != 0)
+ res = 1;
+ }
+ FC_SCRATCH_RELEASE(isp, chan);
+ isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GFT_ID result is %d", chan, res);
+ return (res);
+}
+
+static int
isp_scan_fabric(ispsoftc_t *isp, int chan)
{
fcparam *fcp = FCPARAM(isp, chan);
@@ -3586,7 +3726,7 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
uint16_t nphdl;
isp_pdb_t pdb;
int portidx, portlim, r;
- sns_gid_ft_rsp_t *rs;
+ sns_gid_xx_rsp_t *rs;
if (fcp->isp_loopstate < LOOP_LSCAN_DONE)
return (-1);
@@ -3627,7 +3767,7 @@ fail:
}
/* Get list of port IDs from SNS. */
- r = isp_gid_ft(isp, chan);
+ r = isp_gid_pt(isp, chan);
if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
goto abort;
if (r > 0) {
@@ -3638,7 +3778,7 @@ fail:
return (-1);
}
- rs = (sns_gid_ft_rsp_t *) fcp->isp_scanscratch;
+ rs = (sns_gid_xx_rsp_t *) fcp->isp_scanscratch;
if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
goto abort;
if (rs->snscb_cthdr.ct_cmd_resp != LS_ACC) {
@@ -3648,7 +3788,7 @@ fail:
} else {
level = ISP_LOGWARN;
}
- isp_prt(isp, level, "Chan %d Fabric Nameserver rejected GID_FT"
+ isp_prt(isp, level, "Chan %d Fabric Nameserver rejected GID_PT"
" (Reason=0x%x Expl=0x%x)", chan,
rs->snscb_cthdr.ct_reason,
rs->snscb_cthdr.ct_explanation);
@@ -3780,6 +3920,20 @@ relogin:
continue;
}
+ r = isp_gff_id(isp, chan, portid);
+ if (r == 0) {
+ isp_prt(isp, ISP_LOG_SANCFG,
+ "Chan %d Port 0x%06x is not an FCP target", chan, portid);
+ continue;
+ }
+ if (r < 0)
+ r = isp_gft_id(isp, chan, portid);
+ if (r == 0) {
+ isp_prt(isp, ISP_LOG_SANCFG,
+ "Chan %d Port 0x%06x is not FCP", chan, portid);
+ continue;
+ }
+
if (isp_login_device(isp, chan, portid, &pdb,
&FCPARAM(isp, 0)->isp_lasthdl)) {
if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index 9e904da35184..354d2d4aa03f 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2009-2017 Alexander Motin <mav@FreeBSD.org>
* Copyright (c) 1997-2009 by Matthew Jacob
* All rights reserved.
*
@@ -169,6 +170,8 @@ isp_attach_chan(ispsoftc_t *isp, struct cam_devq *devq, int chan)
fc->path = path;
fc->isp = isp;
fc->ready = 1;
+ fcp->isp_use_gft_id = 1;
+ fcp->isp_use_gff_id = 1;
callout_init_mtx(&fc->gdt, &isp->isp_lock, 0);
TASK_INIT(&fc->gtask, 1, isp_gdt_task, fc);
@@ -235,6 +238,12 @@ isp_attach_chan(ispsoftc_t *isp, struct cam_devq *devq, int chan)
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"topo", CTLFLAG_RD, &fcp->isp_topo, 0,
"Connection topology");
+ SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "use_gft_id", CTLFLAG_RWTUN, &fcp->isp_use_gft_id, 0,
+ "Use GFT_ID during fabric scan");
+ SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "use_gff_id", CTLFLAG_RWTUN, &fcp->isp_use_gff_id, 0,
+ "Use GFF_ID during fabric scan");
}
return (0);
}
diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c
index 83cf39217e90..72e2f179e3f2 100644
--- a/sys/dev/isp/isp_library.c
+++ b/sys/dev/isp/isp_library.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2009-2017 Alexander Motin <mav@FreeBSD.org>
* Copyright (c) 1997-2009 by Matthew Jacob
* All rights reserved.
*
@@ -1742,7 +1743,7 @@ isp_put_gid_ft_request(ispsoftc_t *isp, sns_gid_ft_req_t *src, sns_gid_ft_req_t
}
void
-isp_put_gxn_id_request(ispsoftc_t *isp, sns_gxn_id_req_t *src, sns_gxn_id_req_t *dst)
+isp_put_gid_pt_request(ispsoftc_t *isp, sns_gid_pt_req_t *src, sns_gid_pt_req_t *dst)
{
ISP_IOXPUT_16(isp, src->snscb_rblen, &dst->snscb_rblen);
ISP_IOXPUT_16(isp, src->snscb_reserved0, &dst->snscb_reserved0);
@@ -1753,48 +1754,46 @@ isp_put_gxn_id_request(ispsoftc_t *isp, sns_gxn_id_req_t *src, sns_gxn_id_req_t
ISP_IOXPUT_16(isp, src->snscb_sblen, &dst->snscb_sblen);
ISP_IOXPUT_16(isp, src->snscb_reserved1, &dst->snscb_reserved1);
ISP_IOXPUT_16(isp, src->snscb_cmd, &dst->snscb_cmd);
- ISP_IOXPUT_16(isp, src->snscb_reserved2, &dst->snscb_reserved2);
+ ISP_IOXPUT_16(isp, src->snscb_mword_div_2, &dst->snscb_mword_div_2);
ISP_IOXPUT_32(isp, src->snscb_reserved3, &dst->snscb_reserved3);
- ISP_IOXPUT_32(isp, src->snscb_portid, &dst->snscb_portid);
+ ISP_IOXPUT_8(isp, src->snscb_port_type, &dst->snscb_port_type);
+ ISP_IOXPUT_8(isp, src->snscb_domain, &dst->snscb_domain);
+ ISP_IOXPUT_8(isp, src->snscb_area, &dst->snscb_area);
+ ISP_IOXPUT_8(isp, src->snscb_flags, &dst->snscb_flags);
}
-/*
- * Generic SNS response - not particularly useful since the per-command data
- * isn't always 16 bit words.
- */
void
-isp_get_sns_response(ispsoftc_t *isp, sns_scrsp_t *src, sns_scrsp_t *dst, int nwords)
+isp_put_gxx_id_request(ispsoftc_t *isp, sns_gxx_id_req_t *src, sns_gxx_id_req_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],
- dst->snscb_port_id[i]);
- }
- for (i = 0; i < 8; i++) {
- ISP_IOXGET_8(isp, &src->snscb_portname[i],
- dst->snscb_portname[i]);
- }
- for (i = 0; i < nwords; i++) {
- ISP_IOXGET_16(isp, &src->snscb_data[i], dst->snscb_data[i]);
- }
+ ISP_IOXPUT_16(isp, src->snscb_rblen, &dst->snscb_rblen);
+ ISP_IOXPUT_16(isp, src->snscb_reserved0, &dst->snscb_reserved0);
+ 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_reserved1, &dst->snscb_reserved1);
+ 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_reserved3, &dst->snscb_reserved3);
+ ISP_IOXPUT_32(isp, src->snscb_portid, &dst->snscb_portid);
}
void
-isp_get_gid_ft_response(ispsoftc_t *isp, sns_gid_ft_rsp_t *src, sns_gid_ft_rsp_t *dst, int nwords)
+isp_get_gid_xx_response(ispsoftc_t *isp, sns_gid_xx_rsp_t *src, sns_gid_xx_rsp_t *dst, int nwords)
{
- int i;
+ int i, j;
+
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);
+ ISP_IOZGET_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]);
+ ISP_IOZGET_8(isp, &src->snscb_ports[i].portid[j],
+ dst->snscb_ports[i].portid[j]);
}
- if (dst->snscb_ports[i].control & 0x80) {
+ if (dst->snscb_ports[i].control & 0x80)
break;
- }
}
}
@@ -1802,9 +1801,21 @@ void
isp_get_gxn_id_response(ispsoftc_t *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_IOZGET_8(isp, &src->snscb_wwn[i], dst->snscb_wwn[i]);
+}
+
+void
+isp_get_gft_id_response(ispsoftc_t *isp, sns_gft_id_rsp_t *src, sns_gft_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]);
+ ISP_IOZGET_32(isp, &src->snscb_fc4_types[i],
+ dst->snscb_fc4_types[i]);
}
}
@@ -1812,9 +1823,11 @@ void
isp_get_gff_id_response(ispsoftc_t *isp, sns_gff_id_rsp_t *src, sns_gff_id_rsp_t *dst)
{
int i;
+
isp_get_ct_hdr(isp, &src->snscb_cthdr, &dst->snscb_cthdr);
for (i = 0; i < 32; i++) {
- ISP_IOXGET_32(isp, &src->snscb_fc4_features[i], dst->snscb_fc4_features[i]);
+ ISP_IOZGET_32(isp, &src->snscb_fc4_features[i],
+ dst->snscb_fc4_features[i]);
}
}
@@ -1823,42 +1836,42 @@ isp_get_ga_nxt_response(ispsoftc_t *isp, sns_ga_nxt_rsp_t *src, sns_ga_nxt_rsp_t
{
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);
+ ISP_IOZGET_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], dst->snscb_port_id[i]);
+ ISP_IOZGET_8(isp, &src->snscb_port_id[i], dst->snscb_port_id[i]);
}
for (i = 0; i < 8; i++) {
- ISP_IOXGET_8(isp, &src->snscb_portname[i], dst->snscb_portname[i]);
+ ISP_IOZGET_8(isp, &src->snscb_portname[i], dst->snscb_portname[i]);
}
- ISP_IOXGET_8(isp, &src->snscb_pnlen, dst->snscb_pnlen);
+ ISP_IOZGET_8(isp, &src->snscb_pnlen, dst->snscb_pnlen);
for (i = 0; i < 255; i++) {
- ISP_IOXGET_8(isp, &src->snscb_pname[i], dst->snscb_pname[i]);
+ ISP_IOZGET_8(isp, &src->snscb_pname[i], dst->snscb_pname[i]);
}
for (i = 0; i < 8; i++) {
- ISP_IOXGET_8(isp, &src->snscb_nodename[i], dst->snscb_nodename[i]);
+ ISP_IOZGET_8(isp, &src->snscb_nodename[i], dst->snscb_nodename[i]);
}
- ISP_IOXGET_8(isp, &src->snscb_nnlen, dst->snscb_nnlen);
+ ISP_IOZGET_8(isp, &src->snscb_nnlen, dst->snscb_nnlen);
for (i = 0; i < 255; i++) {
- ISP_IOXGET_8(isp, &src->snscb_nname[i], dst->snscb_nname[i]);
+ ISP_IOZGET_8(isp, &src->snscb_nname[i], dst->snscb_nname[i]);
}
for (i = 0; i < 8; i++) {
- ISP_IOXGET_8(isp, &src->snscb_ipassoc[i], dst->snscb_ipassoc[i]);
+ ISP_IOZGET_8(isp, &src->snscb_ipassoc[i], dst->snscb_ipassoc[i]);
}
for (i = 0; i < 16; i++) {
- ISP_IOXGET_8(isp, &src->snscb_ipaddr[i], dst->snscb_ipaddr[i]);
+ ISP_IOZGET_8(isp, &src->snscb_ipaddr[i], dst->snscb_ipaddr[i]);
}
for (i = 0; i < 4; i++) {
- ISP_IOXGET_8(isp, &src->snscb_svc_class[i], dst->snscb_svc_class[i]);
+ ISP_IOZGET_8(isp, &src->snscb_svc_class[i], dst->snscb_svc_class[i]);
}
for (i = 0; i < 32; i++) {
- ISP_IOXGET_8(isp, &src->snscb_fc4_types[i], dst->snscb_fc4_types[i]);
+ ISP_IOZGET_8(isp, &src->snscb_fc4_types[i], dst->snscb_fc4_types[i]);
}
for (i = 0; i < 8; i++) {
- ISP_IOXGET_8(isp, &src->snscb_fpname[i], dst->snscb_fpname[i]);
+ ISP_IOZGET_8(isp, &src->snscb_fpname[i], dst->snscb_fpname[i]);
}
- ISP_IOXGET_8(isp, &src->snscb_reserved, dst->snscb_reserved);
+ ISP_IOZGET_8(isp, &src->snscb_reserved, dst->snscb_reserved);
for (i = 0; i < 3; i++) {
- ISP_IOXGET_8(isp, &src->snscb_hardaddr[i], dst->snscb_hardaddr[i]);
+ ISP_IOZGET_8(isp, &src->snscb_hardaddr[i], dst->snscb_hardaddr[i]);
}
}
diff --git a/sys/dev/isp/isp_library.h b/sys/dev/isp/isp_library.h
index 8ec97c1ceb4f..1b45ad22ee5d 100644
--- a/sys/dev/isp/isp_library.h
+++ b/sys/dev/isp/isp_library.h
@@ -1,5 +1,6 @@
/* $FreeBSD$ */
/*-
+ * Copyright (c) 2009-2017 Alexander Motin <mav@FreeBSD.org>
* Copyright (c) 1997-2009 by Matthew Jacob
* All rights reserved.
*
@@ -127,10 +128,11 @@ void isp_put_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *, isp_ct_pt_t *);
void isp_put_ms(ispsoftc_t *isp, isp_ms_t *, isp_ms_t *);
void isp_put_sns_request(ispsoftc_t *, sns_screq_t *, sns_screq_t *);
void isp_put_gid_ft_request(ispsoftc_t *, sns_gid_ft_req_t *, sns_gid_ft_req_t *);
-void isp_put_gxn_id_request(ispsoftc_t *, sns_gxn_id_req_t *, sns_gxn_id_req_t *);
-void isp_get_sns_response(ispsoftc_t *, sns_scrsp_t *, sns_scrsp_t *, int);
-void isp_get_gid_ft_response(ispsoftc_t *, sns_gid_ft_rsp_t *, sns_gid_ft_rsp_t *, int);
+void isp_put_gid_pt_request(ispsoftc_t *, sns_gid_pt_req_t *, sns_gid_pt_req_t *);
+void isp_put_gxx_id_request(ispsoftc_t *, sns_gxx_id_req_t *, sns_gxx_id_req_t *);
+void isp_get_gid_xx_response(ispsoftc_t *, sns_gid_xx_rsp_t *, sns_gid_xx_rsp_t *, int);
void isp_get_gxn_id_response(ispsoftc_t *, sns_gxn_id_rsp_t *, sns_gxn_id_rsp_t *);
+void isp_get_gft_id_response(ispsoftc_t *, sns_gft_id_rsp_t *, sns_gft_id_rsp_t *);
void isp_get_gff_id_response(ispsoftc_t *, sns_gff_id_rsp_t *, sns_gff_id_rsp_t *);
void isp_get_ga_nxt_response(ispsoftc_t *, sns_ga_nxt_rsp_t *, sns_ga_nxt_rsp_t *);
void isp_get_els(ispsoftc_t *, els_t *, els_t *);
diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h
index deb40866a5d4..3d3d5f2ac950 100644
--- a/sys/dev/isp/ispmbox.h
+++ b/sys/dev/isp/ispmbox.h
@@ -1,5 +1,6 @@
/* $FreeBSD$ */
/*-
+ * Copyright (c) 2009-2017 Alexander Motin <mav@FreeBSD.org>
* Copyright (c) 1997-2009 by Matthew Jacob
* All rights reserved.
*
@@ -1551,6 +1552,7 @@ typedef struct {
#define SNS_GA_NXT 0x100
#define SNS_GPN_ID 0x112
#define SNS_GNN_ID 0x113
+#define SNS_GFT_ID 0x117
#define SNS_GFF_ID 0x11F
#define SNS_GID_FT 0x171
#define SNS_GID_PT 0x1A1
@@ -1580,18 +1582,18 @@ typedef struct {
} sns_ga_nxt_req_t;
#define SNS_GA_NXT_REQ_SIZE (sizeof (sns_ga_nxt_req_t))
-typedef struct {
+typedef struct { /* Used for GFT_ID, GFF_ID, etc. */
uint16_t snscb_rblen; /* response buffer length (words) */
uint16_t snscb_reserved0;
uint16_t snscb_addr[4]; /* response buffer address */
uint16_t snscb_sblen; /* subcommand buffer length (words) */
uint16_t snscb_reserved1;
uint16_t snscb_cmd;
- uint16_t snscb_reserved2;
+ uint16_t snscb_mword_div_2;
uint32_t snscb_reserved3;
uint32_t snscb_portid;
-} sns_gxn_id_req_t;
-#define SNS_GXN_ID_REQ_SIZE (sizeof (sns_gxn_id_req_t))
+} sns_gxx_id_req_t;
+#define SNS_GXX_ID_REQ_SIZE (sizeof (sns_gxx_id_req_t))
typedef struct {
uint16_t snscb_rblen; /* response buffer length (words) */
@@ -1613,6 +1615,22 @@ typedef struct {
uint16_t snscb_sblen; /* subcommand buffer length (words) */
uint16_t snscb_reserved1;
uint16_t snscb_cmd;
+ uint16_t snscb_mword_div_2;
+ uint32_t snscb_reserved3;
+ uint8_t snscb_port_type;
+ uint8_t snscb_domain;
+ uint8_t snscb_area;
+ uint8_t snscb_flags;
+} sns_gid_pt_req_t;
+#define SNS_GID_PT_REQ_SIZE (sizeof (sns_gid_pt_req_t))
+
+typedef struct {
+ uint16_t snscb_rblen; /* response buffer length (words) */
+ uint16_t snscb_reserved0;
+ uint16_t snscb_addr[4]; /* response buffer address */
+ uint16_t snscb_sblen; /* subcommand buffer length (words) */
+ uint16_t snscb_reserved1;
+ uint16_t snscb_cmd;
uint16_t snscb_reserved2;
uint32_t snscb_reserved3;
uint32_t snscb_port;
@@ -1656,18 +1674,24 @@ typedef struct {
typedef struct {
ct_hdr_t snscb_cthdr;
+ uint32_t snscb_fc4_types[8];
+} sns_gft_id_rsp_t;
+#define SNS_GFT_ID_RESP_SIZE (sizeof (sns_gft_id_rsp_t))
+
+typedef struct {
+ ct_hdr_t snscb_cthdr;
uint32_t snscb_fc4_features[32];
} sns_gff_id_rsp_t;
#define SNS_GFF_ID_RESP_SIZE (sizeof (sns_gff_id_rsp_t))
-typedef struct {
+typedef struct { /* Used for GID_FT, GID_PT, etc. */
ct_hdr_t snscb_cthdr;
struct {
uint8_t control;
uint8_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))
+} sns_gid_xx_rsp_t;
+#define SNS_GID_XX_RESP_SIZE(x) ((sizeof (sns_gid_xx_rsp_t)) + ((x - 1) << 2))
/*
* Other Misc Structures
diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h
index 89c132b39875..c49ec3aff192 100644
--- a/sys/dev/isp/ispvar.h
+++ b/sys/dev/isp/ispvar.h
@@ -1,5 +1,6 @@
/* $FreeBSD$ */
/*-
+ * Copyright (c) 2009-2017 Alexander Motin <mav@FreeBSD.org>
* Copyright (c) 1997-2009 by Matthew Jacob
* All rights reserved.
*
@@ -446,6 +447,8 @@ typedef struct {
uint16_t isp_login_hdl; /* Logging in handle */
uint8_t isp_retry_delay;
uint8_t isp_retry_count;
+ int isp_use_gft_id; /* Use GFT_ID */
+ int isp_use_gff_id; /* Use GFF_ID */
/*
* Current active WWNN/WWPN