Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 6 Jul 2014 07:34:18 +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: r268309 - in head/sys/cam: ctl scsi
Message-ID:  <201407060734.s667YIME034350@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Sun Jul  6 07:34:18 2014
New Revision: 268309
URL: http://svnweb.freebsd.org/changeset/base/268309

Log:
  Add support for SCSI Ports (88h) VPD page.

Modified:
  head/sys/cam/ctl/ctl.c
  head/sys/cam/scsi/scsi_all.h

Modified: head/sys/cam/ctl/ctl.c
==============================================================================
--- head/sys/cam/ctl/ctl.c	Sun Jul  6 07:02:36 2014	(r268308)
+++ head/sys/cam/ctl/ctl.c	Sun Jul  6 07:34:18 2014	(r268309)
@@ -315,10 +315,11 @@ SYSCTL_INT(_kern_cam_ctl, OID_AUTO, verb
     &verbose, 0, "Show SCSI errors returned to initiator");
 
 /*
- * Serial number (0x80), device id (0x83), supported pages (0x00),
- * Block limits (0xB0) and Logical Block Provisioning (0xB2)
+ * Supported pages (0x00), Serial number (0x80), Device ID (0x83),
+ * SCSI Ports (0x88), Block limits (0xB0) and
+ * Logical Block Provisioning (0xB2)
  */
-#define SCSI_EVPD_NUM_SUPPORTED_PAGES	5
+#define SCSI_EVPD_NUM_SUPPORTED_PAGES	6
 
 static void ctl_isc_event_handler(ctl_ha_channel chanel, ctl_ha_event event,
 				  int param);
@@ -376,6 +377,8 @@ static void ctl_hndl_per_res_out_on_othe
 static int ctl_inquiry_evpd_supported(struct ctl_scsiio *ctsio, int alloc_len);
 static int ctl_inquiry_evpd_serial(struct ctl_scsiio *ctsio, int alloc_len);
 static int ctl_inquiry_evpd_devid(struct ctl_scsiio *ctsio, int alloc_len);
+static int ctl_inquiry_evpd_scsi_ports(struct ctl_scsiio *ctsio,
+					 int alloc_len);
 static int ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio,
 					 int alloc_len);
 static int ctl_inquiry_evpd_lbp(struct ctl_scsiio *ctsio, int alloc_len);
@@ -7238,7 +7241,7 @@ ctl_report_tagret_port_groups(struct ctl
 			    TPG_ASYMMETRIC_ACCESS_NONOPTIMIZED;
 		tpg_desc->support = TPG_AO_SUP;
 		if (!single)
-			tpg_desc->support = TPG_AN_SUP;
+			tpg_desc->support |= TPG_AN_SUP;
 		scsi_ulto2b(g + 1, tpg_desc->target_port_group);
 		tpg_desc->status = TPG_IMPLICIT;
 		pc = 0;
@@ -9626,10 +9629,12 @@ ctl_inquiry_evpd_supported(struct ctl_sc
 	pages->page_list[1] = SVPD_UNIT_SERIAL_NUMBER;
 	/* Device Identification */
 	pages->page_list[2] = SVPD_DEVICE_ID;
+	/* SCSI Ports */
+	pages->page_list[3] = SVPD_SCSI_PORTS;
 	/* Block limits */
-	pages->page_list[3] = SVPD_BLOCK_LIMITS;
+	pages->page_list[4] = SVPD_BLOCK_LIMITS;
 	/* Logical Block Provisioning */
-	pages->page_list[4] = SVPD_LBP;
+	pages->page_list[5] = SVPD_LBP;
 
 	ctsio->scsi_status = SCSI_STATUS_OK;
 
@@ -9820,6 +9825,117 @@ ctl_inquiry_evpd_devid(struct ctl_scsiio
 }
 
 static int
+ctl_inquiry_evpd_scsi_ports(struct ctl_scsiio *ctsio, int alloc_len)
+{
+	struct ctl_softc *softc = control_softc;
+	struct scsi_vpd_scsi_ports *sp;
+	struct scsi_vpd_port_designation *pd;
+	struct scsi_vpd_port_designation_cont *pdc;
+	struct ctl_lun *lun;
+	struct ctl_port *port;
+	int data_len, num_target_ports, id_len, g, pg, p;
+	int num_target_port_groups, single;
+
+	lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
+
+	single = ctl_is_single;
+	if (single)
+		num_target_port_groups = 1;
+	else
+		num_target_port_groups = NUM_TARGET_PORT_GROUPS;
+	num_target_ports = 0;
+	id_len = 0;
+	mtx_lock(&softc->ctl_lock);
+	STAILQ_FOREACH(port, &softc->port_list, links) {
+		if ((port->status & CTL_PORT_STATUS_ONLINE) == 0)
+			continue;
+		if (ctl_map_lun_back(port->targ_port, lun->lun) >=
+		    CTL_MAX_LUNS)
+			continue;
+		num_target_ports++;
+		if (port->port_devid)
+			id_len += port->port_devid->len;
+	}
+	mtx_unlock(&softc->ctl_lock);
+
+	data_len = sizeof(struct scsi_vpd_scsi_ports) + num_target_port_groups *
+	    num_target_ports * (sizeof(struct scsi_vpd_port_designation) +
+	     sizeof(struct scsi_vpd_port_designation_cont)) + id_len;
+	ctsio->kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
+	sp = (struct scsi_vpd_scsi_ports *)ctsio->kern_data_ptr;
+	ctsio->kern_sg_entries = 0;
+
+	if (data_len < alloc_len) {
+		ctsio->residual = alloc_len - data_len;
+		ctsio->kern_data_len = data_len;
+		ctsio->kern_total_len = data_len;
+	} else {
+		ctsio->residual = 0;
+		ctsio->kern_data_len = alloc_len;
+		ctsio->kern_total_len = alloc_len;
+	}
+	ctsio->kern_data_resid = 0;
+	ctsio->kern_rel_offset = 0;
+	ctsio->kern_sg_entries = 0;
+
+	/*
+	 * The control device is always connected.  The disk device, on the
+	 * other hand, may not be online all the time.  Need to change this
+	 * to figure out whether the disk device is actually online or not.
+	 */
+	if (lun != NULL)
+		sp->device = (SID_QUAL_LU_CONNECTED << 5) |
+				  lun->be_lun->lun_type;
+	else
+		sp->device = (SID_QUAL_LU_OFFLINE << 5) | T_DIRECT;
+
+	sp->page_code = SVPD_SCSI_PORTS;
+	scsi_ulto2b(data_len - sizeof(struct scsi_vpd_scsi_ports),
+	    sp->page_length);
+	pd = &sp->design[0];
+
+	mtx_lock(&softc->ctl_lock);
+	if (softc->flags & CTL_FLAG_MASTER_SHELF)
+		pg = 0;
+	else
+		pg = 1;
+	for (g = 0; g < num_target_port_groups; g++) {
+		STAILQ_FOREACH(port, &softc->port_list, links) {
+			if ((port->status & CTL_PORT_STATUS_ONLINE) == 0)
+				continue;
+			if (ctl_map_lun_back(port->targ_port, lun->lun) >=
+			    CTL_MAX_LUNS)
+				continue;
+			p = port->targ_port % CTL_MAX_PORTS + g * CTL_MAX_PORTS;
+			scsi_ulto2b(p, pd->relative_port_id);
+			scsi_ulto2b(0, pd->initiator_transportid_length);
+			pdc = (struct scsi_vpd_port_designation_cont *)
+			    &pd->initiator_transportid[0];
+			if (port->port_devid && g == pg) {
+				id_len = port->port_devid->len;
+				scsi_ulto2b(port->port_devid->len,
+				    pdc->target_port_descriptors_length);
+				memcpy(pdc->target_port_descriptors,
+				    port->port_devid->data, port->port_devid->len);
+			} else {
+				id_len = 0;
+				scsi_ulto2b(0, pdc->target_port_descriptors_length);
+			}
+			pd = (struct scsi_vpd_port_designation *)
+			    ((uint8_t *)pdc->target_port_descriptors + id_len);
+		}
+	}
+	mtx_unlock(&softc->ctl_lock);
+
+	ctsio->scsi_status = SCSI_STATUS_OK;
+	ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
+	ctsio->be_move_done = ctl_config_move_done;
+	ctl_datamove((union ctl_io *)ctsio);
+
+	return (CTL_RETVAL_COMPLETE);
+}
+
+static int
 ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio, int alloc_len)
 {
 	struct scsi_vpd_block_limits *bl_ptr;
@@ -9950,6 +10066,9 @@ ctl_inquiry_evpd(struct ctl_scsiio *ctsi
 	case SVPD_DEVICE_ID:
 		retval = ctl_inquiry_evpd_devid(ctsio, alloc_len);
 		break;
+	case SVPD_SCSI_PORTS:
+		retval = ctl_inquiry_evpd_scsi_ports(ctsio, alloc_len);
+		break;
 	case SVPD_BLOCK_LIMITS:
 		retval = ctl_inquiry_evpd_block_limits(ctsio, alloc_len);
 		break;

Modified: head/sys/cam/scsi/scsi_all.h
==============================================================================
--- head/sys/cam/scsi/scsi_all.h	Sun Jul  6 07:02:36 2014	(r268308)
+++ head/sys/cam/scsi/scsi_all.h	Sun Jul  6 07:34:18 2014	(r268309)
@@ -1733,6 +1733,31 @@ struct scsi_diag_page {
 	uint8_t params[0];
 };
 
+struct scsi_vpd_port_designation
+{
+	uint8_t reserved[2];
+	uint8_t relative_port_id[2];
+	uint8_t reserved2[2];
+	uint8_t initiator_transportid_length[2];
+	uint8_t initiator_transportid[0];
+};
+
+struct scsi_vpd_port_designation_cont
+{
+	uint8_t reserved[2];
+	uint8_t target_port_descriptors_length[2];
+	struct scsi_vpd_id_descriptor target_port_descriptors[0];
+};
+
+struct scsi_vpd_scsi_ports
+{
+	u_int8_t device;
+	u_int8_t page_code;
+#define	SVPD_SCSI_PORTS		0x88
+	u_int8_t page_length[2];
+	struct scsi_vpd_port_designation design[];
+};
+
 /*
  * ATA Information VPD Page based on
  * T10/2126-D Revision 04
@@ -1923,8 +1948,9 @@ struct scsi_target_group
 {
 	uint8_t opcode;
 	uint8_t service_action;
+#define	STG_PDF_MASK		0xe0
 #define	STG_PDF_LENGTH		0x00
-#define	RPL_PDF_EXTENDED	0x20
+#define	STG_PDF_EXTENDED	0x20
 	uint8_t reserved1[4];
 	uint8_t length[4];
 	uint8_t reserved2;
@@ -1974,7 +2000,7 @@ struct scsi_target_group_data {
 
 struct scsi_target_group_data_extended {
 	uint8_t length[4];	/* length of returned data, in bytes */
-	uint8_t format_type;	/* STG_PDF_LENGTH or RPL_PDF_EXTENDED */
+	uint8_t format_type;	/* STG_PDF_LENGTH or STG_PDF_EXTENDED */
 	uint8_t	implicit_transition_time;
 	uint8_t reserved[2];
 	struct scsi_target_port_group_descriptor groups[];



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