📄 scsiata.cpp
字号:
feature = ATA_SMART_AUTO_OFFLINE; sector_count = select; // YET NOTE - THIS IS A NON-DATA COMMAND!! break; case AUTOSAVE: feature = ATA_SMART_AUTOSAVE; sector_count = select; // YET NOTE - THIS IS A NON-DATA COMMAND!! break; case IMMEDIATE_OFFLINE: feature = ATA_SMART_IMMEDIATE_OFFLINE; lba_low = select; break; case STATUS_CHECK: // This command uses HDIO_DRIVE_TASK and has different syntax than // the other commands. feature = ATA_SMART_STATUS; /* SMART RETURN STATUS */ ck_cond = 1; break; default: pout("Unrecognized command %d in sat_command_interface()\n" "Please contact " PACKAGE_BUGREPORT "\n", command); errno=ENOSYS; return -1; } if (ATA_SMART_CMD == ata_command) { lba_mid = 0x4f; lba_high = 0xc2; } if ((SAT_ATA_PASSTHROUGH_12LEN == con->satpassthrulen) || (SAT_ATA_PASSTHROUGH_16LEN == con->satpassthrulen)) passthru_size = con->satpassthrulen; cdb[0] = (SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ? SAT_ATA_PASSTHROUGH_12 : SAT_ATA_PASSTHROUGH_16; cdb[1] = (protocol << 1) | extend; cdb[2] = (ck_cond << 5) | (t_dir << 3) | (byte_block << 2) | t_length; cdb[(SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ? 3 : 4] = feature; cdb[(SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ? 4 : 6] = sector_count; cdb[(SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ? 5 : 8] = lba_low; cdb[(SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ? 6 : 10] = lba_mid; cdb[(SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ? 7 : 12] = lba_high; cdb[(SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ? 9 : 14] = ata_command; memset(&io_hdr, 0, sizeof(io_hdr)); if (0 == t_length) { io_hdr.dxfer_dir = DXFER_NONE; io_hdr.dxfer_len = 0; } else if (t_dir) { /* from device */ io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = copydata; io_hdr.dxferp = (unsigned char *)data; memset(data, 0, copydata); /* prefill with zeroes */ } else { /* to device */ io_hdr.dxfer_dir = DXFER_TO_DEVICE; io_hdr.dxfer_len = outlen; io_hdr.dxferp = (unsigned char *)data; } io_hdr.cmnd = cdb; io_hdr.cmnd_len = passthru_size; io_hdr.sensep = sense; io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl); if (0 != status) { if (con->reportscsiioctl > 0) pout("sat_command_interface: do_scsi_cmnd_io() failed, " "status=%d\n", status); return -1; } ardp = NULL; ard_len = 0; have_sense = sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len, &ssh); if (have_sense) { /* look for SAT ATA Return Descriptor */ ardp = sg_scsi_sense_desc_find(io_hdr.sensep, io_hdr.resp_sense_len, ATA_RETURN_DESCRIPTOR); if (ardp) { ard_len = ardp[1] + 2; if (ard_len < 12) ard_len = 12; else if (ard_len > 14) ard_len = 14; } scsi_do_sense_disect(&io_hdr, &sinfo); status = scsiSimpleSenseFilter(&sinfo); if (0 != status) { if (con->reportscsiioctl > 0) { pout("sat_command_interface: scsi error: %s\n", scsiErrString(status)); if (ardp && (con->reportscsiioctl > 1)) { pout("Values from ATA Return Descriptor are:\n"); dStrHex((const char *)ardp, ard_len, 1); } } if (t_dir && (t_length > 0) && (copydata > 0)) memset(data, 0, copydata); return -1; } } if (ck_cond) { /* expecting SAT specific sense data */ if (have_sense) { if (ardp) { if (con->reportscsiioctl > 1) { pout("Values from ATA Return Descriptor are:\n"); dStrHex((const char *)ardp, ard_len, 1); } if (ATA_CHECK_POWER_MODE == ata_command) data[0] = ardp[5]; /* sector count (0:7) */ else if (STATUS_CHECK == command) { if ((ardp[9] == 0x4f) && (ardp[11] == 0xc2)) return 0; /* GOOD smart status */ if ((ardp[9] == 0xf4) && (ardp[11] == 0x2c)) return 1; // smart predicting failure, "bad" status // We haven't gotten output that makes sense so // print out some debugging info syserror("Error SMART Status command failed"); pout("Please get assistance from " PACKAGE_HOMEPAGE "\n"); pout("Values from ATA Return Descriptor are:\n"); dStrHex((const char *)ardp, ard_len, 1); return -1; } } } if (ardp == NULL) ck_cond = 0; /* not the type of sense data expected */ } if (0 == ck_cond) { if (have_sense) { if ((ssh.response_code >= 0x72) && ((SCSI_SK_NO_SENSE == ssh.sense_key) || (SCSI_SK_RECOVERED_ERR == ssh.sense_key)) && (0 == ssh.asc) && (SCSI_ASCQ_ATA_PASS_THROUGH == ssh.ascq)) { if (ardp) { if (con->reportscsiioctl > 0) { pout("Values from ATA Return Descriptor are:\n"); dStrHex((const char *)ardp, ard_len, 1); } return -1; } } } } return 0;}/* Attempt an IDENTIFY DEVICE ATA command via SATL when packet_interface is 0 otherwise attempt IDENTIFY PACKET DEVICE. If successful return 1, else 0 */int has_sat_pass_through(int device, int packet_interface){ char data[512]; smart_command_set command; command = packet_interface ? PIDENTIFY : IDENTIFY; if (0 == sat_command_interface(device, command, 0, data)) return 1; else return 0;}/* Next two functions are borrowed from sg_lib.c in the sg3_utils package. Same copyrght owner, same license as this file. */int sg_scsi_normalize_sense(const unsigned char * sensep, int sb_len, struct sg_scsi_sense_hdr * sshp){ if (sshp) memset(sshp, 0, sizeof(struct sg_scsi_sense_hdr)); if ((NULL == sensep) || (0 == sb_len) || (0x70 != (0x70 & sensep[0]))) return 0; if (sshp) { sshp->response_code = (0x7f & sensep[0]); if (sshp->response_code >= 0x72) { /* descriptor format */ if (sb_len > 1) sshp->sense_key = (0xf & sensep[1]); if (sb_len > 2) sshp->asc = sensep[2]; if (sb_len > 3) sshp->ascq = sensep[3]; if (sb_len > 7) sshp->additional_length = sensep[7]; } else { /* fixed format */ if (sb_len > 2) sshp->sense_key = (0xf & sensep[2]); if (sb_len > 7) { sb_len = (sb_len < (sensep[7] + 8)) ? sb_len : (sensep[7] + 8); if (sb_len > 12) sshp->asc = sensep[12]; if (sb_len > 13) sshp->ascq = sensep[13]; } } } return 1;}const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep, int sense_len, int desc_type){ int add_sen_len, add_len, desc_len, k; const unsigned char * descp; if ((sense_len < 8) || (0 == (add_sen_len = sensep[7]))) return NULL; if ((sensep[0] < 0x72) || (sensep[0] > 0x73)) return NULL; add_sen_len = (add_sen_len < (sense_len - 8)) ? add_sen_len : (sense_len - 8); descp = &sensep[8]; for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) { descp += desc_len; add_len = (k < (add_sen_len - 1)) ? descp[1]: -1; desc_len = add_len + 2; if (descp[0] == desc_type) return descp; if (add_len < 0) /* short descriptor ?? */ break; } return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -