예제 #1
0
static int
examine_pages(int sg_fd, int inq_pdt, int inq_byte6,
              const struct opts_t * optsp)
{
    int k, res, header, mresp_len, len;
    unsigned char rbuf[256];
    const char * cp;

    mresp_len = (optsp->do_raw || optsp->do_hex) ? sizeof(rbuf) : 4;
    for (header = 0, k = 0; k < PG_CODE_MAX; ++k) {
        if (optsp->do_six) {
            res = sg_ll_mode_sense6(sg_fd, 0, 0, k, 0, rbuf, mresp_len,
                                    1, optsp->do_verbose);
            if (SG_LIB_CAT_INVALID_OP == res) {
                fprintf(stderr, ">>>>>> try again without the '-6' "
                        "switch for a 10 byte MODE SENSE command\n");
                return res;
            } else if (SG_LIB_CAT_NOT_READY == res) {
                fprintf(stderr, "MODE SENSE (6) failed, device not ready\n");
                return res;
            }
        } else {
            res = sg_ll_mode_sense10(sg_fd, 0, 0, 0, k, 0, rbuf, mresp_len,
                                     1, optsp->do_verbose);
            if (SG_LIB_CAT_INVALID_OP == res) {
                fprintf(stderr, ">>>>>> try again with a '-6' "
                        "switch for a 6 byte MODE SENSE command\n");
                return res;
            } else if (SG_LIB_CAT_NOT_READY == res) {
                fprintf(stderr, "MODE SENSE (10) failed, device not ready\n");
                return res;
            }
        }
        if (0 == res) {
            len = optsp->do_six ? (rbuf[0] + 1) :
                                  ((rbuf[0] << 8) + rbuf[1] + 2);
            if (len > mresp_len)
                len = mresp_len;
            if (optsp->do_raw) {
                dStrRaw((const char *)rbuf, len);
                continue;
            }
            if (0 == header) {
                printf("Discovered mode pages:\n");
                header = 1;
            }
            cp = find_page_code_desc(k, 0, inq_pdt, inq_byte6, -1);
            if (cp)
                printf("    %s\n", cp);
            else
                printf("    [0x%x]\n", k);
            if (optsp->do_hex)
                dStrHex((const char *)rbuf, len, 1);
        }
    }
    return res;
}
예제 #2
0
파일: sg_safte.c 프로젝트: junroh/sg3_utils
/* Buffer ID 0x04: Read Device Slot Status (mandatory) */
static int
do_safte_slot_status(int sg_fd, int do_hex, int do_raw, int verbose)
{
    int res, i;
    unsigned int rb_len;
    unsigned char *rb_buff, slot_status;

    rb_len = safte_cfg.slots * 4;
    rb_buff = (unsigned char *)malloc(rb_len);

    if (verbose > 1)
        pr2serr("Use READ BUFFER,mode=vendor_specific,buff_id=4 to read "
                "device slot status\n");
    res = sg_ll_read_buffer(sg_fd, RWB_MODE_VENDOR, 4, 0,
                            rb_buff, rb_len, 0, verbose);
    if (res && res != SG_LIB_CAT_RECOVERED) {
        free(rb_buff);
        return res;
    }

    if (do_raw > 1) {
        dStrRaw((const char *)rb_buff, buf_capacity);
        return 0;
    }
    if (do_hex > 1) {
        dStrHex((const char *)rb_buff, buf_capacity, 1);
        return 0;
    }
    printf("Slot status:\n");
    for (i = 0; i < safte_cfg.slots; i++) {
        slot_status = rb_buff[i * 4 + 3];
        printf("\tSlot %d: ", i);
        if (slot_status & 0x7) {
            if (slot_status & 0x1)
                printf("inserted ");
            if (slot_status & 0x2)
                printf("ready ");
            if (slot_status & 0x4)
                printf("activated ");
            printf("\n");
        } else {
            printf("empty\n");
        }
    }
    free(rb_buff);
    return 0;
}
예제 #3
0
파일: sg_safte.c 프로젝트: WOWers/sg3_utils
/* Buffer ID 0x02: Read Usage Statistics (optional) */
static int
do_safte_usage_statistics(int sg_fd, int do_hex, int do_raw, int verbose)
{
    int res;
    unsigned int rb_len;
    unsigned char *rb_buff;
    unsigned int minutes;

    rb_len = 16 + safte_cfg.vendor_specific;
    rb_buff = (unsigned char *)malloc(rb_len);

    if (verbose > 1)
        fprintf(stderr, "Use READ BUFFER,mode=vendor_specific,buff_id=2 "
                "to read usage statistics\n");
    res = sg_ll_read_buffer(sg_fd, RWB_MODE_VENDOR, 2, 0,
                            rb_buff, rb_len, 0, verbose);
    if (res) {
        if (res == SG_LIB_CAT_ILLEGAL_REQ) {
            printf("Usage Statistics:\n\tNot implemented\n");
            return 0;
        }
        if (res != SG_LIB_CAT_RECOVERED) {
            free(rb_buff);
            return res;
        }
    }

    if (do_raw > 1) {
        dStrRaw((const char *)rb_buff, buf_capacity);
        return 0;
    }
    if (do_hex > 1) {
        dStrHex((const char *)rb_buff, buf_capacity, 1);
        return 0;
    }
    printf("Usage Statistics:\n");
    minutes = (rb_buff[0] << 24) + (rb_buff[1] << 16) +
        (rb_buff[2] <<  8) + rb_buff[3];
    printf("\tPower on Minutes: %u\n", minutes);
    minutes = (rb_buff[4] << 24) + (rb_buff[5] << 16) +
        (rb_buff[6] <<  8) + rb_buff[7];
    printf("\tPower on Cycles: %u\n", minutes);

    free(rb_buff);
    return 0;
}
예제 #4
0
파일: sg_safte.c 프로젝트: junroh/sg3_utils
/* Buffer ID 0x03: Read Device Insertions (optional) */
static int
do_safte_slot_insertions(int sg_fd, int do_hex, int do_raw, int verbose)
{
    int res, i;
    unsigned int rb_len;
    unsigned char *rb_buff, slot_status;

    rb_len = safte_cfg.slots * 2;
    rb_buff = (unsigned char *)malloc(rb_len);

    if (verbose > 1)
        pr2serr("Use READ BUFFER,mode=vendor_specific,buff_id=3 to read "
                "device insertions\n");
    res = sg_ll_read_buffer(sg_fd, RWB_MODE_VENDOR, 3, 0,
                            rb_buff, rb_len, 0, verbose);
    if (res ) {
        if (res == SG_LIB_CAT_ILLEGAL_REQ) {
                printf("Slot insertions:\n\tNot implemented\n");
                return 0;
        }
        if (res != SG_LIB_CAT_RECOVERED) {
                free(rb_buff);
                return res;
        }
    }

    if (do_raw > 1) {
        dStrRaw((const char *)rb_buff, buf_capacity);
        return 0;
    }
    if (do_hex > 1) {
        dStrHex((const char *)rb_buff, buf_capacity, 1);
        return 0;
    }
    printf("Slot insertions:\n");
    for (i = 0; i < safte_cfg.slots; i++) {
        slot_status = sg_get_unaligned_be16(rb_buff + (i * 2));
        printf("\tSlot %d: %d insertions", i, slot_status);
    }
    free(rb_buff);
    return 0;
}
예제 #5
0
int
main(int argc, char * argv[])
{
    int res, c, k, len, act_resplen;
    int aff_context = 0;
    int do_hex = 0;
    int phy_id = 0;
    int phy_id_given = 0;
    int do_raw = 0;
    int verbose = 0;
    int do_zero = 0;
    int64_t sa_ll;
    uint64_t sa = 0;
    char i_params[256];
    char device_name[512];
    char b[256];
    unsigned char smp_req[] = {SMP_FRAME_TYPE_REQ, SMP_FN_REPORT_PHY_SATA,
                               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    unsigned char smp_resp[SMP_FN_REPORT_PHY_SATA_RESP_LEN];
    struct smp_req_resp smp_rr;
    struct smp_target_obj tobj;
    int subvalue = 0;
    char * cp;
    int ret = 0;

    memset(device_name, 0, sizeof device_name);
    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "ahHI:p:rs:vVz", long_options,
                        &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'a':
           aff_context = smp_get_num(optarg);
           if ((aff_context < 0) || (aff_context > 255)) {
                pr2serr("bad argument to '--affiliation'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'h':
        case '?':
            usage();
            return 0;
        case 'H':
            ++do_hex;
            break;
        case 'I':
            strncpy(i_params, optarg, sizeof(i_params));
            i_params[sizeof(i_params) - 1] = '\0';
            break;
        case 'p':
           phy_id = smp_get_num(optarg);
           if ((phy_id < 0) || (phy_id > 254)) {
                pr2serr("bad argument to '--phy', expect value from 0 to "
                        "254\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            ++phy_id_given;
            break;
        case 'r':
            ++do_raw;
            break;
        case 's':
           sa_ll = smp_get_llnum(optarg);
           if (-1LL == sa_ll) {
                pr2serr("bad argument to '--sa'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            sa = (uint64_t)sa_ll;
            break;
        case 'v':
            ++verbose;
            break;
        case 'V':
            pr2serr("version: %s\n", version_str);
            return 0;
        case 'z':
            ++do_zero;
            break;
        default:
            pr2serr("unrecognised switch code 0x%x ??\n", c);
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (optind < argc) {
        if ('\0' == device_name[0]) {
            strncpy(device_name, argv[optind], sizeof(device_name) - 1);
            device_name[sizeof(device_name) - 1] = '\0';
            ++optind;
        }
        if (optind < argc) {
            for (; optind < argc; ++optind)
                pr2serr("Unexpected extra argument: %s\n", argv[optind]);
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (0 == device_name[0]) {
        cp = getenv("SMP_UTILS_DEVICE");
        if (cp)
            strncpy(device_name, cp, sizeof(device_name) - 1);
        else {
            pr2serr("missing device name on command line\n    [Could use "
                    "environment variable SMP_UTILS_DEVICE instead]\n");
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if ((cp = strchr(device_name, SMP_SUBVALUE_SEPARATOR))) {
        *cp = '\0';
        if (1 != sscanf(cp + 1, "%d", &subvalue)) {
            pr2serr("expected number after separator in SMP_DEVICE name\n");
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (0 == sa) {
        cp = getenv("SMP_UTILS_SAS_ADDR");
        if (cp) {
           sa_ll = smp_get_llnum(cp);
           if (-1LL == sa_ll) {
                pr2serr("bad value in environment variable "
                        "SMP_UTILS_SAS_ADDR\n    use 0\n");
                sa_ll = 0;
            }
            sa = (uint64_t)sa_ll;
        }
    }
    if (sa > 0) {
        if (! smp_is_naa5(sa)) {
            pr2serr("SAS (target) address not in naa-5 format (may need "
                    "leading '0x')\n");
            if ('\0' == i_params[0]) {
                pr2serr("    use '--interface=' to override\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
        }
    }

    res = smp_initiator_open(device_name, subvalue, i_params, sa,
                             &tobj, verbose);
    if (res < 0)
        return SMP_LIB_FILE_ERROR;

    if (! do_zero) {     /* SAS-2 or later */
        len = (sizeof(smp_resp) - 8) / 4;
        smp_req[2] = (len < 0x100) ? len : 0xff; /* Allocated Response Len */
        smp_req[3] = 2; /* Request Length: in dwords */
    }
    smp_req[9] = phy_id;
    smp_req[10] = aff_context;
    if (verbose) {
        pr2serr("    Report phy SATA request: ");
        for (k = 0; k < (int)sizeof(smp_req); ++k)
            pr2serr("%02x ", smp_req[k]);
        pr2serr("\n");
    }
    memset(&smp_rr, 0, sizeof(smp_rr));
    smp_rr.request_len = sizeof(smp_req);
    smp_rr.request = smp_req;
    smp_rr.max_response_len = sizeof(smp_resp);
    smp_rr.response = smp_resp;
    res = smp_send_req(&tobj, &smp_rr, verbose);

    if (res) {
        pr2serr("smp_send_req failed, res=%d\n", res);
        if (0 == verbose)
            pr2serr("    try adding '-v' option for more debug\n");
        ret = -1;
        goto err_out;
    }
    if (smp_rr.transport_err) {
        pr2serr("smp_send_req transport_error=%d\n", smp_rr.transport_err);
        ret = -1;
        goto err_out;
    }
    act_resplen = smp_rr.act_response_len;
    if ((act_resplen >= 0) && (act_resplen < 4)) {
        pr2serr("response too short, len=%d\n", act_resplen);
        ret = SMP_LIB_CAT_MALFORMED;
        goto err_out;
    }
    len = smp_resp[3];
    if ((0 == len) && (0 == smp_resp[2])) {
        len = smp_get_func_def_resp_len(smp_resp[1]);
        if (len < 0) {
            len = 0;
            if (verbose > 0)
                pr2serr("unable to determine response length\n");
        }
    }
    len = 4 + (len * 4);        /* length in bytes, excluding 4 byte CRC */
    if ((act_resplen >= 0) && (len > act_resplen)) {
        if (verbose)
            pr2serr("actual response length [%d] less than deduced length "
                    "[%d]\n", act_resplen, len);
        len = act_resplen;
    }
    if (do_hex || do_raw) {
        if (do_hex)
            dStrHex((const char *)smp_resp, len, 1);
        else
            dStrRaw((const char *)smp_resp, len);
        if (SMP_FRAME_TYPE_RESP != smp_resp[0])
            ret = SMP_LIB_CAT_MALFORMED;
        else if (smp_resp[1] != smp_req[1])
            ret = SMP_LIB_CAT_MALFORMED;
        else if (smp_resp[2]) {
            if (verbose)
                pr2serr("Report phy SATA result: %s\n",
                        smp_get_func_res_str(smp_resp[2], sizeof(b), b));
            ret = smp_resp[2];
        }
        goto err_out;
    }
    if (SMP_FRAME_TYPE_RESP != smp_resp[0]) {
        pr2serr("expected SMP frame response type, got=0x%x\n", smp_resp[0]);
        ret = SMP_LIB_CAT_MALFORMED;
        goto err_out;
    }
    if (smp_resp[1] != smp_req[1]) {
        pr2serr("Expected function code=0x%x, got=0x%x\n", smp_req[1],
                smp_resp[1]);
        ret = SMP_LIB_CAT_MALFORMED;
        goto err_out;
    }
    if (smp_resp[2]) {
        cp = smp_get_func_res_str(smp_resp[2], sizeof(b), b);
        pr2serr("Report phy SATA result%s: %s\n",
                (phy_id_given ? "" : " (for phy_id=0)"), cp);
        ret = smp_resp[2];
        goto err_out;
    }
    printf("Report phy SATA response:\n");
    res = sg_get_unaligned_be16(smp_resp + 4);
    if (verbose || (res > 0))
        printf("  expander change count: %d\n", res);
    printf("  phy identifier: %d\n", smp_resp[9]);
    printf("  STP I_T nexus loss occurred: %d\n", !!(smp_resp[11] & 0x4));
    printf("  affiliations supported: %d\n", !!(smp_resp[11] & 0x2));
    printf("  affiliation valid: %d\n", !!(smp_resp[11] & 0x1));
    printf("  STP SAS address: 0x%" PRIx64 "\n",
           sg_get_unaligned_be64(smp_resp + 16));
    printf("  register device to host FIS:\n    ");
    for (k = 0; k < 20; ++k)
        printf("%02x ", smp_resp[24 + k]);
    printf("\n");
    printf("  affiliated STP initiator SAS address: 0x%" PRIx64 "\n",
           sg_get_unaligned_be64(smp_resp + 48));
    if (len > 63)
        printf("  STP I_T nexus loss SAS address: 0x%" PRIx64 "\n",
               sg_get_unaligned_be64(smp_resp + 56));
    if (len > 67) {
        printf("  affiliation context: %d\n", smp_resp[65]);
        printf("  current affiliation contexts: %d\n", smp_resp[66]);
        printf("  maximum affiliation contexts: %d\n", smp_resp[67]);
    }

err_out:
    res = smp_initiator_close(&tobj);
    if (res < 0) {
        pr2serr("close error: %s\n", safe_strerror(errno));
        if (0 == ret)
            return SMP_LIB_FILE_ERROR;
    }
    if (ret < 0)
        ret = SMP_LIB_CAT_OTHER;
    if (verbose && ret)
        pr2serr("Exit status %d indicates error detected\n", ret);
    return ret;
}
예제 #6
0
int
main(int argc, char * argv[])
{
    int res, c, k, j, m, len, desc_len, num_desc, numzg, max_sszg;
    int desc_per_resp, first, rtype, act_resplen;
    int do_append = 0;
    int do_hex = 0;
    int multiple = 0;
    int nocomma = 0;
    int mndesc = DEF_MAX_NUM_DESC;
    int mndesc_given = 0;
    const char * permf = NULL;
    int do_raw = 0;
    int report_type = 0;
    int sszg = 0;
    int bits_col = 0;
    int verbose = 0;
    int64_t sa_ll;
    uint64_t sa = 0;
    char i_params[256];
    char device_name[512];
    char b[256];
    unsigned char smp_req[12];
    unsigned char smp_resp[SMP_FN_REPORT_ZONE_PERMISSION_TBL_RESP_LEN];
    struct smp_req_resp smp_rr;
    struct smp_target_obj tobj;
    int subvalue = 0;
    char * cp;
    unsigned char * descp;
    FILE * foutp = stdout;
    int ret = 0;

    memset(device_name, 0, sizeof device_name);
    memset(smp_resp, 0, sizeof smp_resp);
    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "aB:f:hHI:mn:NP:rR:s:vV", long_options,
                        &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'a':
            ++do_append;
            break;
        case 'B':
           bits_col = smp_get_num(optarg);
           if ((bits_col < 1) || (bits_col > 256)) {
                pr2serr("bad argument to '--bits=', expect 1 to 256\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'f':       /* note: maps to '--start=SS' option */
           sszg = smp_get_num(optarg);
           if ((sszg < 0) || (sszg > 255)) {
                pr2serr("bad argument to '--start=', expect 0 to 255\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'h':
        case '?':
            usage();
            return 0;
        case 'H':
            ++do_hex;
            break;
        case 'I':
            strncpy(i_params, optarg, sizeof(i_params));
            i_params[sizeof(i_params) - 1] = '\0';
            break;
        case 'n':
           mndesc = smp_get_num(optarg);
           if ((mndesc < 0) || (mndesc > 63)) {
                pr2serr("bad argument to '--num=', expect 0 to 63\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            if (0 == mndesc)
                mndesc = DEF_MAX_NUM_DESC;
            else
                ++mndesc_given;
            break;
        case 'm':
            ++multiple;
            break;
        case 'N':
            ++nocomma;
            break;
        case 'P':
           permf = optarg;
            break;
        case 'r':
            ++do_raw;
            break;
        case 'R':
           report_type = smp_get_num(optarg);
           if ((report_type < 0) || (report_type > 3)) {
                pr2serr("bad argument to '--report=', expect 0 to 3\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 's':
           sa_ll = smp_get_llnum(optarg);
           if (-1LL == sa_ll) {
                pr2serr("bad argument to '--sa'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            sa = (uint64_t)sa_ll;
            break;
        case 'v':
            ++verbose;
            break;
        case 'V':
            pr2serr("version: %s\n", version_str);
            return 0;
        default:
            pr2serr("unrecognised switch code 0x%x ??\n", c);
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (optind < argc) {
        if ('\0' == device_name[0]) {
            strncpy(device_name, argv[optind], sizeof(device_name) - 1);
            device_name[sizeof(device_name) - 1] = '\0';
            ++optind;
        }
        if (optind < argc) {
            for (; optind < argc; ++optind)
                pr2serr("Unexpected extra argument: %s\n", argv[optind]);
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (0 == device_name[0]) {
        cp = getenv("SMP_UTILS_DEVICE");
        if (cp)
            strncpy(device_name, cp, sizeof(device_name) - 1);
        else {
            pr2serr("missing device name on command line\n    [Could use "
                    "environment variable SMP_UTILS_DEVICE instead]\n");
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if ((cp = strchr(device_name, SMP_SUBVALUE_SEPARATOR))) {
        *cp = '\0';
        if (1 != sscanf(cp + 1, "%d", &subvalue)) {
            pr2serr("expected number after separator in SMP_DEVICE name\n");
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (0 == sa) {
        cp = getenv("SMP_UTILS_SAS_ADDR");
        if (cp) {
           sa_ll = smp_get_llnum(cp);
           if (-1LL == sa_ll) {
                pr2serr("bad value in environment variable "
                        "SMP_UTILS_SAS_ADDR\n    use 0\n");
                sa_ll = 0;
            }
            sa = (uint64_t)sa_ll;
        }
    }
    if (sa > 0) {
        if (! smp_is_naa5(sa)) {
            pr2serr("SAS (target) address not in naa-5 format (may need "
                    "leading '0x')\n");
            if ('\0' == i_params[0]) {
                pr2serr("    use '--interface=' to override\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
        }
    }
    if (multiple && mndesc_given) {
        pr2serr("--multiple and --num clash, give one or the other\n");
        return SMP_LIB_SYNTAX_ERROR;
    }

    res = smp_initiator_open(device_name, subvalue, i_params, sa,
                             &tobj, verbose);
    if (res < 0)
        return SMP_LIB_FILE_ERROR;
    if (permf) {
        if ((1 == strlen(permf)) && (0 == strcmp("-", permf)))
            ;
        else {
            foutp = fopen(permf, (do_append ? "a" : "w"));
            if (NULL == foutp) {
                pr2serr("unable to open %s, error: %s\n", permf,
                        safe_strerror(errno));
                ret = SMP_LIB_FILE_ERROR;
                goto err_out;
            }
        }
    }
    max_sszg = 256;
    desc_per_resp = 63;

    for (j = sszg, first = 1; j < max_sszg; j +=  desc_per_resp) {
        memset(smp_req, 0, sizeof smp_req);
        smp_req[0] = SMP_FRAME_TYPE_REQ;
        smp_req[1] = SMP_FN_REPORT_ZONE_PERMISSION_TBL;
        len = (sizeof(smp_resp) - 8) / 4;
        smp_req[2] = (len < 0x100) ? len : 0xff; /* Allocated Response Len */
        smp_req[3] = 0x1;
        smp_req[4] = report_type & 0x3;
        smp_req[6] = j & 0xff;
        numzg = max_sszg - j;
        if (desc_per_resp < numzg)
            numzg = desc_per_resp;
        if (mndesc < numzg)
            numzg = mndesc;
        smp_req[7] = numzg & 0xff;
        if (verbose) {
            pr2serr("    Report zone permission table request: ");
            for (k = 0; k < (int)sizeof(smp_req); ++k)
                pr2serr("%02x ", smp_req[k]);
            pr2serr("\n");
        }
        memset(&smp_rr, 0, sizeof(smp_rr));
        smp_rr.request_len = sizeof(smp_req);
        smp_rr.request = smp_req;
        smp_rr.max_response_len = sizeof(smp_resp);
        smp_rr.response = smp_resp;
        res = smp_send_req(&tobj, &smp_rr, verbose);

        if (res) {
            pr2serr("smp_send_req failed, res=%d\n", res);
            if (0 == verbose)
                pr2serr("    try adding '-v' option for more debug\n");
            ret = -1;
            goto err_out;
        }
        if (smp_rr.transport_err) {
            pr2serr("smp_send_req transport_error=%d\n", smp_rr.transport_err);
            ret = -1;
            goto err_out;
        }
        act_resplen = smp_rr.act_response_len;
        if ((act_resplen >= 0) && (act_resplen < 4)) {
            pr2serr("response too short, len=%d\n", act_resplen);
            ret = SMP_LIB_CAT_MALFORMED;
            goto err_out;
        }
        len = smp_resp[3];
        if ((0 == len) && (0 == smp_resp[2])) {
            len = smp_get_func_def_resp_len(smp_resp[1]);
            if (len < 0) {
                len = 0;
                if (verbose > 0)
                    pr2serr("unable to determine response length\n");
            }
        }
        len = 4 + (len * 4);    /* length in bytes, excluding 4 byte CRC */
        if ((act_resplen >= 0) && (len > act_resplen)) {
            if (verbose)
                pr2serr("actual response length [%d] less than deduced "
                        "length [%d]\n", act_resplen, len);
            len = act_resplen;
        }
        if (do_hex || do_raw) {
            if (do_hex)
                dStrHex((const char *)smp_resp, len, 1);
            else
                dStrRaw((const char *)smp_resp, len);
            if (SMP_FRAME_TYPE_RESP != smp_resp[0])
                ret = SMP_LIB_CAT_MALFORMED;
            if (smp_resp[1] != smp_req[1])
                ret = SMP_LIB_CAT_MALFORMED;
            if (smp_resp[2]) {
                ret = smp_resp[2];
                if (verbose)
                    pr2serr("Report zone permission table result: %s\n",
                            smp_get_func_res_str(ret, sizeof(b), b));
            }
            goto err_out;
        }
        if (SMP_FRAME_TYPE_RESP != smp_resp[0]) {
            pr2serr("expected SMP frame response type, got=0x%x\n",
                    smp_resp[0]);
            ret = SMP_LIB_CAT_MALFORMED;
            goto err_out;
        }
        if (smp_resp[1] != smp_req[1]) {
            pr2serr("Expected function code=0x%x, got=0x%x\n", smp_req[1],
                    smp_resp[1]);
            ret = SMP_LIB_CAT_MALFORMED;
            goto err_out;
        }
        if (smp_resp[2]) {
            cp = smp_get_func_res_str(smp_resp[2], sizeof(b), b);
            pr2serr("Report zone permission table result: %s\n", cp);
            ret = smp_resp[2];
            goto err_out;
        }
        numzg = (0xc0 & smp_resp[7]) >> 6;
        desc_len = smp_resp[13] * 4;
        num_desc = smp_resp[15];
        rtype = 0x3 & smp_resp[6];
        if (first) {
            first = 0;
            if (0 == numzg) {
                max_sszg = 128;
                desc_per_resp = 63;
            } else {
                max_sszg = 256;
                desc_per_resp = 31;
            }
            fprintf(foutp, "# Report zone permission table response:\n");
            res = sg_get_unaligned_be16(smp_resp + 4);
            if (verbose || res)
                fprintf(foutp, "#  Expander change count: %d\n", res);
            fprintf(foutp, "#  zone locked: %d\n", !! (0x80 & smp_resp[6]));
            fprintf(foutp, "#  report type: %d [%s]\n", rtype,
                    decode_rtype[rtype]);
            fprintf(foutp, "#  number of zone groups: %d (%s)\n", numzg,
                    decode_numzg[numzg]);
            if (verbose) {
                fprintf(foutp, "#  zone permission descriptor length: %d "
                        "dwords\n", smp_resp[13]);
                fprintf(foutp, "#  starting source zone group%s: %d\n",
                        (multiple ? " (of first request)" : ""),
                        smp_resp[14]);
                fprintf(foutp, "#  number of zone permission descriptors%s: "
                        "%d\n", (multiple ? " (of first request)" : ""),
                        num_desc);
            } else if (! multiple)
                fprintf(foutp, "#  number of zone permission descriptors: "
                        "%d\n", num_desc);
            if (sszg > 0)
                fprintf(foutp, "--start=%d\n", sszg);
            if (bits_col) {
                fprintf(foutp, "\n\nOutput unsuitable for "
                        "smp_conf_zone_perm_tbl utility\n\n    ");
                for (k = 0; k < bits_col; ++k)
                    fprintf(foutp, "%d", k % 10);
                fprintf(foutp, "\n\n");
            }
            if (0 == numzg_blen[numzg]) {
                pr2serr("unexpected number of zone groups: %d\n", numzg);
                goto err_out;
            }
        }
        descp = smp_resp + 16;
        for (k = 0; k < num_desc; ++k, descp += desc_len) {
            if (0 == bits_col) {
                for (m = 0; m < desc_len; ++m) {
                    if (nocomma)
                        fprintf(foutp, "%02x", descp[m]);
                    else {
                        if (0 == m)
                            fprintf(foutp, "%x", descp[m]);
                        else
                            fprintf(foutp, ",%x", descp[m]);
                    }
                }
            } else {    /* --bit=<bits_col> given */
                int by, bi;

                if ((k + j) >= bits_col)
                    break;
                fprintf(foutp, "%-4d", j + k);
                for (m = 0; m < bits_col; ++m) {
                    by = (m / 8) + 1;
                    bi = m % 8;
                    fprintf(foutp, "%d", (descp[desc_len - by] >> bi) & 0x1);
                }
            }
            fprintf(foutp, "\n");
        }
        if ((0 == multiple) || (mndesc < desc_per_resp))
            break;
    }

err_out:
    if (foutp && (stdout != foutp)) {
        fclose(foutp);
        foutp = NULL;
    }
    res = smp_initiator_close(&tobj);
    if (res < 0) {
        pr2serr("close error: %s\n", safe_strerror(errno));
        if (0 == ret)
            return SMP_LIB_FILE_ERROR;
    }
    if (ret < 0)
        ret = SMP_LIB_CAT_OTHER;
    if (verbose && ret)
        pr2serr("Exit status %d indicates error detected\n", ret);
    return ret;
}
예제 #7
0
int
main(int argc, char * argv[])
{
    bool do_long = false;
    bool o_readonly = false;
    bool do_raw = false;
    bool verbose_given = false;
    bool version_given = false;
    int res, c, len, k;
    int sg_fd = -1;
    int do_help = 0;
    int do_hex = 0;
    int rb_id = 0;
    int rb_len = 4;
    int rb_mode = 0;
    int rb_mode_sp = 0;
    int resid = 0;
    int verbose = 0;
    int ret = 0;
    int64_t ll;
    uint64_t rb_offset = 0;
    const char * device_name = NULL;
    uint8_t * resp;
    const struct mode_s * mp;

    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "hHi:l:Lm:o:rRS:vV", long_options,
                        &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'h':
        case '?':
            ++do_help;
            break;
        case 'H':
            ++do_hex;
            break;
        case 'i':
            rb_id = sg_get_num(optarg);
            if ((rb_id < 0) || (rb_id > 255)) {
                pr2serr("argument to '--id' should be in the range 0 to "
                        "255\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            break;
        case 'l':
            rb_len = sg_get_num(optarg);
            if (rb_len < 0) {
                pr2serr("bad argument to '--length'\n");
                return SG_LIB_SYNTAX_ERROR;
             }
             if (rb_len > 0xffffff) {
                pr2serr("argument to '--length' must be <= 0xffffff\n");
                return SG_LIB_SYNTAX_ERROR;
             }
             break;
        case 'L':
            do_long = true;
            break;
        case 'm':
            if (isdigit(*optarg)) {
                rb_mode = sg_get_num(optarg);
                if ((rb_mode < 0) || (rb_mode > 31)) {
                    pr2serr("argument to '--mode' should be in the range 0 "
                            "to 31\n");
                    return SG_LIB_SYNTAX_ERROR;
                }
            } else {
                len = strlen(optarg);
                for (mp = modes; mp->mode_string; ++mp) {
                    if (0 == strncmp(mp->mode_string, optarg, len)) {
                        rb_mode = mp->mode;
                        break;
                    }
                }
                if (NULL == mp->mode_string) {
                    print_modes();
                    return SG_LIB_SYNTAX_ERROR;
                }
            }
            break;
        case 'o':
           ll = sg_get_llnum(optarg);
           if (ll < 0) {
                pr2serr("bad argument to '--offset'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            rb_offset = ll;
            break;
        case 'r':
            do_raw = true;
            break;
        case 'R':
            o_readonly = true;
            break;
        case 'S':
           rb_mode_sp = sg_get_num(optarg);
           if ((rb_mode_sp < 0) || (rb_mode_sp > 7)) {
                pr2serr("expected argument to '--specific' to be 0 to 7\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            break;
        case 'v':
            verbose_given = true;
            ++verbose;
            break;
        case 'V':
            version_given = true;
            break;
        default:
            pr2serr("unrecognised option code 0x%x ??\n", c);
            usage();
            return SG_LIB_SYNTAX_ERROR;
        }
    }
    if (do_help) {
        if (do_help > 1) {
            usage();
            pr2serr("\n");
            print_modes();
        } else
            usage();
        return 0;
    }
    if (optind < argc) {
        if (NULL == device_name) {
            device_name = argv[optind];
            ++optind;
        }
        if (optind < argc) {
            for (; optind < argc; ++optind)
                pr2serr("Unexpected extra argument: %s\n", argv[optind]);
            usage();
            return SG_LIB_SYNTAX_ERROR;
        }
    }

#ifdef DEBUG
    pr2serr("In DEBUG mode, ");
    if (verbose_given && version_given) {
        pr2serr("but override: '-vV' given, zero verbose and continue\n");
        verbose_given = false;
        version_given = false;
        verbose = 0;
    } else if (! verbose_given) {
        pr2serr("set '-vv'\n");
        verbose = 2;
    } else
        pr2serr("keep verbose=%d\n", verbose);
#else
    if (verbose_given && version_given)
        pr2serr("Not in DEBUG mode, so '-vV' has no special action\n");
#endif
    if (version_given) {
        pr2serr("version: %s\n", version_str);
        return 0;
    }

    if (NULL == device_name) {
        pr2serr("Missing device name!\n\n");
        usage();
        return SG_LIB_SYNTAX_ERROR;
    }

    len = rb_len ? rb_len : 8;
    resp = (uint8_t *)malloc(len);
    if (NULL == resp) {
        pr2serr("unable to allocate %d bytes on the heap\n", len);
        return SG_LIB_CAT_OTHER;
    }
    memset(resp, 0, len);

    if (do_raw) {
        if (sg_set_binary_mode(STDOUT_FILENO) < 0) {
            perror("sg_set_binary_mode");
            ret = SG_LIB_FILE_ERROR;
            goto fini;
        }
    }

#ifdef SG_LIB_WIN32
#ifdef SG_LIB_WIN32_DIRECT
    if (verbose > 4)
        pr2serr("Initial win32 SPT interface state: %s\n",
                scsi_pt_win32_spt_state() ? "direct" : "indirect");
    scsi_pt_win32_direct(SG_LIB_WIN32_DIRECT /* SPT pt interface */);
#endif
#endif

    sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose);
    if (sg_fd < 0) {
        if (verbose)
            pr2serr("open error: %s: %s\n", device_name,
                    safe_strerror(-sg_fd));
        ret = sg_convert_errno(-sg_fd);
        goto fini;
    }

    if (do_long)
        res = sg_ll_read_buffer_16(sg_fd, rb_mode, rb_mode_sp, rb_id,
                                   rb_offset, resp, rb_len, &resid, true,
                                   verbose);
    else if (rb_offset > 0xffffff) {
        pr2serr("--offset value is too large for READ BUFFER(10), try "
                "--16\n");
        ret = SG_LIB_SYNTAX_ERROR;
        goto fini;
    } else
        res = sg_ll_read_buffer_10(sg_fd, rb_mode, rb_mode_sp, rb_id,
                                   (uint32_t)rb_offset, resp, rb_len, &resid,
                                   true, verbose);
    if (0 != res) {
        char b[80];

        ret = res;
        if (res > 0) {
            sg_get_category_sense_str(res, sizeof(b), b, verbose);
            pr2serr("Read buffer(%d) failed: %s\n", (do_long ? 16 : 10), b);
        }
        goto fini;
    }
    if (resid > 0)
        rb_len -= resid;        /* got back less than requested */
    if (rb_len > 0) {
        if (do_raw)
            dStrRaw(resp, rb_len);
        else if (do_hex || (rb_len < 4))
            hex2stdout((const uint8_t *)resp, rb_len, ((do_hex > 1) ? 0 : 1));
        else {
            switch (rb_mode) {
            case MODE_DESCRIPTOR:
                k = sg_get_unaligned_be24(resp + 1);
                printf("OFFSET BOUNDARY: %d, Buffer offset alignment: "
                       "%d-byte\n", resp[0], (1 << resp[0]));
                printf("BUFFER CAPACITY: %d (0x%x)\n", k, k);
                break;
            case MODE_ECHO_BDESC:
                k = sg_get_unaligned_be16(resp + 2) & 0x1fff;
                printf("EBOS:%d\n", resp[0] & 1 ? 1 : 0);
                printf("Echo buffer capacity: %d (0x%x)\n", k, k);
                break;
            default:
                hex2stdout((const uint8_t *)resp, rb_len,
                           (verbose > 1 ? 0 : 1));
                break;
            }
        }
    }

fini:
    if (resp)
        free(resp);
    if (sg_fd >= 0) {
        res = sg_cmds_close_device(sg_fd);
        if (res < 0) {
            pr2serr("close error: %s\n", safe_strerror(-res));
            if (0 == ret)
                ret = sg_convert_errno(-res);
        }
    }
    if (0 == verbose) {
        if (! sg_if_can2stderr("sg_read_buffer failed: ", ret))
            pr2serr("Some error occurred, try again with '-v' "
                    "or '-vv' for more information\n");
    }
    return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
예제 #8
0
파일: sg_rtpg.c 프로젝트: WOWers/sg3_utils
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)
예제 #9
0
파일: sg_safte.c 프로젝트: junroh/sg3_utils
/* Buffer ID 0x05: Read Global Flags (optional) */
static int
do_safte_global_flags(int sg_fd, int do_hex, int do_raw, int verbose)
{
    int res;
    unsigned int rb_len;
    unsigned char *rb_buff;

    rb_len = 16;
    rb_buff = (unsigned char *)malloc(rb_len);

    if (verbose > 1)
        pr2serr("Use READ BUFFER,mode=vendor_specific,buff_id=5 to read "
                "global flags\n");
    res = sg_ll_read_buffer(sg_fd, RWB_MODE_VENDOR, 5, 0,
                            rb_buff, rb_len, 0, verbose);
    if (res ) {
        if (res == SG_LIB_CAT_ILLEGAL_REQ) {
                printf("Global Flags:\n\tNot implemented\n");
                return 0;
        }
        if (res != SG_LIB_CAT_RECOVERED) {
                free(rb_buff);
                return res;
        }
    }

    if (do_raw > 1) {
        dStrRaw((const char *)rb_buff, buf_capacity);
        return 0;
    }
    if (do_hex > 1) {
        dStrHex((const char *)rb_buff, buf_capacity, 1);
        return 0;
    }
    printf("Global Flags:\n");
    printf("\tAudible Alarm Control: %s\n",
           rb_buff[0] & 0x1?"on":"off");
    printf("\tGlobal Failure Indicator: %s\n",
           rb_buff[0] & 0x2?"on":"off");
    printf("\tGlobal Warning Indicator: %s\n",
           rb_buff[0] & 0x4?"on":"off");
    printf("\tEnclosure Power: %s\n",
           rb_buff[0] & 0x8?"on":"off");
    printf("\tCooling Failure: %s\n",
           rb_buff[0] & 0x10?"yes":"no");
    printf("\tPower Failure: %s\n",
           rb_buff[0] & 0x20?"yes":"no");
    printf("\tDrive Failure: %s\n",
           rb_buff[0] & 0x40?"yes":"no");
    printf("\tDrive Warning: %s\n",
           rb_buff[0] & 0x80?"yes":"no");
    printf("\tArray Failure: %s\n",
           rb_buff[1] & 0x1?"yes":"no");
    printf("\tArray Warning: %s\n",
           rb_buff[0] & 0x2?"yes":"no");
    printf("\tEnclosure Lock: %s\n",
           rb_buff[0] & 0x4?"on":"off");
    printf("\tEnclosure Identify: %s\n",
           rb_buff[0] & 0x8?"on":"off");

    free(rb_buff);
    return 0;
}
예제 #10
0
int
main(int argc, char * argv[])
{
    int sg_fd, k, j, res, c, rlen, num_descs;
    int do_brief = 0;
    int do_hex = 0;
    int64_t ll;
    uint64_t lba = 0;
    uint64_t d_lba = 0;
    uint32_t d_blocks = 0;
    int maxlen = DEF_GLBAS_BUFF_LEN;
    int do_raw = 0;
    int o_readonly = 0;
    int verbose = 0;
    const char * device_name = NULL;
    const unsigned char * ucp;
    int ret = 0;

    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "bhHl:m:rRvV", long_options,
                        &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'b':
            ++do_brief;
            break;
        case 'h':
        case '?':
            usage();
            return 0;
        case 'H':
            ++do_hex;
            break;
        case 'l':
            ll = sg_get_llnum(optarg);
            if (-1 == ll) {
                fprintf(stderr, "bad argument to '--lba'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            lba = (uint64_t)ll;
            break;
        case 'm':
            maxlen = sg_get_num(optarg);
            if ((maxlen < 0) || (maxlen > MAX_GLBAS_BUFF_LEN)) {
                fprintf(stderr, "argument to '--maxlen' should be %d or "
                        "less\n", MAX_GLBAS_BUFF_LEN);
                return SG_LIB_SYNTAX_ERROR;
            }
            break;
        case 'r':
            ++do_raw;
            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 (maxlen > DEF_GLBAS_BUFF_LEN) {
        glbasBuffp = (unsigned char *)calloc(maxlen, 1);
        if (NULL == glbasBuffp) {
            fprintf(stderr, "unable to allocate %d bytes on heap\n", maxlen);
            return SG_LIB_SYNTAX_ERROR;
        }
    }
    if (do_raw) {
        if (sg_set_binary_mode(STDOUT_FILENO) < 0) {
            perror("sg_set_binary_mode");
            ret = SG_LIB_FILE_ERROR;
            goto free_buff;
        }
    }

    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));
        ret = SG_LIB_FILE_ERROR;
        goto free_buff;
    }

    res = sg_ll_get_lba_status(sg_fd, lba, glbasBuffp, maxlen, 1,
                               verbose);
    ret = res;
    if (0 == res) {
        /* in sbc3r25 offset for calculating the 'parameter data length'
         * (rlen variable below) was reduced from 8 to 4. */
        if (maxlen >= 4)
            rlen = (glbasBuffp[0] << 24) + (glbasBuffp[1] << 16) +
                   (glbasBuffp[2] << 8) + glbasBuffp[3] + 4;
        else
            rlen = maxlen;
        k = (rlen > maxlen) ? maxlen : rlen;
        if (do_raw) {
            dStrRaw((const char *)glbasBuffp, k);
            goto the_end;
        }
        if (do_hex) {
            dStrHex((const char *)glbasBuffp, k, 1);
            goto the_end;
        }
        if (maxlen < 4) {
            if (verbose)
                fprintf(stderr, "Exiting because allocation length (maxlen) "
                        " less than 4\n");
            goto the_end;
        }
        if ((verbose > 1) || (verbose && (rlen > maxlen))) {
            fprintf(stderr, "response length %d bytes\n", rlen);
            if (rlen > maxlen)
                fprintf(stderr, "  ... which is greater than maxlen "
                        "(allocation length %d), truncation\n", maxlen);
        }
        if (rlen > maxlen)
            rlen = maxlen;

        if (do_brief > 1) {
            if (rlen < 24) {
                fprintf(stderr, "Need maxlen and response length to "
                        " be at least 24, have %d bytes\n", rlen);
                ret = SG_LIB_CAT_OTHER;
                goto the_end;
            }
            res = decode_lba_status_desc(glbasBuffp + 8, &d_lba, &d_blocks);
            if ((res < 0) || (res > 15)) {
                fprintf(stderr, "first LBA status descriptor returned %d "
                        "??\n", res);
                ret = SG_LIB_CAT_OTHER;
                goto the_end;
            }
            if ((lba < d_lba) || (lba >= (d_lba + d_blocks))) {
                fprintf(stderr, "given LBA not in range of first "
                        "descriptor:\n" "  descriptor LBA: 0x");
                for (j = 0; j < 8; ++j)
                    fprintf(stderr, "%02x", glbasBuffp[8 + j]);
                fprintf(stderr, "  blocks: 0x%x  p_status: %d\n",
                        (unsigned int)d_blocks, res);
                ret = SG_LIB_CAT_OTHER;
                goto the_end;
            }
            printf("%d\n", res);
            goto the_end;
        }

        if (rlen < 24) {
            printf("No complete LBA status descriptors available\n");
            goto the_end;
        }
        num_descs = (rlen - 8) / 16;
        if (verbose)
            fprintf(stderr, "%d complete LBA status descriptors found\n",
                    num_descs);
        for (ucp = glbasBuffp + 8, k = 0; k < num_descs; ucp += 16, ++k) {
            res = decode_lba_status_desc(ucp, &d_lba, &d_blocks);
            if ((res < 0) || (res > 15))
                fprintf(stderr, "descriptor %d: bad LBA status descriptor "
                        "returned %d\n", k + 1, res);
            if (do_brief) {
                printf("0x");
                for (j = 0; j < 8; ++j)
                    printf("%02x", ucp[j]);
                printf("  0x%x  %d\n", (unsigned int)d_blocks, res);
            } else {
                printf("descriptor LBA: 0x");
                for (j = 0; j < 8; ++j)
                    printf("%02x", ucp[j]);
                printf("  blocks: %u", (unsigned int)d_blocks);
                switch (res) {
                case 0:
                    printf("  mapped\n");
                    break;
                case 1:
                    printf("  deallocated\n");
                    break;
                case 2:
                    printf("  anchored\n");
                    break;
                default:
                    printf("  Provisioning status: %d\n", res);
                    break;
                }
            }
        }
        if ((num_descs * 16) + 8 < rlen)
            fprintf(stderr, "incomplete trailing LBA status descriptors "
                    "found\n");
    } else if (SG_LIB_CAT_INVALID_OP == res)
        fprintf(stderr, "Get LBA Status command not supported\n");
    else if (SG_LIB_CAT_ILLEGAL_REQ == res)
        fprintf(stderr, "Get LBA Status command: bad field in cdb\n");
    else {
        char b[80];

        sg_get_category_sense_str(res, sizeof(b), b, verbose);
        fprintf(stderr, "Get LBA Status command: %s\n", b);
    }

the_end:
    res = sg_cmds_close_device(sg_fd);
    if (res < 0) {
        fprintf(stderr, "close error: %s\n", safe_strerror(-res));
        if (0 == ret)
            ret = SG_LIB_FILE_ERROR;
    }
free_buff:
    if (glbasBuffp && (glbasBuffp != glbasBuff))
        free(glbasBuffp);
    return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
예제 #11
0
int
main(int argc, char * argv[])
{
    int res, c, len, k;
    int sg_fd = -1;
    int do_help = 0;
    int do_hex = 0;
    int do_long = 0;
    int o_readonly = 0;
    int rb_id = 0;
    int rb_len = 4;
    int rb_mode = 0;
    int rb_mode_sp = 0;
    int64_t ll;
    uint64_t rb_offset = 0;
    int do_raw = 0;
    int resid = 0;
    int verbose = 0;
    int ret = 0;
    const char * device_name = NULL;
    unsigned char * resp;
    const struct mode_s * mp;

    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "hHi:l:Lm:o:rRS:vV", long_options,
                        &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'h':
        case '?':
            ++do_help;
            break;
        case 'H':
            ++do_hex;
            break;
        case 'i':
            rb_id = sg_get_num(optarg);
            if ((rb_id < 0) || (rb_id > 255)) {
                fprintf(stderr, "argument to '--id' should be in the range "
                        "0 to 255\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            break;
        case 'l':
            rb_len = sg_get_num(optarg);
            if (rb_len < 0) {
                fprintf(stderr, "bad argument to '--length'\n");
                return SG_LIB_SYNTAX_ERROR;
             }
             if (rb_len > 0xffffff) {
                fprintf(stderr, "argument to '--length' must be <= "
                        "0xffffff\n");
                return SG_LIB_SYNTAX_ERROR;
             }
             break;
        case 'L':
            ++do_long;
            break;
        case 'm':
            if (isdigit(*optarg)) {
                rb_mode = sg_get_num(optarg);
                if ((rb_mode < 0) || (rb_mode > 31)) {
                    fprintf(stderr, "argument to '--mode' should be in the "
                            "range 0 to 31\n");
                    return SG_LIB_SYNTAX_ERROR;
                }
            } else {
                len = strlen(optarg);
                for (mp = modes; mp->mode_string; ++mp) {
                    if (0 == strncmp(mp->mode_string, optarg, len)) {
                        rb_mode = mp->mode;
                        break;
                    }
                }
                if (NULL == mp) {
                    print_modes();
                    return SG_LIB_SYNTAX_ERROR;
                }
            }
            break;
        case 'o':
           ll = sg_get_llnum(optarg);
           if (ll < 0) {
                fprintf(stderr, "bad argument to '--offset'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            rb_offset = ll;
            break;
        case 'r':
            ++do_raw;
            break;
        case 'R':
            ++o_readonly;
            break;
        case 'S':
           rb_mode_sp = sg_get_num(optarg);
           if ((rb_mode_sp < 0) || (rb_mode_sp > 7)) {
                fprintf(stderr, "expected argument to '--specific' to be 0 "
                        "to 7\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            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 (do_help) {
        if (do_help > 1) {
            usage();
            fprintf(stderr, "\n");
            print_modes();
        } else
            usage();
        return 0;
    }
    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 (rb_len > 0) {
        resp = (unsigned char *)malloc(rb_len);
        if (NULL == resp) {
            fprintf(stderr, "unable to allocate %d bytes on the heap\n",
                    rb_len);
            return SG_LIB_CAT_OTHER;
        }
        memset(resp, 0, rb_len);
    } else
        resp = NULL;

    if (do_raw) {
        if (sg_set_binary_mode(STDOUT_FILENO) < 0) {
            perror("sg_set_binary_mode");
            ret = SG_LIB_FILE_ERROR;
            goto fini;
        }
    }

#ifdef SG_LIB_WIN32
#ifdef SG_LIB_WIN32_DIRECT
    if (verbose > 4)
        fprintf(stderr, "Initial win32 SPT interface state: %s\n",
                scsi_pt_win32_spt_state() ? "direct" : "indirect");
    scsi_pt_win32_direct(SG_LIB_WIN32_DIRECT /* SPT pt interface */);
#endif
#endif

    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));
        ret = SG_LIB_FILE_ERROR;
        goto fini;
    }

    if (do_long)
        res = ll_read_buffer_16(sg_fd, rb_mode, rb_mode_sp, rb_id, rb_offset,
                                resp, rb_len, &resid, 1, verbose);
    else if (rb_offset > 0xffffff) {
        fprintf(stderr, "--offset value is too large for READ BUFFER(10), "
                "try --16\n");
        ret = SG_LIB_SYNTAX_ERROR;
        goto fini;
    } else
        res = ll_read_buffer_10(sg_fd, rb_mode, rb_mode_sp, rb_id,
                                (uint32_t)rb_offset, resp, rb_len, &resid, 1,
                                verbose);
    if (0 != res) {
        char b[80];

        ret = res;
        if (res > 0) {
            sg_get_category_sense_str(res, sizeof(b), b, verbose);
            fprintf(stderr, "Read buffer(%d) failed: %s\n",
                    (do_long ? 16 : 10), b);
        }
        goto fini;
    }
    if (resid > 0)
        rb_len -= resid;        /* got back less than requested */
    if (rb_len > 0) {
        if (do_raw)
            dStrRaw((const char *)resp, rb_len);
        else if (do_hex || (rb_len < 4))
            dStrHex((const char *)resp, rb_len, ((do_hex > 1) ? 0 : 1));
        else {
            switch (rb_mode) {
            case MODE_DESCRIPTOR:
                k = (resp[1] << 16) | (resp[2] << 8) | resp[3];
                printf("OFFSET BOUNDARY: %d, Buffer offset alignment: "
                       "%d-byte\n", resp[0], (1 << resp[0]));
                printf("BUFFER CAPACITY: %d (0x%x)\n", k, k);
                break;
            case MODE_ECHO_BDESC:
                k = ((resp[2] & 0x1F) << 8) | resp[3];

                printf("EBOS:%d\n", resp[0] & 1 ? 1 : 0);
                printf("Echo buffer capacity: %d (0x%x)\n", k, k);
                break;
            default:
                dStrHex((const char *)resp, rb_len, (verbose > 1 ? 0 : 1));
                break;
            }
        }
    }

fini:
    if (resp)
        free(resp);
    if (sg_fd >= 0) {
        res = sg_cmds_close_device(sg_fd);
        if (res < 0) {
            fprintf(stderr, "close error: %s\n", safe_strerror(-res));
            if (0 == ret)
                return SG_LIB_FILE_ERROR;
        }
    }
    return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
예제 #12
0
int
main(int argc, char * argv[])
{
    int sg_fd, res, c, len, resid, rlen, in_len;
    unsigned int ra_len;
    int ret = 0;
    const char * device_name = NULL;
    const char * fname = NULL;
    unsigned char * rabp = NULL;
    struct opts_t opts;
    struct opts_t * op;
    char b[80];

    op = &opts;
    memset(op, 0, sizeof(opts));
    op->filter = -1;
    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "ceE:f:F:hHi:l:m:p:qrRs:vV",
                        long_options, &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'c':
            ++op->cache;
            break;
        case 'e':
            ++op->enumerate;
            break;
        case 'E':
           op->ea = sg_get_num(optarg);
           if ((op->ea < 0) || (op->ea > 65535)) {
                pr2serr("bad argument to '--ea=EA', expect 0 to 65535\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            break;
        case 'f':
           op->filter = sg_get_num(optarg);
           if ((op->filter < -3) || (op->filter > 65535)) {
                pr2serr("bad argument to '--filter=FL', expect -3 to "
                        "65535\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            break;
        case 'F':
           op->fai = sg_get_num(optarg);
           if ((op->fai < 0) || (op->fai > 65535)) {
                pr2serr("bad argument to '--first=FAI', expect 0 to 65535\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            break;
        case 'h':
        case '?':
            usage();
            return 0;
        case 'H':
            ++op->do_hex;
            break;
        case 'i':
            fname = optarg;
            break;
        case 'l':
           op->lvn = sg_get_num(optarg);
           if ((op->lvn < 0) || (op->lvn > 255)) {
                pr2serr("bad argument to '--lvn=LVN', expect 0 to 255\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            break;
        case 'm':
            op->maxlen = sg_get_num(optarg);
            if ((op->maxlen < 0) || (op->maxlen > MAX_RATTR_BUFF_LEN)) {
                pr2serr("argument to '--maxlen' should be %d or "
                        "less\n", MAX_RATTR_BUFF_LEN);
                return SG_LIB_SYNTAX_ERROR;
            }
            break;
        case 'p':
           op->pn = sg_get_num(optarg);
           if ((op->pn < 0) || (op->pn > 255)) {
                pr2serr("bad argument to '--pn=PN', expect 0 to 255\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            break;
        case 'q':
            ++op->quiet;
            break;
        case 'r':
            ++op->do_raw;
            break;
        case 'R':
            ++op->o_readonly;
            break;
        case 's':
           if (isdigit(*optarg)) {
               op->sa = sg_get_num(optarg);
               if ((op->sa < 0) || (op->sa > 63)) {
                    pr2serr("bad argument to '--sa=SA', expect 0 to 63\n");
                    return SG_LIB_SYNTAX_ERROR;
                }
            } else {
                res = find_sa_acron(optarg);
                if (res < 0) {
                    enum_sa_acrons();
                    return SG_LIB_SYNTAX_ERROR;
                }
                op->sa = res;
            }
            break;
        case 'v':
            ++op->verbose;
            break;
        case 'V':
            pr2serr("version: %s\n", version_str);
            return 0;
        default:
            pr2serr("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)
                pr2serr("Unexpected extra argument: %s\n", argv[optind]);
            usage();
            return SG_LIB_SYNTAX_ERROR;
        }
    }

    if (op->enumerate) {
        enum_attributes();
        printf("\n");
        enum_sa_acrons();
        return 0;
    }

    if (fname && device_name) {
        pr2serr("since '--in=FN' given, ignoring DEVICE\n");
        device_name = NULL;
    }

    if (0 == op->maxlen)
        op->maxlen = DEF_RATTR_BUFF_LEN;
    rabp = (unsigned char *)calloc(1, op->maxlen);
    if (NULL == rabp) {
        pr2serr("unable to calloc %d bytes\n", op->maxlen);
        return SG_LIB_CAT_OTHER;
    }

    if (NULL == device_name) {
        if (fname) {
            if (f2hex_arr(fname, op->do_raw, 0, rabp, &in_len, op->maxlen)) {
                ret = SG_LIB_FILE_ERROR;
                goto clean_up;
            }
            if (op->do_raw)
                op->do_raw = 0;    /* can interfere on decode */
            if (in_len < 4) {
                pr2serr("--in=%s only decoded %d bytes (needs 4 at least)\n",
                        fname, in_len);
                ret = SG_LIB_SYNTAX_ERROR;
                goto clean_up;
            }
            decode_all_sa_s(rabp, in_len, op);
            goto clean_up;
        }
        pr2serr("missing device name!\n");
        usage();
        ret = SG_LIB_SYNTAX_ERROR;
        goto clean_up;
    }

    if (op->do_raw) {
        if (sg_set_binary_mode(STDOUT_FILENO) < 0) {
            perror("sg_set_binary_mode");
            ret = SG_LIB_FILE_ERROR;
                goto clean_up;
        }
    }

    sg_fd = sg_cmds_open_device(device_name, op->o_readonly, op->verbose);
    if (sg_fd < 0) {
        pr2serr("open error: %s: %s\n", device_name,
                safe_strerror(-sg_fd));
        ret = SG_LIB_FILE_ERROR;
        goto clean_up;
    }

    res = sg_ll_read_attr(sg_fd, rabp, &resid, op);
    ret = res;
    if (0 == res) {
        rlen = op->maxlen - resid;
        if (rlen < 4) {
            pr2serr("Response length (%d) too short\n", rlen);
            ret = SG_LIB_CAT_MALFORMED;
            goto close_then_end;
        }
        if ((op->sa <= RA_HIGHEST_SA) && (op->sa != RA_SMC2_SA)) {
            ra_len = ((RA_LV_LIST_SA == op->sa) ||
                      (RA_PART_LIST_SA == op->sa)) ?
                        (unsigned int)sg_get_unaligned_be16(rabp + 0) :
                        sg_get_unaligned_be32(rabp + 0) + 2;
            ra_len += 2;
        } else
            ra_len = rlen;
        if ((int)ra_len > rlen) {
            if (op->verbose)
                pr2serr("ra_len available is %d, response length is %d\n",
                        ra_len, rlen);
            len = rlen;
        } else
            len = (int)ra_len;
        if (op->do_raw) {
            dStrRaw((const char *)rabp, len);
            goto close_then_end;
        }
        decode_all_sa_s(rabp, len, op);
    } else if (SG_LIB_CAT_INVALID_OP == res)
        pr2serr("Read attribute command not supported\n");
    else {
        sg_get_category_sense_str(res, sizeof(b), b, op->verbose);
        pr2serr("Read attribute command: %s\n", b);
    }

close_then_end:
    res = sg_cmds_close_device(sg_fd);
    if (res < 0) {
        pr2serr("close error: %s\n", safe_strerror(-res));
        if (0 == ret)
            ret = SG_LIB_FILE_ERROR;
    }
clean_up:
    if (rabp)
        free(rabp);
    return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
예제 #13
0
int
main(int argc, char * argv[])
{
    bool do_one_segment = false;
    bool o_readonly = false;
    bool do_raw = false;
    bool verbose_given = false;
    bool version_given = false;
    int k, res, c, rlen;
    int sg_fd = -1;
    int do_hex = 0;
    int maxlen = DEF_REFER_BUFF_LEN;
    int verbose = 0;
    int desc = 0;
    int ret = 0;
    int64_t ll;
    uint64_t lba = 0;
    const char * device_name = NULL;
    const uint8_t * bp;
    uint8_t * referralBuffp = referralBuff;
    uint8_t * free_referralBuffp = NULL;

    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "hHl:m:rRsvV", long_options,
                        &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'h':
        case '?':
            usage();
            return 0;
        case 'H':
            ++do_hex;
            break;
        case 'l':
            ll = sg_get_llnum(optarg);
            if (-1 == ll) {
                pr2serr("bad argument to '--lba'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            lba = (uint64_t)ll;
            break;
        case 'm':
            maxlen = sg_get_num(optarg);
            if ((maxlen < 0) || (maxlen > MAX_REFER_BUFF_LEN)) {
                pr2serr("argument to '--maxlen' should be %d or less\n",
                        MAX_REFER_BUFF_LEN);
                return SG_LIB_SYNTAX_ERROR;
            }
            break;
        case 's':
            do_one_segment = true;
            break;
        case 'r':
            do_raw = true;
            break;
        case 'R':
            o_readonly = true;
            break;
        case 'v':
            verbose_given = true;
            ++verbose;
            break;
        case 'V':
            version_given = true;
            break;
        default:
            pr2serr("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)
                pr2serr("Unexpected extra argument: %s\n", argv[optind]);
            usage();
            return SG_LIB_SYNTAX_ERROR;
        }
    }
#ifdef DEBUG
    pr2serr("In DEBUG mode, ");
    if (verbose_given && version_given) {
        pr2serr("but override: '-vV' given, zero verbose and continue\n");
        verbose_given = false;
        version_given = false;
        verbose = 0;
    } else if (! verbose_given) {
        pr2serr("set '-vv'\n");
        verbose = 2;
    } else
        pr2serr("keep verbose=%d\n", verbose);
#else
    if (verbose_given && version_given)
        pr2serr("Not in DEBUG mode, so '-vV' has no special action\n");
#endif
    if (version_given) {
        pr2serr("version: %s\n", version_str);
        return 0;
    }

    if (NULL == device_name) {
        pr2serr("No DEVICE argument given\n\n");
        usage();
        return SG_LIB_SYNTAX_ERROR;
    }
    if (maxlen > DEF_REFER_BUFF_LEN) {
        referralBuffp = (uint8_t *)sg_memalign(maxlen, 0,
                                               &free_referralBuffp,
                                               verbose > 3);
        if (NULL == referralBuffp) {
            pr2serr("unable to allocate %d bytes on heap\n", maxlen);
            return sg_convert_errno(ENOMEM);
        }
    }
    if (do_raw) {
        if (sg_set_binary_mode(STDOUT_FILENO) < 0) {
            perror("sg_set_binary_mode");
            ret = SG_LIB_FILE_ERROR;
            goto free_buff;
        }
    }

    sg_fd = sg_cmds_open_device(device_name, o_readonly, verbose);
    if (sg_fd < 0) {
        if (verbose)
            pr2serr("open error: %s: %s\n", device_name,
                    safe_strerror(-sg_fd));
        ret = sg_convert_errno(-sg_fd);
        goto free_buff;
    }

    res = sg_ll_report_referrals(sg_fd, lba, do_one_segment, referralBuffp,
                                 maxlen, true, verbose);
    ret = res;
    if (0 == res) {
        if (maxlen >= 4)
            /*
             * This is strictly speaking incorrect. However, the
             * spec reserved bytes 0 and 1, so some implementations
             * might want to use them to increase the number of
             * possible user segments.
             * And maybe someone takes a pity and updates the spec ...
             */
            rlen = sg_get_unaligned_be32(referralBuffp + 0) + 4;
        else
            rlen = maxlen;
        k = (rlen > maxlen) ? maxlen : rlen;
        if (do_raw) {
            dStrRaw(referralBuffp, k);
            goto the_end;
        }
        if (do_hex) {
            hex2stdout(referralBuffp, k, 1);
            goto the_end;
        }
        if (maxlen < 4) {
            if (verbose)
                pr2serr("Exiting because allocation length (maxlen)  less "
                        "than 4\n");
            goto the_end;
        }
        if ((verbose > 1) || (verbose && (rlen > maxlen))) {
            pr2serr("response length %d bytes\n", rlen);
            if (rlen > maxlen)
                pr2serr("  ... which is greater than maxlen (allocation "
                        "length %d), truncation\n", maxlen);
        }
        if (rlen > maxlen)
            rlen = maxlen;

        bp = referralBuffp + 4;
        k = 0;
        printf("Report referrals:\n");
        while (k < rlen - 4) {
            printf("  descriptor %d:\n", desc);
            res = decode_referral_desc(bp + k, rlen - 4 - k);
            if (res < 0) {
                pr2serr("bad user data segment referral descriptor\n");
                break;
            }
            k += res;
            desc++;
        }
    } else {
        char b[80];

        sg_get_category_sense_str(res, sizeof(b), b, verbose);
        pr2serr("Report Referrals command failed: %s\n", b);
    }

the_end:
    res = sg_cmds_close_device(sg_fd);
    if (res < 0) {
        pr2serr("close error: %s\n", safe_strerror(-res));
        if (0 == ret)
            ret = sg_convert_errno(-res);
    }
free_buff:
    if (free_referralBuffp)
        free(free_referralBuffp);
    if (0 == verbose) {
        if (! sg_if_can2stderr("sg_referrals failed: ", ret))
            pr2serr("Some error occurred, try again with '-v' "
                    "or '-vv' for more information\n");
    }
    return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
예제 #14
0
int
main(int argc, char * argv[])
{
    int res, c, k, len, act_resplen;
    const char * fpass = NULL;
    int do_hex = 0;
    int do_phex = 0;
    int do_raw = 0;
    int rtype = 0;
    int verbose = 0;
    int64_t sa_ll;
    uint64_t sa = 0;
    char i_params[256];
    char device_name[512];
    char b[256];
    unsigned char smp_req[] = {SMP_FRAME_TYPE_REQ,
                               SMP_FN_REPORT_ZONE_MANAGER_PASS,
                               9, 1, 0, 0, 0, 0, 0, 0, 0, 0};
    unsigned char smp_resp[SMP_FN_REPORT_ZONE_MAN_PASS_RESP_LEN];
    struct smp_req_resp smp_rr;
    struct smp_target_obj tobj;
    int subvalue = 0;
    char * cp;
    FILE * foutp = stdout;
    int ret = 0;

    memset(device_name, 0, sizeof device_name);
    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "F:hHI:prR:s:vV", long_options,
                        &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'F':
            fpass = optarg;
            break;
        case 'h':
        case '?':
            usage();
            return 0;
        case 'H':
            ++do_hex;
            break;
        case 'I':
            strncpy(i_params, optarg, sizeof(i_params));
            i_params[sizeof(i_params) - 1] = '\0';
            break;
        case 'p':
            ++do_phex;
            break;
        case 'r':
            ++do_raw;
            break;
        case 'R':
           rtype = smp_get_num(optarg);
           if ((rtype < 0) || (rtype > 3)) {
                pr2serr("bad argument to '--report=', expect 0 to 3\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 's':
           sa_ll = smp_get_llnum(optarg);
           if (-1LL == sa_ll) {
                pr2serr("bad argument to '--sa'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            sa = (uint64_t)sa_ll;
            break;
        case 'v':
            ++verbose;
            break;
        case 'V':
            pr2serr("version: %s\n", version_str);
            return 0;
        default:
            pr2serr("unrecognised switch code 0x%x ??\n", c);
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (optind < argc) {
        if ('\0' == device_name[0]) {
            strncpy(device_name, argv[optind], sizeof(device_name) - 1);
            device_name[sizeof(device_name) - 1] = '\0';
            ++optind;
        }
        if (optind < argc) {
            for (; optind < argc; ++optind)
                pr2serr("Unexpected extra argument: %s\n", argv[optind]);
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (0 == device_name[0]) {
        cp = getenv("SMP_UTILS_DEVICE");
        if (cp)
            strncpy(device_name, cp, sizeof(device_name) - 1);
        else {
            pr2serr("missing device name on command line\n    [Could use "
                    "environment variable SMP_UTILS_DEVICE instead]\n");
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if ((cp = strchr(device_name, SMP_SUBVALUE_SEPARATOR))) {
        *cp = '\0';
        if (1 != sscanf(cp + 1, "%d", &subvalue)) {
            pr2serr("expected number after separator in SMP_DEVICE name\n");
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (0 == sa) {
        cp = getenv("SMP_UTILS_SAS_ADDR");
        if (cp) {
           sa_ll = smp_get_llnum(cp);
           if (-1LL == sa_ll) {
                pr2serr("bad value in environment variable "
                        "SMP_UTILS_SAS_ADDR\n    use 0\n");
                sa_ll = 0;
            }
            sa = (uint64_t)sa_ll;
        }
    }
    if (sa > 0) {
        if (! smp_is_naa5(sa)) {
            pr2serr("SAS (target) address not in naa-5 format (may need "
                    "leading '0x')\n");
            if ('\0' == i_params[0]) {
                pr2serr("    use '--interface=' to override\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
        }
    }

    res = smp_initiator_open(device_name, subvalue, i_params, sa,
                             &tobj, verbose);
    if (res < 0)
        return SMP_LIB_FILE_ERROR;

    len = (sizeof(smp_resp) - 8) / 4;
    smp_req[2] = (len < 0x100) ? len : 0xff; /* Allocated Response Len */
    smp_req[4] = rtype & 0x3;
    if (verbose) {
        pr2serr("    Report zone manager password request: ");
        for (k = 0; k < (int)sizeof(smp_req); ++k)
            pr2serr("%02x ", smp_req[k]);
        pr2serr("\n");
    }
    memset(&smp_rr, 0, sizeof(smp_rr));
    smp_rr.request_len = sizeof(smp_req);
    smp_rr.request = smp_req;
    smp_rr.max_response_len = sizeof(smp_resp);
    smp_rr.response = smp_resp;
    res = smp_send_req(&tobj, &smp_rr, verbose);

    if (res) {
        pr2serr("smp_send_req failed, res=%d\n", res);
        if (0 == verbose)
            pr2serr("    try adding '-v' option for more debug\n");
        ret = -1;
        goto err_out;
    }
    if (smp_rr.transport_err) {
        pr2serr("smp_send_req transport_error=%d\n", smp_rr.transport_err);
        ret = -1;
        goto err_out;
    }
    act_resplen = smp_rr.act_response_len;
    if ((act_resplen >= 0) && (act_resplen < 4)) {
        pr2serr("response too short, len=%d\n", act_resplen);
        ret = SMP_LIB_CAT_MALFORMED;
        goto err_out;
    }
    len = smp_resp[3];
    if ((0 == len) && (0 == smp_resp[2])) {
        len = smp_get_func_def_resp_len(smp_resp[1]);
        if (len < 0) {
            len = 0;
            if (verbose > 0)
                pr2serr("unable to determine response length\n");
        }
    }
    len = 4 + (len * 4);        /* length in bytes, excluding 4 byte CRC */
    if ((act_resplen >= 0) && (len > act_resplen)) {
        if (verbose)
            pr2serr("actual response length [%d] less than deduced length "
                    "[%d]\n", act_resplen, len);
        len = act_resplen;
    }
    if (do_hex || do_raw) {
        if (do_hex)
            dStrHex((const char *)smp_resp, len, 1);
        else
            dStrRaw((const char *)smp_resp, len);
        if (SMP_FRAME_TYPE_RESP != smp_resp[0])
            ret = SMP_LIB_CAT_MALFORMED;
        if (smp_resp[1] != smp_req[1])
            ret = SMP_LIB_CAT_MALFORMED;
        if (smp_resp[2]) {
            ret = smp_resp[2];
            if (verbose)
                pr2serr("Report zone manager password result: %s\n",
                        smp_get_func_res_str(ret, sizeof(b), b));
        }
        goto err_out;
    }
    if (SMP_FRAME_TYPE_RESP != smp_resp[0]) {
        pr2serr("expected SMP frame response type, got=0x%x\n", smp_resp[0]);
        ret = SMP_LIB_CAT_MALFORMED;
        goto err_out;
    }
    if (smp_resp[1] != smp_req[1]) {
        pr2serr("Expected function code=0x%x, got=0x%x\n", smp_req[1],
                smp_resp[1]);
        ret = SMP_LIB_CAT_MALFORMED;
        goto err_out;
    }
    if (smp_resp[2]) {
        cp = smp_get_func_res_str(smp_resp[2], sizeof(b), b);
        pr2serr("Report zone manager password result: %s\n", cp);
        ret = smp_resp[2];
        goto err_out;
    }
    if (fpass) {
        if ((1 == strlen(fpass)) && (0 == strcmp("-", fpass)))
            ;   /* accept "-" as synonym for stdout */
        else {
            foutp = fopen(fpass, "w");
            if (NULL == foutp) {
                pr2serr("unable to open %s, error: %s\n", fpass,
                        safe_strerror(errno));
                ret = SMP_LIB_FILE_ERROR;
                goto err_out;
            }
        }
    }

    if (fpass) {
        fprintf(foutp, "# Report zone manager password response:\n");
        res = sg_get_unaligned_be16(smp_resp + 4);
        if (verbose || res)
            fprintf(foutp, "#  Expander change count: %d\n", res);
        fprintf(foutp, "#  Report type: %d\n", smp_resp[6] & 0x3);
    }

    if (do_phex) {
        for (k = 0; k < 32; ++k) {
            if (0 == k)
                fprintf(foutp, "%x", smp_resp[8 + k]);
            else
                fprintf(foutp, ",%x", smp_resp[8 + k]);
        }
        fprintf(foutp, "\n");
    } else {
        len = strlen((const char *)(smp_resp + 8));
        fprintf(foutp, "'%.*s'\n", len, smp_resp + 8);
    }

err_out:
    if (foutp && (stdout != foutp)) {
        fclose(foutp);
        foutp = NULL;
    }
    res = smp_initiator_close(&tobj);
    if (res < 0) {
        pr2serr("close error: %s\n", safe_strerror(errno));
        if (0 == ret)
            return SMP_LIB_FILE_ERROR;
    }
    if (ret < 0)
        ret = SMP_LIB_CAT_OTHER;
    if (verbose && ret)
        pr2serr("Exit status %d indicates error detected\n", ret);
    return ret;
}
예제 #15
0
int
main(int argc, char * argv[])
{
    int res, c, k, len, off, decoded, act_resplen;
    int rcount = 1;
    int enhanced = 0;
    int do_hex = 0;
    int rindex = 0;
    int phy_id = 0;
    int do_raw = 0;
    int rtype = 0;
    int verbose = 0;
    int64_t sa_ll;
    uint64_t sa = 0;
    char i_params[256];
    char device_name[512];
    unsigned char smp_req[] = {SMP_FRAME_TYPE_REQ, SMP_FN_READ_GPIO_REG,
                               0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    unsigned char smp_resp[SMP_MAX_RESP_LEN];
    struct smp_target_obj tobj;
    struct smp_req_resp smp_rr;
    int subvalue = 0;
    char * cp;
    int ret = 0;
    char b[128];

    memset(device_name, 0, sizeof device_name);
    memset(i_params, 0, sizeof i_params);
    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "c:EhHi:I:p:rs:t:vV", long_options,
                        &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'c':
            rcount = smp_get_num(optarg);
            if ((rcount < 1) || (rcount > 255)) {
                pr2serr("bad argument to '--count'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'E':
            ++enhanced;
            break;
        case 'h':
        case '?':
            usage();
            return 0;
        case 'H':
            ++do_hex;
            break;
        case 'i':
            rindex = smp_get_num(optarg);
            if ((rindex < 0) || (rindex > 255)) {
                pr2serr("bad argument to '--index'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'I':
            strncpy(i_params, optarg, sizeof(i_params));
            i_params[sizeof(i_params) - 1] = '\0';
            break;
        case 'p':
           phy_id = smp_get_num(optarg);
           if ((phy_id < 0) || (phy_id > 254)) {
                pr2serr("bad argument to '--phy', expect value from 0 to "
                        "254\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            if (verbose)
                pr2serr("'--phy=<n>' option not needed so ignored\n");
            break;
        case 'r':
            ++do_raw;
            break;
        case 's':
           sa_ll = smp_get_llnum(optarg);
           if (-1LL == sa_ll) {
                pr2serr("bad argument to '--sa'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            sa = (uint64_t)sa_ll;
            break;
        case 't':
            rtype = smp_get_num(optarg);
            if ((rtype < 0) || (rtype > 255)) {
                pr2serr("bad argument to '--type'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'v':
            ++verbose;
            break;
        case 'V':
            pr2serr("version: %s\n", version_str);
            return 0;
        default:
            pr2serr("unrecognised switch code 0x%x ??\n", c);
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (optind < argc) {
        if ('\0' == device_name[0]) {
            strncpy(device_name, argv[optind], sizeof(device_name) - 1);
            device_name[sizeof(device_name) - 1] = '\0';
            ++optind;
        }
        if (optind < argc) {
            for (; optind < argc; ++optind)
                pr2serr("Unexpected extra argument: %s\n", argv[optind]);
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (0 == device_name[0]) {
        cp = getenv("SMP_UTILS_DEVICE");
        if (cp)
            strncpy(device_name, cp, sizeof(device_name) - 1);
        else {
            pr2serr("missing device name on command line\n    [Could use "
                    "environment variable SMP_UTILS_DEVICE instead]\n");
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if ((cp = strchr(device_name, SMP_SUBVALUE_SEPARATOR))) {
        *cp = '\0';
        if (1 != sscanf(cp + 1, "%d", &subvalue)) {
            pr2serr("expected number after separator in SMP_DEVICE name\n");
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (0 == sa) {
        cp = getenv("SMP_UTILS_SAS_ADDR");
        if (cp) {
           sa_ll = smp_get_llnum(cp);
           if (-1LL == sa_ll) {
                pr2serr("bad value in environment variable "
                        "SMP_UTILS_SAS_ADDR\n    use 0\n");
                sa_ll = 0;
            }
            sa = (uint64_t)sa_ll;
        }
    }
    if (sa > 0) {
        if (! smp_is_naa5(sa)) {
            pr2serr("SAS (target) address not in naa-5 format (may need "
                    "leading '0x')\n");
            if ('\0' == i_params[0]) {
                pr2serr("    use '--interface=' to override\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
        }
    }

    res = smp_initiator_open(device_name, subvalue, i_params, sa,
                             &tobj, verbose);
    if (res < 0)
        return SMP_LIB_FILE_ERROR;
    if (enhanced) {
        smp_req[1] = SMP_FN_READ_GPIO_REG_ENH;
        smp_req[2] = rcount;    /* response payload in dwords */
        smp_req[3] = 0x1;       /* 12 byte request */
        off = 2;
    } else
        off = 0;
    smp_req[2 + off] = rtype;
    smp_req[3 + off] = rindex;
    smp_req[4 + off] = rcount;
    if (verbose) {
        pr2serr("    Read GPIO register%s request: ",
                (enhanced ? " enhanced" : ""));
        for (k = 0; k < (int)sizeof(smp_req); ++k)
            pr2serr("%02x ", smp_req[k]);
        pr2serr("\n");
    }
    memset(&smp_rr, 0, sizeof(smp_rr));
    smp_rr.request_len = sizeof(smp_req);
    smp_rr.request = smp_req;
    smp_rr.max_response_len = sizeof(smp_resp);
    smp_rr.response = smp_resp;
    res = smp_send_req(&tobj, &smp_rr, verbose);

    if (res) {
        pr2serr("smp_send_req failed, res=%d\n", res);
        if (0 == verbose)
            pr2serr("    try adding '-v' option for more debug\n");
        ret = -1;
        goto err_out;
    }
    if (smp_rr.transport_err) {
        pr2serr("smp_send_req transport_error=%d\n", smp_rr.transport_err);
        ret = -1;
        goto err_out;
    }
    act_resplen = smp_rr.act_response_len;
    if ((act_resplen >= 0) && (act_resplen < 4)) {
        pr2serr("response too short, len=%d\n", act_resplen);
        ret = SMP_LIB_CAT_MALFORMED;
        goto err_out;
    }
    if (enhanced) {
        len = smp_resp[3];
        if ((len != rcount) && verbose)
            pr2serr("requested %d dwords but received %d\n", rcount, len);
    } else
        len = rcount;
    len = 4 + (len * 4);      /* length in bytes, excluding 4 byte CRC */
    if ((act_resplen >= 0) && (len > act_resplen)) {
        if (verbose)
            pr2serr("actual response length [%d] less than deduced length "
                    "[%d]\n", act_resplen, len);
        len = act_resplen;
    }
    if (do_hex || do_raw) {
        if (do_hex)
            dStrHex((const char *)smp_resp, len, 1);
        else
            dStrRaw((const char *)smp_resp, len);
        if (SMP_FRAME_TYPE_RESP != smp_resp[0])
            ret = SMP_LIB_CAT_MALFORMED;
        else if (smp_resp[1] != smp_req[1])
            ret = SMP_LIB_CAT_MALFORMED;
        else if (smp_resp[2])
            ret = smp_resp[2];
        goto err_out;
    }
    if (SMP_FRAME_TYPE_RESP != smp_resp[0]) {
        pr2serr("expected SMP frame response type, got=0x%x\n", smp_resp[0]);
        ret = SMP_LIB_CAT_MALFORMED;
        goto err_out;
    }
    if (smp_resp[1] != smp_req[1]) {
        pr2serr("Expected function code=0x%x, got=0x%x\n", smp_req[1],
                smp_resp[1]);
        ret = SMP_LIB_CAT_MALFORMED;
        goto err_out;
    }
    if (smp_resp[2]) {
        ret = smp_resp[2];
        cp = smp_get_func_res_str(ret, sizeof(b), b);
        pr2serr("Read gpio register%s result: %s\n",
                (enhanced ? " enhanced" : ""), cp);
        goto err_out;
    }
    printf("Read GPIO register%s response:\n",
           (enhanced ? " enhanced" : ""));
    decoded = 0;
    if (0 == rtype) {
        off = 4;
        if (0 == rindex) {
            printf("  GPIO_CFG[0]:\n");
            printf("    version: %d\n", (smp_resp[off + 1] & 0xf));
            printf("    GPIO enable: %d\n", !!(smp_resp[off + 2] & 0x80));
            printf("    cfg register count: %d\n",
                   ((smp_resp[off + 2] >> 4) & 0x7));
            printf("    gp register count: %d\n", (smp_resp[off + 2] & 0xf));
            printf("    supported drive count: %d\n", smp_resp[off + 3]);
            ++decoded;
            off += 4;
        }
예제 #16
0
int
main(int argc, char * argv[])
{
    bool do_raw = false;
    bool readonly = false;
    bool verbose_given = false;
    bool version_given = false;
    int sg_fd, k, m, res, c;
    int do_hex = 0;
    int verbose = 0;
    int ret = 0;
    uint32_t max_block_size;
    uint16_t min_block_size;
    const char * device_name = NULL;

    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "hHrRvV", long_options,
                        &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'h':
        case '?':
            usage();
            return 0;
        case 'H':
            ++do_hex;
            break;
        case 'r':
            do_raw = true;
            break;
        case 'R':
            readonly = true;
            break;
        case 'v':
            verbose_given = true;
            ++verbose;
            break;
        case 'V':
            version_given = true;
            break;
        default:
            pr2serr("invalid option -%c ??\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)
                pr2serr("Unexpected extra argument: %s\n", argv[optind]);
            usage();
            return SG_LIB_SYNTAX_ERROR;
        }
    }
#ifdef DEBUG
    pr2serr("In DEBUG mode, ");
    if (verbose_given && version_given) {
        pr2serr("but override: '-vV' given, zero verbose and continue\n");
        verbose_given = false;
        version_given = false;
        verbose = 0;
    } else if (! verbose_given) {
        pr2serr("set '-vv'\n");
        verbose = 2;
    } else
        pr2serr("keep verbose=%d\n", verbose);
#else
    if (verbose_given && version_given)
        pr2serr("Not in DEBUG mode, so '-vV' has no special action\n");
#endif
    if (version_given) {
        pr2serr("version: %s\n", version_str);
        return 0;
    }

    if (NULL == device_name) {
        pr2serr("missing device name!\n");
        usage();
        return SG_LIB_SYNTAX_ERROR;
    }

    sg_fd = sg_cmds_open_device(device_name, readonly, verbose);
    if (sg_fd < 0) {
        if (verbose)
            pr2serr("open error: %s: %s\n", device_name,
                    safe_strerror(-sg_fd));
        ret = sg_convert_errno(-sg_fd);
        goto the_end2;
    }

    memset(readBlkLmtBuff, 0x0, 6);
    res = sg_ll_read_block_limits(sg_fd, readBlkLmtBuff, 6, true, verbose);
    ret = res;
    if (0 == res) {
      if (do_hex) {
        hex2stdout(readBlkLmtBuff, sizeof(readBlkLmtBuff), 1);
        goto the_end;
      } else if (do_raw) {
        dStrRaw((const char *)readBlkLmtBuff, sizeof(readBlkLmtBuff));
        goto the_end;
      }

      max_block_size = sg_get_unaligned_be32(readBlkLmtBuff + 0);
      min_block_size = sg_get_unaligned_be16(readBlkLmtBuff + 4);
      k = min_block_size / 1024;
      pr2serr("Read Block Limits results:\n");
      pr2serr("\tMinimum block size: %u byte(s)",
              (unsigned int)min_block_size);
      if (k != 0)
        pr2serr(", %d KB", k);
      pr2serr("\n");
      k = max_block_size / 1024;
      m = max_block_size / 1048576;
      pr2serr("\tMaximum block size: %u byte(s)",
              (unsigned int)max_block_size);
      if (k != 0)
        pr2serr(", %d KB", k);
      if (m != 0)
        pr2serr(", %d MB", m);
      pr2serr("\n");
    } else {
        char b[80];

        sg_get_category_sense_str(res, sizeof(b), b, verbose);
        pr2serr("Read block limits: %s\n", b);
        if (0 == verbose)
            pr2serr("    try '-v' option for more information\n");
    }

the_end:
    res = sg_cmds_close_device(sg_fd);
    if (res < 0) {
        pr2serr("close error: %s\n", safe_strerror(-res));
        if (0 == ret)
            ret = sg_convert_errno(-res);
    }
the_end2:
    if (0 == verbose) {
        if (! sg_if_can2stderr("sg_read_block_limits failed: ", ret))
            pr2serr("Some error occurred, try again with '-v' or '-vv' for "
                    "more information\n");
    }
    return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
예제 #17
0
int
main(int argc, char * argv[])
{
    int sg_fd, k, num, len, res, md_len, bd_len, longlba, page_num, spf;
    char ebuff[EBUFF_SZ];
    const char * descp;
    unsigned char * rsp_buff = NULL;
    unsigned char def_rsp_buff[DEF_ALLOC_LEN];
    unsigned char * malloc_rsp_buff = NULL;
    int rsp_buff_size = DEF_ALLOC_LEN;
    int ret = 0;
    int density_code_off, t_proto, inq_pdt, inq_byte6, resp_mode6;
    int num_ua_pages;
    unsigned char * ucp;
    unsigned char uc;
    struct sg_simple_inquiry_resp inq_out;
    char pdt_name[64];
    struct opts_t opts;

    memset(&opts, 0, sizeof(opts));
    opts.pg_code = -1;
    res = process_cl(&opts, argc, argv);
    if (res)
        return SG_LIB_SYNTAX_ERROR;
    if (opts.do_help) {
        usage_for(&opts);
        return 0;
    }
    if (opts.do_version) {
        fprintf(stderr, "Version string: %s\n", version_str);
        return 0;
    }

    if (NULL == opts.device_name) {
        if (opts.do_list) {
            if ((opts.pg_code < 0) || (opts.pg_code > PG_CODE_MAX)) {
                printf("    Assume peripheral device type: disk\n");
                list_page_codes(0, 0, -1);
            } else {
                printf("    peripheral device type: %s\n",
                       sg_get_pdt_str(opts.pg_code, sizeof(pdt_name),
                                      pdt_name));
                if (opts.subpg_code_set)
                    list_page_codes(opts.pg_code, 0, opts.subpg_code);
                else
                    list_page_codes(opts.pg_code, 0, -1);
            }
            return 0;
        }
        fprintf(stderr, "No DEVICE argument given\n");
        usage_for(&opts);
        return SG_LIB_SYNTAX_ERROR;
    }

    if (opts.do_examine && (opts.pg_code >= 0)) {
        fprintf(stderr, "can't give '-e' and a page number\n");
        return SG_LIB_SYNTAX_ERROR;
    }

    if ((opts.do_six) && (opts.do_llbaa)) {
        fprintf(stderr, "LLBAA not defined for MODE SENSE 6, try "
                "without '-L'\n");
        return SG_LIB_SYNTAX_ERROR;
    }
    if (opts.maxlen > 0) {
        if (opts.do_six && (opts.maxlen > 255)) {
            fprintf(stderr, "For Mode Sense (6) maxlen cannot exceed "
                    "255\n");
            return SG_LIB_SYNTAX_ERROR;
        }
        if (opts.maxlen > DEF_ALLOC_LEN) {
            malloc_rsp_buff = (unsigned char *)malloc(opts.maxlen);
            if (NULL == malloc_rsp_buff) {
                fprintf(stderr, "Unable to malloc maxlen=%d bytes\n",
                        opts.maxlen);
                return SG_LIB_SYNTAX_ERROR;
            }
            rsp_buff = malloc_rsp_buff;
        } else
            rsp_buff = def_rsp_buff;
        rsp_buff_size = opts.maxlen;
    } else {    /* maxlen == 0 */
        rsp_buff_size = opts.do_six ? DEF_6_ALLOC_LEN : DEF_ALLOC_LEN;
        rsp_buff = def_rsp_buff;
    }
    /* If no pages or list selected than treat as 'a' */
    if (! ((opts.pg_code >= 0) || opts.do_all || opts.do_list ||
            opts.do_examine))
        opts.do_all = 1;

    if (opts.do_raw) {
        if (sg_set_binary_mode(STDOUT_FILENO) < 0) {
            perror("sg_set_binary_mode");
            return SG_LIB_FILE_ERROR;
        }
    }

    if ((sg_fd = sg_cmds_open_device(opts.device_name, 1 /* ro */,
                                     opts.do_verbose)) < 0) {
        fprintf(stderr, "error opening file: %s: %s\n",
                opts.device_name, safe_strerror(-sg_fd));
        if (malloc_rsp_buff)
            free(malloc_rsp_buff);
        return SG_LIB_FILE_ERROR;
    }

    if (sg_simple_inquiry(sg_fd, &inq_out, 1, opts.do_verbose)) {
        fprintf(stderr, "%s doesn't respond to a SCSI INQUIRY\n",
                opts.device_name);
        ret = SG_LIB_CAT_OTHER;
        goto finish;
    }
    inq_pdt = inq_out.peripheral_type;
    inq_byte6 = inq_out.byte_6;
    if (0 == opts.do_raw)
        printf("    %.8s  %.16s  %.4s   peripheral_type: %s [0x%x]\n",
               inq_out.vendor, inq_out.product, inq_out.revision,
               sg_get_pdt_str(inq_pdt, sizeof(pdt_name), pdt_name), inq_pdt);
    if (opts.do_list) {
        if (opts.subpg_code_set)
            list_page_codes(inq_pdt, inq_byte6, opts.subpg_code);
        else
            list_page_codes(inq_pdt, inq_byte6, -1);
        goto finish;
    }
    if (opts.do_examine) {
        ret = examine_pages(sg_fd, inq_pdt, inq_byte6, &opts);
        goto finish;
    }
    if (PG_CODE_ALL == opts.pg_code) {
        if (0 == opts.do_all)
            ++opts.do_all;
    } else if (opts.do_all)
        opts.pg_code = PG_CODE_ALL;
    if (opts.do_all > 1)
        opts.subpg_code = SPG_CODE_ALL;

    if (opts.do_raw > 1) {
        if (opts.do_all) {
            if (opts.opt_new)
                fprintf(stderr, "'-R' requires a specific (sub)page, not "
                        "all\n");
            else
                fprintf(stderr, "'-r' requires a specific (sub)page, not "
                        "all\n");
            usage_for(&opts);
            ret = SG_LIB_SYNTAX_ERROR;
            goto finish;
        }
    }

    memset(rsp_buff, 0, sizeof(rsp_buff));
    if (opts.do_six) {
        res = sg_ll_mode_sense6(sg_fd, opts.do_dbd, opts.page_control,
                                opts.pg_code, opts.subpg_code, rsp_buff,
                                rsp_buff_size, 1, opts.do_verbose);
        if (SG_LIB_CAT_INVALID_OP == res)
            fprintf(stderr, ">>>>>> try again without the '-6' "
                    "switch for a 10 byte MODE SENSE command\n");
    } else {
        res = sg_ll_mode_sense10(sg_fd, opts.do_llbaa, opts.do_dbd,
                                 opts.page_control, opts.pg_code,
                                 opts.subpg_code, rsp_buff, rsp_buff_size,
                                 1, opts.do_verbose);
        if (SG_LIB_CAT_INVALID_OP == res)
            fprintf(stderr, ">>>>>> try again with a '-6' "
                    "switch for a 6 byte MODE SENSE command\n");
    }
    if (SG_LIB_CAT_ILLEGAL_REQ == res) {
        if (opts.subpg_code > 0)
            fprintf(stderr, "invalid field in cdb (perhaps subpages "
                    "not supported)\n");
        else if (opts.page_control > 0)
            fprintf(stderr, "invalid field in cdb (perhaps "
                    "page control (PC) not supported)\n");
        else
            fprintf(stderr, "invalid field in cdb (perhaps "
                "page 0x%x not supported)\n", opts.pg_code);
    } else if (SG_LIB_CAT_NOT_READY == res)
        fprintf(stderr, "device not ready\n");
    else if (SG_LIB_CAT_UNIT_ATTENTION == res)
        fprintf(stderr, "unit attention\n");
    else if (SG_LIB_CAT_ABORTED_COMMAND == res)
        fprintf(stderr, "aborted command\n");
    ret = res;
    if (0 == res) {
        int medium_type, specific, headerlen;

        ret = 0;
        resp_mode6 = opts.do_six;
        if (opts.do_flexible) {
            num = rsp_buff[0];
            if (opts.do_six && (num < 3))
                resp_mode6 = 0;
            if ((0 == opts.do_six) && (num > 5)) {
                if ((num > 11) && (0 == (num % 2)) && (0 == rsp_buff[4]) &&
                    (0 == rsp_buff[5]) && (0 == rsp_buff[6])) {
                    rsp_buff[1] = num;
                    rsp_buff[0] = 0;
                    fprintf(stderr, ">>> msense(10) but resp[0]=%d and "
                            "not msense(6) response so fix length\n", num);
                } else
                    resp_mode6 = 1;
            }
        }
        if ((! opts.do_raw) && (1 != opts.do_hex)) {
            if (resp_mode6 == opts.do_six)
                printf("Mode parameter header from MODE SENSE(%s):\n",
                       (opts.do_six ? "6" : "10"));
            else
                printf(" >>> Mode parameter header from MODE SENSE(%s),\n"
                       "     decoded as %s byte response:\n",
                       (opts.do_six ? "6" : "10"), (resp_mode6 ? "6" : "10"));
        }
        if (resp_mode6) {
            headerlen = 4;
            md_len = rsp_buff[0] + 1;
            bd_len = rsp_buff[3];
            medium_type = rsp_buff[1];
            specific = rsp_buff[2];
            longlba = 0;
        } else {
            headerlen = 8;
            md_len = (rsp_buff[0] << 8) + rsp_buff[1] + 2;
            bd_len = (rsp_buff[6] << 8) + rsp_buff[7];
            medium_type = rsp_buff[2];
            specific = rsp_buff[3];
            longlba = rsp_buff[4] & 1;
        }
        if ((bd_len + headerlen) > md_len) {
            fprintf(stderr, "Invalid block descriptor length=%d, ignore\n",
                    bd_len);
            bd_len = 0;
        }
        if (opts.do_raw) {
            if (1 == opts.do_raw)
                dStrRaw((const char *)rsp_buff, md_len);
            else {
                ucp = rsp_buff + bd_len + headerlen;
                md_len -= bd_len + headerlen;
                spf = ((ucp[0] & 0x40) ? 1 : 0);
                len = (spf ? ((ucp[2] << 8) + ucp[3] + 4) : (ucp[1] + 2));
                len = (len < md_len) ? len : md_len;
                for (k = 0; k < len; ++k)
                    printf("%02x\n", ucp[k]);
            }
            goto finish;
        }
        if (1 == opts.do_hex) {
            dStrHex((const char *)rsp_buff, md_len, 1);
            goto finish;
        } else if (opts.do_hex > 1)
            dStrHex((const char *)rsp_buff, headerlen, 1);
        if (0 == inq_pdt)
            printf("  Mode data length=%d, medium type=0x%.2x, WP=%d,"
                   " DpoFua=%d, longlba=%d\n", md_len, medium_type,
                   !!(specific & 0x80), !!(specific & 0x10), longlba);
        else
            printf("  Mode data length=%d, medium type=0x%.2x, specific"
                   " param=0x%.2x, longlba=%d\n", md_len, medium_type,
                   specific, longlba);
        if (md_len > rsp_buff_size) {
            printf("Only fetched %d bytes of response, truncate output\n",
                   rsp_buff_size);
            md_len = rsp_buff_size;
            if (bd_len + headerlen > rsp_buff_size)
                bd_len = rsp_buff_size - headerlen;
        }
        if (! opts.do_dbout) {
            printf("  Block descriptor length=%d\n", bd_len);
            if (bd_len > 0) {
                len = 8;
                density_code_off = 0;
                num = bd_len;
                if (longlba) {
                    printf("> longlba direct access device block "
                           "descriptors:\n");
                    len = 16;
                    density_code_off = 8;
                }
                else if (0 == inq_pdt) {
                    printf("> Direct access device block descriptors:\n");
                    density_code_off = 4;
                }
                else
                    printf("> General mode parameter block descriptors:\n");

                ucp = rsp_buff + headerlen;
                while (num > 0) {
                    printf("   Density code=0x%x\n",
                           *(ucp + density_code_off));
                    dStrHex((const char *)ucp, len, 1);
                    ucp += len;
                    num -= len;
                }
                printf("\n");
            }
        }
        ucp = rsp_buff + bd_len + headerlen;    /* start of mode page(s) */
        md_len -= bd_len + headerlen;           /* length of mode page(s) */
        num_ua_pages = 0;
        for (k = 0; md_len > 0; ++k) { /* got mode page(s) */
            if ((k > 0) && (! opts.do_all) &&
                (SPG_CODE_ALL != opts.subpg_code)) {
                fprintf(stderr, "Unexpectedly received extra mode page "
                                "responses, ignore\n");
                break;
            }
            uc = *ucp;
            spf = ((uc & 0x40) ? 1 : 0);
            len = (spf ? ((ucp[2] << 8) + ucp[3] + 4) : (ucp[1] + 2));
            page_num = ucp[0] & PG_CODE_MASK;
            if (0x0 == page_num) {
                ++num_ua_pages;
                if((num_ua_pages > 3) && (md_len > 0xa00)) {
                    fprintf(stderr, ">>> Seen 3 unit attention pages "
                            "(only one should be at end)\n     and mpage "
                            "length=%d, looks malformed, try '-f' option\n",
                            md_len);
                    break;
                }
            }
            if (opts.do_hex) {
                if (spf)
                    printf(">> page_code=0x%x, subpage_code=0x%x, page_cont"
                           "rol=%d\n", page_num, ucp[1], opts.page_control);
                else
                    printf(">> page_code=0x%x, page_control=%d\n", page_num,
                           opts.page_control);
            } else {
                descp = NULL;
                if ((0x18 == page_num) || (0x19 == page_num)) {
                    t_proto = (spf ? ucp[5] : ucp[2]) & 0xf;
                    descp = find_page_code_desc(page_num, (spf ? ucp[1] : 0),
                                                inq_pdt, inq_byte6, t_proto);
                } else
                    descp = find_page_code_desc(page_num, (spf ? ucp[1] : 0),
                                                inq_pdt, inq_byte6, -1);
                if (NULL == descp) {
                    if (spf)
                        snprintf(ebuff, EBUFF_SZ, "0x%x, subpage_code: 0x%x",
                                 page_num, ucp[1]);
                    else
                        snprintf(ebuff, EBUFF_SZ, "0x%x", page_num);
                }
                if (descp)
                    printf(">> %s, page_control: %s\n", descp,
                           pg_control_str_arr[opts.page_control]);
                else
                    printf(">> page_code: %s, page_control: %s\n", ebuff,
                           pg_control_str_arr[opts.page_control]);
            }
            num = (len > md_len) ? md_len : len;
            if ((k > 0) && (num > 256)) {
                num = 256;
                fprintf(stderr, ">>> page length (%d) > 256 bytes, unlikely "
                                "trim\n    Try '-f' option\n", len);
            }
            dStrHex((const char *)ucp, num , 1);
            ucp += len;
            md_len -= len;
        }
    }

finish:
    sg_cmds_close_device(sg_fd);
    if (malloc_rsp_buff)
        free(malloc_rsp_buff);
    return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
예제 #18
0
static int
do_identify_dev(int sg_fd, bool do_packet, int cdb_len, bool ck_cond,
                bool extend, bool do_ident, int do_hex, bool do_raw,
                int verbose)
{
    bool t_type = false;/* false -> 512 byte blocks,
                           true -> device's LB size */
    bool t_dir = true;  /* false -> to device, true -> from device */
    bool byte_block = true; /* false -> bytes, true -> 512 byte blocks (if
                               t_type=false) */
    bool got_ard = false;         /* got ATA result descriptor */
    bool got_fixsense = false;    /* got ATA result in fixed format sense */
    bool ok;
    int j, res, ret, sb_sz;
    /* Following for ATA READ/WRITE MULTIPLE (EXT) cmds, normally 0 */
    int multiple_count = 0;
    int protocol = 4;   /* PIO data-in */
    int t_length = 2;   /* 0 -> no data transferred, 2 -> sector count */
    int resid = 0;
    uint64_t ull;
    struct sg_scsi_sense_hdr ssh;
    uint8_t inBuff[ID_RESPONSE_LEN];
    uint8_t sense_buffer[64];
    uint8_t ata_return_desc[16];
    uint8_t apt_cdb[SAT_ATA_PASS_THROUGH16_LEN] =
                {SAT_ATA_PASS_THROUGH16, 0, 0, 0, 0, 0, 0, 0,
                 0, 0, 0, 0, 0, 0, 0, 0};
    uint8_t apt12_cdb[SAT_ATA_PASS_THROUGH12_LEN] =
                {SAT_ATA_PASS_THROUGH12, 0, 0, 0, 0, 0, 0, 0,
                 0, 0, 0, 0};
    uint8_t apt32_cdb[SAT_ATA_PASS_THROUGH32_LEN];
    const unsigned short * usp;

    sb_sz = sizeof(sense_buffer);
    memset(sense_buffer, 0, sb_sz);
    memset(apt32_cdb, 0, sizeof(apt32_cdb));
    memset(ata_return_desc, 0, sizeof(ata_return_desc));
    ok = false;
    switch (cdb_len) {
    case SAT_ATA_PASS_THROUGH32_LEN:    /* SAT-4 revision 5 or later */
        /* Prepare SCSI ATA PASS-THROUGH COMMAND(32) command */
        sg_put_unaligned_be16(1, apt32_cdb + 22);     /* count=1 */
        apt32_cdb[25] = (do_packet ? ATA_IDENTIFY_PACKET_DEVICE :
                                       ATA_IDENTIFY_DEVICE);
        apt32_cdb[10] = (multiple_count << 5) | (protocol << 1);
        if (extend)
            apt32_cdb[10] |= 0x1;
        apt32_cdb[11] = t_length;
        if (ck_cond)
            apt32_cdb[11] |= 0x20;
        if (t_type)
            apt32_cdb[11] |= 0x10;
        if (t_dir)
            apt32_cdb[11] |= 0x8;
        if (byte_block)
            apt32_cdb[11] |= 0x4;
        /* following call takes care of all bytes below offset 10 in cdb */
        res = sg_ll_ata_pt(sg_fd, apt32_cdb, cdb_len, DEF_TIMEOUT, inBuff,
                           NULL /* doutp */, ID_RESPONSE_LEN, sense_buffer,
                           sb_sz, ata_return_desc,
                           sizeof(ata_return_desc), &resid, verbose);
        break;
    case SAT_ATA_PASS_THROUGH16_LEN:
        /* Prepare SCSI ATA PASS-THROUGH COMMAND(16) command */
        apt_cdb[6] = 1;   /* sector count */
        apt_cdb[14] = (do_packet ? ATA_IDENTIFY_PACKET_DEVICE :
                                     ATA_IDENTIFY_DEVICE);
        apt_cdb[1] = (multiple_count << 5) | (protocol << 1);
        if (extend)
            apt_cdb[1] |= 0x1;
        apt_cdb[2] = t_length;
        if (ck_cond)
            apt_cdb[2] |= 0x20;
        if (t_type)
            apt_cdb[2] |= 0x10;
        if (t_dir)
            apt_cdb[2] |= 0x8;
        if (byte_block)
            apt_cdb[2] |= 0x4;
        res = sg_ll_ata_pt(sg_fd, apt_cdb, cdb_len, DEF_TIMEOUT, inBuff,
                           NULL /* doutp */, ID_RESPONSE_LEN, sense_buffer,
                           sb_sz, ata_return_desc,
                           sizeof(ata_return_desc), &resid, verbose);
        break;
    case SAT_ATA_PASS_THROUGH12_LEN:
        /* Prepare SCSI ATA PASS-THROUGH COMMAND(12) command */
        apt12_cdb[4] = 1;   /* sector count */
        apt12_cdb[9] = (do_packet ? ATA_IDENTIFY_PACKET_DEVICE :
                                      ATA_IDENTIFY_DEVICE);
        apt12_cdb[1] = (multiple_count << 5) | (protocol << 1);
        apt12_cdb[2] = t_length;
        if (ck_cond)
            apt12_cdb[2] |= 0x20;
        if (t_type)
            apt12_cdb[2] |= 0x10;
        if (t_dir)
            apt12_cdb[2] |= 0x8;
        if (byte_block)
            apt12_cdb[2] |= 0x4;
        res = sg_ll_ata_pt(sg_fd, apt12_cdb, cdb_len, DEF_TIMEOUT, inBuff,
                           NULL /* doutp */, ID_RESPONSE_LEN, sense_buffer,
                           sb_sz, ata_return_desc,
                           sizeof(ata_return_desc), &resid, verbose);
        break;
    default:
        pr2serr("%s: bad cdb_len=%d\n", __func__, cdb_len);
        return -1;
    }
    if (0 == res) {
        ok = true;
        if (verbose > 2)
            pr2serr("command completed with SCSI GOOD status\n");
    } else if ((res > 0) && (res & SAM_STAT_CHECK_CONDITION)) {
        if (verbose > 1) {
            pr2serr("ATA pass-through:\n");
            sg_print_sense(NULL, sense_buffer, sb_sz,
                           ((verbose > 2) ? 1 : 0));
        }
        if (sg_scsi_normalize_sense(sense_buffer, sb_sz, &ssh)) {
            switch (ssh.sense_key) {
            case SPC_SK_ILLEGAL_REQUEST:
                if ((0x20 == ssh.asc) && (0x0 == ssh.ascq)) {
                    ret = SG_LIB_CAT_INVALID_OP;
                    if (verbose < 2)
                        pr2serr("ATA PASS-THROUGH (%d) not supported\n",
                                cdb_len);
                } else {
                    ret = SG_LIB_CAT_ILLEGAL_REQ;
                    if (verbose < 2)
                        pr2serr("ATA PASS-THROUGH (%d), bad field in cdb\n",
                                cdb_len);
                }
                return ret;
            case SPC_SK_NO_SENSE:
            case SPC_SK_RECOVERED_ERROR:
                if ((0x0 == ssh.asc) &&
                    (ASCQ_ATA_PT_INFO_AVAILABLE == ssh.ascq)) {
                    if (0x72 == ssh.response_code) {
                        if (SAT_ATA_RETURN_DESC != ata_return_desc[0]) {
                            if (verbose)
                                pr2serr("did not find ATA Return (sense) "
                                        "Descriptor\n");
                            return SG_LIB_CAT_RECOVERED;
                        }
                        got_ard = true;
                        break;
                    } else if (0x70 == ssh.response_code) {
                        got_fixsense = true;
                        break;
                    } else {
                        if (verbose < 2)
                            pr2serr("ATA PASS-THROUGH (%d), unexpected  "
                                    "response_code=0x%x\n", ssh.response_code,
                                    cdb_len);
                        return SG_LIB_CAT_RECOVERED;
                    }
                } else if (SPC_SK_RECOVERED_ERROR == ssh.sense_key)
                    return SG_LIB_CAT_RECOVERED;
                else {
                    if ((0x0 == ssh.asc) && (0x0 == ssh.ascq))
                        break;
                    return SG_LIB_CAT_SENSE;
                }
            case SPC_SK_UNIT_ATTENTION:
                if (verbose < 2)
                    pr2serr("ATA PASS-THROUGH (%d), Unit Attention detected\n",
                            cdb_len);
                return SG_LIB_CAT_UNIT_ATTENTION;
            case SPC_SK_NOT_READY:
                if (verbose < 2)
                    pr2serr("ATA PASS-THROUGH (%d), device not ready\n",
                            cdb_len);
                return SG_LIB_CAT_NOT_READY;
            case SPC_SK_MEDIUM_ERROR:
            case SPC_SK_HARDWARE_ERROR:
                if (verbose < 2)
                    pr2serr("ATA PASS-THROUGH (%d), medium or hardware "
                            "error\n", cdb_len);
                return SG_LIB_CAT_MEDIUM_HARD;
            case SPC_SK_ABORTED_COMMAND:
                if (0x10 == ssh.asc) {
                    pr2serr("Aborted command: protection information\n");
                    return SG_LIB_CAT_PROTECTION;
                } else {
                    pr2serr("Aborted command: try again with%s '-p' option\n",
                            (do_packet ? "out" : ""));
                    return SG_LIB_CAT_ABORTED_COMMAND;
                }
            case SPC_SK_DATA_PROTECT:
                pr2serr("ATA PASS-THROUGH (%d): data protect, read only "
                        "media?\n", cdb_len);
                return SG_LIB_CAT_DATA_PROTECT;
            default:
                if (verbose < 2)
                    pr2serr("ATA PASS-THROUGH (%d), some sense data, use "
                            "'-v' for more information\n", cdb_len);
                return SG_LIB_CAT_SENSE;
            }
        } else {
            pr2serr("CHECK CONDITION without response code ??\n");
            return SG_LIB_CAT_SENSE;
        }
        if (0x72 != (sense_buffer[0] & 0x7f)) {
            pr2serr("expected descriptor sense format, response code=0x%x\n",
                    sense_buffer[0]);
            return SG_LIB_CAT_MALFORMED;
        }
    } else if (res > 0) {
        if (SAM_STAT_RESERVATION_CONFLICT == res) {
            pr2serr("SCSI status: RESERVATION CONFLICT\n");
            return SG_LIB_CAT_RES_CONFLICT;
        } else {
            pr2serr("Unexpected SCSI status=0x%x\n", res);
            return SG_LIB_CAT_MALFORMED;
        }
    } else {
        pr2serr("ATA pass-through (%d) failed\n", cdb_len);
        if (verbose < 2)
            pr2serr("    try adding '-v' for more information\n");
        return -1;
    }

    if ((SAT_ATA_RETURN_DESC == ata_return_desc[0]) && (! got_ard))
        pr2serr("Seem to have got ATA Result Descriptor but it was not "
                "indicated\n");
    if (got_ard) {
        if (ata_return_desc[3] & 0x4) {
                pr2serr("error indication in returned FIS: aborted command\n");
                pr2serr("    try again with%s '-p' option\n",
                        (do_packet ? "out" : ""));
                return SG_LIB_CAT_ABORTED_COMMAND;
        }
        ok = true;
    }
    if (got_fixsense) {
        if (0x4 & sense_buffer[3]) { /* Error is MSB of Info field */
                pr2serr("error indication in returned FIS: aborted command\n");
                pr2serr("    try again with%s '-p' option\n",
                        (do_packet ? "out" : ""));
                return SG_LIB_CAT_ABORTED_COMMAND;
        }
        ok = true;
    }

    if (ok) { /* output result if it is available */
        if (do_raw)
            dStrRaw(inBuff, 512);
        else if (0 == do_hex) {
            if (do_ident) {
                usp = (const unsigned short *)inBuff;
                ull = 0;
                for (j = 0; j < 4; ++j) {
                    if (j > 0)
                        ull <<= 16;
                    ull |= usp[108 + j];
                }
                printf("0x%016" PRIx64 "\n", ull);
            } else {
                printf("Response for IDENTIFY %sDEVICE ATA command:\n",
                       (do_packet ? "PACKET " : ""));
                dWordHex((const unsigned short *)inBuff, 256, 0,
                         sg_is_big_endian());
            }
        } else if (1 == do_hex)
            hex2stdout(inBuff, 512, 0);
        else if (2 == do_hex)
            dWordHex((const unsigned short *)inBuff, 256, 0,
                     sg_is_big_endian());
        else if (3 == do_hex) /* '-HHH' suitable for "hdparm --Istdin" */
            dWordHex((const unsigned short *)inBuff, 256, -2,
                     sg_is_big_endian());
        else     /* '-HHHH' hex bytes only */
            hex2stdout(inBuff, 512, -1);
    }
    return 0;
}
예제 #19
0
파일: sg_safte.c 프로젝트: junroh/sg3_utils
/* Buffer ID 0x01: Read Enclosure Status (mandatory) */
static int
do_safte_encl_status(int sg_fd, int do_hex, int do_raw, int verbose)
{
    int res, i, offset;
    unsigned int rb_len;
    unsigned char *rb_buff;

    rb_len = safte_cfg.fans + safte_cfg.psupplies + safte_cfg.slots +
        safte_cfg.temps + 5 + safte_cfg.vendor_specific;
    rb_buff = (unsigned char *)malloc(rb_len);


    if (verbose > 1)
        pr2serr("Use READ BUFFER,mode=vendor_specific,buff_id=1 to read "
                "enclosure status\n");
    res = sg_ll_read_buffer(sg_fd, RWB_MODE_VENDOR, 1, 0,
                            rb_buff, rb_len, 0, verbose);
    if (res && res != SG_LIB_CAT_RECOVERED)
        return res;

    if (do_raw > 1) {
        dStrRaw((const char *)rb_buff, buf_capacity);
        return 0;
    }
    if (do_hex > 1) {
        dStrHex((const char *)rb_buff, buf_capacity, 1);
        return 0;
    }
    printf("Enclosure Status:\n");
    offset = 0;
    for (i = 0; i < safte_cfg.fans; i++) {
        printf("\tFan %d status: ", i);
        switch(rb_buff[i]) {
            case 0:
                printf("operational\n");
                break;
            case 1:
                printf("malfunctioning\n");
                break;
            case 2:
                printf("not installed\n");
                break;
            case 80:
                printf("not reportable\n");
                break;
            default:
                printf("unknown\n");
                break;
        }
    }

    offset += safte_cfg.fans;
    for (i = 0; i < safte_cfg.psupplies; i++) {
        printf("\tPower supply %d status: ", i);
        switch(rb_buff[i + offset]) {
            case 0:
                printf("operational / on\n");
                break;
            case 1:
                printf("operational / off\n");
                break;
            case 0x10:
                printf("malfunctioning / on\n");
                break;
            case 0x11:
                printf("malfunctioning / off\n");
                break;
            case 0x20:
                printf("not present\n");
                break;
            case 0x21:
                printf("present\n");
                break;
            case 0x80:
                printf("not reportable\n");
                break;
            default:
                printf("unknown\n");
                break;
        }
    }

    offset += safte_cfg.psupplies;
    for (i = 0; i < safte_cfg.slots; i++) {
        printf("\tDevice Slot %d: SCSI ID %d\n", i, rb_buff[i + offset]);
    }

    offset += safte_cfg.slots;
    if (safte_cfg.flags & SAFTE_CFG_FLAG_DOORLOCK) {
        switch(rb_buff[offset]) {
            case 0x0:
                printf("\tDoor lock status: locked\n");
                break;
            case 0x01:
                printf("\tDoor lock status: unlocked\n");
                break;
            case 0x80:
                printf("\tDoor lock status: not reportable\n");
                break;
        }
    } else {
        printf("\tDoor lock status: not installed\n");
    }

    offset++;
    if (!(safte_cfg.flags & SAFTE_CFG_FLAG_ALARM)) {
        printf("\tSpeaker status: not installed\n");
    } else {
        switch(rb_buff[offset]) {
            case 0x0:
                printf("\tSpeaker status: off\n");
                break;
            case 0x01:
                printf("\tSpeaker status: on\n");
                break;
        }
    }

    offset++;
    for (i = 0; i < safte_cfg.temps; i++) {
        int temp = rb_buff[i + offset];
        int is_celsius = !!(safte_cfg.flags & SAFTE_CFG_FLAG_CELSIUS);

        if (! is_celsius)
            temp -= 10;

        printf("\tTemperature sensor %d: %d deg %c\n", i, temp,
               is_celsius ? 'C' : 'F');
    }

    offset += safte_cfg.temps;
    if (safte_cfg.thermostats) {
        if (rb_buff[offset] & 0x80) {
            printf("\tEnclosure Temperature alert status: abnormal\n");
        } else {
            printf("\tEnclosure Temperature alert status: normal\n");
        }
    }
    return 0;
}
예제 #20
0
int
main(int argc, char * argv[])
{
    int res, c, k, len, sas1_1, sas2, act_resplen;
    int do_hex = 0;
    int do_raw = 0;
    int verbose = 0;
    int do_zero = 0;
    int64_t sa_ll;
    uint64_t sa = 0;
    char i_params[256];
    char device_name[512];
    char b[256];
    unsigned char smp_req[] = {SMP_FRAME_TYPE_REQ,
                               SMP_FN_REPORT_MANUFACTURER, 0, 0, 0, 0, 0, 0};
    unsigned char smp_resp[SMP_FN_REPORT_MANUFACTURER_RESP_LEN];
    struct smp_req_resp smp_rr;
    struct smp_target_obj tobj;
    int subvalue = 0;
    char * cp;
    int ret = 0;

    memset(device_name, 0, sizeof device_name);
    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "hHI:p:rs:vVz", long_options,
                        &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'h':
        case '?':
            usage();
            return 0;
        case 'H':
            ++do_hex;
            break;
        case 'I':
            strncpy(i_params, optarg, sizeof(i_params));
            i_params[sizeof(i_params) - 1] = '\0';
            break;
        case 'r':
            ++do_raw;
            break;
        case 's':
           sa_ll = smp_get_llnum(optarg);
           if (-1LL == sa_ll) {
                pr2serr("bad argument to '--sa'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            sa = (uint64_t)sa_ll;
            break;
        case 'v':
            ++verbose;
            break;
        case 'V':
            pr2serr("version: %s\n", version_str);
            return 0;
        case 'z':
            ++do_zero;
            break;
        default:
            pr2serr("unrecognised switch code 0x%x ??\n", c);
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (optind < argc) {
        if ('\0' == device_name[0]) {
            strncpy(device_name, argv[optind], sizeof(device_name) - 1);
            device_name[sizeof(device_name) - 1] = '\0';
            ++optind;
        }
        if (optind < argc) {
            for (; optind < argc; ++optind)
                pr2serr("Unexpected extra argument: %s\n", argv[optind]);
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (0 == device_name[0]) {
        cp = getenv("SMP_UTILS_DEVICE");
        if (cp)
            strncpy(device_name, cp, sizeof(device_name) - 1);
        else {
            pr2serr("missing device name on command line\n    [Could use "
                    "environment variable SMP_UTILS_DEVICE instead]\n");
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if ((cp = strchr(device_name, SMP_SUBVALUE_SEPARATOR))) {
        *cp = '\0';
        if (1 != sscanf(cp + 1, "%d", &subvalue)) {
            pr2serr("expected number after separator in SMP_DEVICE name\n");
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (0 == sa) {
        cp = getenv("SMP_UTILS_SAS_ADDR");
        if (cp) {
           sa_ll = smp_get_llnum(cp);
           if (-1LL == sa_ll) {
                pr2serr("bad value in environment variable "
                        "SMP_UTILS_SAS_ADDR\n    use 0\n");
                sa_ll = 0;
            }
            sa = (uint64_t)sa_ll;
        }
    }
    if (sa > 0) {
        if (! smp_is_naa5(sa)) {
            pr2serr("SAS (target) address not in naa-5 format (may need "
                    "leading '0x')\n");
            if ('\0' == i_params[0]) {
                pr2serr("    use '--interface=' to override\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
        }
    }

    res = smp_initiator_open(device_name, subvalue, i_params, sa,
                             &tobj, verbose);
    if (res < 0)
        return SMP_LIB_FILE_ERROR;

    if (! do_zero) {
        len = (sizeof(smp_resp) - 8) / 4;
        smp_req[2] = (len < 0x100) ? len : 0xff;
    }
    if (verbose) {
        pr2serr("    Report manufacturer information request: ");
        for (k = 0; k < (int)sizeof(smp_req); ++k)
            pr2serr("%02x ", smp_req[k]);
        pr2serr("\n");
    }
    memset(&smp_rr, 0, sizeof(smp_rr));
    smp_rr.request_len = sizeof(smp_req);
    smp_rr.request = smp_req;
    smp_rr.max_response_len = sizeof(smp_resp);
    smp_rr.response = smp_resp;
    res = smp_send_req(&tobj, &smp_rr, verbose);

    if (res) {
        pr2serr("smp_send_req failed, res=%d\n", res);
        if (0 == verbose)
            pr2serr("    try adding '-v' option for more debug\n");
        ret = -1;
        goto err_out;
    }
    if (smp_rr.transport_err) {
        pr2serr("smp_send_req transport_error=%d\n", smp_rr.transport_err);
        ret = -1;
        goto err_out;
    }
    act_resplen = smp_rr.act_response_len;
    if ((act_resplen >= 0) && (act_resplen < 4)) {
        pr2serr("response too short, len=%d\n", act_resplen);
        ret = SMP_LIB_CAT_MALFORMED;
        goto err_out;
    }
    len = smp_resp[3];
    if ((0 == len) && (0 == smp_resp[2])) {
        len = smp_get_func_def_resp_len(smp_resp[1]);
        if (len < 0) {
            len = 0;
            if (verbose > 0)
                pr2serr("unable to determine response length\n");
        }
    }
    len = 4 + (len * 4);        /* length in bytes, excluding 4 byte CRC */
    if ((act_resplen >= 0) && (len > act_resplen)) {
        if (verbose)
            pr2serr("actual response length [%d] less than deduced length "
                    "[%d]\n", act_resplen, len);
        len = act_resplen;
    }
    if (do_hex || do_raw) {
        if (do_hex)
            dStrHex((const char *)smp_resp, len, 1);
        else
            dStrRaw((const char *)smp_resp, len);
        if (SMP_FRAME_TYPE_RESP != smp_resp[0])
            ret = SMP_LIB_CAT_MALFORMED;
        else if (smp_resp[1] != smp_req[1])
            ret = SMP_LIB_CAT_MALFORMED;
        else if (smp_resp[2]) {
            if (verbose)
                pr2serr("Report manufacturer information result: %s\n",
                        smp_get_func_res_str(smp_resp[2], sizeof(b), b));
            ret = smp_resp[2];
        }
        goto err_out;
    }
    if (SMP_FRAME_TYPE_RESP != smp_resp[0]) {
        pr2serr("expected SMP frame response type, got=0x%x\n", smp_resp[0]);
        ret = SMP_LIB_CAT_MALFORMED;
        goto err_out;
    }
    if (smp_resp[1] != smp_req[1]) {
        pr2serr("Expected function code=0x%x, got=0x%x\n", smp_req[1],
                smp_resp[1]);
        ret = SMP_LIB_CAT_MALFORMED;
        goto err_out;
    }
    if (smp_resp[2]) {
        cp = smp_get_func_res_str(smp_resp[2], sizeof(b), b);
        pr2serr("Report manufacturer information result: %s\n", cp);
        ret = smp_resp[2];
        goto err_out;
    }
    sas1_1 = smp_resp[8] & 1;
    sas2 = !! (smp_resp[3]);

    printf("Report manufacturer response:\n");
    if (sas2 || (verbose > 3)) {
        res = sg_get_unaligned_be16(smp_resp + 4);
        if (verbose || res)
            printf("  Expander change count: %d\n", res);
    }
    printf("  SAS-1.1 format: %d\n", sas1_1);
    printf("  vendor identification: %.8s\n", smp_resp + 12);
    printf("  product identification: %.16s\n", smp_resp + 20);
    printf("  product revision level: %.4s\n", smp_resp + 36);
    if (sas1_1) {
        if (smp_resp[40])
            printf("  component vendor identification: %.8s\n",
                   smp_resp + 40);
        res = sg_get_unaligned_be16(smp_resp + 48);
        if (res)
            printf("  component id: %d\n", res);
        if (smp_resp[50])
            printf("  component revision level: %d\n", smp_resp[50]);
    }

err_out:
    res = smp_initiator_close(&tobj);
    if (res < 0) {
        pr2serr("close error: %s\n", safe_strerror(errno));
        if (0 == ret)
            return SMP_LIB_FILE_ERROR;
    }
    if (ret < 0)
        ret = SMP_LIB_CAT_OTHER;
    if (verbose && ret)
        pr2serr("Exit status %d indicates error detected\n", ret);
    return ret;
}
예제 #21
0
int
main(int argc, char * argv[])
{
    int sg_fd, res, c;
    int do_origin = 0;
    int do_set = 0;
    int do_srep = 0;
    int do_raw = 0;
    int readonly = 0;
    bool secs_given = false;
    int verbose = 0;
    uint64_t secs = 0;
    uint64_t msecs = 0;
    int64_t ll;
    const char * device_name = NULL;
    const char * cmd_name;
    int ret = 0;

    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "hm:orRs:SvV", long_options,
                        &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'h':
        case '?':
            usage();
            return 0;
        case 'm':
            ll = sg_get_llnum(optarg);
            if (-1 == ll) {
                pr2serr("bad argument to '--milliseconds=MS'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            msecs = (uint64_t)ll;
            ++do_set;
            break;
        case 'o':
            ++do_origin;
            break;
        case 'r':
            ++do_raw;
            break;
        case 'R':
            ++readonly;
            break;
        case 's':
            ll = sg_get_llnum(optarg);
            if (-1 == ll) {
                pr2serr("bad argument to '--seconds=SEC'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            secs = (uint64_t)ll;
            ++do_set;
            secs_given = true;
            break;
        case 'S':
            ++do_srep;
            break;
        case 'v':
            ++verbose;
            break;
        case 'V':
            pr2serr("version: %s\n", version_str);
            return 0;
        default:
            pr2serr("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)
                pr2serr("Unexpected extra argument: %s\n", argv[optind]);
            usage();
            return SG_LIB_SYNTAX_ERROR;
        }
    }

    if (do_set > 1) {
        pr2serr("either --milliseconds=MS or --seconds=SEC may be given, "
                "not both\n");
        usage();
        return SG_LIB_SYNTAX_ERROR;
    }

    if (NULL == device_name) {
        pr2serr("missing device name!\n");
        usage();
        return SG_LIB_SYNTAX_ERROR;
    }

    sg_fd = sg_cmds_open_device(device_name, readonly, verbose);
    if (sg_fd < 0) {
        pr2serr("open error: %s: %s\n", device_name,
                safe_strerror(-sg_fd));
        return SG_LIB_FILE_ERROR;
    }

    memset(d_buff, 0, 12);
    if (do_set) {
        cmd_name = "Set timestamp";
        sg_put_unaligned_be48(secs_given ? (secs * 1000) : msecs, d_buff + 4);
        res = sg_ll_set_timestamp(sg_fd, d_buff, 12, 1, verbose);
    } else {
        cmd_name = "Report timestamp";
        res = sg_ll_rep_timestamp(sg_fd, d_buff, 12, NULL, 1, verbose);
        if (0 == res) {
            if (do_raw)
                dStrRaw((const char *)d_buff, 12);
            else {
                int len = sg_get_unaligned_be16(d_buff + 0);
                if (len < 8)
                    pr2serr("timestamp parameter data length too short, "
                            "expect >= 10, got %d\n", len + 2);
                else {
                    if (do_origin)
                        printf("Device clock %s\n",
                               ts_origin_arr[0x7 & d_buff[2]]);
                    msecs = sg_get_unaligned_be48(d_buff + 4);
                    printf("%" PRIu64 "\n", do_srep ? (msecs / 1000) : msecs);
                }
            }
        }
    }
    ret = res;
    if (res) {
        if (SG_LIB_CAT_INVALID_OP == res)
            pr2serr("%s command not supported\n", cmd_name);
        else {
            char b[80];

            sg_get_category_sense_str(res, sizeof(b), b, verbose);
            pr2serr("%s command: %s\n", cmd_name, b);
        }
    }

    res = sg_cmds_close_device(sg_fd);
    if (res < 0) {
        pr2serr("close error: %s\n", safe_strerror(-res));
        if (0 == ret)
            return SG_LIB_FILE_ERROR;
    }
    return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
예제 #22
0
int
main(int argc, char * argv[])
{
    int res, c, k, len, act_resplen;
    int expected_cc = 0;
    int do_hex = 0;
    int do_min = 0;
    int do_max = 0;
    int op_val = 0;
    int sas_pa = 0;
    int sas_sl = 0;
    int sata_pa = 0;
    int sata_sl = 0;
    int pptv = -1;
    int phy_id = 0;
    int pwrdis = 0;
    int do_raw = 0;
    int verbose = 0;
    int64_t sa_ll;
    uint64_t sa = 0;
    uint64_t adn = 0;
    char i_params[256];
    char device_name[512];
    char b[256];
    unsigned char smp_req[] = {SMP_FRAME_TYPE_REQ, SMP_FN_PHY_CONTROL, 0, 9,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, };
    unsigned char smp_resp[8];
    struct smp_req_resp smp_rr;
    struct smp_target_obj tobj;
    struct smp_val_name * vnp;
    int subvalue = 0;
    char * cp;
    int ret = 0;

    memset(device_name, 0, sizeof device_name);
    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "a:D:E:hHI:l:L:m:M:o:p:P:q:Q;rs:vV",
                        long_options, &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'a':
           sa_ll = smp_get_llnum(optarg);
           if (-1LL == sa_ll) {
                pr2serr("bad argument to '--attached'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            adn = (uint64_t)sa_ll;
            break;
        case 'D':
           pwrdis = smp_get_num(optarg);
           if ((pwrdis < 0) || (pwrdis > 3)) {
                pr2serr("bad argument to '--pwrdis'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'E':
            expected_cc = smp_get_num(optarg);
            if ((expected_cc < 0) || (expected_cc > 65535)) {
                pr2serr("bad argument to '--expected'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'h':
        case '?':
            usage();
            return 0;
        case 'H':
            ++do_hex;
            break;
        case 'I':
            strncpy(i_params, optarg, sizeof(i_params));
            i_params[sizeof(i_params) - 1] = '\0';
            break;
        case 'm':
            do_min = smp_get_num(optarg);
            switch (do_min) {
            case 0:
            case 8:
            case 9:
            case 10:
            case 11:
            case 12:
                break;
            default:
                pr2serr("bad argument to '--min', want 0, 8, 9, 10, 11 or "
                        "12\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'M':
            do_max = smp_get_num(optarg);
            switch (do_max) {
            case 0:
            case 8:
            case 9:
            case 10:
            case 11:
            case 12:
                break;
            default:
                pr2serr("bad argument to '--max', want 0, 8, 9, 10, 11 or "
                        "12\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'l':
           sas_sl = smp_get_num(optarg);
           if ((sas_sl < 0) || (sas_sl > 3)) {
                pr2serr("bad argument to '--sas_sl'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'L':
           sata_sl = smp_get_num(optarg);
           if ((sata_sl < 0) || (sata_sl > 3)) {
                pr2serr("bad argument to '--sata_sl'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'o':
            if (isalpha(optarg[0])) {
                for (vnp = op_abbrev; vnp->name; ++vnp) {
                    if (0 == strncmp(optarg, vnp->name, 2))
                        break;
                }
                if (vnp->name)
                    op_val = vnp->value;
                else {
                    pr2serr("bad argument to '--op'\n");
                    list_op_abbrevs();
                    return SMP_LIB_SYNTAX_ERROR;
                }
            } else {
                op_val = smp_get_num(optarg);
                if ((op_val < 0) || (op_val > 255)) {
                    pr2serr("bad numeric argument to '--op'\n");
                    return SMP_LIB_SYNTAX_ERROR;
                }
            }
            break;
        case 'p':
           phy_id = smp_get_num(optarg);
           if ((phy_id < 0) || (phy_id > 254)) {
                pr2serr("bad argument to '--phy', expect value from 0 to "
                        "254\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'P':
           pptv = smp_get_num(optarg);
           if ((pptv < 0) || (pptv > 15)) {
                pr2serr("bad argument to '--pptv', want value from 0 to 15 "
                        "inclusive\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'q':
           sas_pa = smp_get_num(optarg);
           if ((sas_pa < 0) || (sas_pa > 3)) {
                pr2serr("bad argument to '--sas_pa'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'Q':
           sata_pa = smp_get_num(optarg);
           if ((sata_pa < 0) || (sata_pa > 3)) {
                pr2serr("bad argument to '--sata_pa'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'r':
            ++do_raw;
            break;
        case 's':
           sa_ll = smp_get_llnum(optarg);
           if (-1LL == sa_ll) {
                pr2serr("bad argument to '--sa'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            sa = (uint64_t)sa_ll;
            break;
        case 'v':
            ++verbose;
            break;
        case 'V':
            pr2serr("version: %s\n", version_str);
            return 0;
        default:
            pr2serr("unrecognised switch code 0x%x ??\n", c);
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (optind < argc) {
        if ('\0' == device_name[0]) {
            strncpy(device_name, argv[optind], sizeof(device_name) - 1);
            device_name[sizeof(device_name) - 1] = '\0';
            ++optind;
        }
        if (optind < argc) {
            for (; optind < argc; ++optind)
                pr2serr("Unexpected extra argument: %s\n", argv[optind]);
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (0 == device_name[0]) {
        cp = getenv("SMP_UTILS_DEVICE");
        if (cp)
            strncpy(device_name, cp, sizeof(device_name) - 1);
        else {
            pr2serr("missing device name on command line\n    [Could use "
                    "environment variable SMP_UTILS_DEVICE instead]\n");
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if ((cp = strchr(device_name, SMP_SUBVALUE_SEPARATOR))) {
        *cp = '\0';
        if (1 != sscanf(cp + 1, "%d", &subvalue)) {
            pr2serr("expected number after separator in SMP_DEVICE name\n");
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (0 == sa) {
        cp = getenv("SMP_UTILS_SAS_ADDR");
        if (cp) {
           sa_ll = smp_get_llnum(cp);
           if (-1LL == sa_ll) {
                pr2serr("bad value in environment variable "
                        "SMP_UTILS_SAS_ADDR\n    use 0\n");
                sa_ll = 0;
            }
            sa = (uint64_t)sa_ll;
        }
    }
    if (sa > 0) {
        if (! smp_is_naa5(sa)) {
            pr2serr("SAS (target) address not in naa-5 format (may need "
                    "leading '0x')\n");
            if ('\0' == i_params[0]) {
                pr2serr("    use '--interface=' to override\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
        }
    }

    res = smp_initiator_open(device_name, subvalue, i_params, sa,
                             &tobj, verbose);
    if (res < 0)
        return SMP_LIB_FILE_ERROR;

    sg_put_unaligned_be16(expected_cc, smp_req + 4);
    smp_req[9] = phy_id;
    smp_req[10] = op_val;
    if (pptv >= 0) {
        smp_req[11] |= 1;
        smp_req[36] |= (pptv & 0xf);
    }
    if (adn)
        sg_put_unaligned_be64(adn, smp_req + 24);
    smp_req[32] |= (do_min << 4);
    smp_req[33] |= (do_max << 4);
    smp_req[34] = (sas_sl << 6) | (sas_pa << 4) | (sata_sl << 2) | sata_pa;
    smp_req[35] = (pwrdis << 6);        /* added spl3r3 */
    if (verbose) {
        pr2serr("    Phy control request: ");
        for (k = 0; k < (int)sizeof(smp_req); ++k) {
            if (0 == (k % 16))
                pr2serr("\n      ");
            else if (0 == (k % 8))
                pr2serr(" ");
            pr2serr("%02x ", smp_req[k]);
        }
        pr2serr("\n");
    }

    memset(&smp_rr, 0, sizeof(smp_rr));
    smp_rr.request_len = sizeof(smp_req);
    smp_rr.request = smp_req;
    smp_rr.max_response_len = sizeof(smp_resp);
    smp_rr.response = smp_resp;
    res = smp_send_req(&tobj, &smp_rr, verbose);

    if (res) {
        pr2serr("smp_send_req failed, res=%d\n", res);
        if (0 == verbose)
            pr2serr("    try adding '-v' option for more debug\n");
        ret = -1;
        goto err_out;
    }
    if (smp_rr.transport_err) {
        pr2serr("smp_send_req transport_error=%d\n", smp_rr.transport_err);
        ret = -1;
        goto err_out;
    }
    act_resplen = smp_rr.act_response_len;
    if ((act_resplen >= 0) && (act_resplen < 4)) {
        pr2serr("response too short, len=%d\n", act_resplen);
        ret = SMP_LIB_CAT_MALFORMED;
        goto err_out;
    }
    len = smp_resp[3];
    if ((0 == len) && (0 == smp_resp[2])) {
        len = smp_get_func_def_resp_len(smp_resp[1]);
        if (len < 0) {
            len = 0;
            if (verbose > 0)
                pr2serr("unable to determine response length\n");
        }
    }
    len = 4 + (len * 4);        /* length in bytes, excluding 4 byte CRC */
    if ((act_resplen >= 0) && (len > act_resplen)) {
        if (verbose)
            pr2serr("actual response length [%d] less than deduced length "
                    "[%d]\n", act_resplen, len);
        len = act_resplen;
    }
    if (do_hex || do_raw) {
        if (do_hex)
            dStrHex((const char *)smp_resp, len, 1);
        else
            dStrRaw((const char *)smp_resp, len);
        if (SMP_FRAME_TYPE_RESP != smp_resp[0])
            ret = SMP_LIB_CAT_MALFORMED;
        else if (smp_resp[1] != smp_req[1])
            ret = SMP_LIB_CAT_MALFORMED;
        else if (smp_resp[2]) {
            if (verbose)
                pr2serr("Phy control result: %s\n",
                        smp_get_func_res_str(smp_resp[2], sizeof(b), b));
            ret = smp_resp[2];
        }
        goto err_out;
    }
    if (SMP_FRAME_TYPE_RESP != smp_resp[0]) {
        pr2serr("expected SMP frame response type, got=0x%x\n", smp_resp[0]);
        ret = SMP_LIB_CAT_MALFORMED;
        goto err_out;
    }
    if (smp_resp[1] != smp_req[1]) {
        pr2serr("Expected function code=0x%x, got=0x%x\n", smp_req[1],
                smp_resp[1]);
        ret = SMP_LIB_CAT_MALFORMED;
        goto err_out;
    }
    if (smp_resp[2]) {
        cp = smp_get_func_res_str(smp_resp[2], sizeof(b), b);
        pr2serr("Phy control result: %s\n", cp);
        ret = smp_resp[2];
        goto err_out;
    }

err_out:
    res = smp_initiator_close(&tobj);
    if (res < 0) {
        pr2serr("close error: %s\n", safe_strerror(errno));
        if (0 == ret)
            return SMP_LIB_FILE_ERROR;
    }
    if (ret < 0)
        ret = SMP_LIB_CAT_OTHER;
    if (verbose && ret)
        pr2serr("Exit status %d indicates error detected\n", ret);
    return ret;
}
예제 #23
0
파일: sg_safte.c 프로젝트: junroh/sg3_utils
int
main(int argc, char * argv[])
{
    int sg_fd, c, ret, peri_type, no_hex_raw;
    int res = SG_LIB_CAT_OTHER;
    const char * device_name = NULL;
    char ebuff[EBUFF_SZ];
    unsigned char *rb_buff;
    int do_config = 0;
    int do_status = 0;
    int do_slots = 0;
    int do_flags = 0;
    int do_usage = 0;
    int do_hex = 0;
    int do_raw = 0;
    int verbose = 0;
    int do_insertions = 0;
    const char * cp;
    char buff[48];
    char b[80];
    struct sg_simple_inquiry_resp inq_resp;
    const char op_name[] = "READ BUFFER";

    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "cdfhHirsuvV?", long_options,
                        &option_index);

        if (c == -1)
            break;

        switch (c) {
            case 'c':
                do_config = 1;
                break;
            case 'd':
                do_slots = 1;
                break;
            case 'f':
                do_flags = 1;
                break;
            case 'h':
            case '?':
                usage();
                return 0;
            case 'H':
                ++do_hex;
                break;
            case 'i':
                do_insertions = 1;
                break;
            case 'r':
                ++do_raw;
                break;
            case 's':
                do_status = 1;
                break;
            case 'u':
                do_usage = 1;
                break;
            case 'v':
                ++verbose;
                break;
            case 'V':
                pr2serr("Version string: %s\n", version_str);
                exit(0);
            default:
                pr2serr("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)
                pr2serr("Unexpected extra argument: %s\n", argv[optind]);
            usage();
            return SG_LIB_SYNTAX_ERROR;
        }
    }

    if (NULL == device_name) {
        pr2serr("missing device name!\n");
        usage();
        return SG_LIB_SYNTAX_ERROR;
    }
    if (do_raw) {
        if (sg_set_binary_mode(STDOUT_FILENO) < 0) {
            perror("sg_set_binary_mode");
            return SG_LIB_FILE_ERROR;
        }
    }

    if ((sg_fd = sg_cmds_open_device(device_name, 0 /* rw */, verbose)) < 0) {
        snprintf(ebuff, EBUFF_SZ, "sg_safte: error opening file: %s (rw)",
                 device_name);
        perror(ebuff);
        return SG_LIB_FILE_ERROR;
    }
    no_hex_raw = ((0 == do_hex) && (0 == do_raw));

    if (no_hex_raw) {
        if (0 == sg_simple_inquiry(sg_fd, &inq_resp, 1, verbose)) {
            printf("  %.8s  %.16s  %.4s\n", inq_resp.vendor,
                   inq_resp.product, inq_resp.revision);
            peri_type = inq_resp.peripheral_type;
            cp = sg_get_pdt_str(peri_type, sizeof(buff), buff);
            if (strlen(cp) > 0)
                printf("  Peripheral device type: %s\n", cp);
            else
                printf("  Peripheral device type: 0x%x\n", peri_type);
        } else {
            pr2serr("sg_safte: %s doesn't respond to a SCSI INQUIRY\n",
                    device_name);
            return SG_LIB_CAT_OTHER;
        }
    }

    rb_buff = (unsigned char *)malloc(buf_capacity);
    if (!rb_buff)
        goto err_out;

    memset(rb_buff, 0, buf_capacity);

    res = read_safte_configuration(sg_fd, rb_buff, buf_capacity, verbose);
    switch (res) {
    case 0:
    case SG_LIB_CAT_RECOVERED:
        break;
    default:
        goto err_out;
    }
    if (1 == do_raw) {
        dStrRaw((const char *)rb_buff, buf_capacity);
        goto finish;
    }
    if (1 == do_hex) {
        dStrHex((const char *)rb_buff, buf_capacity, 1);
        goto finish;
    }

    if (do_config && no_hex_raw)
        print_safte_configuration();

    if (do_status) {
        res = do_safte_encl_status(sg_fd, do_hex, do_raw, verbose);
        switch (res) {
            case 0:
            case SG_LIB_CAT_RECOVERED:
                break;
            default:
                goto err_out;
        }
    }

    if (do_usage) {
        res = do_safte_usage_statistics(sg_fd, do_hex, do_raw, verbose);
        switch (res) {
            case 0:
            case SG_LIB_CAT_RECOVERED:
                break;
            default:
                goto err_out;
        }
    }

    if (do_insertions) {
        res = do_safte_slot_insertions(sg_fd, do_hex, do_raw, verbose);
        switch (res) {
            case 0:
            case SG_LIB_CAT_RECOVERED:
                break;
            default:
                goto err_out;
        }
    }

    if (do_slots) {
        res = do_safte_slot_status(sg_fd, do_hex, do_raw, verbose);
        switch (res) {
            case 0:
            case SG_LIB_CAT_RECOVERED:
                break;
            default:
                goto err_out;
        }
    }

    if (do_flags) {
        res = do_safte_global_flags(sg_fd, do_hex, do_raw, verbose);
        switch (res) {
            case 0:
            case SG_LIB_CAT_RECOVERED:
                break;
            default:
                goto err_out;
        }
    }
finish:
    res = 0;

err_out:
    switch (res) {
    case 0:
    case SG_LIB_CAT_RECOVERED:
        break;
    default:
        sg_get_category_sense_str(res, sizeof(b), b, verbose);
        pr2serr("%s failed: %s\n", op_name, b);
        break;
    }
    ret = res;
    res = sg_cmds_close_device(sg_fd);
    if (res < 0) {
        pr2serr("close error: %s\n", safe_strerror(-res));
        if (0 == ret)
            return SG_LIB_FILE_ERROR;
    }
    return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
예제 #24
0
int
main(int argc, char * argv[])
{
    int res, c, k, len, act_resplen;
    int do_disable = 0;
    int expected_cc = 0;
    int do_hex = 0;
    int er_ind = 0;
    int phy_id = 0;
    int do_raw = 0;
    int verbose = 0;
    int64_t sa_ll;
    uint64_t sa = 0;
    uint64_t routed = 0;
    char i_params[256];
    char device_name[512];
    char b[256];
    unsigned char smp_req[] = {SMP_FRAME_TYPE_REQ, SMP_FN_CONFIG_ROUTE_INFO,
                               0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
    unsigned char smp_resp[8];
    struct smp_req_resp smp_rr;
    struct smp_target_obj tobj;
    int subvalue = 0;
    char * cp;
    int ret = 0;

    memset(device_name, 0, sizeof device_name);
    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "dE:hHi:I:p:rR:s:vV", long_options,
                        &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'd':
            do_disable = 1;
            break;
        case 'E':
            expected_cc = smp_get_num(optarg);
            if ((expected_cc < 0) || (expected_cc > 65535)) {
                pr2serr("bad argument to '--expected'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'h':
        case '?':
            usage();
            return 0;
        case 'H':
            ++do_hex;
            break;
        case 'I':
            strncpy(i_params, optarg, sizeof(i_params));
            i_params[sizeof(i_params) - 1] = '\0';
            break;
        case 'i':
            er_ind = smp_get_num(optarg);
            if ((er_ind < 0) || (er_ind > 65535)) {
                pr2serr("bad argument to '--index'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'p':
            phy_id = smp_get_num(optarg);
            if ((phy_id < 0) || (phy_id > 254)) {
                pr2serr("bad argument to '--phy', expect value from 0 to "
                        "254\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            break;
        case 'r':
            ++do_raw;
            break;
        case 'R':
            sa_ll = smp_get_llnum(optarg);
            if (-1LL == sa_ll) {
                pr2serr("bad argument to '--routed'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            routed = (uint64_t)sa_ll;
            break;
        case 's':
            sa_ll = smp_get_llnum(optarg);
            if (-1LL == sa_ll) {
                pr2serr("bad argument to '--sa'\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
            sa = (uint64_t)sa_ll;
            break;
        case 'v':
            ++verbose;
            break;
        case 'V':
            pr2serr("version: %s\n", version_str);
            return 0;
        default:
            pr2serr("unrecognised switch code 0x%x ??\n", c);
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (optind < argc) {
        if ('\0' == device_name[0]) {
            strncpy(device_name, argv[optind], sizeof(device_name) - 1);
            device_name[sizeof(device_name) - 1] = '\0';
            ++optind;
        }
        if (optind < argc) {
            for (; optind < argc; ++optind)
                pr2serr("Unexpected extra argument: %s\n", argv[optind]);
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (0 == device_name[0]) {
        cp = getenv("SMP_UTILS_DEVICE");
        if (cp)
            strncpy(device_name, cp, sizeof(device_name) - 1);
        else {
            pr2serr("missing device name on command line\n    [Could use "
                    "environment variable SMP_UTILS_DEVICE instead]\n");
            usage();
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if ((cp = strchr(device_name, SMP_SUBVALUE_SEPARATOR))) {
        *cp = '\0';
        if (1 != sscanf(cp + 1, "%d", &subvalue)) {
            pr2serr("expected number after separator in SMP_DEVICE name\n");
            return SMP_LIB_SYNTAX_ERROR;
        }
    }
    if (0 == sa) {
        cp = getenv("SMP_UTILS_SAS_ADDR");
        if (cp) {
           sa_ll = smp_get_llnum(cp);
           if (-1LL == sa_ll) {
                pr2serr("bad value in environment variable "
                        "SMP_UTILS_SAS_ADDR\n    use 0\n");
                sa_ll = 0;
            }
            sa = (uint64_t)sa_ll;
        }
    }
    if (sa > 0) {
        if (! smp_is_naa5(sa)) {
            pr2serr("SAS (target) address not in naa-5 format (may need "
                    "leading '0x')\n");
            if ('\0' == i_params[0]) {
                pr2serr("    use '--interface=' to override\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
        }
    }
    if (routed) {
        if (! smp_is_naa5(routed)) {
            pr2serr("routed SAS address not in naa-5 format\n");
            if ('\0' == i_params[0]) {
                pr2serr("    use any '--interface=' to continue\n");
                return SMP_LIB_SYNTAX_ERROR;
            }
        }
    }

    res = smp_initiator_open(device_name, subvalue, i_params, sa,
                             &tobj, verbose);
    if (res < 0)
        return SMP_LIB_FILE_ERROR;

    sg_put_unaligned_be16(expected_cc, smp_req + 4);
    sg_put_unaligned_be16(er_ind, smp_req + 6);
    smp_req[9] = phy_id;
    if (do_disable)
        smp_req[12] |= 0x80;
    if (routed) {
        sg_put_unaligned_be64(routed, smp_req + 16);
    }
    if (verbose) {
        pr2serr("    Configure route information request: ");
        for (k = 0; k < (int)sizeof(smp_req); ++k) {
            if (0 == (k % 16))
                pr2serr("\n      ");
            else if (0 == (k % 8))
                pr2serr(" ");
            pr2serr("%02x ", smp_req[k]);
        }
        pr2serr("\n");
    }
    memset(&smp_rr, 0, sizeof(smp_rr));
    smp_rr.request_len = sizeof(smp_req);
    smp_rr.request = smp_req;
    smp_rr.max_response_len = sizeof(smp_resp);
    smp_rr.response = smp_resp;
    res = smp_send_req(&tobj, &smp_rr, verbose);

    if (res) {
        pr2serr("smp_send_req failed, res=%d\n", res);
        if (0 == verbose)
            pr2serr("    try adding '-v' option for more debug\n");
        ret = -1;
        goto err_out;
    }
    if (smp_rr.transport_err) {
        pr2serr("smp_send_req transport_error=%d\n", smp_rr.transport_err);
        ret = -1;
        goto err_out;
    }
    act_resplen = smp_rr.act_response_len;
    if ((act_resplen >= 0) && (act_resplen < 4)) {
        pr2serr("response too short, len=%d\n", act_resplen);
        ret = SMP_LIB_CAT_MALFORMED;
        goto err_out;
    }
    len = smp_resp[3];
    if ((0 == len) && (0 == smp_resp[2])) {
        len = smp_get_func_def_resp_len(smp_resp[1]);
        if (len < 0) {
            len = 0;
            if (verbose > 0)
                pr2serr("unable to determine response length\n");
        }
    }
    len = 4 + (len * 4);        /* length in bytes, excluding 4 byte CRC */
    if ((act_resplen >= 0) && (len > act_resplen)) {
        if (verbose)
            pr2serr("actual response length [%d] less than deduced length "
                    "[%d]\n", act_resplen, len);
        len = act_resplen;
    }
    if (do_hex || do_raw) {
        if (do_hex)
            dStrHex((const char *)smp_resp, len, 1);
        else
            dStrRaw((const char *)smp_resp, len);
        if (SMP_FRAME_TYPE_RESP != smp_resp[0])
            ret = SMP_LIB_CAT_MALFORMED;
        else if (smp_resp[1] != smp_req[1])
            ret = SMP_LIB_CAT_MALFORMED;
        else if (smp_resp[2]) {
            if (verbose)
                pr2serr("Configure route information result: %s\n",
                        smp_get_func_res_str(smp_resp[2], sizeof(b), b));
            ret = smp_resp[2];
        }
        goto err_out;
    }
    if (SMP_FRAME_TYPE_RESP != smp_resp[0]) {
        pr2serr("expected SMP frame response type, got=0x%x\n", smp_resp[0]);
        ret = SMP_LIB_CAT_MALFORMED;
        goto err_out;
    }
    if (smp_resp[1] != smp_req[1]) {
        pr2serr("Expected function code=0x%x, got=0x%x\n", smp_req[1],
                smp_resp[1]);
        ret = SMP_LIB_CAT_MALFORMED;
        goto err_out;
    }
    if (smp_resp[2]) {
        cp = smp_get_func_res_str(smp_resp[2], sizeof(b), b);
        pr2serr("Configure route information result: %s\n", cp);
        ret = smp_resp[2];
        goto err_out;
    }
err_out:
    res = smp_initiator_close(&tobj);
    if (res < 0) {
        pr2serr("close error: %s\n", safe_strerror(errno));
        if (0 == ret)
            return SMP_LIB_FILE_ERROR;
    }
        if (ret < 0)
        ret = SMP_LIB_CAT_OTHER;
    if (verbose && ret)
        pr2serr("Exit status %d indicates error detected\n", ret);
    return ret;
}