Exemplo n.º 1
0
/* Returns 1 if no errors found and thus nothing printed; otherwise
   prints error/warning (prefix by 'leadin') and returns 0. */
static int
sg_linux_sense_print(const char * leadin, int scsi_status, int host_status,
                     int driver_status, const unsigned char * sense_buffer,
                     int sb_len, int raw_sinfo)
{
    int done_leadin = 0;
    int done_sense = 0;

    scsi_status &= 0x7e; /*sanity */
    if ((0 == scsi_status) && (0 == host_status) && (0 == driver_status))
        return 1;       /* No problems */
    if (0 != scsi_status) {
        if (leadin)
            pr2ws("%s: ", leadin);
        done_leadin = 1;
        pr2ws("SCSI status: ");
        sg_print_scsi_status(scsi_status);
        pr2ws("\n");
        if (sense_buffer && ((scsi_status == SAM_STAT_CHECK_CONDITION) ||
                             (scsi_status == SAM_STAT_COMMAND_TERMINATED))) {
            /* SAM_STAT_COMMAND_TERMINATED is obsolete */
            sg_print_sense(0, sense_buffer, sb_len, raw_sinfo);
            done_sense = 1;
        }
    }
    if (0 != host_status) {
        if (leadin && (! done_leadin))
            pr2ws("%s: ", leadin);
        if (done_leadin)
            pr2ws("plus...: ");
        else
            done_leadin = 1;
        sg_print_host_status(host_status);
        pr2ws("\n");
    }
    if (0 != driver_status) {
        if (done_sense &&
            (SG_LIB_DRIVER_SENSE == (SG_LIB_DRIVER_MASK & driver_status)))
            return 0;
        if (leadin && (! done_leadin))
            pr2ws("%s: ", leadin);
        if (done_leadin)
            pr2ws("plus...: ");
        else
            done_leadin = 1;
        sg_print_driver_status(driver_status);
        pr2ws("\n");
        if (sense_buffer && (! done_sense) &&
            (SG_LIB_DRIVER_SENSE == (SG_LIB_DRIVER_MASK & driver_status)))
            sg_print_sense(0, sense_buffer, sb_len, raw_sinfo);
    }
    return 0;
}
Exemplo n.º 2
0
static int
do_cmd_sense(int sg_fd, int hex, int quiet, int verbose)
{
    int res, resp_len, sk, asc, ascq, progress, something;
    unsigned char buff[32];
    char b[128];

    memset(buff, 0, sizeof(buff));
    res = sg_ll_request_sense(sg_fd, 0 /* fixed format */,
                              buff, sizeof(buff), 1, verbose);
    if (0 == res) {
        resp_len = buff[7] + 8;
        if (resp_len > (int)sizeof(buff))
            resp_len = sizeof(buff);
        sk = (0xf & buff[2]);
        if (hex) {
            dStrHex((const char *)buff, resp_len, 1);
            return 0;
        }
        something = 0;
        if (verbose) {
            fprintf(stderr, "Decode response as sense data:\n");
            sg_print_sense(NULL, buff, resp_len, 0);
            if (verbose > 1) {
                fprintf(stderr, "\nOutput response in hex\n");
                dStrHex((const char *)buff, resp_len, 1);
            }
            something = 1;
        }
        asc = (resp_len > 12) ? buff[12] : 0;
        ascq = (resp_len > 13) ? buff[13] : 0;
        if (sg_get_sense_progress_fld(buff, resp_len, &progress)) {
            printf("Operation in progress, %d%% done\n",
                   progress * 100 / 65536);
            something = 1;
        }
        if (0 == sk) {  /* NO SENSE */
            /* check for hardware threshold exceeded or warning */
            if ((0xb == asc) || (0x5d == asc))
                printf("%s\n", sg_get_asc_ascq_str(asc, ascq,
                                                   (int)sizeof(b), b));
            /* check for low power conditions */
            if (0x5e == asc)
                printf("%s\n", sg_get_asc_ascq_str(asc, ascq,
                                                   (int)sizeof(b), b));
            return 0;
        } else {
            if (! (something || verbose || quiet)) {
                fprintf(stderr, "Decode response as sense data:\n");
                sg_print_sense(NULL, buff, resp_len, 0);
            }
            return 0;
        }
    } else if (SG_LIB_CAT_INVALID_OP == res)
        fprintf(stderr, "Request Sense command not supported\n");
    else if (SG_LIB_CAT_ILLEGAL_REQ == res)
        fprintf(stderr, "bad field in Request Sense cdb\n");
    else if (SG_LIB_CAT_NOT_READY == res)
        fprintf(stderr, "Request Sense failed, device not ready\n");
    else if (SG_LIB_CAT_ABORTED_COMMAND == res)
        fprintf(stderr, "Request Sense failed, aborted command\n");
    else {
        fprintf(stderr, "Request Sense command failed\n");
        if (0 == verbose)
            fprintf(stderr, "    try the '-v' option for "
                    "more information\n");
    }
    return res;
}
Exemplo n.º 3
0
static int
do_read_gplog(int sg_fd, int ata_cmd, unsigned char *inbuff,
              const struct opts_t * op)
{
    int res, ret;
    int extend = 1;
    int protocol;
    int t_dir = 1;      /* 0 -> to device, 1 -> from device */
    int byte_block = 1; /* 0 -> bytes, 1 -> 512 byte blocks */
    int t_length = 2;   /* 0 -> no data transferred, 2 -> sector count */
    int t_type = 0; /* 0 -> 512 byte blocks, 1 -> logical sectors */
    int resid = 0;
    int got_ard = 0;    /* got ATA result descriptor */
    int sb_sz;
    struct sg_scsi_sense_hdr ssh;
    unsigned char sense_buffer[64];
    unsigned char ata_return_desc[16];
    unsigned char 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};
    unsigned char apt12_cdb[SAT_ATA_PASS_THROUGH12_LEN] =
                {SAT_ATA_PASS_THROUGH12, 0, 0, 0, 0, 0, 0, 0,
                 0, 0, 0, 0};
    char cmd_name[32];

    snprintf(cmd_name, sizeof(cmd_name), "ATA PASS-THROUGH (%d)",
             op->cdb_len);
    if (ata_cmd == ATA_READ_LOG_DMA_EXT) {
        protocol = 6; /* DMA */
    } else {
        protocol = 4; /* PIO Data-In */
    }
    sb_sz = sizeof(sense_buffer);
    memset(sense_buffer, 0, sb_sz);
    memset(ata_return_desc, 0, sizeof(ata_return_desc));
    memset(inbuff, 0, op->count * 512);
    if (op->verbose > 1)
        pr2serr("Building ATA READ LOG%s EXT command; la=0x%x, pn=0x%x\n",
                ((ata_cmd == ATA_READ_LOG_DMA_EXT) ? " DMA" : ""), op->la,
                op->pn);
    if (op->cdb_len == 16) {
        /* Prepare ATA PASS-THROUGH COMMAND (16) command */
        apt_cdb[14] = ata_cmd;
        sg_put_unaligned_be16((uint16_t)op->count, apt_cdb + 5);
        apt_cdb[8] = op->la;
        sg_put_unaligned_be16((uint16_t)op->pn, apt_cdb + 9);
        apt_cdb[1] = (protocol << 1) | extend;
        apt_cdb[2] = (op->ck_cond << 5) | (t_type << 4) | (t_dir << 3) |
                       (byte_block << 2) | t_length;
        res = sg_ll_ata_pt(sg_fd, apt_cdb, op->cdb_len, DEF_TIMEOUT, inbuff,
                           NULL, op->count * 512, sense_buffer,
                           sb_sz, ata_return_desc,
                           sizeof(ata_return_desc), &resid, op->verbose);
    } else {
        /* Prepare ATA PASS-THROUGH COMMAND (12) command */
        /* Cannot map upper 8 bits of the pn since no LBA (39:32) field */
        apt12_cdb[9] = ata_cmd;
        apt12_cdb[4] = op->count;
        apt12_cdb[5] = op->la;
        apt12_cdb[6] = op->pn & 0xff;
        /* apt12_cdb[7] = (op->pn >> 8) & 0xff; */
        apt12_cdb[1] = (protocol << 1);
        apt12_cdb[2] = (op->ck_cond << 5) | (t_type << 4) | (t_dir << 3) |
                         (byte_block << 2) | t_length;
        res = sg_ll_ata_pt(sg_fd, apt12_cdb, op->cdb_len, DEF_TIMEOUT,
                           inbuff, NULL, op->count * 512, sense_buffer,
                           sb_sz, ata_return_desc,
                           sizeof(ata_return_desc), &resid, op->verbose);
    }
    if (0 == res) {
        if (op->verbose > 2)
            pr2serr("command completed with SCSI GOOD status\n");
        if ((0 == op->hex) || (2 == op->hex))
            dWordHex((const unsigned short *)inbuff, op->count * 256, 0,
                     sg_is_big_endian());
        else if (1 == op->hex)
            dStrHex((const char *)inbuff, 512, 0);
        else if (3 == op->hex)  /* '-HHH' suitable for "hdparm --Istdin" */
            dWordHex((const unsigned short *)inbuff, 256, -2,
                     sg_is_big_endian());
        else    /* '-HHHH' hex bytes only */
            dStrHex((const char *)inbuff, 512, -1);
    } else if ((res > 0) && (res & SAM_STAT_CHECK_CONDITION)) {
        if (op->verbose > 1) {
            pr2serr("ATA pass through:\n");
            sg_print_sense(NULL, sense_buffer, sb_sz,
                           ((op->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 (op->verbose < 2)
                        pr2serr("%s not supported\n", cmd_name);
                } else {
                    ret = SG_LIB_CAT_ILLEGAL_REQ;
                    if (op->verbose < 2)
                        pr2serr("%s, bad field in cdb\n", cmd_name);
                }
                return ret;
            case SPC_SK_NO_SENSE:
            case SPC_SK_RECOVERED_ERROR:
                if ((0x0 == ssh.asc) &&
                    (ASCQ_ATA_PT_INFO_AVAILABLE == ssh.ascq)) {
                    if (SAT_ATA_RETURN_DESC != ata_return_desc[0]) {
                        if (op->verbose)
                            pr2serr("did not find ATA Return (sense) "
                                    "Descriptor\n");
                        return SG_LIB_CAT_RECOVERED;
                    }
                    got_ard = 1;
                    break;
                } 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 (op->verbose < 2)
                    pr2serr("%s, Unit Attention detected\n", cmd_name);
                return SG_LIB_CAT_UNIT_ATTENTION;
            case SPC_SK_NOT_READY:
                if (op->verbose < 2)
                    pr2serr("%s, device not ready\n", cmd_name);
                return SG_LIB_CAT_NOT_READY;
            case SPC_SK_MEDIUM_ERROR:
            case SPC_SK_HARDWARE_ERROR:
                if (op->verbose < 2)
                    pr2serr("%s, medium or hardware error\n", cmd_name);
                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\n");
                    return SG_LIB_CAT_ABORTED_COMMAND;
                }
            case SPC_SK_DATA_PROTECT:
                pr2serr("%s: data protect, read only media?\n", cmd_name);
                return SG_LIB_CAT_DATA_PROTECT;
            default:
                if (op->verbose < 2)
                    pr2serr("%s, some sense data, use '-v' for more "
                            "information\n", cmd_name);
                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("%s failed\n", cmd_name);
        if (op->verbose < 2)
            pr2serr("    try adding '-v' for more information\n");
        return -1;
    }

    if ((SAT_ATA_RETURN_DESC == ata_return_desc[0]) && (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");
                return SG_LIB_CAT_ABORTED_COMMAND;
        }
    }
    return 0;
}
Exemplo n.º 4
0
int main(int argc, char * argv[])
{
    int bsg_fd, k, ok;
    unsigned char inqCmdBlk[INQ_CMD_LEN] =
                                {0x12, 0, 0, 0, INQ_REPLY_LEN, 0};
    unsigned char sdiagCmdBlk[SDIAG_CMD_LEN] =
                                {0x1d, 0, 0, 0, 0, 0};
    unsigned char inqBuff[16][INQ_REPLY_LEN];
    struct sg_io_v4 io_hdr[16];
    struct sg_io_v4 rio_hdr;
    char * file_name = 0;
    char ebuff[EBUFF_SZ];
    unsigned char sense_buffer[16][SENSE_BUFFER_LEN];
    int q_at_tail = 0;

    for (k = 1; k < argc; ++k) {
        if (0 == memcmp("-t", argv[k], 2))
            ++q_at_tail;
        else if (*argv[k] == '-') {
            printf("Unrecognized switch: %s\n", argv[k]);
            file_name = 0;
            break;
        }
        else if (0 == file_name)
            file_name = argv[k];
        else {
            printf("too many arguments\n");
            file_name = 0;
            break;
        }
    }
    if (0 == file_name) {
        printf("Usage: 'bsg_queue_tst [-t] <bsg_device>'\n"
               "where:\n      -t   queue_at_tail (def: q_at_head)\n");
        return 1;
    }

    /* An access mode of O_RDWR is required for write()/read() interface */
    if ((bsg_fd = open(file_name, O_RDWR)) < 0) {
        snprintf(ebuff, EBUFF_SZ,
                 "bsg_queue_tst: error opening file: %s", file_name);
        perror(ebuff);
        return 1;
    }

    for (k = 0; k < 16; ++k) {
        /* Prepare INQUIRY command */
        memset(&io_hdr[k], 0, sizeof(struct sg_io_v4));
        io_hdr[k].guard = 'Q';
        /* io_hdr[k].iovec_count = 0; */  /* memset takes care of this */
        if (0 == (k % 3)) {
            io_hdr[k].request_len = sizeof(sdiagCmdBlk);
            io_hdr[k].request = (uint64_t)(long)sdiagCmdBlk;
        } else {
            io_hdr[k].request_len = sizeof(inqCmdBlk);
            io_hdr[k].request = (uint64_t)(long)inqCmdBlk;
            io_hdr[k].din_xfer_len = INQ_REPLY_LEN;
            io_hdr[k].din_xferp = (uint64_t)(long)inqBuff[k];
        }
        io_hdr[k].response = (uint64_t)(long)sense_buffer[k];
        io_hdr[k].max_response_len = SENSE_BUFFER_LEN;
        io_hdr[k].timeout = 20000;     /* 20000 millisecs == 20 seconds */
        io_hdr[k].usr_ptr = k;
        /* default is to queue at head (in SCSI mid level) */
        if (q_at_tail)
            io_hdr[k].flags |= BSG_FLAG_Q_AT_TAIL;
        else
            io_hdr[k].flags |= BSG_FLAG_Q_AT_HEAD;

        if (write(bsg_fd, &io_hdr[k], sizeof(struct sg_io_v4)) < 0) {
            perror("bsg_queue_tst: bsg write error");
            close(bsg_fd);
            return 1;
        }
    }
    /* sleep(3); */
    for (k = 0; k < 16; ++k) {
        memset(&rio_hdr, 0, sizeof(struct sg_io_v4));
        rio_hdr.guard = 'Q';
        if (read(bsg_fd, &rio_hdr, sizeof(struct sg_io_v4)) < 0) {
            perror("bsg_queue_tst: bsg read error");
            close(bsg_fd);
            return 1;
        }
        /* now for the error processing */
        ok = 0;
        if (0 == rio_hdr.device_status)
            ok = 1;
        else {
            switch (sg_err_category_sense((unsigned char *)(long)
                    rio_hdr.response, rio_hdr.response_len)) {
            case SG_LIB_CAT_CLEAN:
                ok = 1;
                break;
            case SG_LIB_CAT_RECOVERED:
                printf("Recovered error, continuing\n");
                ok = 1;
                break;
            default: /* won't bother decoding other categories */
                fprintf(stderr, "command error:\n");
                sg_print_sense(NULL, (unsigned char *)(long)rio_hdr.response,
                               rio_hdr.response_len, 1);
                break;
            }
        }

        if (ok) { /* output result if it is available */
            /* if (0 == rio_hdr.pack_id) */
            if (0 == (rio_hdr.usr_ptr % 3))
                printf("SEND DIAGNOSTIC %d duration=%u\n",
                       (int)rio_hdr.usr_ptr, rio_hdr.duration);
            else
                printf("INQUIRY %d duration=%u\n", (int)rio_hdr.usr_ptr,
                       rio_hdr.duration);
        }
    }

    close(bsg_fd);
    return 0;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
int main(int argc, char * argv[])
{
    int c, n, len;
    int verbose = 0;
    int ret = 1;
    char b[2048];

    while (1) {
        int option_index = 0;

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

        switch (c) {
        case 'h':
        case '?':
            usage();
            return 0;
        case 'v':
            ++verbose;
            break;
        case 'V':
            fprintf(stderr, "version: %s\n", version_str);
            return 0;
        default:
            fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
            usage();
            return 1;
        }
    }
    if (optind < argc) {
        if (optind < argc) {
            for (; optind < argc; ++optind)
                fprintf(stderr, "Unexpected extra argument: %s\n",
                        argv[optind]);
            usage();
            return 1;
        }
    }

    printf("Testing my_snprintf():\n");
    sg_print_sense("desc_sense_data test", desc_sense_data, (int)sizeof(desc_sense_data), 1);
    printf("\n");

#if 1
    sg_get_sense_str("sg_get_sense_str", desc_sense_data, sizeof(desc_sense_data), 1, sizeof(b), b);
    printf("sg_get_sense_str: strlen(b)->%zd\n", strlen(b));
    printf("%s", b);
    printf("\n");
#endif

    b[0] = '\0';
    len = sizeof(b);
    n = my_snprintf(b, len, "%s", "test");
    printf("my_snprintf(,%d,,\"test\") -> %d; strlen(b) -> %zd\n",
           len, n, strlen(b));
    if (strlen(b) > 0)
        printf("Resulting string: %s\n", b);

    b[0] = '\0';
    len = -1;
    n = my_snprintf(b, len, "%s", "test");
    printf("my_snprintf(,%d,,\"test\") -> %d; strlen(b) -> %zd\n",
           len, n, strlen(b));
    if (strlen(b) > 0)
        printf("Resulting string: %s\n", b);

    b[0] = '\0';
    len = 0;
    n = my_snprintf(b, len, "%s", "test");
    printf("my_snprintf(,%d,,\"test\") -> %d; strlen(b) -> %zd\n",
           len, n, strlen(b));
    if (strlen(b) > 0)
        printf("Resulting string: %s\n", b);

    b[0] = '\0';
    len = 1;
    n = my_snprintf(b, len, "%s", "test");
    printf("my_snprintf(,%d,,\"test\") -> %d; strlen(b) -> %zd\n",
           len, n, strlen(b));
    if (strlen(b) > 0)
        printf("Resulting string: %s\n", b);

    b[0] = '\0';
    len = 2;
    n = my_snprintf(b, len, "%s", "test");
    printf("my_snprintf(,%d,,\"test\") -> %d; strlen(b) -> %zd\n",
           len, n, strlen(b));
    if (strlen(b) > 0)
        printf("Resulting string: %s\n", b);

    b[0] = '\0';
    len = 3;
    n = my_snprintf(b, len, "%s", "test");
    printf("my_snprintf(,%d,,\"test\") -> %d; strlen(b) -> %zd\n",
           len, n, strlen(b));
    if (strlen(b) > 0)
        printf("Resulting string: %s\n", b);

    b[0] = '\0';
    len = 4;
    n = my_snprintf(b, len, "%s", "test");
    printf("my_snprintf(,%d,,\"test\") -> %d; strlen(b) -> %zd\n",
           len, n, strlen(b));
    if (strlen(b) > 0)
        printf("Resulting string: %s\n", b);

    b[0] = '\0';
    len = 5;
    n = my_snprintf(b, len, "%s", "test");
    printf("my_snprintf(,%d,,\"test\") -> %d; strlen(b) -> %zd\n",
           len, n, strlen(b));
    if (strlen(b) > 0)
        printf("Resulting string: %s\n", b);

    b[0] = '\0';
    len = 6;
    n = my_snprintf(b, len, "%s", "test");
    printf("my_snprintf(,%d,,\"test\") -> %d; strlen(b) -> %zd\n",
           len, n, strlen(b));
    if (strlen(b) > 0)
        printf("Resulting string: %s\n", b);

    b[0] = '\0';
    len = 7;
    n = my_snprintf(b, len, "%s", "test");
    printf("my_snprintf(,%d,,\"test\") -> %d; strlen(b) -> %zd\n",
           len, n, strlen(b));
    if (strlen(b) > 0)
        printf("Resulting string: %s\n", b);

    return ret;
}
Exemplo n.º 7
0
int main(/* int argc, char * argv[] */)
{
    unsigned char err1[] = {0x72, 0x5, 0x4, 0x1, 0, 0, 0, 32,
                            0x2, 0x6, 0, 0, 0xc8, 0x0, 0x3, 0,
                            0, 0xa, 0x80, 0, 1, 2, 3, 4,
                            0xaa, 0xbb, 0xcc, 0xdd,
                            1, 0xa, 0, 0, 1, 2, 3, 4,
                            0xaa, 0xbb, 0xee, 0xff};
    unsigned char err2[] = {0x72, SPC_SK_MEDIUM_ERROR, 0x4, 0x1, 0x80, 0, 0,
                            32,
                            0x2, 0x6, 0, 0, 0xc8, 0x0, 0x3, 0,
                            0, 0xa, 0x80, 0, 1, 2, 3, 4,
                            0xaa, 0xbb, 0xcc, 0xdd,
                            1, 0xa, 0, 0, 1, 2, 3, 4,
                            0xaa, 0xbb, 0xee, 0xff};
                           /* Set SDAT_OVFL */
    unsigned char err3[] = {0x72, SPC_SK_NO_SENSE, 0x4, 0x1, 0, 0, 0, 8,
                            0x2, 0x6, 0, 0, 0xc8, 0x0, 0x3, 0};
    unsigned char err4[] = {0x73, SPC_SK_COPY_ABORTED, 0x4, 0x1, 0, 0, 0, 22,
                            0x2, 0x6, 0, 0, 0xc8, 0x0, 0x3, 0,
                            0x3, 0x2, 0, 0x55,
                            0x5, 0x2, 0, 0x20,
                            0x85, 0x4, 0, 0x20, 0x33, 0x44};
                           /* Set Filemark, EOM, ILI and SDAT_OVFL */
    unsigned char err5[] = {0xf1, 0, (0xf0 | SPC_SK_ILLEGAL_REQUEST), 0x11,
                            0x22, 0x33, 0x44, 0xa,
                            0x0, 0x0, 0, 0, 0x4, 0x1, 0, 0xcf, 0, 5,};
    unsigned char err6[] = {0x72, SPC_SK_NO_SENSE, 0x4, 0x1, 0, 0, 0, 14,
                            0x9, 0xc, 1, 0, 0x11, 0x22, 0x66, 0x33,
                            0x77, 0x44, 0x88, 0x55, 0x1, 0x2};
    unsigned char err7[] = {0xf1, 0, 0xe5, 0x11, 0x22, 0x33, 0x44, 0xa,
                            0x0, 0x0, 0x0, 0x0, 0x24, 0x1, 0xbb,
                            0xc9, 0x0, 0x2};
    char leadin[128];
    char b[2048];
    int k, prev_len;

    sg_print_sense("err1 test", err1, sizeof(err1), 1 /* raw_info */);
    sg_print_sense("\nerr2 test", err2, sizeof(err2), 1);
    sg_print_sense("\nerr3 test", err3, sizeof(err3), 1);
    sg_print_sense("\nerr4 test", err4, sizeof(err4), 1);
    sg_print_sense("\nerr5 test", err5, sizeof(err5), 1);
    sg_print_sense("\nerr6 test", err6, sizeof(err6), 1);
    sg_print_sense("\nerr7 test", err7, sizeof(err7), 1);

    printf("\n\nTry different output string sizes with "
           "sg_get_sense_str(err2):\n");
    for (k = 1, prev_len = -1; k < 512; ++k) {
        snprintf(leadin, sizeof(leadin), "blen=%d", k);
        sg_get_sense_str(leadin, err2, sizeof(err2), 0, k, b);
        printf("%s\n", b);
        if (prev_len == (int)strlen(b))
            break;
        else
            prev_len = strlen(b);
    }

    printf("\n\nTry different output string sizes with "
           "sg_get_sense_str(err4):\n");
    for (k = 1, prev_len = -1; k < 512; ++k) {
        snprintf(leadin, sizeof(leadin), "blen=%d", k);
        sg_get_sense_str(leadin, err4, sizeof(err4), 0, k, b);
        printf("%s\n", b);
        if (prev_len == (int)strlen(b))
            break;
        else
            prev_len = strlen(b);
    }
    return 0;
}
Exemplo n.º 8
0
int
main(int argc, char *argv[])
{
    int ret = 0;
    int res_cat, status, slen, k, ret2;
    int sg_fd = -1;
    struct sg_pt_base *ptvp = NULL;
    unsigned char sense_buffer[32];
    unsigned char * dxfer_buffer_in = NULL;
    unsigned char * dxfer_buffer_out = NULL;
    unsigned char *wrkBuf = NULL;
    struct opts_t opts;
    struct opts_t * op;
    char b[128];

    op = &opts;
    memset(op, 0, sizeof(opts));
    op->timeout = DEFAULT_TIMEOUT;
    ret = process_cl(op, argc, argv);
    if (ret != 0) {
        usage();
        goto done;
    } else if (op->do_help) {
        usage();
        goto done;
    } else if (op->do_version) {
        version();
        goto done;
    }

    sg_fd = scsi_pt_open_device(op->device_name, op->readonly,
                                op->do_verbose);
    if (sg_fd < 0) {
        fprintf(stderr, "%s: %s\n", op->device_name, safe_strerror(-sg_fd));
        ret = SG_LIB_FILE_ERROR;
        goto done;
    }

    ptvp = construct_scsi_pt_obj();
    if (ptvp == NULL) {
        fprintf(stderr, "out of memory\n");
        ret = SG_LIB_CAT_OTHER;
        goto done;
    }
    if (op->do_verbose) {
        fprintf(stderr, "    cdb to send: ");
        for (k = 0; k < op->cdb_length; ++k)
            fprintf(stderr, "%02x ", op->cdb[k]);
        fprintf(stderr, "\n");
        if (op->do_verbose > 2) {
            sg_get_command_name(op->cdb, 0, sizeof(b) - 1, b);
            b[sizeof(b) - 1] = '\0';
            fprintf(stderr, "    Command name: %s\n", b);
        }
    }
    set_scsi_pt_cdb(ptvp, op->cdb, op->cdb_length);
    set_scsi_pt_sense(ptvp, sense_buffer, sizeof(sense_buffer));

    if (op->do_dataout) {
        dxfer_buffer_out = fetch_dataout(op);
        if (dxfer_buffer_out == NULL) {
            ret = SG_LIB_CAT_OTHER;
            goto done;
        }
        set_scsi_pt_data_out(ptvp, dxfer_buffer_out, op->dataout_len);
    }
    if (op->do_datain) {
        dxfer_buffer_in = my_memalign(op->datain_len, &wrkBuf);
        if (dxfer_buffer_in == NULL) {
            perror("malloc");
            ret = SG_LIB_CAT_OTHER;
            goto done;
        }
        set_scsi_pt_data_in(ptvp, dxfer_buffer_in, op->datain_len);
    }

    ret = do_scsi_pt(ptvp, sg_fd, op->timeout, op->do_verbose);
    if (ret > 0) {
        if (SCSI_PT_DO_BAD_PARAMS == ret) {
            fprintf(stderr, "do_scsi_pt: bad pass through setup\n");
            ret = SG_LIB_CAT_OTHER;
        } else if (SCSI_PT_DO_TIMEOUT == ret) {
            fprintf(stderr, "do_scsi_pt: timeout\n");
            ret = SG_LIB_CAT_TIMEOUT;
        } else
            ret = SG_LIB_CAT_OTHER;
        goto done;
    } else if (ret < 0) {
        fprintf(stderr, "do_scsi_pt: %s\n", safe_strerror(-ret));
        ret = SG_LIB_CAT_OTHER;
        goto done;
    }

    slen = 0;
    res_cat = get_scsi_pt_result_category(ptvp);
    switch (res_cat) {
    case SCSI_PT_RESULT_GOOD:
        ret = 0;
        break;
    case SCSI_PT_RESULT_SENSE:
        slen = get_scsi_pt_sense_len(ptvp);
        ret = sg_err_category_sense(sense_buffer, slen);
        break;
    case SCSI_PT_RESULT_TRANSPORT_ERR:
        get_scsi_pt_transport_err_str(ptvp, sizeof(b), b);
        fprintf(stderr, ">>> transport error: %s\n", b);
        ret = SG_LIB_CAT_OTHER;
        break;
    case SCSI_PT_RESULT_OS_ERR:
        get_scsi_pt_os_err_str(ptvp, sizeof(b), b);
        fprintf(stderr, ">>> os error: %s\n", b);
        ret = SG_LIB_CAT_OTHER;
        break;
    default:
        fprintf(stderr, ">>> unknown pass through result category (%d)\n",
                res_cat);
        ret = SG_LIB_CAT_OTHER;
        break;
    }

    status = get_scsi_pt_status_response(ptvp);
    fprintf(stderr, "SCSI Status: ");
    sg_print_scsi_status(status);
    fprintf(stderr, "\n\n");
    if ((SAM_STAT_CHECK_CONDITION == status) && (! op->no_sense)) {
        if (SCSI_PT_RESULT_SENSE != res_cat)
            slen = get_scsi_pt_sense_len(ptvp);
        if (0 == slen)
            fprintf(stderr, ">>> Strange: status is CHECK CONDITION but no "
                    "Sense Information\n");
        else {
            fprintf(stderr, "Sense Information:\n");
            sg_print_sense(NULL, sense_buffer, slen, (op->do_verbose > 0));
            fprintf(stderr, "\n");
        }
    }
    if (SAM_STAT_RESERVATION_CONFLICT == status)
        ret = SG_LIB_CAT_RES_CONFLICT;

    if (op->do_datain) {
        int data_len = op->datain_len - get_scsi_pt_resid(ptvp);

        if (ret && !(SG_LIB_CAT_RECOVERED == ret ||
                     SG_LIB_CAT_NO_SENSE == ret))
            fprintf(stderr, "Error %d occurred, no data received\n", ret);
        else if (data_len == 0) {
            fprintf(stderr, "No data received\n");
        } else {
            if (op->datain_file == NULL && !op->datain_binary) {
                fprintf(stderr, "Received %d bytes of data:\n", data_len);
                dStrHexErr((const char *)dxfer_buffer_in, data_len, 0);
            } else {
                const char * cp = "stdout";

                if (op->datain_file &&
                    ! ((1 == strlen(op->datain_file)) &&
                       ('-' == op->datain_file[0])))
                    cp = op->datain_file;
                fprintf(stderr, "Writing %d bytes of data to %s\n", data_len,
                        cp);
                ret2 = write_dataout(op->datain_file, dxfer_buffer_in,
                                     data_len);
                if (0 != ret2) {
                    if (0 == ret)
                        ret = ret2;
                    goto done;
                }
            }
        }
    }

done:
    if (op->do_verbose) {
        sg_get_category_sense_str(ret, sizeof(b), b, op->do_verbose - 1);
        fprintf(stderr, "%s\n", b);
    }
    if (wrkBuf)
        free(wrkBuf);
    if (ptvp)
        destruct_scsi_pt_obj(ptvp);
    if (sg_fd >= 0)
        scsi_pt_close_device(sg_fd);
    return ret;
}