|
|
39359f |
From 4fed8b17b1cd75492d20cf701ebe4f66e13385f5 Mon Sep 17 00:00:00 2001
|
|
|
39359f |
From: David Sommerseth <davids@redhat.com>
|
|
|
39359f |
Date: Fri, 29 Apr 2016 01:12:20 +0200
|
|
|
39359f |
Subject: [PATCH] Add upstream updates to sg_inq, sg_rdac and sg_vpd
|
|
|
39359f |
|
|
|
39359f |
---
|
|
|
39359f |
src/sg_inq.c | 165 +++++++++++++++++++++++++++++++-----
|
|
|
39359f |
src/sg_rdac.c | 216 ++++++++++++++++++++++++++++++++++-------------
|
|
|
39359f |
src/sg_vpd_vendor.c | 239 +++++++++++++++++++++++++++++++++++++++++++++++-----
|
|
|
39359f |
3 files changed, 519 insertions(+), 101 deletions(-)
|
|
|
39359f |
|
|
|
39359f |
diff --git a/src/sg_inq.c b/src/sg_inq.c
|
|
|
39359f |
index 80c8aec..9666e08 100644
|
|
|
39359f |
--- a/src/sg_inq.c
|
|
|
39359f |
+++ b/src/sg_inq.c
|
|
|
39359f |
@@ -2225,8 +2225,8 @@ decode_rdac_vpd_c2(unsigned char * buff, int len)
|
|
|
39359f |
"not possible.\n" , buff[4], buff[5], buff[6], buff[7]);
|
|
|
39359f |
return;
|
|
|
39359f |
}
|
|
|
39359f |
- printf(" Software Version: %d.%d.%d\n", buff[8], buff[9], buff[10]);
|
|
|
39359f |
- printf(" Software Date: %02x/%02x/%02x\n", buff[11], buff[12], buff[13]);
|
|
|
39359f |
+ printf(" Software Version: %02x.%02x.%02x\n", buff[8], buff[9], buff[10]);
|
|
|
39359f |
+ printf(" Software Date: %02d/%02d/%02d\n", buff[11], buff[12], buff[13]);
|
|
|
39359f |
printf(" Features:");
|
|
|
39359f |
if (buff[14] & 0x01)
|
|
|
39359f |
printf(" Dual Active,");
|
|
|
39359f |
@@ -2235,15 +2235,77 @@ decode_rdac_vpd_c2(unsigned char * buff, int len)
|
|
|
39359f |
if (buff[14] & 0x04)
|
|
|
39359f |
printf(" Multiple Sub-enclosures,");
|
|
|
39359f |
if (buff[14] & 0x08)
|
|
|
39359f |
- printf(" DCE/DRM,");
|
|
|
39359f |
+ printf(" DCE/DRM/DSS/DVE,");
|
|
|
39359f |
if (buff[14] & 0x10)
|
|
|
39359f |
- printf(" AVT,");
|
|
|
39359f |
+ printf(" Asymmetric Logical Unit Access,");
|
|
|
39359f |
printf("\n");
|
|
|
39359f |
printf(" Max. #of LUNS: %d\n", buff[15]);
|
|
|
39359f |
return;
|
|
|
39359f |
}
|
|
|
39359f |
|
|
|
39359f |
static void
|
|
|
39359f |
+decode_rdac_vpd_c9_rtpg_data(unsigned char aas, unsigned char vendor)
|
|
|
39359f |
+{
|
|
|
39359f |
+ printf(" Asymmetric Access State:");
|
|
|
39359f |
+ switch(aas & 0x0F) {
|
|
|
39359f |
+ case 0x0:
|
|
|
39359f |
+ printf(" Active/Optimized");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x1:
|
|
|
39359f |
+ printf(" Active/Non-Optimized");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x2:
|
|
|
39359f |
+ printf(" Standby");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x3:
|
|
|
39359f |
+ printf(" Unavailable");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0xE:
|
|
|
39359f |
+ printf(" Offline");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0xF:
|
|
|
39359f |
+ printf(" Transitioning");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ default:
|
|
|
39359f |
+ printf(" (unknown)");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ }
|
|
|
39359f |
+ printf("\n");
|
|
|
39359f |
+
|
|
|
39359f |
+ printf(" Vendor Specific Field:");
|
|
|
39359f |
+ switch(vendor) {
|
|
|
39359f |
+ case 0x01:
|
|
|
39359f |
+ printf(" Operating normally");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x02:
|
|
|
39359f |
+ printf(" Non-responsive to queries");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x03:
|
|
|
39359f |
+ printf(" Controller being held in reset");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x04:
|
|
|
39359f |
+ printf(" Performing controller firmware download (1st controller)");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x05:
|
|
|
39359f |
+ printf(" Performing controller firmware download (2nd controller)");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x06:
|
|
|
39359f |
+ printf(" Quiesced as a result of an administrative request");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x07:
|
|
|
39359f |
+ printf(" Service mode as a result of an administrative request");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0xFF:
|
|
|
39359f |
+ printf(" Details are not available");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ default:
|
|
|
39359f |
+ printf(" (unknown)");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ }
|
|
|
39359f |
+ printf("\n");
|
|
|
39359f |
+}
|
|
|
39359f |
+
|
|
|
39359f |
+static void
|
|
|
39359f |
decode_rdac_vpd_c9(unsigned char * buff, int len)
|
|
|
39359f |
{
|
|
|
39359f |
if (len < 3) {
|
|
|
39359f |
@@ -2260,14 +2322,18 @@ decode_rdac_vpd_c9(unsigned char * buff, int len)
|
|
|
39359f |
fprintf(stderr, "Invalid page version '%c' (should be 1)\n",
|
|
|
39359f |
buff[7]);
|
|
|
39359f |
}
|
|
|
39359f |
- printf(" AVT:");
|
|
|
39359f |
- if (buff[8] & 0x80) {
|
|
|
39359f |
- printf(" Enabled");
|
|
|
39359f |
- if (buff[8] & 0x40)
|
|
|
39359f |
- printf(" (Allow reads on sector 0)");
|
|
|
39359f |
- printf("\n");
|
|
|
39359f |
+ if ( (buff[8] & 0xE0) == 0xE0 ) {
|
|
|
39359f |
+ printf(" IOShipping (ALUA): Enabled\n");
|
|
|
39359f |
} else {
|
|
|
39359f |
- printf(" Disabled\n");
|
|
|
39359f |
+ printf(" AVT:");
|
|
|
39359f |
+ if (buff[8] & 0x80) {
|
|
|
39359f |
+ printf(" Enabled");
|
|
|
39359f |
+ if (buff[8] & 0x40)
|
|
|
39359f |
+ printf(" (Allow reads on sector 0)");
|
|
|
39359f |
+ printf("\n");
|
|
|
39359f |
+ } else {
|
|
|
39359f |
+ printf(" Disabled\n");
|
|
|
39359f |
+ }
|
|
|
39359f |
}
|
|
|
39359f |
printf(" Volume Access via: ");
|
|
|
39359f |
if (buff[8] & 0x01)
|
|
|
39359f |
@@ -2275,17 +2341,72 @@ decode_rdac_vpd_c9(unsigned char * buff, int len)
|
|
|
39359f |
else
|
|
|
39359f |
printf("alternate controller\n");
|
|
|
39359f |
|
|
|
39359f |
- printf(" Path priority: %d ", buff[9] & 0xf);
|
|
|
39359f |
- switch(buff[9] & 0xf) {
|
|
|
39359f |
- case 0x1:
|
|
|
39359f |
- printf("(preferred path)\n");
|
|
|
39359f |
- break;
|
|
|
39359f |
- case 0x2:
|
|
|
39359f |
- printf("(secondary path)\n");
|
|
|
39359f |
- break;
|
|
|
39359f |
- default:
|
|
|
39359f |
- printf("(unknown)\n");
|
|
|
39359f |
- break;
|
|
|
39359f |
+ if (buff[8] & 0x08) {
|
|
|
39359f |
+ printf(" Path priority: %d ", buff[15] & 0xf);
|
|
|
39359f |
+ switch(buff[15] & 0xf) {
|
|
|
39359f |
+ case 0x1:
|
|
|
39359f |
+ printf("(preferred path)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x2:
|
|
|
39359f |
+ printf("(secondary path)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ default:
|
|
|
39359f |
+ printf("(unknown)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ }
|
|
|
39359f |
+
|
|
|
39359f |
+ printf(" Preferred Path Auto Changeable:");
|
|
|
39359f |
+ switch(buff[14] & 0x3C) {
|
|
|
39359f |
+ case 0x14:
|
|
|
39359f |
+ printf(" No (User Disabled and Host Type Restricted)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x18:
|
|
|
39359f |
+ printf(" No (User Disabled)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x24:
|
|
|
39359f |
+ printf(" No (Host Type Restricted)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x28:
|
|
|
39359f |
+ printf(" Yes\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ default:
|
|
|
39359f |
+ printf(" (Unknown)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ }
|
|
|
39359f |
+
|
|
|
39359f |
+ printf(" Implicit Failback:");
|
|
|
39359f |
+ switch(buff[14] & 0x03) {
|
|
|
39359f |
+ case 0x1:
|
|
|
39359f |
+ printf(" Disabled\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x2:
|
|
|
39359f |
+ printf(" Enabled\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ default:
|
|
|
39359f |
+ printf(" (Unknown)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ }
|
|
|
39359f |
+ } else {
|
|
|
39359f |
+ printf(" Path priority: %d ", buff[9] & 0xf);
|
|
|
39359f |
+ switch(buff[9] & 0xf) {
|
|
|
39359f |
+ case 0x1:
|
|
|
39359f |
+ printf("(preferred path)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x2:
|
|
|
39359f |
+ printf("(secondary path)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ default:
|
|
|
39359f |
+ printf("(unknown)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ }
|
|
|
39359f |
+ }
|
|
|
39359f |
+
|
|
|
39359f |
+ if (buff[8] & 0x80) {
|
|
|
39359f |
+ printf(" Target Port Group Data (This controller):\n");
|
|
|
39359f |
+ decode_rdac_vpd_c9_rtpg_data(buff[10], buff[11]);
|
|
|
39359f |
+
|
|
|
39359f |
+ printf(" Target Port Group Data (Alternate controller):\n");
|
|
|
39359f |
+ decode_rdac_vpd_c9_rtpg_data(buff[12], buff[13]);
|
|
|
39359f |
}
|
|
|
39359f |
|
|
|
39359f |
return;
|
|
|
39359f |
diff --git a/src/sg_rdac.c b/src/sg_rdac.c
|
|
|
39359f |
index 41ec544..ea243a2 100644
|
|
|
39359f |
--- a/src/sg_rdac.c
|
|
|
39359f |
+++ b/src/sg_rdac.c
|
|
|
39359f |
@@ -28,12 +28,20 @@
|
|
|
39359f |
static const char * version_str = "1.06 20130507";
|
|
|
39359f |
|
|
|
39359f |
unsigned char mode6_hdr[] = {
|
|
|
39359f |
- 75, /* Length */
|
|
|
39359f |
+ 0x75, /* Length */
|
|
|
39359f |
0, /* medium */
|
|
|
39359f |
0, /* params */
|
|
|
39359f |
8, /* Block descriptor length */
|
|
|
39359f |
};
|
|
|
39359f |
|
|
|
39359f |
+unsigned char mode10_hdr[] = {
|
|
|
39359f |
+ 0x01, 0x18, /* Length */
|
|
|
39359f |
+ 0, /* medium */
|
|
|
39359f |
+ 0, /* params */
|
|
|
39359f |
+ 0, 0, /* reserved */
|
|
|
39359f |
+ 0, 0, /* block descriptor length */
|
|
|
39359f |
+};
|
|
|
39359f |
+
|
|
|
39359f |
unsigned char block_descriptor[] = {
|
|
|
39359f |
0, /* Density code */
|
|
|
39359f |
0, 0, 0, /* Number of blocks */
|
|
|
39359f |
@@ -41,22 +49,35 @@ unsigned char block_descriptor[] = {
|
|
|
39359f |
0, 0x02, 0, /* 512 byte blocks */
|
|
|
39359f |
};
|
|
|
39359f |
|
|
|
39359f |
-struct rdac_legacy_page {
|
|
|
39359f |
- unsigned char page_code;
|
|
|
39359f |
- unsigned char page_length;
|
|
|
39359f |
- char current_serial[16];
|
|
|
39359f |
- char alternate_serial[16];
|
|
|
39359f |
+struct rdac_page_common {
|
|
|
39359f |
+ unsigned char current_serial[16];
|
|
|
39359f |
+ unsigned char alternate_serial[16];
|
|
|
39359f |
unsigned char current_mode_msb;
|
|
|
39359f |
unsigned char current_mode_lsb;
|
|
|
39359f |
unsigned char alternate_mode_msb;
|
|
|
39359f |
unsigned char alternate_mode_lsb;
|
|
|
39359f |
unsigned char quiescence;
|
|
|
39359f |
unsigned char options;
|
|
|
39359f |
+};
|
|
|
39359f |
+
|
|
|
39359f |
+struct rdac_legacy_page {
|
|
|
39359f |
+ unsigned char page_code;
|
|
|
39359f |
+ unsigned char page_length;
|
|
|
39359f |
+ struct rdac_page_common attr;
|
|
|
39359f |
unsigned char lun_table[32];
|
|
|
39359f |
unsigned char lun_table_exp[32];
|
|
|
39359f |
unsigned short reserved;
|
|
|
39359f |
};
|
|
|
39359f |
|
|
|
39359f |
+struct rdac_expanded_page {
|
|
|
39359f |
+ unsigned char page_code;
|
|
|
39359f |
+ unsigned char subpage_code;
|
|
|
39359f |
+ unsigned char page_length[2];
|
|
|
39359f |
+ struct rdac_page_common attr;
|
|
|
39359f |
+ unsigned char lun_table[256];
|
|
|
39359f |
+ unsigned char reserved[2];
|
|
|
39359f |
+};
|
|
|
39359f |
+
|
|
|
39359f |
static int do_verbose = 0;
|
|
|
39359f |
|
|
|
39359f |
static void dump_mode_page( unsigned char *page, int len )
|
|
|
39359f |
@@ -83,30 +104,52 @@ static void dump_mode_page( unsigned char *page, int len )
|
|
|
39359f |
#define RDAC_CONTROLLER_PAGE_LEN 0x68
|
|
|
39359f |
#define LEGACY_PAGE 0x00
|
|
|
39359f |
#define EXPANDED_LUN_SPACE_PAGE 0x01
|
|
|
39359f |
+#define EXPANDED_LUN_SPACE_PAGE_LEN 0x128
|
|
|
39359f |
#define RDAC_FAIL_ALL_PATHS 0x1
|
|
|
39359f |
#define RDAC_FAIL_SELECTED_PATHS 0x2
|
|
|
39359f |
#define RDAC_FORCE_QUIESCENCE 0x2
|
|
|
39359f |
#define RDAC_QUIESCENCE_TIME 10
|
|
|
39359f |
|
|
|
39359f |
-static int fail_all_paths(int fd)
|
|
|
39359f |
+static int fail_all_paths(int fd, int use_6_byte)
|
|
|
39359f |
{
|
|
|
39359f |
- unsigned char fail_paths_pg[118];
|
|
|
39359f |
+ unsigned char fail_paths_pg[308];
|
|
|
39359f |
struct rdac_legacy_page *rdac_page;
|
|
|
39359f |
+ struct rdac_expanded_page *rdac_page_exp;
|
|
|
39359f |
+ struct rdac_page_common *rdac_common = NULL;
|
|
|
39359f |
+
|
|
|
39359f |
int res;
|
|
|
39359f |
|
|
|
39359f |
- memset(fail_paths_pg, 0, 118);
|
|
|
39359f |
- memcpy(fail_paths_pg, mode6_hdr, 4);
|
|
|
39359f |
- memcpy(fail_paths_pg + 4, block_descriptor, 8);
|
|
|
39359f |
- rdac_page = (struct rdac_legacy_page *)(fail_paths_pg + 4 + 8);
|
|
|
39359f |
- rdac_page->page_code = RDAC_CONTROLLER_PAGE | 0x40;
|
|
|
39359f |
- rdac_page->page_length = RDAC_CONTROLLER_PAGE_LEN;
|
|
|
39359f |
- rdac_page->quiescence = RDAC_QUIESCENCE_TIME;
|
|
|
39359f |
- rdac_page->options = RDAC_FORCE_QUIESCENCE;
|
|
|
39359f |
- rdac_page->current_mode_lsb = RDAC_FAIL_ALL_PATHS;
|
|
|
39359f |
+ memset(fail_paths_pg, 0, 308);
|
|
|
39359f |
+ if (use_6_byte) {
|
|
|
39359f |
+ memcpy(fail_paths_pg, mode6_hdr, 4);
|
|
|
39359f |
+ memcpy(fail_paths_pg + 4, block_descriptor, 8);
|
|
|
39359f |
+ rdac_page = (struct rdac_legacy_page *)(fail_paths_pg + 4 + 8);
|
|
|
39359f |
+ rdac_page->page_code = RDAC_CONTROLLER_PAGE;
|
|
|
39359f |
+ rdac_page->page_length = RDAC_CONTROLLER_PAGE_LEN;
|
|
|
39359f |
+ rdac_common = &rdac_page->attr;
|
|
|
39359f |
+ } else {
|
|
|
39359f |
+ memcpy(fail_paths_pg, mode10_hdr, 8);
|
|
|
39359f |
+ rdac_page_exp = (struct rdac_expanded_page *)(fail_paths_pg + 8);
|
|
|
39359f |
+ rdac_page_exp->page_code = RDAC_CONTROLLER_PAGE | 0x40;
|
|
|
39359f |
+ rdac_page_exp->subpage_code = 0x1;
|
|
|
39359f |
+ rdac_page_exp->page_length[0] = EXPANDED_LUN_SPACE_PAGE_LEN >> 8;
|
|
|
39359f |
+ rdac_page_exp->page_length[1] = EXPANDED_LUN_SPACE_PAGE_LEN & 0xFF;
|
|
|
39359f |
+ rdac_common = &rdac_page_exp->attr;
|
|
|
39359f |
+ }
|
|
|
39359f |
|
|
|
39359f |
- res = sg_ll_mode_select6(fd, 1 /* pf */, 0 /* sp */,
|
|
|
39359f |
- fail_paths_pg, 118,
|
|
|
39359f |
- 1, (do_verbose ? 2 : 0));
|
|
|
39359f |
+ rdac_common->current_mode_lsb = RDAC_FAIL_ALL_PATHS;
|
|
|
39359f |
+ rdac_common->quiescence = RDAC_QUIESCENCE_TIME;
|
|
|
39359f |
+ rdac_common->options = RDAC_FORCE_QUIESCENCE;
|
|
|
39359f |
+
|
|
|
39359f |
+ if (use_6_byte) {
|
|
|
39359f |
+ res = sg_ll_mode_select6(fd, 1 /* pf */, 0 /* sp */,
|
|
|
39359f |
+ fail_paths_pg, 118,
|
|
|
39359f |
+ 1, (do_verbose ? 2 : 0));
|
|
|
39359f |
+ } else {
|
|
|
39359f |
+ res = sg_ll_mode_select10(fd, 1 /* pf */, 0 /* sp */,
|
|
|
39359f |
+ fail_paths_pg, 308,
|
|
|
39359f |
+ 1, (do_verbose ? 2: 0));
|
|
|
39359f |
+ }
|
|
|
39359f |
|
|
|
39359f |
switch (res) {
|
|
|
39359f |
case 0:
|
|
|
39359f |
@@ -137,27 +180,54 @@ static int fail_all_paths(int fd)
|
|
|
39359f |
return res;
|
|
|
39359f |
}
|
|
|
39359f |
|
|
|
39359f |
-static int fail_this_path(int fd, int lun)
|
|
|
39359f |
+static int fail_this_path(int fd, int lun, int use_6_byte)
|
|
|
39359f |
{
|
|
|
39359f |
- unsigned char fail_paths_pg[118];
|
|
|
39359f |
+ unsigned char fail_paths_pg[308];
|
|
|
39359f |
struct rdac_legacy_page *rdac_page;
|
|
|
39359f |
+ struct rdac_expanded_page *rdac_page_exp;
|
|
|
39359f |
+ struct rdac_page_common *rdac_common = NULL;
|
|
|
39359f |
int res;
|
|
|
39359f |
|
|
|
39359f |
- memset(fail_paths_pg, 0, 118);
|
|
|
39359f |
- memcpy(fail_paths_pg, mode6_hdr, 4);
|
|
|
39359f |
- memcpy(fail_paths_pg + 4, block_descriptor, 8);
|
|
|
39359f |
- rdac_page = (struct rdac_legacy_page *)(fail_paths_pg + 4 + 8);
|
|
|
39359f |
- rdac_page->page_code = RDAC_CONTROLLER_PAGE | 0x40;
|
|
|
39359f |
- rdac_page->page_length = RDAC_CONTROLLER_PAGE_LEN;
|
|
|
39359f |
- rdac_page->current_mode_lsb = RDAC_FAIL_SELECTED_PATHS;
|
|
|
39359f |
- rdac_page->quiescence = RDAC_QUIESCENCE_TIME;
|
|
|
39359f |
- rdac_page->options = RDAC_FORCE_QUIESCENCE;
|
|
|
39359f |
- memset(rdac_page->lun_table, 0x0, 32);
|
|
|
39359f |
- rdac_page->lun_table[lun] = 0x81;
|
|
|
39359f |
-
|
|
|
39359f |
- res = sg_ll_mode_select6(fd, 1 /* pf */, 0 /* sp */,
|
|
|
39359f |
- fail_paths_pg, 118,
|
|
|
39359f |
- 1, (do_verbose ? 2 : 0));
|
|
|
39359f |
+ if (use_6_byte && lun > 32) {
|
|
|
39359f |
+ fprintf(stderr, "must use 10 byte cdb to fail luns over 32\n");
|
|
|
39359f |
+ return -1;
|
|
|
39359f |
+ }
|
|
|
39359f |
+
|
|
|
39359f |
+ memset(fail_paths_pg, 0, 308);
|
|
|
39359f |
+ if (use_6_byte) {
|
|
|
39359f |
+ memcpy(fail_paths_pg, mode6_hdr, 4);
|
|
|
39359f |
+ memcpy(fail_paths_pg + 4, block_descriptor, 8);
|
|
|
39359f |
+ rdac_page = (struct rdac_legacy_page *)(fail_paths_pg + 4 + 8);
|
|
|
39359f |
+ rdac_page->page_code = RDAC_CONTROLLER_PAGE;
|
|
|
39359f |
+ rdac_page->page_length = RDAC_CONTROLLER_PAGE_LEN;
|
|
|
39359f |
+ rdac_common = &rdac_page->attr;
|
|
|
39359f |
+ memset(rdac_page->lun_table, 0x0, 32);
|
|
|
39359f |
+ rdac_page->lun_table[lun] = 0x81;
|
|
|
39359f |
+ } else {
|
|
|
39359f |
+ memcpy(fail_paths_pg, mode10_hdr, 8);
|
|
|
39359f |
+ rdac_page_exp = (struct rdac_expanded_page *)(fail_paths_pg + 8);
|
|
|
39359f |
+ rdac_page_exp->page_code = RDAC_CONTROLLER_PAGE | 0x40;
|
|
|
39359f |
+ rdac_page_exp->subpage_code = 0x1;
|
|
|
39359f |
+ rdac_page_exp->page_length[0] = EXPANDED_LUN_SPACE_PAGE_LEN >> 8;
|
|
|
39359f |
+ rdac_page_exp->page_length[1] = EXPANDED_LUN_SPACE_PAGE_LEN & 0xFF;
|
|
|
39359f |
+ rdac_common = &rdac_page_exp->attr;
|
|
|
39359f |
+ memset(rdac_page_exp->lun_table, 0x0, 256);
|
|
|
39359f |
+ rdac_page_exp->lun_table[lun] = 0x81;
|
|
|
39359f |
+ }
|
|
|
39359f |
+
|
|
|
39359f |
+ rdac_common->current_mode_lsb = RDAC_FAIL_SELECTED_PATHS;
|
|
|
39359f |
+ rdac_common->quiescence = RDAC_QUIESCENCE_TIME;
|
|
|
39359f |
+ rdac_common->options = RDAC_FORCE_QUIESCENCE;
|
|
|
39359f |
+
|
|
|
39359f |
+ if (use_6_byte) {
|
|
|
39359f |
+ res = sg_ll_mode_select6(fd, 1 /* pf */, 0 /* sp */,
|
|
|
39359f |
+ fail_paths_pg, 118,
|
|
|
39359f |
+ 1, (do_verbose ? 2 : 0));
|
|
|
39359f |
+ } else {
|
|
|
39359f |
+ res = sg_ll_mode_select10(fd, 1 /* pf */, 0 /* sp */,
|
|
|
39359f |
+ fail_paths_pg, 308,
|
|
|
39359f |
+ 1, (do_verbose ? 2: 0));
|
|
|
39359f |
+ }
|
|
|
39359f |
|
|
|
39359f |
switch (res) {
|
|
|
39359f |
case 0:
|
|
|
39359f |
@@ -189,16 +259,29 @@ static int fail_this_path(int fd, int lun)
|
|
|
39359f |
return res;
|
|
|
39359f |
}
|
|
|
39359f |
|
|
|
39359f |
-static void print_rdac_mode( unsigned char *ptr )
|
|
|
39359f |
+static void print_rdac_mode( unsigned char *ptr, int subpg)
|
|
|
39359f |
{
|
|
|
39359f |
- struct rdac_legacy_page *rdac_ptr;
|
|
|
39359f |
- int i, k, bd_len;
|
|
|
39359f |
-
|
|
|
39359f |
- bd_len = ptr[3];
|
|
|
39359f |
-
|
|
|
39359f |
- rdac_ptr = (struct rdac_legacy_page *)(ptr + 4 + bd_len);
|
|
|
39359f |
+ struct rdac_legacy_page *legacy;
|
|
|
39359f |
+ struct rdac_expanded_page *expanded;
|
|
|
39359f |
+ struct rdac_page_common *rdac_ptr = NULL;
|
|
|
39359f |
+ unsigned char * lun_table = NULL;
|
|
|
39359f |
+ int i, k, bd_len, lun_table_len;
|
|
|
39359f |
+
|
|
|
39359f |
+ if (subpg == 1) {
|
|
|
39359f |
+ bd_len = ptr[7];
|
|
|
39359f |
+ expanded = (struct rdac_expanded_page *)(ptr + 8 + bd_len);
|
|
|
39359f |
+ rdac_ptr = &expanded->attr;
|
|
|
39359f |
+ lun_table = expanded->lun_table;
|
|
|
39359f |
+ lun_table_len = 256;
|
|
|
39359f |
+ } else {
|
|
|
39359f |
+ bd_len = ptr[3];
|
|
|
39359f |
+ legacy = (struct rdac_legacy_page *)(ptr + 4 + bd_len);
|
|
|
39359f |
+ rdac_ptr = &legacy->attr;
|
|
|
39359f |
+ lun_table = legacy->lun_table;
|
|
|
39359f |
+ lun_table_len = 32;
|
|
|
39359f |
+ }
|
|
|
39359f |
|
|
|
39359f |
- printf("RDAC Legacy page\n");
|
|
|
39359f |
+ printf("RDAC %s page\n", (subpg == 1) ? "Expanded" : "Legacy");
|
|
|
39359f |
printf(" Controller serial: %s\n",
|
|
|
39359f |
rdac_ptr->current_serial);
|
|
|
39359f |
printf(" Alternate controller serial: %s\n",
|
|
|
39359f |
@@ -239,9 +322,6 @@ static void print_rdac_mode( unsigned char *ptr )
|
|
|
39359f |
case 0x01:
|
|
|
39359f |
printf("alternate controller present; ");
|
|
|
39359f |
break;
|
|
|
39359f |
- case 0x02:
|
|
|
39359f |
- printf("active/active mode; ");
|
|
|
39359f |
- break;
|
|
|
39359f |
default:
|
|
|
39359f |
printf("(Unknown status 0x%x); ",
|
|
|
39359f |
rdac_ptr->alternate_mode_msb);
|
|
|
39359f |
@@ -257,7 +337,10 @@ static void print_rdac_mode( unsigned char *ptr )
|
|
|
39359f |
case 0x2:
|
|
|
39359f |
printf("Dual active mode\n");
|
|
|
39359f |
break;
|
|
|
39359f |
- case 0x04:
|
|
|
39359f |
+ case 0x3:
|
|
|
39359f |
+ printf("Not present\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x4:
|
|
|
39359f |
printf("held in reset\n");
|
|
|
39359f |
break;
|
|
|
39359f |
default:
|
|
|
39359f |
@@ -266,11 +349,14 @@ static void print_rdac_mode( unsigned char *ptr )
|
|
|
39359f |
}
|
|
|
39359f |
printf(" Quiescence timeout: %d\n", rdac_ptr->quiescence);
|
|
|
39359f |
printf(" RDAC option 0x%x\n", rdac_ptr->options);
|
|
|
39359f |
- printf (" LUN Table:\n");
|
|
|
39359f |
- for (k = 0; k < 32; k += 8) {
|
|
|
39359f |
- printf(" %x:",k / 8);
|
|
|
39359f |
- for (i = 0; i < 8; i++) {
|
|
|
39359f |
- switch (rdac_ptr->lun_table[k + i]) {
|
|
|
39359f |
+ printf(" ALUA: %s\n", (rdac_ptr->options & 0x4 ? "Enabled" : "Disabled" ));
|
|
|
39359f |
+ printf(" Force Quiescence: %s\n", (rdac_ptr->options & 0x2 ? "Enabled" : "Disabled" ));
|
|
|
39359f |
+ printf (" LUN Table: (p = preferred, a = alternate, u = utm lun)\n");
|
|
|
39359f |
+ printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n");
|
|
|
39359f |
+ for (k = 0; k < lun_table_len; k += 16) {
|
|
|
39359f |
+ printf(" 0x%x:",k / 16);
|
|
|
39359f |
+ for (i = 0; i < 16; i++) {
|
|
|
39359f |
+ switch (lun_table[k + i]) {
|
|
|
39359f |
case 0x0:
|
|
|
39359f |
printf(" x");
|
|
|
39359f |
break;
|
|
|
39359f |
@@ -287,6 +373,9 @@ static void print_rdac_mode( unsigned char *ptr )
|
|
|
39359f |
printf(" ?");
|
|
|
39359f |
break;
|
|
|
39359f |
}
|
|
|
39359f |
+ if (i == 7) {
|
|
|
39359f |
+ printf(" ");
|
|
|
39359f |
+ }
|
|
|
39359f |
}
|
|
|
39359f |
printf("\n");
|
|
|
39359f |
}
|
|
|
39359f |
@@ -296,6 +385,7 @@ static void usage()
|
|
|
39359f |
{
|
|
|
39359f |
printf("Usage: sg_rdac [-a] [-f=LUN] [-v] [-V] DEVICE\n"
|
|
|
39359f |
" where:\n"
|
|
|
39359f |
+ " -6 use 6 byte cdbs for mode sense/select\n"
|
|
|
39359f |
" -a transfer all devices to the controller\n"
|
|
|
39359f |
" serving DEVICE.\n"
|
|
|
39359f |
" -f=LUN transfer the device at LUN to the\n"
|
|
|
39359f |
@@ -316,6 +406,7 @@ int main(int argc, char * argv[])
|
|
|
39359f |
int fail_all = 0;
|
|
|
39359f |
int fail_path = 0;
|
|
|
39359f |
int ret = 0;
|
|
|
39359f |
+ int use_6_byte = 0;
|
|
|
39359f |
|
|
|
39359f |
if (argc < 2) {
|
|
|
39359f |
usage ();
|
|
|
39359f |
@@ -333,6 +424,9 @@ int main(int argc, char * argv[])
|
|
|
39359f |
else if (!strcmp(*argptr, "-a")) {
|
|
|
39359f |
++fail_all;
|
|
|
39359f |
}
|
|
|
39359f |
+ else if (!strcmp(*argptr, "-6")) {
|
|
|
39359f |
+ use_6_byte = 1;
|
|
|
39359f |
+ }
|
|
|
39359f |
else if (!strcmp(*argptr, "-V")) {
|
|
|
39359f |
fprintf(stderr, "sg_rdac version: %s\n", version_str);
|
|
|
39359f |
return 0;
|
|
|
39359f |
@@ -364,18 +458,24 @@ int main(int argc, char * argv[])
|
|
|
39359f |
}
|
|
|
39359f |
|
|
|
39359f |
if (fail_all) {
|
|
|
39359f |
- res = fail_all_paths(fd);
|
|
|
39359f |
+ res = fail_all_paths(fd, use_6_byte);
|
|
|
39359f |
} else if (fail_path) {
|
|
|
39359f |
- res = fail_this_path(fd, lun);
|
|
|
39359f |
+ res = fail_this_path(fd, lun, use_6_byte);
|
|
|
39359f |
} else {
|
|
|
39359f |
- res = sg_ll_mode_sense6(fd, /*DBD*/ 0, /* page control */0,
|
|
|
39359f |
+ if (use_6_byte) {
|
|
|
39359f |
+ res = sg_ll_mode_sense6(fd, /*DBD*/ 0, /* page control */0,
|
|
|
39359f |
0x2c, 0, rsp_buff, 252,
|
|
|
39359f |
1, do_verbose);
|
|
|
39359f |
+ } else {
|
|
|
39359f |
+ res = sg_ll_mode_sense10(fd, /*llbaa*/ 0, /*DBD*/ 0, /* page control */0,
|
|
|
39359f |
+ 0x2c, 0x1, rsp_buff, 308,
|
|
|
39359f |
+ 1, do_verbose);
|
|
|
39359f |
+ }
|
|
|
39359f |
|
|
|
39359f |
if (!res) {
|
|
|
39359f |
if (do_verbose)
|
|
|
39359f |
dump_mode_page(rsp_buff, rsp_buff[0]);
|
|
|
39359f |
- print_rdac_mode(rsp_buff);
|
|
|
39359f |
+ print_rdac_mode(rsp_buff, !use_6_byte);
|
|
|
39359f |
}
|
|
|
39359f |
}
|
|
|
39359f |
ret = res;
|
|
|
39359f |
diff --git a/src/sg_vpd_vendor.c b/src/sg_vpd_vendor.c
|
|
|
39359f |
index 10d455a..45e2b9d 100644
|
|
|
39359f |
--- a/src/sg_vpd_vendor.c
|
|
|
39359f |
+++ b/src/sg_vpd_vendor.c
|
|
|
39359f |
@@ -89,20 +89,20 @@ static struct svpd_values_name_t vendor_vpd_pg[] = {
|
|
|
39359f |
{VPD_V_DEV_BEH_SEA, 0, -1, 1, "devb", "Device behavior (Seagate)"},
|
|
|
39359f |
{VPD_V_EDID_RDAC, 0, -1, 1, "edid", "Extended device identification "
|
|
|
39359f |
"(RDAC)"},
|
|
|
39359f |
- {VPD_V_FEAT_RDAC, 1, -1, 1, "feat", "Feature Parameters (RDAC)"},
|
|
|
39359f |
+ {VPD_V_FEAT_RDAC, 1, -1, 1, "prm4", "Feature Parameters (RDAC)"},
|
|
|
39359f |
{VPD_V_FIRM_SEA, 0, -1, 1, "firm", "Firmware numbers (Seagate)"},
|
|
|
39359f |
- {VPD_V_FVER_RDAC, 1, -1, 1, "fver", "Firmware version (RDAC)"},
|
|
|
39359f |
+ {VPD_V_FVER_RDAC, 1, -1, 1, "fwr4", "Firmware version (RDAC)"},
|
|
|
39359f |
{VPD_V_HP3PAR, 2, -1, 1, "hp3par", "Volume information (HP/3PAR)"},
|
|
|
39359f |
- {VPD_V_HVER_RDAC, 3, -1, 1, "hver", "Hardware version (RDAC)"},
|
|
|
39359f |
+ {VPD_V_HVER_RDAC, 3, -1, 1, "hwr4", "Hardware version (RDAC)"},
|
|
|
39359f |
{VPD_V_JUMP_SEA, 0, -1, 1, "jump", "Jump setting (Seagate)"},
|
|
|
39359f |
{VPD_V_RVSI_RDAC, 0, -1, 1, "rvsi", "Replicated volume source "
|
|
|
39359f |
"identifier (RDAC)"},
|
|
|
39359f |
{VPD_V_SAID_RDAC, 0, -1, 1, "said", "Storage array world wide name "
|
|
|
39359f |
"(RDAC)"},
|
|
|
39359f |
- {VPD_V_SUBS_RDAC, 0, -1, 1, "sub", "Subsystem identifier (RDAC)"},
|
|
|
39359f |
- {VPD_V_SVER_RDAC, 1, -1, 1, "sver", "Software version (RDAC)"},
|
|
|
39359f |
+ {VPD_V_SUBS_RDAC, 0, -1, 1, "subs", "Subsystem identifier (RDAC)"},
|
|
|
39359f |
+ {VPD_V_SVER_RDAC, 1, -1, 1, "swr4", "Software version (RDAC)"},
|
|
|
39359f |
{VPD_V_UPR_EMC, 1, -1, 1, "upr", "Unit path report (EMC)"},
|
|
|
39359f |
- {VPD_V_VAC_RDAC, 0, -1, 1, "vac", "Volume access control (RDAC)"},
|
|
|
39359f |
+ {VPD_V_VAC_RDAC, 0, -1, 1, "vac1", "Volume access control (RDAC)"},
|
|
|
39359f |
{0, 0, 0, 0, NULL, NULL},
|
|
|
39359f |
};
|
|
|
39359f |
|
|
|
39359f |
@@ -439,7 +439,7 @@ decode_rdac_vpd_c0(unsigned char * buff, int len)
|
|
|
39359f |
memcpy(name, buff + 152, 2);
|
|
|
39359f |
printf(" Board Revision: %s\n", name);
|
|
|
39359f |
memset(name, 0, 65);
|
|
|
39359f |
- memcpy(name, buff + 154, 2);
|
|
|
39359f |
+ memcpy(name, buff + 154, 4);
|
|
|
39359f |
printf(" Board Identifier: %s\n", name);
|
|
|
39359f |
|
|
|
39359f |
return;
|
|
|
39359f |
@@ -461,7 +461,7 @@ decode_rdac_vpd_c1(unsigned char * buff, int len)
|
|
|
39359f |
"not possible.\n" , buff[4], buff[5], buff[6], buff[7]);
|
|
|
39359f |
return;
|
|
|
39359f |
}
|
|
|
39359f |
- printf(" Firmware Version: %x.%x.%x\n", buff[8], buff[9], buff[10]);
|
|
|
39359f |
+ printf(" Firmware Version: %02x.%02x.%02x\n", buff[8], buff[9], buff[10]);
|
|
|
39359f |
printf(" Firmware Date: %02d/%02d/%02d\n", buff[11], buff[12], buff[13]);
|
|
|
39359f |
|
|
|
39359f |
num_part = (len - 12) / 16;
|
|
|
39359f |
@@ -504,7 +504,7 @@ decode_rdac_vpd_c2(unsigned char * buff, int len)
|
|
|
39359f |
"not possible.\n" , buff[4], buff[5], buff[6], buff[7]);
|
|
|
39359f |
return;
|
|
|
39359f |
}
|
|
|
39359f |
- printf(" Software Version: %x.%x.%x\n", buff[8], buff[9], buff[10]);
|
|
|
39359f |
+ printf(" Software Version: %02x.%02x.%02x\n", buff[8], buff[9], buff[10]);
|
|
|
39359f |
printf(" Software Date: %02d/%02d/%02d\n", buff[11], buff[12], buff[13]);
|
|
|
39359f |
printf(" Features:");
|
|
|
39359f |
if (buff[14] & 0x01)
|
|
|
39359f |
@@ -514,9 +514,9 @@ decode_rdac_vpd_c2(unsigned char * buff, int len)
|
|
|
39359f |
if (buff[14] & 0x04)
|
|
|
39359f |
printf(" Multiple Sub-enclosures,");
|
|
|
39359f |
if (buff[14] & 0x08)
|
|
|
39359f |
- printf(" DCE/DRM,");
|
|
|
39359f |
+ printf(" DCE/DRM/DSS/DVE,");
|
|
|
39359f |
if (buff[14] & 0x10)
|
|
|
39359f |
- printf(" AVT,");
|
|
|
39359f |
+ printf(" Asymmetric Logical Unit Access,");
|
|
|
39359f |
printf("\n");
|
|
|
39359f |
printf(" Max. #of LUNS: %d\n", buff[15]);
|
|
|
39359f |
|
|
|
39359f |
@@ -562,6 +562,7 @@ decode_rdac_vpd_c3(unsigned char * buff, int len)
|
|
|
39359f |
printf(" UTM: %s\n", buff[11] & 0x80?"enabled":"disabled");
|
|
|
39359f |
if ((buff[11] & 0x80))
|
|
|
39359f |
printf(" UTM LUN: %02x\n", buff[11] & 0x7f);
|
|
|
39359f |
+ printf(" Persistent Reservations Bus Reset Support: %s\n", buff[12] & 0x01?"enabled":"disabled");
|
|
|
39359f |
|
|
|
39359f |
return;
|
|
|
39359f |
}
|
|
|
39359f |
@@ -603,6 +604,32 @@ decode_rdac_vpd_c4(unsigned char * buff, int len)
|
|
|
39359f |
printf(" (Board ID 2880)\n");
|
|
|
39359f |
else if (!strcmp(subsystem_rev, "14.0"))
|
|
|
39359f |
printf(" (Board ID 2822)\n");
|
|
|
39359f |
+ else if (!strcmp(subsystem_rev, "15.0"))
|
|
|
39359f |
+ printf(" (Board ID 6091)\n");
|
|
|
39359f |
+ else if (!strcmp(subsystem_rev, "16.0"))
|
|
|
39359f |
+ printf(" (Board ID 3992)\n");
|
|
|
39359f |
+ else if (!strcmp(subsystem_rev, "16.1"))
|
|
|
39359f |
+ printf(" (Board ID 3991)\n");
|
|
|
39359f |
+ else if (!strcmp(subsystem_rev, "17.0"))
|
|
|
39359f |
+ printf(" (Board ID 1331)\n");
|
|
|
39359f |
+ else if (!strcmp(subsystem_rev, "17.1"))
|
|
|
39359f |
+ printf(" (Board ID 1332)\n");
|
|
|
39359f |
+ else if (!strcmp(subsystem_rev, "17.3"))
|
|
|
39359f |
+ printf(" (Board ID 1532)\n");
|
|
|
39359f |
+ else if (!strcmp(subsystem_rev, "17.4"))
|
|
|
39359f |
+ printf(" (Board ID 1932)\n");
|
|
|
39359f |
+ else if (!strcmp(subsystem_rev, "42.0"))
|
|
|
39359f |
+ printf(" (Board ID 26x0)\n");
|
|
|
39359f |
+ else if (!strcmp(subsystem_rev, "43.0"))
|
|
|
39359f |
+ printf(" (Board ID 498x)\n");
|
|
|
39359f |
+ else if (!strcmp(subsystem_rev, "44.0"))
|
|
|
39359f |
+ printf(" (Board ID 548x)\n");
|
|
|
39359f |
+ else if (!strcmp(subsystem_rev, "45.0"))
|
|
|
39359f |
+ printf(" (Board ID 5501)\n");
|
|
|
39359f |
+ else if (!strcmp(subsystem_rev, "46.0"))
|
|
|
39359f |
+ printf(" (Board ID 2701)\n");
|
|
|
39359f |
+ else if (!strcmp(subsystem_rev, "47.0"))
|
|
|
39359f |
+ printf(" (Board ID 5601)\n");
|
|
|
39359f |
else
|
|
|
39359f |
printf(" (Board ID unknown)\n");
|
|
|
39359f |
|
|
|
39359f |
@@ -612,6 +639,16 @@ decode_rdac_vpd_c4(unsigned char * buff, int len)
|
|
|
39359f |
}
|
|
|
39359f |
|
|
|
39359f |
static void
|
|
|
39359f |
+convert_binary_to_ascii(unsigned char * src, unsigned char * dst, int len)
|
|
|
39359f |
+{
|
|
|
39359f |
+ int i;
|
|
|
39359f |
+
|
|
|
39359f |
+ for (i = 0; i < len; i++) {
|
|
|
39359f |
+ sprintf((char *)(dst+2*i), "%02x", *(src+i));
|
|
|
39359f |
+ }
|
|
|
39359f |
+}
|
|
|
39359f |
+
|
|
|
39359f |
+static void
|
|
|
39359f |
decode_rdac_vpd_c8(unsigned char * buff, int len)
|
|
|
39359f |
{
|
|
|
39359f |
int i;
|
|
|
39359f |
@@ -623,6 +660,8 @@ decode_rdac_vpd_c8(unsigned char * buff, int len)
|
|
|
39359f |
int label_len;
|
|
|
39359f |
char uuid[33];
|
|
|
39359f |
int uuid_len;
|
|
|
39359f |
+ unsigned char port_id[128];
|
|
|
39359f |
+ int n;
|
|
|
39359f |
|
|
|
39359f |
if (len < 0xab) {
|
|
|
39359f |
fprintf(stderr, "Extended Device Identification VPD page length too "
|
|
|
39359f |
@@ -679,10 +718,110 @@ decode_rdac_vpd_c8(unsigned char * buff, int len)
|
|
|
39359f |
|
|
|
39359f |
printf(" Logical Unit Number: %s\n", uuid);
|
|
|
39359f |
|
|
|
39359f |
+ /* Initiator transport ID */
|
|
|
39359f |
+ if ( buff[10] & 0x01 ) {
|
|
|
39359f |
+ memset(port_id, 0, 128);
|
|
|
39359f |
+ printf(" Transport Protocol: ");
|
|
|
39359f |
+ switch (buff[175] & 0x0F) {
|
|
|
39359f |
+ case TPROTO_FCP: /* FC */
|
|
|
39359f |
+ printf("FC\n");
|
|
|
39359f |
+ convert_binary_to_ascii(&buff[183], port_id, 8);
|
|
|
39359f |
+ n = 199;
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case TPROTO_SRP: /* SRP */
|
|
|
39359f |
+ printf("SRP\n");
|
|
|
39359f |
+ convert_binary_to_ascii(&buff[183], port_id, 8);
|
|
|
39359f |
+ n = 199;
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case TPROTO_ISCSI: /* iSCSI */
|
|
|
39359f |
+ printf("iSCSI\n");
|
|
|
39359f |
+ n = (buff[177] << 8) + buff[178];
|
|
|
39359f |
+ memcpy(port_id, &buff[179], n);
|
|
|
39359f |
+ n = 179 + n;
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case TPROTO_SAS: /* SAS */
|
|
|
39359f |
+ printf("SAS\n");
|
|
|
39359f |
+ convert_binary_to_ascii(&buff[179], port_id, 8);
|
|
|
39359f |
+ n = 199;
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ default:
|
|
|
39359f |
+ return; /* Can't continue decoding, so return */
|
|
|
39359f |
+ }
|
|
|
39359f |
+
|
|
|
39359f |
+ printf(" Initiator Port Identifier: %s\n", port_id);
|
|
|
39359f |
+ if ( buff[10] & 0x02 ) {
|
|
|
39359f |
+ memset(port_id, 0, 128);
|
|
|
39359f |
+ memcpy(port_id, &buff[n], 8);
|
|
|
39359f |
+ printf(" Supplemental Vendor ID: %s\n", port_id);
|
|
|
39359f |
+ }
|
|
|
39359f |
+ }
|
|
|
39359f |
+
|
|
|
39359f |
return;
|
|
|
39359f |
}
|
|
|
39359f |
|
|
|
39359f |
static void
|
|
|
39359f |
+decode_rdac_vpd_c9_rtpg_data(unsigned char aas, unsigned char vendor)
|
|
|
39359f |
+{
|
|
|
39359f |
+ printf(" Asymmetric Access State:");
|
|
|
39359f |
+ switch(aas & 0x0F) {
|
|
|
39359f |
+ case 0x0:
|
|
|
39359f |
+ printf(" Active/Optimized");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x1:
|
|
|
39359f |
+ printf(" Active/Non-Optimized");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x2:
|
|
|
39359f |
+ printf(" Standby");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x3:
|
|
|
39359f |
+ printf(" Unavailable");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0xE:
|
|
|
39359f |
+ printf(" Offline");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0xF:
|
|
|
39359f |
+ printf(" Transitioning");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ default:
|
|
|
39359f |
+ printf(" (unknown)");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ }
|
|
|
39359f |
+ printf("\n");
|
|
|
39359f |
+
|
|
|
39359f |
+ printf(" Vendor Specific Field:");
|
|
|
39359f |
+ switch(vendor) {
|
|
|
39359f |
+ case 0x01:
|
|
|
39359f |
+ printf(" Operating normally");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x02:
|
|
|
39359f |
+ printf(" Non-responsive to queries");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x03:
|
|
|
39359f |
+ printf(" Controller being held in reset");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x04:
|
|
|
39359f |
+ printf(" Performing controller firmware download (1st controller)");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x05:
|
|
|
39359f |
+ printf(" Performing controller firmware download (2nd controller)");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x06:
|
|
|
39359f |
+ printf(" Quiesced as a result of an administrative request");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x07:
|
|
|
39359f |
+ printf(" Service mode as a result of an administrative request");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0xFF:
|
|
|
39359f |
+ printf(" Details are not available");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ default:
|
|
|
39359f |
+ printf(" (unknown)");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ }
|
|
|
39359f |
+ printf("\n");
|
|
|
39359f |
+}
|
|
|
39359f |
+
|
|
|
39359f |
+static void
|
|
|
39359f |
decode_rdac_vpd_c9(unsigned char * buff, int len)
|
|
|
39359f |
{
|
|
|
39359f |
if (len < 3) {
|
|
|
39359f |
@@ -699,14 +838,18 @@ decode_rdac_vpd_c9(unsigned char * buff, int len)
|
|
|
39359f |
fprintf(stderr, "Invalid page version '%c' (should be 1)\n",
|
|
|
39359f |
buff[7]);
|
|
|
39359f |
}
|
|
|
39359f |
- printf(" AVT:");
|
|
|
39359f |
- if (buff[8] & 0x80) {
|
|
|
39359f |
- printf(" Enabled");
|
|
|
39359f |
- if (buff[8] & 0x40)
|
|
|
39359f |
- printf(" (Allow reads on sector 0)");
|
|
|
39359f |
- printf("\n");
|
|
|
39359f |
+ if ( (buff[8] & 0xE0) == 0xE0 ) {
|
|
|
39359f |
+ printf(" IOShipping (ALUA): Enabled\n");
|
|
|
39359f |
} else {
|
|
|
39359f |
- printf(" Disabled\n");
|
|
|
39359f |
+ printf(" AVT:");
|
|
|
39359f |
+ if (buff[8] & 0x80) {
|
|
|
39359f |
+ printf(" Enabled");
|
|
|
39359f |
+ if (buff[8] & 0x40)
|
|
|
39359f |
+ printf(" (Allow reads on sector 0)");
|
|
|
39359f |
+ printf("\n");
|
|
|
39359f |
+ } else {
|
|
|
39359f |
+ printf(" Disabled\n");
|
|
|
39359f |
+ }
|
|
|
39359f |
}
|
|
|
39359f |
printf(" Volume Access via: ");
|
|
|
39359f |
if (buff[8] & 0x01)
|
|
|
39359f |
@@ -714,8 +857,54 @@ decode_rdac_vpd_c9(unsigned char * buff, int len)
|
|
|
39359f |
else
|
|
|
39359f |
printf("alternate controller\n");
|
|
|
39359f |
|
|
|
39359f |
- printf(" Path priority: %d ", buff[9] & 0xf);
|
|
|
39359f |
- switch(buff[9] & 0xf) {
|
|
|
39359f |
+ if (buff[8] & 0x08) {
|
|
|
39359f |
+ printf(" Path priority: %d ", buff[15] & 0xf);
|
|
|
39359f |
+ switch(buff[15] & 0xf) {
|
|
|
39359f |
+ case 0x1:
|
|
|
39359f |
+ printf("(preferred path)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x2:
|
|
|
39359f |
+ printf("(secondary path)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ default:
|
|
|
39359f |
+ printf("(unknown)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ }
|
|
|
39359f |
+
|
|
|
39359f |
+ printf(" Preferred Path Auto Changeable:");
|
|
|
39359f |
+ switch(buff[14] & 0x3C) {
|
|
|
39359f |
+ case 0x14:
|
|
|
39359f |
+ printf(" No (User Disabled and Host Type Restricted)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x18:
|
|
|
39359f |
+ printf(" No (User Disabled)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x24:
|
|
|
39359f |
+ printf(" No (Host Type Restricted)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x28:
|
|
|
39359f |
+ printf(" Yes\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ default:
|
|
|
39359f |
+ printf(" (Unknown)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ }
|
|
|
39359f |
+
|
|
|
39359f |
+ printf(" Implicit Failback:");
|
|
|
39359f |
+ switch(buff[14] & 0x03) {
|
|
|
39359f |
+ case 0x1:
|
|
|
39359f |
+ printf(" Disabled\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ case 0x2:
|
|
|
39359f |
+ printf(" Enabled\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ default:
|
|
|
39359f |
+ printf(" (Unknown)\n");
|
|
|
39359f |
+ break;
|
|
|
39359f |
+ }
|
|
|
39359f |
+ } else {
|
|
|
39359f |
+ printf(" Path priority: %d ", buff[9] & 0xf);
|
|
|
39359f |
+ switch(buff[9] & 0xf) {
|
|
|
39359f |
case 0x1:
|
|
|
39359f |
printf("(preferred path)\n");
|
|
|
39359f |
break;
|
|
|
39359f |
@@ -725,9 +914,17 @@ decode_rdac_vpd_c9(unsigned char * buff, int len)
|
|
|
39359f |
default:
|
|
|
39359f |
printf("(unknown)\n");
|
|
|
39359f |
break;
|
|
|
39359f |
+ }
|
|
|
39359f |
}
|
|
|
39359f |
|
|
|
39359f |
- return;
|
|
|
39359f |
+
|
|
|
39359f |
+ if (buff[8] & 0x80) {
|
|
|
39359f |
+ printf(" Target Port Group Data (This controller):\n");
|
|
|
39359f |
+ decode_rdac_vpd_c9_rtpg_data(buff[10], buff[11]);
|
|
|
39359f |
+
|
|
|
39359f |
+ printf(" Target Port Group Data (Alternate controller):\n");
|
|
|
39359f |
+ decode_rdac_vpd_c9_rtpg_data(buff[12], buff[13]);
|
|
|
39359f |
+ }
|
|
|
39359f |
}
|
|
|
39359f |
|
|
|
39359f |
static void
|
|
|
39359f |
--
|
|
|
39359f |
1.8.3.1
|
|
|
39359f |
|