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