4 * Home page of code is: http://smartmontools.sourceforge.net
6 * Copyright (C) 2006 Douglas Gilbert <dougg@torque.net>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
13 * You should have received a copy of the GNU General Public License
14 * (for example COPYING); if not, write to the Free
15 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 * The code in this file is based on the SCSI to ATA Translation (SAT)
18 * draft found at http://www.t10.org . The original draft used for this
19 * code is sat-r08.pdf which is not too far away from becoming a
20 * standard. The SAT commands of interest to smartmontools are the
21 * ATA PASS THROUGH SCSI (16) and ATA PASS THROUGH SCSI (12) defined in
22 * section 12 of that document.
24 * With more transports "hiding" SATA disks (and other S-ATAPI devices)
25 * behind a SCSI command set, accessing special features like SMART
26 * information becomes a challenge. The SAT standard offers ATA PASS
27 * THROUGH commands for special usages. Note that the SAT layer may
28 * be inside a generic OS layer (e.g. libata in linux), in a host
29 * adapter (HA or HBA) firmware, or somewhere on the interconnect
30 * between the host computer and the SATA devices (e.g. a RAID made
31 * of SATA disks and the RAID talks "SCSI" to the host computer).
32 * Note that in the latter case, this code does not solve the
33 * addressing issue (i.e. which SATA disk to address behind the logical
34 * SCSI (RAID) interface).
48 const char *scsiata_c_cvsid
="$Id: scsiata.cpp,v 1.8 2007/12/03 02:14:20 dpgilbert Exp $"
49 CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSICMDS_H_CVSID SCSIATA_H_CVSID UTILITY_H_CVSID
;
51 /* for passing global control variables */
52 extern smartmonctrl
*con
;
54 #define DEF_SAT_ATA_PASSTHRU_SIZE 16
55 #define ATA_RETURN_DESCRIPTOR 9
58 // cdb[0]: ATA PASS THROUGH (16) SCSI command opcode byte (0x85)
59 // cdb[1]: multiple_count, protocol + extend
60 // cdb[2]: offline, ck_cond, t_dir, byte_block + t_length
61 // cdb[3]: features (15:8)
62 // cdb[4]: features (7:0)
63 // cdb[5]: sector_count (15:8)
64 // cdb[6]: sector_count (7:0)
65 // cdb[7]: lba_low (15:8)
66 // cdb[8]: lba_low (7:0)
67 // cdb[9]: lba_mid (15:8)
68 // cdb[10]: lba_mid (7:0)
69 // cdb[11]: lba_high (15:8)
70 // cdb[12]: lba_high (7:0)
72 // cdb[14]: (ata) command
73 // cdb[15]: control (SCSI, leave as zero)
75 // 24 bit lba (from MSB): cdb[12] cdb[10] cdb[8]
76 // 48 bit lba (from MSB): cdb[11] cdb[9] cdb[7] cdb[12] cdb[10] cdb[8]
79 // cdb[0]: ATA PASS THROUGH (12) SCSI command opcode byte (0xa1)
80 // cdb[1]: multiple_count, protocol + extend
81 // cdb[2]: offline, ck_cond, t_dir, byte_block + t_length
82 // cdb[3]: features (7:0)
83 // cdb[4]: sector_count (7:0)
84 // cdb[5]: lba_low (7:0)
85 // cdb[6]: lba_mid (7:0)
86 // cdb[7]: lba_high (7:0)
88 // cdb[9]: (ata) command
90 // cdb[11]: control (SCSI, leave as zero)
93 // ATA Return Descriptor (component of descriptor sense data)
94 // des[0]: descriptor code (0x9)
95 // des[1]: additional descriptor length (0xc)
96 // des[2]: extend (bit 0)
98 // des[4]: sector_count (15:8)
99 // des[5]: sector_count (7:0)
100 // des[6]: lba_low (15:8)
101 // des[7]: lba_low (7:0)
102 // des[8]: lba_mid (15:8)
103 // des[9]: lba_mid (7:0)
104 // des[10]: lba_high (15:8)
105 // des[11]: lba_high (7:0)
112 // This interface routine takes ATA SMART commands and packages
113 // them in the SAT-defined ATA PASS THROUGH SCSI commands. There are
114 // two available SCSI commands: a 12 byte and 16 byte variant; the
115 // one used is chosen via con->satpassthrulen .
116 // DETAILED DESCRIPTION OF ARGUMENTS
117 // device: is the file descriptor provided by (a SCSI dvice type) open()
118 // command: defines the different ATA operations.
119 // select: additional input data if needed (which log, which type of
121 // data: location to write output data, if needed (512 bytes).
122 // Note: not all commands use all arguments.
124 // -1 if the command failed
125 // 0 if the command succeeded,
126 // STATUS_CHECK routine:
127 // -1 if the command failed
128 // 0 if the command succeeded and disk SMART status is "OK"
129 // 1 if the command succeeded and disk SMART status is "FAILING"
131 int sat_command_interface(int device
, smart_command_set command
, int select
,
134 struct scsi_cmnd_io io_hdr
;
135 struct scsi_sense_disect sinfo
;
136 struct sg_scsi_sense_hdr ssh
;
137 unsigned char cdb
[SAT_ATA_PASSTHROUGH_16LEN
];
138 unsigned char sense
[32];
139 const unsigned char * ardp
;
140 int status
, ard_len
, have_sense
;
144 int ck_cond
= 0; /* set to 1 to read register(s) back */
145 int protocol
= 3; /* non-data */
146 int t_dir
= 1; /* 0 -> to device, 1 -> from device */
147 int byte_block
= 1; /* 0 -> bytes, 1 -> 512 byte blocks */
148 int t_length
= 0; /* 0 -> no data transferred */
151 int sector_count
= 0;
155 int passthru_size
= DEF_SAT_ATA_PASSTHRU_SIZE
;
157 memset(cdb
, 0, sizeof(cdb
));
158 memset(sense
, 0, sizeof(sense
));
160 ata_command
= ATA_SMART_CMD
;
162 case CHECK_POWER_MODE
:
163 ata_command
= ATA_CHECK_POWER_MODE
;
167 case READ_VALUES
: /* READ DATA */
168 feature
= ATA_SMART_READ_VALUES
;
169 sector_count
= 1; /* one (512 byte) block */
170 protocol
= 4; /* PIO data-in */
171 t_length
= 2; /* sector count holds count */
174 case READ_THRESHOLDS
: /* obsolete */
175 feature
= ATA_SMART_READ_THRESHOLDS
;
176 sector_count
= 1; /* one (512 byte) block */
178 protocol
= 4; /* PIO data-in */
179 t_length
= 2; /* sector count holds count */
183 feature
= ATA_SMART_READ_LOG_SECTOR
;
184 sector_count
= 1; /* one (512 byte) block */
186 protocol
= 4; /* PIO data-in */
187 t_length
= 2; /* sector count holds count */
191 feature
= ATA_SMART_WRITE_LOG_SECTOR
;
192 sector_count
= 1; /* one (512 byte) block */
194 protocol
= 5; /* PIO data-out */
195 t_length
= 2; /* sector count holds count */
196 t_dir
= 0; /* to device */
200 ata_command
= ATA_IDENTIFY_DEVICE
;
201 sector_count
= 1; /* one (512 byte) block */
202 protocol
= 4; /* PIO data-in */
203 t_length
= 2; /* sector count holds count */
207 ata_command
= ATA_IDENTIFY_PACKET_DEVICE
;
208 sector_count
= 1; /* one (512 byte) block */
209 protocol
= 4; /* PIO data-in */
210 t_length
= 2; /* sector count (7:0) holds count */
214 feature
= ATA_SMART_ENABLE
;
218 feature
= ATA_SMART_DISABLE
;
222 // this command only says if SMART is working. It could be
223 // replaced with STATUS_CHECK below.
224 feature
= ATA_SMART_STATUS
;
228 feature
= ATA_SMART_AUTO_OFFLINE
;
229 sector_count
= select
; // YET NOTE - THIS IS A NON-DATA COMMAND!!
232 feature
= ATA_SMART_AUTOSAVE
;
233 sector_count
= select
; // YET NOTE - THIS IS A NON-DATA COMMAND!!
235 case IMMEDIATE_OFFLINE
:
236 feature
= ATA_SMART_IMMEDIATE_OFFLINE
;
240 // This command uses HDIO_DRIVE_TASK and has different syntax than
241 // the other commands.
242 feature
= ATA_SMART_STATUS
; /* SMART RETURN STATUS */
246 pout("Unrecognized command %d in sat_command_interface()\n"
247 "Please contact " PACKAGE_BUGREPORT
"\n", command
);
251 if (ATA_SMART_CMD
== ata_command
) {
256 if ((SAT_ATA_PASSTHROUGH_12LEN
== con
->satpassthrulen
) ||
257 (SAT_ATA_PASSTHROUGH_16LEN
== con
->satpassthrulen
))
258 passthru_size
= con
->satpassthrulen
;
259 cdb
[0] = (SAT_ATA_PASSTHROUGH_12LEN
== passthru_size
) ?
260 SAT_ATA_PASSTHROUGH_12
: SAT_ATA_PASSTHROUGH_16
;
262 cdb
[1] = (protocol
<< 1) | extend
;
263 cdb
[2] = (ck_cond
<< 5) | (t_dir
<< 3) |
264 (byte_block
<< 2) | t_length
;
265 cdb
[(SAT_ATA_PASSTHROUGH_12LEN
== passthru_size
) ? 3 : 4] = feature
;
266 cdb
[(SAT_ATA_PASSTHROUGH_12LEN
== passthru_size
) ? 4 : 6] = sector_count
;
267 cdb
[(SAT_ATA_PASSTHROUGH_12LEN
== passthru_size
) ? 5 : 8] = lba_low
;
268 cdb
[(SAT_ATA_PASSTHROUGH_12LEN
== passthru_size
) ? 6 : 10] = lba_mid
;
269 cdb
[(SAT_ATA_PASSTHROUGH_12LEN
== passthru_size
) ? 7 : 12] = lba_high
;
270 cdb
[(SAT_ATA_PASSTHROUGH_12LEN
== passthru_size
) ? 9 : 14] = ata_command
;
272 memset(&io_hdr
, 0, sizeof(io_hdr
));
274 io_hdr
.dxfer_dir
= DXFER_NONE
;
275 io_hdr
.dxfer_len
= 0;
276 } else if (t_dir
) { /* from device */
277 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
278 io_hdr
.dxfer_len
= copydata
;
279 io_hdr
.dxferp
= (unsigned char *)data
;
280 memset(data
, 0, copydata
); /* prefill with zeroes */
281 } else { /* to device */
282 io_hdr
.dxfer_dir
= DXFER_TO_DEVICE
;
283 io_hdr
.dxfer_len
= outlen
;
284 io_hdr
.dxferp
= (unsigned char *)data
;
287 io_hdr
.cmnd_len
= passthru_size
;
288 io_hdr
.sensep
= sense
;
289 io_hdr
.max_sense_len
= sizeof(sense
);
290 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
292 status
= do_scsi_cmnd_io(device
, &io_hdr
, con
->reportscsiioctl
);
294 if (con
->reportscsiioctl
> 0)
295 pout("sat_command_interface: do_scsi_cmnd_io() failed, "
296 "status=%d\n", status
);
301 have_sense
= sg_scsi_normalize_sense(io_hdr
.sensep
, io_hdr
.resp_sense_len
,
304 /* look for SAT ATA Return Descriptor */
305 ardp
= sg_scsi_sense_desc_find(io_hdr
.sensep
,
306 io_hdr
.resp_sense_len
,
307 ATA_RETURN_DESCRIPTOR
);
309 ard_len
= ardp
[1] + 2;
312 else if (ard_len
> 14)
315 scsi_do_sense_disect(&io_hdr
, &sinfo
);
316 status
= scsiSimpleSenseFilter(&sinfo
);
318 if (con
->reportscsiioctl
> 0) {
319 pout("sat_command_interface: scsi error: %s\n",
320 scsiErrString(status
));
321 if (ardp
&& (con
->reportscsiioctl
> 1)) {
322 pout("Values from ATA Return Descriptor are:\n");
323 dStrHex((const char *)ardp
, ard_len
, 1);
326 if (t_dir
&& (t_length
> 0) && (copydata
> 0))
327 memset(data
, 0, copydata
);
331 if (ck_cond
) { /* expecting SAT specific sense data */
334 if (con
->reportscsiioctl
> 1) {
335 pout("Values from ATA Return Descriptor are:\n");
336 dStrHex((const char *)ardp
, ard_len
, 1);
338 if (ATA_CHECK_POWER_MODE
== ata_command
)
339 data
[0] = ardp
[5]; /* sector count (0:7) */
340 else if (STATUS_CHECK
== command
) {
341 if ((ardp
[9] == 0x4f) && (ardp
[11] == 0xc2))
342 return 0; /* GOOD smart status */
343 if ((ardp
[9] == 0xf4) && (ardp
[11] == 0x2c))
344 return 1; // smart predicting failure, "bad" status
345 // We haven't gotten output that makes sense so
346 // print out some debugging info
347 syserror("Error SMART Status command failed");
348 pout("Please get assistance from " PACKAGE_HOMEPAGE
"\n");
349 pout("Values from ATA Return Descriptor are:\n");
350 dStrHex((const char *)ardp
, ard_len
, 1);
356 ck_cond
= 0; /* not the type of sense data expected */
360 if ((ssh
.response_code
>= 0x72) &&
361 ((SCSI_SK_NO_SENSE
== ssh
.sense_key
) ||
362 (SCSI_SK_RECOVERED_ERR
== ssh
.sense_key
)) &&
364 (SCSI_ASCQ_ATA_PASS_THROUGH
== ssh
.ascq
)) {
366 if (con
->reportscsiioctl
> 0) {
367 pout("Values from ATA Return Descriptor are:\n");
368 dStrHex((const char *)ardp
, ard_len
, 1);
378 /* Attempt an IDENTIFY DEVICE ATA command via SATL when packet_interface
379 is 0 otherwise attempt IDENTIFY PACKET DEVICE. If successful
381 int has_sat_pass_through(int device
, int packet_interface
)
384 smart_command_set command
;
386 command
= packet_interface
? PIDENTIFY
: IDENTIFY
;
387 if (0 == sat_command_interface(device
, command
, 0, data
))
393 /* Next two functions are borrowed from sg_lib.c in the sg3_utils
394 package. Same copyrght owner, same license as this file. */
395 int sg_scsi_normalize_sense(const unsigned char * sensep
, int sb_len
,
396 struct sg_scsi_sense_hdr
* sshp
)
399 memset(sshp
, 0, sizeof(struct sg_scsi_sense_hdr
));
400 if ((NULL
== sensep
) || (0 == sb_len
) || (0x70 != (0x70 & sensep
[0])))
403 sshp
->response_code
= (0x7f & sensep
[0]);
404 if (sshp
->response_code
>= 0x72) { /* descriptor format */
406 sshp
->sense_key
= (0xf & sensep
[1]);
408 sshp
->asc
= sensep
[2];
410 sshp
->ascq
= sensep
[3];
412 sshp
->additional_length
= sensep
[7];
413 } else { /* fixed format */
415 sshp
->sense_key
= (0xf & sensep
[2]);
417 sb_len
= (sb_len
< (sensep
[7] + 8)) ? sb_len
:
420 sshp
->asc
= sensep
[12];
422 sshp
->ascq
= sensep
[13];
430 const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep
,
431 int sense_len
, int desc_type
)
433 int add_sen_len
, add_len
, desc_len
, k
;
434 const unsigned char * descp
;
436 if ((sense_len
< 8) || (0 == (add_sen_len
= sensep
[7])))
438 if ((sensep
[0] < 0x72) || (sensep
[0] > 0x73))
440 add_sen_len
= (add_sen_len
< (sense_len
- 8)) ?
441 add_sen_len
: (sense_len
- 8);
443 for (desc_len
= 0, k
= 0; k
< add_sen_len
; k
+= desc_len
) {
445 add_len
= (k
< (add_sen_len
- 1)) ? descp
[1]: -1;
446 desc_len
= add_len
+ 2;
447 if (descp
[0] == desc_type
)
449 if (add_len
< 0) /* short descriptor ?? */