From 4fed8b17b1cd75492d20cf701ebe4f66e13385f5 Mon Sep 17 00:00:00 2001 From: David Sommerseth 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