]> git.proxmox.com Git - mirror_smartmontools-debian.git/blame - scsiata.cpp
bump standards version
[mirror_smartmontools-debian.git] / scsiata.cpp
CommitLineData
4d59bff9
GG
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
1953ff6d 48const char *scsiata_c_cvsid="$Id: scsiata.cpp,v 1.8 2007/12/03 02:14:20 dpgilbert Exp $"
4d59bff9
GG
49CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSICMDS_H_CVSID SCSIATA_H_CVSID UTILITY_H_CVSID;
50
51/* for passing global control variables */
52extern smartmonctrl *con;
53
54#define DEF_SAT_ATA_PASSTHRU_SIZE 16
1953ff6d 55#define ATA_RETURN_DESCRIPTOR 9
4d59bff9
GG
56
57
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)
71// cdb[13]: device
72// cdb[14]: (ata) command
73// cdb[15]: control (SCSI, leave as zero)
74//
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]
77//
78//
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)
87// cdb[8]: device
88// cdb[9]: (ata) command
89// cdb[10]: reserved
90// cdb[11]: control (SCSI, leave as zero)
91//
92//
1953ff6d 93// ATA Return Descriptor (component of descriptor sense data)
4d59bff9
GG
94// des[0]: descriptor code (0x9)
95// des[1]: additional descriptor length (0xc)
96// des[2]: extend (bit 0)
97// des[3]: error
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)
106// des[12]: device
107// des[13]: status
108
109
110
111// PURPOSE
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
120// self-test).
121// data: location to write output data, if needed (512 bytes).
122// Note: not all commands use all arguments.
123// RETURN VALUES
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"
130
131int sat_command_interface(int device, smart_command_set command, int select,
132 char *data)
133{
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];
1953ff6d
GG
139 const unsigned char * ardp;
140 int status, ard_len, have_sense;
4d59bff9
GG
141 int copydata = 0;
142 int outlen = 0;
143 int extend = 0;
1953ff6d 144 int ck_cond = 0; /* set to 1 to read register(s) back */
4d59bff9
GG
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 */
149 int feature = 0;
150 int ata_command = 0;
151 int sector_count = 0;
152 int lba_low = 0;
153 int lba_mid = 0;
154 int lba_high = 0;
155 int passthru_size = DEF_SAT_ATA_PASSTHRU_SIZE;
156
157 memset(cdb, 0, sizeof(cdb));
158 memset(sense, 0, sizeof(sense));
159
160 ata_command = ATA_SMART_CMD;
161 switch (command) {
162 case CHECK_POWER_MODE:
163 ata_command = ATA_CHECK_POWER_MODE;
1953ff6d 164 ck_cond = 1;
4d59bff9
GG
165 copydata = 1;
166 break;
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 */
172 copydata = 512;
173 break;
174 case READ_THRESHOLDS: /* obsolete */
175 feature = ATA_SMART_READ_THRESHOLDS;
176 sector_count = 1; /* one (512 byte) block */
177 lba_low = 1;
178 protocol = 4; /* PIO data-in */
179 t_length = 2; /* sector count holds count */
180 copydata=512;
181 break;
182 case READ_LOG:
183 feature = ATA_SMART_READ_LOG_SECTOR;
184 sector_count = 1; /* one (512 byte) block */
185 lba_low = select;
186 protocol = 4; /* PIO data-in */
187 t_length = 2; /* sector count holds count */
188 copydata = 512;
189 break;
190 case WRITE_LOG:
191 feature = ATA_SMART_WRITE_LOG_SECTOR;
192 sector_count = 1; /* one (512 byte) block */
193 lba_low = select;
194 protocol = 5; /* PIO data-out */
195 t_length = 2; /* sector count holds count */
196 t_dir = 0; /* to device */
197 outlen = 512;
198 break;
199 case IDENTIFY:
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 */
204 copydata = 512;
205 break;
206 case PIDENTIFY:
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 */
211 copydata = 512;
212 break;
213 case ENABLE:
214 feature = ATA_SMART_ENABLE;
215 lba_low = 1;
216 break;
217 case DISABLE:
218 feature = ATA_SMART_DISABLE;
219 lba_low = 1;
220 break;
221 case STATUS:
222 // this command only says if SMART is working. It could be
223 // replaced with STATUS_CHECK below.
224 feature = ATA_SMART_STATUS;
1953ff6d 225 ck_cond = 1;
4d59bff9
GG
226 break;
227 case AUTO_OFFLINE:
228 feature = ATA_SMART_AUTO_OFFLINE;
229 sector_count = select; // YET NOTE - THIS IS A NON-DATA COMMAND!!
230 break;
231 case AUTOSAVE:
232 feature = ATA_SMART_AUTOSAVE;
233 sector_count = select; // YET NOTE - THIS IS A NON-DATA COMMAND!!
234 break;
235 case IMMEDIATE_OFFLINE:
236 feature = ATA_SMART_IMMEDIATE_OFFLINE;
237 lba_low = select;
238 break;
239 case STATUS_CHECK:
240 // This command uses HDIO_DRIVE_TASK and has different syntax than
241 // the other commands.
242 feature = ATA_SMART_STATUS; /* SMART RETURN STATUS */
1953ff6d 243 ck_cond = 1;
4d59bff9
GG
244 break;
245 default:
246 pout("Unrecognized command %d in sat_command_interface()\n"
247 "Please contact " PACKAGE_BUGREPORT "\n", command);
248 errno=ENOSYS;
249 return -1;
250 }
251 if (ATA_SMART_CMD == ata_command) {
252 lba_mid = 0x4f;
253 lba_high = 0xc2;
254 }
255
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;
261
262 cdb[1] = (protocol << 1) | extend;
1953ff6d 263 cdb[2] = (ck_cond << 5) | (t_dir << 3) |
4d59bff9
GG
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;
271
272 memset(&io_hdr, 0, sizeof(io_hdr));
273 if (0 == t_length) {
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;
285 }
286 io_hdr.cmnd = cdb;
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;
291
292 status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
293 if (0 != status) {
294 if (con->reportscsiioctl > 0)
295 pout("sat_command_interface: do_scsi_cmnd_io() failed, "
296 "status=%d\n", status);
297 return -1;
298 }
1953ff6d
GG
299 ardp = NULL;
300 ard_len = 0;
301 have_sense = sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len,
302 &ssh);
303 if (have_sense) {
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);
308 if (ardp) {
309 ard_len = ardp[1] + 2;
310 if (ard_len < 12)
311 ard_len = 12;
312 else if (ard_len > 14)
313 ard_len = 14;
314 }
315 scsi_do_sense_disect(&io_hdr, &sinfo);
316 status = scsiSimpleSenseFilter(&sinfo);
317 if (0 != status) {
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);
324 }
325 }
326 if (t_dir && (t_length > 0) && (copydata > 0))
327 memset(data, 0, copydata);
328 return -1;
329 }
330 }
331 if (ck_cond) { /* expecting SAT specific sense data */
332 if (have_sense) {
333 if (ardp) {
4d59bff9 334 if (con->reportscsiioctl > 1) {
1953ff6d
GG
335 pout("Values from ATA Return Descriptor are:\n");
336 dStrHex((const char *)ardp, ard_len, 1);
4d59bff9 337 }
1953ff6d
GG
338 if (ATA_CHECK_POWER_MODE == ata_command)
339 data[0] = ardp[5]; /* sector count (0:7) */
4d59bff9 340 else if (STATUS_CHECK == command) {
1953ff6d 341 if ((ardp[9] == 0x4f) && (ardp[11] == 0xc2))
4d59bff9 342 return 0; /* GOOD smart status */
1953ff6d 343 if ((ardp[9] == 0xf4) && (ardp[11] == 0x2c))
4d59bff9
GG
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");
1953ff6d
GG
349 pout("Values from ATA Return Descriptor are:\n");
350 dStrHex((const char *)ardp, ard_len, 1);
4d59bff9
GG
351 return -1;
352 }
353 }
354 }
1953ff6d
GG
355 if (ardp == NULL)
356 ck_cond = 0; /* not the type of sense data expected */
4d59bff9 357 }
1953ff6d
GG
358 if (0 == ck_cond) {
359 if (have_sense) {
4d59bff9
GG
360 if ((ssh.response_code >= 0x72) &&
361 ((SCSI_SK_NO_SENSE == ssh.sense_key) ||
362 (SCSI_SK_RECOVERED_ERR == ssh.sense_key)) &&
363 (0 == ssh.asc) &&
364 (SCSI_ASCQ_ATA_PASS_THROUGH == ssh.ascq)) {
1953ff6d 365 if (ardp) {
4d59bff9 366 if (con->reportscsiioctl > 0) {
1953ff6d
GG
367 pout("Values from ATA Return Descriptor are:\n");
368 dStrHex((const char *)ardp, ard_len, 1);
4d59bff9
GG
369 }
370 return -1;
371 }
372 }
4d59bff9
GG
373 }
374 }
375 return 0;
376}
377
378/* Attempt an IDENTIFY DEVICE ATA command via SATL when packet_interface
379 is 0 otherwise attempt IDENTIFY PACKET DEVICE. If successful
380 return 1, else 0 */
381int has_sat_pass_through(int device, int packet_interface)
382{
383 char data[512];
384 smart_command_set command;
385
386 command = packet_interface ? PIDENTIFY : IDENTIFY;
387 if (0 == sat_command_interface(device, command, 0, data))
388 return 1;
389 else
390 return 0;
391}
392
393/* Next two functions are borrowed from sg_lib.c in the sg3_utils
394 package. Same copyrght owner, same license as this file. */
395int sg_scsi_normalize_sense(const unsigned char * sensep, int sb_len,
396 struct sg_scsi_sense_hdr * sshp)
397{
398 if (sshp)
399 memset(sshp, 0, sizeof(struct sg_scsi_sense_hdr));
400 if ((NULL == sensep) || (0 == sb_len) || (0x70 != (0x70 & sensep[0])))
401 return 0;
402 if (sshp) {
403 sshp->response_code = (0x7f & sensep[0]);
404 if (sshp->response_code >= 0x72) { /* descriptor format */
405 if (sb_len > 1)
406 sshp->sense_key = (0xf & sensep[1]);
407 if (sb_len > 2)
408 sshp->asc = sensep[2];
409 if (sb_len > 3)
410 sshp->ascq = sensep[3];
411 if (sb_len > 7)
412 sshp->additional_length = sensep[7];
413 } else { /* fixed format */
414 if (sb_len > 2)
415 sshp->sense_key = (0xf & sensep[2]);
416 if (sb_len > 7) {
417 sb_len = (sb_len < (sensep[7] + 8)) ? sb_len :
418 (sensep[7] + 8);
419 if (sb_len > 12)
420 sshp->asc = sensep[12];
421 if (sb_len > 13)
422 sshp->ascq = sensep[13];
423 }
424 }
425 }
426 return 1;
427}
428
429
430const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep,
431 int sense_len, int desc_type)
432{
433 int add_sen_len, add_len, desc_len, k;
434 const unsigned char * descp;
435
436 if ((sense_len < 8) || (0 == (add_sen_len = sensep[7])))
437 return NULL;
438 if ((sensep[0] < 0x72) || (sensep[0] > 0x73))
439 return NULL;
440 add_sen_len = (add_sen_len < (sense_len - 8)) ?
441 add_sen_len : (sense_len - 8);
442 descp = &sensep[8];
443 for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) {
444 descp += 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)
448 return descp;
449 if (add_len < 0) /* short descriptor ?? */
450 break;
451 }
452 return NULL;
453}