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.
This commit is contained in:
mav 2017-07-03 15:56:45 +00:00
parent 8434f2dd55
commit de1115eaf6
7 changed files with 295 additions and 81 deletions

View File

@ -1,4 +1,4 @@
.\" Copyright (c) 2009-2015 Alexander Motin <mav@FreeBSD.org>
.\" Copyright (c) 2009-2017 Alexander Motin <mav@FreeBSD.org>
.\" Copyright (c) 2006 Marcus Alves Grando
.\" Copyright (c) 1998-2001 Matthew Jacob, for NASA/Ames Research Center
.\"
@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd December 20, 2016
.Dd July 3, 2017
.Dt ISP 4
.Os
.Sh NAME
@ -221,6 +221,15 @@ This value says how long to wait for devices to reappear if they (temporarily)
disappear due to loop or fabric events.
While this timeout is running, I/O
to those devices will simply be held.
.It Va dev.isp.N.use_gff_id
.It Va dev.isp.N.use_gft_id
Setting those options to 0 allows to disable use of GFF_ID and GFT_ID SNS
requests during FC fabric scan.
It may be useful if switch does not implement them correctly,
preventing some devices from being found.
Disabling them may cause unneeded logins to ports not supporting target role
or even FCP at all.
The default is 1 (enabled).
.It Va dev.isp.N.wwnn
This is the readonly World Wide Node Name value for this port.
.It Va dev.isp.N.wwpn
@ -239,7 +248,7 @@ The
driver was written by
.An Matthew Jacob
originally for NetBSD at NASA/Ames Research Center.
Some later improvement was done by
Later improvement was done by
.An Alexander Motin Aq Mt mav@FreeBSD.org .
.Sh BUGS
The driver currently ignores some NVRAM settings.

View File

@ -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,12 +3577,146 @@ 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)
{
@ -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 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
}
/* 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 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
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 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
} 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 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
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)

View File

@ -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);
}

View File

@ -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_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);
}
void
isp_put_gxx_id_request(ispsoftc_t *isp, sns_gxx_id_req_t *src, sns_gxx_id_req_t *dst)
{
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);
}
/*
* 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_get_gid_xx_response(ispsoftc_t *isp, sns_gid_xx_rsp_t *src, sns_gid_xx_rsp_t *dst, int nwords)
{
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]);
}
}
int i, j;
void
isp_get_gid_ft_response(ispsoftc_t *isp, sns_gid_ft_rsp_t *src, sns_gid_ft_rsp_t *dst, int nwords)
{
int 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);
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]);
}
}

View File

@ -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 *);

View File

@ -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) */
@ -1606,6 +1608,22 @@ typedef struct {
} sns_gid_ft_req_t;
#define SNS_GID_FT_REQ_SIZE (sizeof (sns_gid_ft_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_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;
@ -1654,20 +1672,26 @@ typedef struct {
} sns_gxn_id_rsp_t;
#define SNS_GXN_ID_RESP_SIZE (sizeof (sns_gxn_id_rsp_t))
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

View File

@ -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