]> git.proxmox.com Git - mirror_smartmontools-debian.git/blob - scsiata.cpp
Imported smartmontools-5.27.cvs20061002
[mirror_smartmontools-debian.git] / scsiata.cpp
1 /*
2 * scsiata.cpp
3 *
4 * Home page of code is: http://smartmontools.sourceforge.net
5 *
6 * Copyright (C) 2006 Douglas Gilbert <dougg@torque.net>
7 *
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)
11 * any later version.
12 *
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.
16 *
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.
23 *
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).
35 *
36 */
37
38 #include <stdio.h>
39 #include <string.h>
40
41 #include "config.h"
42 #include "int64.h"
43 #include "extern.h"
44 #include "scsicmds.h"
45 #include "scsiata.h"
46 #include "utility.h"
47
48 const char *scsiata_c_cvsid="$Id: scsiata.cpp,v 1.7 2006/08/09 20:40:19 chrfranke Exp $"
49 CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSICMDS_H_CVSID SCSIATA_H_CVSID UTILITY_H_CVSID;
50
51 /* for passing global control variables */
52 extern smartmonctrl *con;
53
54 #define DEF_SAT_ATA_PASSTHRU_SIZE 16
55
56
57 // cdb[0]: ATA PASS THROUGH (16) SCSI command opcode byte (0x85)
58 // cdb[1]: multiple_count, protocol + extend
59 // cdb[2]: offline, ck_cond, t_dir, byte_block + t_length
60 // cdb[3]: features (15:8)
61 // cdb[4]: features (7:0)
62 // cdb[5]: sector_count (15:8)
63 // cdb[6]: sector_count (7:0)
64 // cdb[7]: lba_low (15:8)
65 // cdb[8]: lba_low (7:0)
66 // cdb[9]: lba_mid (15:8)
67 // cdb[10]: lba_mid (7:0)
68 // cdb[11]: lba_high (15:8)
69 // cdb[12]: lba_high (7:0)
70 // cdb[13]: device
71 // cdb[14]: (ata) command
72 // cdb[15]: control (SCSI, leave as zero)
73 //
74 // 24 bit lba (from MSB): cdb[12] cdb[10] cdb[8]
75 // 48 bit lba (from MSB): cdb[11] cdb[9] cdb[7] cdb[12] cdb[10] cdb[8]
76 //
77 //
78 // cdb[0]: ATA PASS THROUGH (12) SCSI command opcode byte (0xa1)
79 // cdb[1]: multiple_count, protocol + extend
80 // cdb[2]: offline, ck_cond, t_dir, byte_block + t_length
81 // cdb[3]: features (7:0)
82 // cdb[4]: sector_count (7:0)
83 // cdb[5]: lba_low (7:0)
84 // cdb[6]: lba_mid (7:0)
85 // cdb[7]: lba_high (7:0)
86 // cdb[8]: device
87 // cdb[9]: (ata) command
88 // cdb[10]: reserved
89 // cdb[11]: control (SCSI, leave as zero)
90 //
91 //
92 // ATA status return descriptor (component of descriptor sense data)
93 // des[0]: descriptor code (0x9)
94 // des[1]: additional descriptor length (0xc)
95 // des[2]: extend (bit 0)
96 // des[3]: error
97 // des[4]: sector_count (15:8)
98 // des[5]: sector_count (7:0)
99 // des[6]: lba_low (15:8)
100 // des[7]: lba_low (7:0)
101 // des[8]: lba_mid (15:8)
102 // des[9]: lba_mid (7:0)
103 // des[10]: lba_high (15:8)
104 // des[11]: lba_high (7:0)
105 // des[12]: device
106 // des[13]: status
107
108
109
110 // PURPOSE
111 // This interface routine takes ATA SMART commands and packages
112 // them in the SAT-defined ATA PASS THROUGH SCSI commands. There are
113 // two available SCSI commands: a 12 byte and 16 byte variant; the
114 // one used is chosen via con->satpassthrulen .
115 // DETAILED DESCRIPTION OF ARGUMENTS
116 // device: is the file descriptor provided by (a SCSI dvice type) open()
117 // command: defines the different ATA operations.
118 // select: additional input data if needed (which log, which type of
119 // self-test).
120 // data: location to write output data, if needed (512 bytes).
121 // Note: not all commands use all arguments.
122 // RETURN VALUES
123 // -1 if the command failed
124 // 0 if the command succeeded,
125 // STATUS_CHECK routine:
126 // -1 if the command failed
127 // 0 if the command succeeded and disk SMART status is "OK"
128 // 1 if the command succeeded and disk SMART status is "FAILING"
129
130 int sat_command_interface(int device, smart_command_set command, int select,
131 char *data)
132 {
133 struct scsi_cmnd_io io_hdr;
134 struct scsi_sense_disect sinfo;
135 struct sg_scsi_sense_hdr ssh;
136 unsigned char cdb[SAT_ATA_PASSTHROUGH_16LEN];
137 unsigned char sense[32];
138 const unsigned char * ucp;
139 int status, len;
140 int copydata = 0;
141 int outlen = 0;
142 int extend = 0;
143 int chk_cond = 0; /* set to 1 to read register(s) back */
144 int protocol = 3; /* non-data */
145 int t_dir = 1; /* 0 -> to device, 1 -> from device */
146 int byte_block = 1; /* 0 -> bytes, 1 -> 512 byte blocks */
147 int t_length = 0; /* 0 -> no data transferred */
148 int feature = 0;
149 int ata_command = 0;
150 int sector_count = 0;
151 int lba_low = 0;
152 int lba_mid = 0;
153 int lba_high = 0;
154 int passthru_size = DEF_SAT_ATA_PASSTHRU_SIZE;
155
156 memset(cdb, 0, sizeof(cdb));
157 memset(sense, 0, sizeof(sense));
158
159 ata_command = ATA_SMART_CMD;
160 switch (command) {
161 case CHECK_POWER_MODE:
162 ata_command = ATA_CHECK_POWER_MODE;
163 chk_cond = 1;
164 copydata = 1;
165 break;
166 case READ_VALUES: /* READ DATA */
167 feature = ATA_SMART_READ_VALUES;
168 sector_count = 1; /* one (512 byte) block */
169 protocol = 4; /* PIO data-in */
170 t_length = 2; /* sector count holds count */
171 copydata = 512;
172 break;
173 case READ_THRESHOLDS: /* obsolete */
174 feature = ATA_SMART_READ_THRESHOLDS;
175 sector_count = 1; /* one (512 byte) block */
176 lba_low = 1;
177 protocol = 4; /* PIO data-in */
178 t_length = 2; /* sector count holds count */
179 copydata=512;
180 break;
181 case READ_LOG:
182 feature = ATA_SMART_READ_LOG_SECTOR;
183 sector_count = 1; /* one (512 byte) block */
184 lba_low = select;
185 protocol = 4; /* PIO data-in */
186 t_length = 2; /* sector count holds count */
187 copydata = 512;
188 break;
189 case WRITE_LOG:
190 feature = ATA_SMART_WRITE_LOG_SECTOR;
191 sector_count = 1; /* one (512 byte) block */
192 lba_low = select;
193 protocol = 5; /* PIO data-out */
194 t_length = 2; /* sector count holds count */
195 t_dir = 0; /* to device */
196 outlen = 512;
197 break;
198 case IDENTIFY:
199 ata_command = ATA_IDENTIFY_DEVICE;
200 sector_count = 1; /* one (512 byte) block */
201 protocol = 4; /* PIO data-in */
202 t_length = 2; /* sector count holds count */
203 copydata = 512;
204 break;
205 case PIDENTIFY:
206 ata_command = ATA_IDENTIFY_PACKET_DEVICE;
207 sector_count = 1; /* one (512 byte) block */
208 protocol = 4; /* PIO data-in */
209 t_length = 2; /* sector count (7:0) holds count */
210 copydata = 512;
211 break;
212 case ENABLE:
213 feature = ATA_SMART_ENABLE;
214 lba_low = 1;
215 break;
216 case DISABLE:
217 feature = ATA_SMART_DISABLE;
218 lba_low = 1;
219 break;
220 case STATUS:
221 // this command only says if SMART is working. It could be
222 // replaced with STATUS_CHECK below.
223 feature = ATA_SMART_STATUS;
224 chk_cond = 1;
225 break;
226 case AUTO_OFFLINE:
227 feature = ATA_SMART_AUTO_OFFLINE;
228 sector_count = select; // YET NOTE - THIS IS A NON-DATA COMMAND!!
229 break;
230 case AUTOSAVE:
231 feature = ATA_SMART_AUTOSAVE;
232 sector_count = select; // YET NOTE - THIS IS A NON-DATA COMMAND!!
233 break;
234 case IMMEDIATE_OFFLINE:
235 feature = ATA_SMART_IMMEDIATE_OFFLINE;
236 lba_low = select;
237 break;
238 case STATUS_CHECK:
239 // This command uses HDIO_DRIVE_TASK and has different syntax than
240 // the other commands.
241 feature = ATA_SMART_STATUS; /* SMART RETURN STATUS */
242 chk_cond = 1;
243 break;
244 default:
245 pout("Unrecognized command %d in sat_command_interface()\n"
246 "Please contact " PACKAGE_BUGREPORT "\n", command);
247 errno=ENOSYS;
248 return -1;
249 }
250 if (ATA_SMART_CMD == ata_command) {
251 lba_mid = 0x4f;
252 lba_high = 0xc2;
253 }
254
255 if ((SAT_ATA_PASSTHROUGH_12LEN == con->satpassthrulen) ||
256 (SAT_ATA_PASSTHROUGH_16LEN == con->satpassthrulen))
257 passthru_size = con->satpassthrulen;
258 cdb[0] = (SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ?
259 SAT_ATA_PASSTHROUGH_12 : SAT_ATA_PASSTHROUGH_16;
260
261 cdb[1] = (protocol << 1) | extend;
262 cdb[2] = (chk_cond << 5) | (t_dir << 3) |
263 (byte_block << 2) | t_length;
264 cdb[(SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ? 3 : 4] = feature;
265 cdb[(SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ? 4 : 6] = sector_count;
266 cdb[(SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ? 5 : 8] = lba_low;
267 cdb[(SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ? 6 : 10] = lba_mid;
268 cdb[(SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ? 7 : 12] = lba_high;
269 cdb[(SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ? 9 : 14] = ata_command;
270
271 memset(&io_hdr, 0, sizeof(io_hdr));
272 if (0 == t_length) {
273 io_hdr.dxfer_dir = DXFER_NONE;
274 io_hdr.dxfer_len = 0;
275 } else if (t_dir) { /* from device */
276 io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
277 io_hdr.dxfer_len = copydata;
278 io_hdr.dxferp = (unsigned char *)data;
279 memset(data, 0, copydata); /* prefill with zeroes */
280 } else { /* to device */
281 io_hdr.dxfer_dir = DXFER_TO_DEVICE;
282 io_hdr.dxfer_len = outlen;
283 io_hdr.dxferp = (unsigned char *)data;
284 }
285 io_hdr.cmnd = cdb;
286 io_hdr.cmnd_len = passthru_size;
287 io_hdr.sensep = sense;
288 io_hdr.max_sense_len = sizeof(sense);
289 io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
290
291 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
292 if (0 != status) {
293 if (con->reportscsiioctl > 0)
294 pout("sat_command_interface: do_scsi_cmnd_io() failed, "
295 "status=%d\n", status);
296 return -1;
297 }
298 if (chk_cond) { /* expecting SAT specific sense data */
299 ucp = NULL;
300 if (sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len,
301 &ssh)) {
302 /* look for SAT extended ATA status return descriptor (9) */
303 ucp = sg_scsi_sense_desc_find(io_hdr.sensep,
304 io_hdr.resp_sense_len, 9);
305 if (ucp) {
306 len = ucp[1] + 2;
307 if (len < 12)
308 len = 12;
309 else if (len > 14)
310 len = 14;
311 if (con->reportscsiioctl > 1) {
312 pout("Values from ATA status return descriptor are:\n");
313 dStrHex((const char *)ucp, len, 1);
314 }
315 if (ATA_CHECK_POWER_MODE == cdb[14])
316 data[0] = ucp[5]; /* sector count (0:7) */
317 else if (STATUS_CHECK == command) {
318 if ((ucp[9] == 0x4f) && (ucp[11] == 0xc2))
319 return 0; /* GOOD smart status */
320 if ((ucp[9] == 0xf4) && (ucp[11] == 0x2c))
321 return 1; // smart predicting failure, "bad" status
322 // We haven't gotten output that makes sense so
323 // print out some debugging info
324 syserror("Error SMART Status command failed");
325 pout("Please get assistance from " PACKAGE_HOMEPAGE "\n");
326 pout("Values from ATA status return descriptor are:\n");
327 dStrHex((const char *)ucp, len, 1);
328 return -1;
329 }
330 }
331 }
332 if (ucp == NULL) {
333 chk_cond = 0; /* not the type of sense data expected */
334 if (t_dir && (t_length > 0))
335 data[0] = 0;
336 }
337 }
338 if (0 == chk_cond) {
339 ucp = NULL;
340 if (sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len,
341 &ssh)) {
342 if ((ssh.response_code >= 0x72) &&
343 ((SCSI_SK_NO_SENSE == ssh.sense_key) ||
344 (SCSI_SK_RECOVERED_ERR == ssh.sense_key)) &&
345 (0 == ssh.asc) &&
346 (SCSI_ASCQ_ATA_PASS_THROUGH == ssh.ascq)) {
347 /* look for SAT extended ATA status return descriptor (9) */
348 ucp = sg_scsi_sense_desc_find(io_hdr.sensep,
349 io_hdr.resp_sense_len, 9);
350 if (ucp) {
351 if (con->reportscsiioctl > 0) {
352 pout("Values from ATA status return descriptor are:\n");
353 len = ucp[1] + 2;
354 if (len < 12)
355 len = 12;
356 else if (len > 14)
357 len = 14;
358 dStrHex((const char *)ucp, len, 1);
359 }
360 return -1;
361 }
362 }
363 scsi_do_sense_disect(&io_hdr, &sinfo);
364 status = scsiSimpleSenseFilter(&sinfo);
365 if (0 != status) {
366 if (con->reportscsiioctl > 0)
367 pout("sat_command_interface: scsi error: %s\n",
368 scsiErrString(status));
369 return -1;
370 }
371 }
372 }
373 return 0;
374 }
375
376 /* Attempt an IDENTIFY DEVICE ATA command via SATL when packet_interface
377 is 0 otherwise attempt IDENTIFY PACKET DEVICE. If successful
378 return 1, else 0 */
379 int has_sat_pass_through(int device, int packet_interface)
380 {
381 char data[512];
382 smart_command_set command;
383
384 command = packet_interface ? PIDENTIFY : IDENTIFY;
385 if (0 == sat_command_interface(device, command, 0, data))
386 return 1;
387 else
388 return 0;
389 }
390
391 /* Next two functions are borrowed from sg_lib.c in the sg3_utils
392 package. Same copyrght owner, same license as this file. */
393 int sg_scsi_normalize_sense(const unsigned char * sensep, int sb_len,
394 struct sg_scsi_sense_hdr * sshp)
395 {
396 if (sshp)
397 memset(sshp, 0, sizeof(struct sg_scsi_sense_hdr));
398 if ((NULL == sensep) || (0 == sb_len) || (0x70 != (0x70 & sensep[0])))
399 return 0;
400 if (sshp) {
401 sshp->response_code = (0x7f & sensep[0]);
402 if (sshp->response_code >= 0x72) { /* descriptor format */
403 if (sb_len > 1)
404 sshp->sense_key = (0xf & sensep[1]);
405 if (sb_len > 2)
406 sshp->asc = sensep[2];
407 if (sb_len > 3)
408 sshp->ascq = sensep[3];
409 if (sb_len > 7)
410 sshp->additional_length = sensep[7];
411 } else { /* fixed format */
412 if (sb_len > 2)
413 sshp->sense_key = (0xf & sensep[2]);
414 if (sb_len > 7) {
415 sb_len = (sb_len < (sensep[7] + 8)) ? sb_len :
416 (sensep[7] + 8);
417 if (sb_len > 12)
418 sshp->asc = sensep[12];
419 if (sb_len > 13)
420 sshp->ascq = sensep[13];
421 }
422 }
423 }
424 return 1;
425 }
426
427
428 const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep,
429 int sense_len, int desc_type)
430 {
431 int add_sen_len, add_len, desc_len, k;
432 const unsigned char * descp;
433
434 if ((sense_len < 8) || (0 == (add_sen_len = sensep[7])))
435 return NULL;
436 if ((sensep[0] < 0x72) || (sensep[0] > 0x73))
437 return NULL;
438 add_sen_len = (add_sen_len < (sense_len - 8)) ?
439 add_sen_len : (sense_len - 8);
440 descp = &sensep[8];
441 for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) {
442 descp += desc_len;
443 add_len = (k < (add_sen_len - 1)) ? descp[1]: -1;
444 desc_len = add_len + 2;
445 if (descp[0] == desc_type)
446 return descp;
447 if (add_len < 0) /* short descriptor ?? */
448 break;
449 }
450 return NULL;
451 }