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