Module Name:    src
Committed By:   mlelstv
Date:           Sat Nov  9 11:09:40 UTC 2024

Modified Files:
        src/sbin/scsictl: scsictl.8 scsictl.c

Log Message:
Add 'identify vpd' to also report Vital Product Data that identifies the device.


To generate a diff of this commit:
cvs rdiff -u -r1.32 -r1.33 src/sbin/scsictl/scsictl.8
cvs rdiff -u -r1.40 -r1.41 src/sbin/scsictl/scsictl.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sbin/scsictl/scsictl.8
diff -u src/sbin/scsictl/scsictl.8:1.32 src/sbin/scsictl/scsictl.8:1.33
--- src/sbin/scsictl/scsictl.8:1.32	Sun Aug 21 12:44:16 2022
+++ src/sbin/scsictl/scsictl.8	Sat Nov  9 11:09:40 2024
@@ -1,4 +1,4 @@
-.\"	$NetBSD: scsictl.8,v 1.32 2022/08/21 12:44:16 mlelstv Exp $
+.\"	$NetBSD: scsictl.8,v 1.33 2024/11/09 11:09:40 mlelstv Exp $
 .\"
 .\" Copyright (c) 1998, 2002 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -119,10 +119,15 @@ This associated sense data has a progres
 how far the format is progressing.
 Note well that most SCSI disk drives prior to
 a few years ago do not support this option.
-.It Cm identify
+.It Cm identify Oo vpd Oc Oc
 Identify the specified device, displaying the device's SCSI
 bus, target, and lun, as well as the device's vendor, product,
 and revision strings.
+.Pp
+When the optional
+.Li vpd
+parameter is added, Vital Product Data that identifies
+the device is also queried and displayed.
 .It Cm reassign Ar blkno Oo blkno Oo ... Oc Oc
 Issues a
 .Li REASSIGN BLOCKS

Index: src/sbin/scsictl/scsictl.c
diff -u src/sbin/scsictl/scsictl.c:1.40 src/sbin/scsictl/scsictl.c:1.41
--- src/sbin/scsictl/scsictl.c:1.40	Sun Aug 21 12:44:16 2022
+++ src/sbin/scsictl/scsictl.c	Sat Nov  9 11:09:40 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: scsictl.c,v 1.40 2022/08/21 12:44:16 mlelstv Exp $	*/
+/*	$NetBSD: scsictl.c,v 1.41 2024/11/09 11:09:40 mlelstv Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
 #include <sys/cdefs.h>
 
 #ifndef lint
-__RCSID("$NetBSD: scsictl.c,v 1.40 2022/08/21 12:44:16 mlelstv Exp $");
+__RCSID("$NetBSD: scsictl.c,v 1.41 2024/11/09 11:09:40 mlelstv Exp $");
 #endif
 
 
@@ -49,6 +49,7 @@ __RCSID("$NetBSD: scsictl.c,v 1.40 2022/
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <string.h>
 #include <unistd.h>
 #include <util.h>
@@ -99,7 +100,7 @@ static struct command device_commands[] 
 	{ "defects",	"[primary] [grown] [block|byte|physical]",
 						device_defects },
 	{ "format",	"[blocksize [immediate]]", 	device_format },
-	{ "identify",	"",			device_identify },
+	{ "identify",	"[vpd]",		device_identify },
 	{ "reassign",	"blkno [blkno [...]]",	device_reassign },
 	{ "release",	"",			device_release },
 	{ "reserve",	"",			device_reserve },
@@ -639,26 +640,113 @@ device_format(int argc, char *argv[])
 	return;
 }
 
+static void
+print_designator(const char *pre, struct scsipi_inquiry_evpd_device_id *did)
+{
+	char buf[252 * 4 + 1];
+	unsigned assoc, proto, code, type;
+	static const char *typestr[] = {
+		"vendor",
+		"t10",
+		"eui64",
+		"naa",
+		"target port",
+		"port group",
+		"lun group",
+		"md5",
+		"scsi",
+		"res9",
+		"res10",
+		"res11",
+		"res12",
+		"res13",
+		"res14",
+		"res15"
+	};
+	static const char *assocstr[] = {
+		"lun",
+		"port",
+		"target",
+		"reserved"
+	};
+	static const char *protostr[] = {
+		"fibre channel",
+		"obsolete",
+		"ssa",
+		"ieee1394",
+		"rdma",
+		"iSCSI",
+		"SAS"
+	};
+	const unsigned maxproto = __arraycount(protostr) - 1;
+	const unsigned isbinary =
+	    __SHIFTOUT(SINQ_DEVICE_ID_CODESET_BINARY, SINQ_DEVICE_ID_CODESET);
+	unsigned k;
+
+	assoc = __SHIFTOUT(did->flags, SINQ_DEVICE_ID_ASSOCIATION);
+	proto = __SHIFTOUT(did->pc, SINQ_DEVICE_ID_PROTOCOL);
+	code = __SHIFTOUT(did->pc, SINQ_DEVICE_ID_CODESET);
+	type = __SHIFTOUT(did->flags, SINQ_DEVICE_ID_TYPE);
+
+	printf("%s%s", pre, assocstr[assoc]);
+	if (did->flags & SINQ_DEVICE_ID_PIV) {
+		if (proto > maxproto)
+			printf(" proto%u", proto);
+		else
+			printf(" %s", protostr[proto]);
+	}
+	printf(" %s: ", typestr[type]);
+
+	if (code == isbinary) {
+		for (k=0; k<did->designator_length; ++k) {
+			printf("%02x", did->designator[k]);
+		}
+		printf("\n");
+	} else {
+		scsi_strvis(buf, sizeof(buf), (char *)did->designator,
+		    did->designator_length);
+		printf("%s\n", buf);
+	}
+}
+
 /*
  * device_identify:
  *
  *	Display the identity of the device, including its SCSI bus,
  *	target, lun, and its vendor/product/revision information.
+ *      Optionally query and display vpd identification data.
  */
 static void
 device_identify(int argc, char *argv[])
 {
 	struct scsipi_inquiry_data inqbuf;
+	struct {
+		struct scsipi_inquiry_evpd_header h;
+		uint8_t d[255 - sizeof(struct scsipi_inquiry_evpd_header)];
+	} evpdbuf;
 	struct scsipi_inquiry cmd;
+	unsigned len, rlen;
+	struct scsipi_inquiry_evpd_serial *ser;
+	struct scsipi_inquiry_evpd_device_id *did;
+	int has_serial;
+	int has_device_id;
+	bool getvpd = false;
+	int i;
 
 	/* x4 in case every character is escaped, +1 for NUL. */
 	char vendor[(sizeof(inqbuf.vendor) * 4) + 1],
 	     product[(sizeof(inqbuf.product) * 4) + 1],
-	     revision[(sizeof(inqbuf.revision) * 4) + 1];
+	     revision[(sizeof(inqbuf.revision) * 4) + 1],
+	     ident[252 * 4 + 1];
 
-	/* No arguments. */
-	if (argc != 0)
+	/* Check optional arguments */
+	for (i = 0; i < argc; i++) {
+		if (strncmp("vpd", argv[i], 3) == 0) {
+			getvpd = true;
+			continue;
+		}
 		usage();
+	}
 
 	memset(&cmd, 0, sizeof(cmd));
 	memset(&inqbuf, 0, sizeof(inqbuf));
@@ -680,6 +768,65 @@ device_identify(int argc, char *argv[])
 	    dvname, dvaddr.addr.scsi.scbus, dvaddr.addr.scsi.target,
 	    dvaddr.addr.scsi.lun, vendor, product, revision);
 
+	if (!getvpd)
+		return;
+
+	cmd.byte2 |= SINQ_EVPD;
+	cmd.pagecode = SINQ_VPD_PAGES;
+
+	scsi_command(fd, &cmd, sizeof(cmd), &evpdbuf, sizeof(evpdbuf),
+	    10000, SCCMD_READ);
+
+	len = be16dec(evpdbuf.h.length);
+	if (len > sizeof(evpdbuf.d))
+		len = 0;
+
+	has_serial = memchr(evpdbuf.d, SINQ_VPD_SERIAL, len) != NULL;
+	has_device_id = memchr(evpdbuf.d, SINQ_VPD_DEVICE_ID, len) != NULL;
+
+	if (has_serial) {
+
+		cmd.byte2 |= SINQ_EVPD;
+		cmd.pagecode = SINQ_VPD_SERIAL;
+
+		scsi_command(fd, &cmd, sizeof(cmd), &evpdbuf, sizeof(evpdbuf),
+		    10000, SCCMD_READ);
+
+		len = be16dec(evpdbuf.h.length);
+		if (len > sizeof(evpdbuf.d))
+			len = 0;
+
+		ser = (struct scsipi_inquiry_evpd_serial *)&evpdbuf.d;
+		scsi_strvis(ident, sizeof(ident), (char *)ser->serial_number, len);
+		printf("VPD Serial:\n");
+		printf("\t%s\n", ident);
+
+	}
+
+	if (has_device_id) {
+
+		cmd.byte2 |= SINQ_EVPD;
+		cmd.pagecode = SINQ_VPD_DEVICE_ID;
+
+		scsi_command(fd, &cmd, sizeof(cmd), &evpdbuf, sizeof(evpdbuf),
+		    10000, SCCMD_READ);
+
+		len = be16dec(evpdbuf.h.length);
+		if (len > sizeof(evpdbuf.d))
+			len = 0;
+
+		printf("VPD Device IDs:\n");
+
+		for (unsigned off=0; off<len - sizeof(*did); off += rlen) {
+			did = (struct scsipi_inquiry_evpd_device_id *)&evpdbuf.d[off];
+			rlen = sizeof(*did) + did->designator_length - 1;
+			if (off + rlen > len)
+				break;
+
+			print_designator("\t", did);
+		}
+	}
+
 	return;
 }
 

Reply via email to