Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 3 Jul 2017 15:56:45 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r320604 - in head: share/man/man4 sys/dev/isp
Message-ID:  <201707031556.v63Fuj4O074204@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Mon Jul  3 15:56:45 2017
New Revision: 320604
URL: https://svnweb.freebsd.org/changeset/base/320604

Log:
  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.

Modified:
  head/share/man/man4/isp.4
  head/sys/dev/isp/isp.c
  head/sys/dev/isp/isp_freebsd.c
  head/sys/dev/isp/isp_library.c
  head/sys/dev/isp/isp_library.h
  head/sys/dev/isp/ispmbox.h
  head/sys/dev/isp/ispvar.h

Modified: head/share/man/man4/isp.4
==============================================================================
--- head/share/man/man4/isp.4	Mon Jul  3 15:54:44 2017	(r320603)
+++ head/share/man/man4/isp.4	Mon Jul  3 15:56:45 2017	(r320604)
@@ -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 reappe
 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.

Modified: head/sys/dev/isp/isp.c
==============================================================================
--- head/sys/dev/isp/isp.c	Mon Jul  3 15:54:44 2017	(r320603)
+++ head/sys/dev/isp/isp.c	Mon Jul  3 15:56:45 2017	(r320604)
@@ -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, in
 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 cm
 	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 cm
 /*
  * 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 cm
 #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);
@@ -3777,6 +3917,20 @@ relogin:
 		if ((fcp->role & ISP_ROLE_INITIATOR) == 0) {
 			isp_prt(isp, ISP_LOG_SANCFG,
 			    "Chan %d Port 0x%06x is not logged in", chan, portid);
+			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;
 		}
 

Modified: head/sys/dev/isp/isp_freebsd.c
==============================================================================
--- head/sys/dev/isp/isp_freebsd.c	Mon Jul  3 15:54:44 2017	(r320603)
+++ head/sys/dev/isp/isp_freebsd.c	Mon Jul  3 15:56:45 2017	(r320604)
@@ -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
 		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
 		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);
 }

Modified: head/sys/dev/isp/isp_library.c
==============================================================================
--- head/sys/dev/isp/isp_library.c	Mon Jul  3 15:54:44 2017	(r320603)
+++ head/sys/dev/isp/isp_library.c	Mon Jul  3 15:56:45 2017	(r320604)
@@ -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
 }
 
 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
 	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_rs
 {
 	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]);
 	}
 }
 

Modified: head/sys/dev/isp/isp_library.h
==============================================================================
--- head/sys/dev/isp/isp_library.h	Mon Jul  3 15:54:44 2017	(r320603)
+++ head/sys/dev/isp/isp_library.h	Mon Jul  3 15:56:45 2017	(r320604)
@@ -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
 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 *);

Modified: head/sys/dev/isp/ispmbox.h
==============================================================================
--- head/sys/dev/isp/ispmbox.h	Mon Jul  3 15:54:44 2017	(r320603)
+++ head/sys/dev/isp/ispmbox.h	Mon Jul  3 15:56:45 2017	(r320604)
@@ -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

Modified: head/sys/dev/isp/ispvar.h
==============================================================================
--- head/sys/dev/isp/ispvar.h	Mon Jul  3 15:54:44 2017	(r320603)
+++ head/sys/dev/isp/ispvar.h	Mon Jul  3 15:56:45 2017	(r320604)
@@ -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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201707031556.v63Fuj4O074204>