Browse Source

SAT: fix S.M.A.R.T. matrix extraction layout for USB storage bridges

Corrects the 16-byte ATA PASS-THROUGH (16) CDB array register mapping
indexes to align perfectly with the T10/SAT specification. Additionally,
relaxes the CAM status validation verification checks to safely accept
CAM_SCSI_STATUS_ERROR states containing successful SCSI CHECK CONDITION
descriptor responses.
master
Sergey Kiselev 3 months ago
parent
commit
eba47b6f0f
  1. 46
      src/libbsdiskinfo.c

46
src/libbsdiskinfo.c

@ -553,27 +553,43 @@ int diskinfo_get_smart_counters(const char *base_disk, struct smart_counter *cou
}
/* --- PROTOCOL BRANCH 1: USB / SCSI Direct Access Devices (da) --- */
if (strncmp(base_disk, "da", 2) == 0) {
if (strncmp(base_disk, "da", 2) == 0) {
memset(&ccb->csio, 0, sizeof(struct ccb_scsiio));
/* Using system-defined SSD_FULL_SIZE macro (252) from cam/scsi/scsi_all.h */
cam_fill_csio(&ccb->csio, 2, NULL, CAM_DIR_IN, CAM_TAG_ACTION_NONE,
cam_fill_csio(&ccb->csio, 2, NULL, CAM_DIR_IN, CAM_TAG_ACTION_NONE,
(uint8_t *)smart_buf, sizeof(struct smart_values), SSD_FULL_SIZE, 16, 5000);
uint8_t *cdb = ccb->csio.cdb_io.cdb_bytes;
cdb[0] = 0x85; /* ATA PASS-THROUGH (16) */
cdb[1] = 4 << 1; /* PIO Data-In protocol */
cdb[2] = 0x08 | 0x02; /* T_LENGTH = 1 (sectors), BY_BYTE = 0 (words) */
cdb[4] = 0xD0; /* SMART Feature register субкоманда */
cdb[6] = 1; /* Sector Count = 1 */
cdb[8] = 0x4F; /* LBA Low = 0x4F (SMART Magic) */
cdb[10] = 0xC2; /* LBA High = 0xC2 (SMART Magic) */
cdb[14] = 0xB0; /* SMART Opcode command */
if (cam_send_ccb(cam_dev, ccb) == 0 && (ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
data_fetched = true;
/* Strict T10 SAT-compliant 16-byte ATA PASS-THROUGH mapping */
cdb[0] = 0x85; /* Opcode: ATA PASS-THROUGH (16) */
cdb[1] = (4 << 1); /* Protocol: PIO Data-In */
cdb[2] = 0x2E; /* T_DIR=1 (In), BYTE_BLOCK=0 (Bytes), T_LENGTH=2 (Sector Count) */
cdb[3] = 0x00; /* Features (HO) */
cdb[4] = 0xD0; /* Features (LO): SMART READ DATA subcommand */
cdb[5] = 0x00; /* Sector Count (HO) */
cdb[6] = 0x01; /* Sector Count (LO): Read 1 sector */
cdb[7] = 0x00; /* LBA Low (HO) */
cdb[8] = 0x00; /* LBA Low (LO) */
cdb[9] = 0x00; /* LBA Mid (HO) */
cdb[10] = 0x4F; /* LBA Mid (LO): SMART Magic Signature */
cdb[11] = 0x00; /* LBA High (HO) */
cdb[12] = 0xC2; /* LBA High (LO): SMART Magic Signature */
cdb[13] = 0x00; /* Device */
cdb[14] = 0xB0; /* ATA Command Opcode: SMART Command */
cdb[15] = 0x00; /* Control */
if (cam_send_ccb(cam_dev, ccb) == 0) {
uint32_t cam_status = ccb->ccb_h.status & CAM_STATUS_MASK;
/*
* Accept standard completion (CAM_REQ_CMP) or T10 SAT-compliant
* auto-sense descriptors (CAM_SCSI_STATUS_ERROR with CHECK CONDITION).
*/
if (cam_status == CAM_REQ_CMP || cam_status == CAM_SCSI_STATUS_ERROR) {
data_fetched = true;
}
}
}
}
/* --- PROTOCOL BRANCH 2: Native SATA/ATA Devices (ada) --- */
else if (strncmp(base_disk, "ada", 3) == 0) {
memset(&ccb->ataio, 0, sizeof(struct ccb_ataio));

Loading…
Cancel
Save