/* Decodes given user data referral segment descriptor * the number of blocks and returns the number of bytes processed, * -1 for error. */ static int decode_referral_desc(const uint8_t * bp, int bytes) { int j, n; uint64_t first, last; if (NULL == bp) return -1; if (bytes < 20) return -1; first = sg_get_unaligned_be64(bp + 4); last = sg_get_unaligned_be64(bp + 12); printf(" target port descriptors: %d\n", bp[3]); printf(" user data segment: first lba %" PRIu64 ", last lba %" PRIu64 "\n", first, last); n = 20; bytes -= n; for (j = 0; j < bp[3]; j++) { if (bytes < 4) return -1; printf(" target port descriptor %d:\n", j); printf(" port group %x state (%s)\n", sg_get_unaligned_be16(bp + n + 2), decode_tpgs_state(bp[n] & 0xf)); n += 4; bytes -= 4; } return n; }
int main(int argc, char * argv[]) { int sg_fd, k, j, off, res, c, report_len, tgt_port_count; unsigned char reportTgtGrpBuff[REPORT_TGT_GRP_BUFF_LEN]; unsigned char * ucp; int decode = 0; int hex = 0; int raw = 0; int o_readonly = 0; int verbose = 0; int extended = 0; const char * device_name = NULL; int ret = 0; while (1) { int option_index = 0; c = getopt_long(argc, argv, "dehHrRvV", long_options, &option_index); if (c == -1) break; switch (c) { case 'd': decode = 1; break; case 'e': extended = 1; break; case 'h': case '?': usage(); return 0; case 'H': hex = 1; break; case 'r': raw = 1; break; case 'R': ++o_readonly; break; case 'v': ++verbose; break; case 'V': fprintf(stderr, "Version: %s\n", version_str); return 0; default: fprintf(stderr, "unrecognised option code 0x%x ??\n", c); usage(); return SG_LIB_SYNTAX_ERROR; } } if (optind < argc) { if (NULL == device_name) { device_name = argv[optind]; ++optind; } if (optind < argc) { for (; optind < argc; ++optind) fprintf(stderr, "Unexpected extra argument: %s\n", argv[optind]); usage(); return SG_LIB_SYNTAX_ERROR; } } if (NULL == device_name) { fprintf(stderr, "missing device name!\n"); usage(); return SG_LIB_SYNTAX_ERROR; } if (raw) { if (sg_set_binary_mode(STDOUT_FILENO) < 0) { perror("sg_set_binary_mode"); return SG_LIB_FILE_ERROR; } } sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose); if (sg_fd < 0) { fprintf(stderr, "open error: %s: %s\n", device_name, safe_strerror(-sg_fd)); return SG_LIB_FILE_ERROR; } memset(reportTgtGrpBuff, 0x0, sizeof(reportTgtGrpBuff)); /* trunc = 0; */ res = sg_ll_report_tgt_prt_grp2(sg_fd, reportTgtGrpBuff, sizeof(reportTgtGrpBuff), extended, 1, verbose); ret = res; if (0 == res) { report_len = (reportTgtGrpBuff[0] << 24) + (reportTgtGrpBuff[1] << 16) + (reportTgtGrpBuff[2] << 8) + reportTgtGrpBuff[3] + 4; if (report_len > (int)sizeof(reportTgtGrpBuff)) { /* trunc = 1; */ fprintf(stderr, " <<report too long for internal buffer," " output truncated\n"); report_len = (int)sizeof(reportTgtGrpBuff); } if (raw) { dStrRaw((const char *)reportTgtGrpBuff, report_len); goto err_out; } if (verbose) printf("Report list length = %d\n", report_len); if (hex) { if (verbose) printf("\nOutput response in hex:\n"); dStrHex((const char *)reportTgtGrpBuff, report_len, 1); goto err_out; } printf("Report target port groups:\n"); ucp = reportTgtGrpBuff + 4; if (extended) { if (0x10 != (ucp[0] & 0x70)) { fprintf(stderr, " <<invalid extended header format\n"); goto err_out; } printf(" Implicit transition time: %d\n", ucp[1]); ucp += 4; } for (k = ucp - reportTgtGrpBuff; k < report_len; k += off, ucp += off) { printf(" target port group id : 0x%x , Pref=%d, Rtpg_fmt=%d\n", (ucp[2] << 8) + ucp[3], !!(ucp[0] & 0x80), (ucp[0] >> 4) & 0x07); printf(" target port group asymmetric access state : "); printf("0x%02x", ucp[0] & 0x0f); if (decode) decode_tpgs_state(ucp[0] & 0x0f); printf("\n"); printf(" T_SUP : %d, ", !!(ucp[1] & 0x80)); printf("O_SUP : %d, ", !!(ucp[1] & 0x40)); printf("LBD_SUP : %d, ", !!(ucp[1] & 0x10)); printf("U_SUP : %d, ", !!(ucp[1] & 0x08)); printf("S_SUP : %d, ", !!(ucp[1] & 0x04)); printf("AN_SUP : %d, ", !!(ucp[1] & 0x02)); printf("AO_SUP : %d\n", !!(ucp[1] & 0x01)); printf(" status code : "); printf("0x%02x", ucp[5]); if (decode) decode_status(ucp[5]); printf("\n"); printf(" vendor unique status : "); printf("0x%02x\n", ucp[6]); printf(" target port count : "); tgt_port_count = ucp[7]; printf("%02x\n", tgt_port_count); for (j = 0; j < tgt_port_count * 4; j += 4) { if (0 == j) printf(" Relative target port ids:\n"); printf(" 0x%02x\n", (ucp[8 + j + 2] << 8) + ucp[8 + j + 3]); } off = 8 + j; } } else if (SG_LIB_CAT_INVALID_OP == res)