summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Goggin <egoggin@emc.com>2005-09-14 20:23:48 +0200
committerKay Sievers <kay.sievers@suse.de>2005-09-14 20:23:48 +0200
commit50be1401743704419ba52174302b4c1d06b3898b (patch)
tree93852844c79062fa6231cd1480687fdad0b75260
parent85701baede56edd4fba042f98550b8dec1a73127 (diff)
scsi_id: derive a UID for a SCSI-2 not compliant with the page 83
This patch is to enable the use of scsi_id to derive a UID for a SCSI-2 device which is not compliant with the page 83 inquiry reply format for either SPC-2 or SPC-3. In this case, the page 83 reply does not contain a list of Identification descriptors but a single binary encoded hexa-decimal Vendor Specified Identifier. The update is being driven by the need for scsi_id to support older model EMC Symmetrix hardware, that is, models 4, 5, and 6.
-rw-r--r--extras/scsi_id/scsi_id.816
-rw-r--r--extras/scsi_id/scsi_id.c14
-rw-r--r--extras/scsi_id/scsi_id.config5
-rw-r--r--extras/scsi_id/scsi_id.h10
-rw-r--r--extras/scsi_id/scsi_serial.c109
5 files changed, 137 insertions, 17 deletions
diff --git a/extras/scsi_id/scsi_id.8 b/extras/scsi_id/scsi_id.8
index 26df0d3e66..4213468ae4 100644
--- a/extras/scsi_id/scsi_id.8
+++ b/extras/scsi_id/scsi_id.8
@@ -91,10 +91,18 @@ to generate any output.
Prefix the identification string with the driver model (sysfs) bus id of
the SCSI device.
.TP
-.BI \-p "\| 0x80 | 0x83"
-Use SCSI INQUIRY VPD page code 0x80 or 0x83. The default behaviour is to
-query the available VPD pages, and use page 0x83 if found, else page 0x80
-if found, else nothing.
+.BI \-p "\| 0x80 | 0x83 | pre-spc3-83"
+Use SCSI INQUIRY VPD page code 0x80, 0x83, or pre-spc3-83.
+.sp
+The default
+behaviour is to query the availabe VPD pages, and use page 0x83 if found,
+else page 0x80 if found, else nothing.
+.sp
+Page pre-spc3-83 should only be utilized for those scsi devices which
+are not compliant with the SPC-2 or SPC-3 format for page 83. While this
+option is used for older model 4, 5, and 6 EMC Symmetrix devices, its
+use with SPC-2 or SPC-3 compliant devices will fallback to the page 83
+format supported by these devices.
.TP
.BI \-s "\| sysfs\-device"
Generate an id for the
diff --git a/extras/scsi_id/scsi_id.c b/extras/scsi_id/scsi_id.c
index a86b004709..e997be9956 100644
--- a/extras/scsi_id/scsi_id.c
+++ b/extras/scsi_id/scsi_id.c
@@ -67,7 +67,7 @@ static int dev_specified;
static int sys_specified;
static char config_file[MAX_NAME_LEN] = SCSI_ID_CONFIG_FILE;
static int display_bus_id;
-static int default_page_code;
+static enum page_code default_page_code;
static int use_stderr;
static int debug;
static int hotplug_mode;
@@ -519,9 +519,11 @@ static int set_options(int argc, char **argv, const char *short_opts,
case 'p':
if (strcmp(optarg, "0x80") == 0) {
- default_page_code = 0x80;
+ default_page_code = PAGE_80;
} else if (strcmp(optarg, "0x83") == 0) {
- default_page_code = 0x83;
+ default_page_code = PAGE_83;
+ } else if (strcmp(optarg, "pre-spc3-83") == 0) {
+ default_page_code = PAGE_83_PRE_SPC3;
} else {
log_message(LOG_WARNING,
"Unknown page code '%s'\n", optarg);
@@ -640,9 +642,11 @@ static int per_dev_options(struct sysfs_device *scsi_dev, int *good_bad,
case 'p':
if (strcmp(optarg, "0x80") == 0) {
- *page_code = 0x80;
+ *page_code = PAGE_80;
} else if (strcmp(optarg, "0x83") == 0) {
- *page_code = 0x83;
+ *page_code = PAGE_83;
+ } else if (strcmp(optarg, "pre-spc3-83") == 0) {
+ *page_code = PAGE_83_PRE_SPC3;
} else {
log_message(LOG_WARNING,
"Unknown page code '%s'\n", optarg);
diff --git a/extras/scsi_id/scsi_id.config b/extras/scsi_id/scsi_id.config
index 0567ecb7d6..4f31b1c498 100644
--- a/extras/scsi_id/scsi_id.config
+++ b/extras/scsi_id/scsi_id.config
@@ -41,3 +41,8 @@ vendor=someone, model=nicedrive, options=-g
# if you rely on the id for persistent naming or multi-path configuration.
## vendor=ELBONIA, model=borken, options=-b
+
+# EMC SYMMETRIX models 4 and 5, and some model 6 systems return the VSI
+# field of the page 83 reply according to SCSI-2 format. This format is
+# binary encoded hexa-decimal as opposed to the Identifiscation descriptor
+# utilized by both SPC-2 and SPC-3 compliant systems.
diff --git a/extras/scsi_id/scsi_id.h b/extras/scsi_id/scsi_id.h
index 74b449e984..1c9ed969a7 100644
--- a/extras/scsi_id/scsi_id.h
+++ b/extras/scsi_id/scsi_id.h
@@ -53,3 +53,13 @@ extern void log_message (int level, const char *format, ...)
#ifndef u8
typedef unsigned char u8;
#endif
+
+/*
+ * Page code values.
+ */
+enum page_code {
+ PAGE_83_PRE_SPC3 = -0x83,
+ PAGE_UNSPECIFIED = 0x00,
+ PAGE_80 = 0x80,
+ PAGE_83 = 0x83,
+};
diff --git a/extras/scsi_id/scsi_serial.c b/extras/scsi_id/scsi_serial.c
index 73d66ee615..d1b1d94f53 100644
--- a/extras/scsi_id/scsi_serial.c
+++ b/extras/scsi_id/scsi_serial.c
@@ -567,12 +567,12 @@ static int do_scsi_page83_inquiry(struct sysfs_device *scsi_dev, int fd,
unsigned char page_83[SCSI_INQ_BUFF_LEN];
memset(page_83, 0, SCSI_INQ_BUFF_LEN);
- retval = scsi_inquiry(scsi_dev, fd, 1, 0x83, page_83,
+ retval = scsi_inquiry(scsi_dev, fd, 1, PAGE_83, page_83,
SCSI_INQ_BUFF_LEN);
if (retval < 0)
return 1;
- if (page_83[1] != 0x83) {
+ if (page_83[1] != PAGE_83) {
log_message(LOG_WARNING, "%s: Invalid page 0x83\n",
scsi_dev->name);
return 1;
@@ -616,6 +616,74 @@ static int do_scsi_page83_inquiry(struct sysfs_device *scsi_dev, int fd,
return 1;
}
+/*
+ * Get device identification VPD page for older SCSI-2 device which is not
+ * compliant with either SPC-2 or SPC-3 format.
+ *
+ * Return the hard coded error code value 2 if the page 83 reply is not
+ * conformant to the SCSI-2 format.
+ */
+static int do_scsi_page83_prespc3_inquiry(struct sysfs_device *scsi_dev, int fd,
+ char *serial, int len)
+{
+ int retval;
+ int i, j;
+ unsigned char page_83[SCSI_INQ_BUFF_LEN];
+
+ memset(page_83, 0, SCSI_INQ_BUFF_LEN);
+ retval = scsi_inquiry(scsi_dev, fd, 1, PAGE_83, page_83, SCSI_INQ_BUFF_LEN);
+ if (retval < 0)
+ return 1;
+
+ if (page_83[1] != PAGE_83) {
+ log_message(LOG_WARNING, "%s: Invalid page 0x83\n", scsi_dev->name);
+ return 1;
+ }
+ /*
+ * Model 4, 5, and (some) model 6 EMC Symmetrix devices return
+ * a page 83 reply according to SCSI-2 format instead of SPC-2/3.
+ *
+ * The SCSI-2 page 83 format returns an IEEE WWN in binary
+ * encoded hexi-decimal in the 16 bytes following the initial
+ * 4-byte page 83 reply header.
+ *
+ * Both the SPC-2 and SPC-3 formats return an IEEE WWN as part
+ * of an Identification descriptor. The 3rd byte of the first
+ * Identification descriptor is a reserved (BSZ) byte field.
+ *
+ * Reference the 7th byte of the page 83 reply to determine
+ * whether the reply is compliant with SCSI-2 or SPC-2/3
+ * specifications. A zero value in the 7th byte indicates
+ * an SPC-2/3 conformant reply, (i.e., the reserved field of the
+ * first Identification descriptor). This byte will be non-zero
+ * for a SCSI-2 conformant page 83 reply from these EMC
+ * Symmetrix models since the 7th byte of the reply corresponds
+ * to the 4th and 5th nibbles of the 6-byte OUI for EMC, that is,
+ * 0x006048.
+ */
+ if (page_83[6] == 0)
+ return 2;
+
+ serial[0] = hex_str[id_search_list[0].id_type];
+ /*
+ * The first four bytes contain data, not a descriptor.
+ */
+ i = 4;
+ j = strlen(serial);
+ /*
+ * Binary descriptor, convert to ASCII,
+ * using two bytes of ASCII for each byte
+ * in the page_83.
+ */
+ while (i < (page_83[3]+4)) {
+ serial[j++] = hex_str[(page_83[i] & 0xf0) >> 4];
+ serial[j++] = hex_str[page_83[i] & 0x0f];
+ i++;
+ }
+ dprintf("using pre-spc3-83 for %s.\n", scsi_dev->name);
+ return 0;
+}
+
/* Get unit serial number VPD page */
static int do_scsi_page80_inquiry(struct sysfs_device *scsi_dev, int fd,
char *serial, int max_len)
@@ -627,11 +695,11 @@ static int do_scsi_page80_inquiry(struct sysfs_device *scsi_dev, int fd,
unsigned char buf[SCSI_INQ_BUFF_LEN];
memset(buf, 0, SCSI_INQ_BUFF_LEN);
- retval = scsi_inquiry(scsi_dev, fd, 1, 0x80, buf, SCSI_INQ_BUFF_LEN);
+ retval = scsi_inquiry(scsi_dev, fd, 1, PAGE_80, buf, SCSI_INQ_BUFF_LEN);
if (retval < 0)
return retval;
- if (buf[1] != 0x80) {
+ if (buf[1] != PAGE_80) {
log_message(LOG_WARNING, "%s: Invalid page 0x80\n",
scsi_dev->name);
return 1;
@@ -674,7 +742,7 @@ int scsi_get_serial (struct sysfs_device *scsi_dev, const char *devname,
return 1;
}
- if (page_code == 0x80) {
+ if (page_code == PAGE_80) {
if (do_scsi_page80_inquiry(scsi_dev, fd, serial, len)) {
retval = 1;
goto completed;
@@ -682,7 +750,7 @@ int scsi_get_serial (struct sysfs_device *scsi_dev, const char *devname,
retval = 0;
goto completed;
}
- } else if (page_code == 0x83) {
+ } else if (page_code == PAGE_83) {
if (do_scsi_page83_inquiry(scsi_dev, fd, serial, len)) {
retval = 1;
goto completed;
@@ -690,6 +758,31 @@ int scsi_get_serial (struct sysfs_device *scsi_dev, const char *devname,
retval = 0;
goto completed;
}
+ } else if (page_code == PAGE_83_PRE_SPC3) {
+ retval = do_scsi_page83_prespc3_inquiry(scsi_dev, fd, serial, len);
+ if (retval) {
+ /*
+ * Fallback to servicing a SPC-2/3 compliant page 83
+ * inquiry if the page 83 reply format does not
+ * conform to pre-SPC3 expectations.
+ */
+ if (retval == 2) {
+ if (do_scsi_page83_inquiry(scsi_dev, fd, serial, len)) {
+ retval = 1;
+ goto completed;
+ } else {
+ retval = 0;
+ goto completed;
+ }
+ }
+ else {
+ retval = 1;
+ goto completed;
+ }
+ } else {
+ retval = 0;
+ goto completed;
+ }
} else if (page_code != 0x00) {
log_message(LOG_WARNING, "%s: unsupported page code 0x%d\n",
scsi_dev->name, page_code);
@@ -713,7 +806,7 @@ int scsi_get_serial (struct sysfs_device *scsi_dev, const char *devname,
dprintf("%s: Checking page0\n", scsi_dev->name);
for (ind = 4; ind <= page0[3] + 3; ind++)
- if (page0[ind] == 0x83)
+ if (page0[ind] == PAGE_83)
if (!do_scsi_page83_inquiry(scsi_dev, fd, serial,
len)) {
/*
@@ -724,7 +817,7 @@ int scsi_get_serial (struct sysfs_device *scsi_dev, const char *devname,
}
for (ind = 4; ind <= page0[3] + 3; ind++)
- if (page0[ind] == 0x80)
+ if (page0[ind] == PAGE_80)
if (!do_scsi_page80_inquiry(scsi_dev, fd, serial,
len)) {
/*