]> git.proxmox.com Git - mirror_smartmontools-debian.git/blob - os_qnxnto.cpp
Updated changelog
[mirror_smartmontools-debian.git] / os_qnxnto.cpp
1
2
3 // This is needed for the various HAVE_* macros and PROJECT_* macros.
4 #include "config.h"
5
6 // These are needed to define prototypes and structures for the
7 // functions defined below
8 #include "int64.h"
9 #include "atacmds.h"
10 #include "scsicmds.h"
11 #include "utility.h"
12
13 // This is to include whatever structures and prototypes you define in
14 // os_generic.h
15 #include "os_qnxnto.h"
16
17 // Needed by '-V' option (CVS versioning) of smartd/smartctl. You
18 // should have one *_H_CVSID macro appearing below for each file
19 // appearing with #include "*.h" above. Please list these (below) in
20 // alphabetic/dictionary order.
21 const char *os_XXXX_c_cvsid="$Id: os_qnxnto.cpp 3191 2010-10-27 19:55:33Z chrfranke $" \
22 ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_QNXNTO_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
23
24
25 // This is here to prevent compiler warnings for unused arguments of
26 // functions.
27 #define ARGUSED(x) ((void)(x))
28
29 // Please eliminate the following block: both the #include and
30 // the 'unsupported()' function. They are only here to warn
31 // unsuspecting users that their Operating System is not supported! If
32 // you wish, you can use a similar warning mechanism for any of the
33 // functions in this file that you can not (or choose not to)
34 // implement.
35
36
37 #ifdef HAVE_UNAME
38 #include <sys/utsname.h>
39 #endif
40 //----------------------------------------------------------------------------------------------
41 // private Functions
42 static int ata_sense_data(void *sdata,int *error,int *key,int *asc,int *ascq);
43 static int ata_interpret_sense(struct cam_pass_thru *cpt,void *sense,int *status,int rcount);
44 static int ata_pass_thru(int fd,struct cam_pass_thru *pcpt);
45 //----------------------------------------------------------------------------------------------
46 static void unsupported(){
47 static int warninggiven;
48
49 if (!warninggiven) {
50 char *osname;
51
52 #ifdef HAVE_UNAME
53 struct utsname ostype;
54 uname(&ostype);
55 osname=ostype.sysname;
56 #else
57 osname="host's";
58 #endif
59
60 pout("\n"
61 "############################################################################\n"
62 "WARNING: smartmontools has not been ported to the %s Operating System.\n"
63 "Please see the files os_generic.cpp and os_generic.h for porting instructions.\n"
64 "############################################################################\n\n",
65 osname);
66 warninggiven=1;
67 }
68
69 return;
70 }
71 // End of the 'unsupported()' block that you should eliminate.
72
73
74 // print examples for smartctl. You should modify this function so
75 // that the device paths are sensible for your OS, and to eliminate
76 // unsupported commands (eg, 3ware controllers).
77 void print_smartctl_examples(){
78 printf("=================================================== SMARTCTL EXAMPLES =====\n\n");
79 #ifdef HAVE_GETOPT_LONG
80 printf(
81 " smartctl -a /dev/hd0 (Prints all SMART information)\n\n"
82 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/hd0\n"
83 " (Enables SMART on first disk)\n\n"
84 " smartctl -t long /dev/hd0 (Executes extended disk self-test)\n\n"
85 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/hd0\n"
86 " (Prints Self-Test & Attribute errors)\n"
87 " smartctl -a --device=3ware,2 /dev/sda\n"
88 " (Prints all SMART info for 3rd ATA disk on 3ware RAID controller)\n"
89 );
90 #else
91 printf(
92 " smartctl -a /dev/hd0 (Prints all SMART information)\n"
93 " smartctl -s on -o on -S on /dev/hd0 (Enables SMART on first disk)\n"
94 " smartctl -t long /dev/hd0 (Executes extended disk self-test)\n"
95 " smartctl -A -l selftest -q errorsonly /dev/hd0\n"
96 " (Prints Self-Test & Attribute errors)\n"
97 " smartctl -a -d 3ware,2 /dev/sda\n"
98 " (Prints all SMART info for 3rd ATA disk on 3ware RAID controller)\n"
99 );
100 #endif
101 return;
102 }
103
104 // tries to guess device type given the name (a path). See utility.h
105 // for return values.
106 static const char *net_dev_prefix = "/dev/";
107 static const char *net_dev_ata_disk = "hd";
108
109 int guess_device_type (const char* dev_name)
110 {
111 int len,dev_prefix_len;
112 dev_prefix_len=strlen(net_dev_prefix);
113 if(!dev_name||!(len=strlen(dev_name)))
114 return(CONTROLLER_UNKNOWN);
115 if (!strncmp(net_dev_prefix,dev_name,dev_prefix_len))
116 {
117 if(len<=dev_prefix_len)
118 return(CONTROLLER_UNKNOWN);
119 else
120 dev_name += dev_prefix_len;
121 }
122 if(!strncmp(net_dev_ata_disk,dev_name,strlen(net_dev_ata_disk)))
123 return(CONTROLLER_ATA);
124 return(CONTROLLER_UNKNOWN);
125 }
126
127 // makes a list of ATA or SCSI devices for the DEVICESCAN directive of
128 // smartd. Returns number N of devices, or -1 if out of
129 // memory. Allocates N+1 arrays: one of N pointers (devlist); the
130 // other N arrays each contain null-terminated character strings. In
131 // the case N==0, no arrays are allocated because the array of 0
132 // pointers has zero length, equivalent to calling malloc(0).
133 int make_device_names (char*** devlist, const char* name) {
134 ARGUSED(devlist);
135 ARGUSED(name);
136 unsupported();
137 return 0;
138 }
139
140 // Like open(). Return non-negative integer handle, only used by the
141 // functions below. type=="ATA" or "SCSI". If you need to store
142 // extra information about your devices, create a private internal
143 // array within this file (see os_freebsd.cpp for an example). If you
144 // can not open the device (permission denied, does not exist, etc)
145 // set errno as open() does and return <0.
146 int deviceopen(const char *pathname, char *type)
147 {
148 if(!strcmp(type, "ATA"))
149 return(open(pathname,O_RDWR|O_NONBLOCK));
150 else
151 return(-1);
152 }
153
154 // Like close(). Acts only on integer handles returned by
155 // deviceopen() above.
156 int deviceclose(int fd)
157 {
158 return(close(fd));
159 }
160 //----------------------------------------------------------------------------------------------
161 // Interface to ATA devices. See os_linux.cpp for the cannonical example.
162 // DETAILED DESCRIPTION OF ARGUMENTS
163 // device: is the integer handle provided by deviceopen()
164 // command: defines the different operations, see atacmds.h
165 // select: additional input data IF NEEDED (which log, which type of
166 // self-test).
167 // data: location to write output data, IF NEEDED (1 or 512 bytes).
168 // Note: not all commands use all arguments.
169 // RETURN VALUES (for all commands BUT command==STATUS_CHECK)
170 // -1 if the command failed
171 // 0 if the command succeeded,
172 // RETURN VALUES if command==STATUS_CHECK
173 // -1 if the command failed OR the disk SMART status can't be determined
174 // 0 if the command succeeded and disk SMART status is "OK"
175 // 1 if the command succeeded and disk SMART status is "FAILING"
176 int ata_command_interface(int fd,smart_command_set command,int select,char *data)
177 {
178 struct cam_pass_thru cpt;
179 ATA_SENSE sense;
180 CDB *cdb;
181 int status,rc;
182 memset(&cpt,0x00,sizeof(struct cam_pass_thru));
183 cdb=(CDB *)cpt.cam_cdb;
184 rc=-1;
185 switch(command)
186 {
187 case READ_VALUES:
188 cpt.cam_flags = CAM_DIR_IN;
189 cpt.cam_cdb_len = 16;
190 cpt.cam_dxfer_len = 512;
191 cpt.cam_data_ptr = (uint32_t)data;
192 cpt.cam_sense_len = sizeof(sense);
193 cpt.cam_sense_ptr = (uint32_t)&sense;
194 cdb->ata_pass_thru.opcode = SC_ATA_PT16;
195 cdb->ata_pass_thru.protocol = ATA_PROTO_PIO_DATA_IN;
196 cdb->ata_pass_thru.flags = ATA_FLG_T_DIR|ATA_FLG_TLEN_STPSIU;
197 cdb->ata_pass_thru.command = ATA_SMART_CMD;
198 cdb->ata_pass_thru.features = ATA_SMART_READ_VALUES;
199 cdb->ata_pass_thru.lba_mid = ATA_SMART_LBA_MID_SIG;
200 cdb->ata_pass_thru.lba_high = ATA_SMART_LBA_HI_SIG;
201 break;
202 case READ_THRESHOLDS:
203 cpt.cam_flags = CAM_DIR_IN;
204 cpt.cam_cdb_len = 16;
205 cpt.cam_dxfer_len = 512;
206 cpt.cam_data_ptr = (uint32_t)data;
207 cpt.cam_sense_len = sizeof(sense);
208 cpt.cam_sense_ptr = (uint32_t)&sense;
209 cdb->ata_pass_thru.opcode = SC_ATA_PT16;
210 cdb->ata_pass_thru.protocol = ATA_PROTO_PIO_DATA_IN;
211 cdb->ata_pass_thru.flags = ATA_FLG_T_DIR|ATA_FLG_TLEN_STPSIU;
212 cdb->ata_pass_thru.command = ATA_SMART_CMD;
213 cdb->ata_pass_thru.features = ATA_SMART_READ_THRESHOLDS;
214 cdb->ata_pass_thru.lba_mid = ATA_SMART_LBA_MID_SIG;
215 cdb->ata_pass_thru.lba_high = ATA_SMART_LBA_HI_SIG;
216 break;
217 case READ_LOG:
218 cpt.cam_flags = CAM_DIR_IN;
219 cpt.cam_cdb_len = 16;
220 cpt.cam_dxfer_len = 512;
221 cpt.cam_data_ptr = (uint32_t)data;
222 cpt.cam_sense_len = sizeof(sense);
223 cpt.cam_sense_ptr = (uint32_t)&sense;
224 cdb->ata_pass_thru.opcode = SC_ATA_PT16;
225 cdb->ata_pass_thru.protocol = ATA_PROTO_PIO_DATA_IN;
226 cdb->ata_pass_thru.flags = ATA_FLG_T_DIR|ATA_FLG_TLEN_STPSIU;
227 cdb->ata_pass_thru.command = ATA_SMART_CMD;
228 cdb->ata_pass_thru.features = ATA_SMART_READ_LOG_SECTOR;
229 cdb->ata_pass_thru.sector_count= 1;
230 cdb->ata_pass_thru.lba_low = select;
231 cdb->ata_pass_thru.lba_mid = ATA_SMART_LBA_MID_SIG;
232 cdb->ata_pass_thru.lba_high = ATA_SMART_LBA_HI_SIG;
233 break;
234 case WRITE_LOG:
235 return(-1);
236 break;
237 case IDENTIFY:
238 cpt.cam_flags = CAM_DIR_IN;
239 cpt.cam_cdb_len = 16;
240 cpt.cam_dxfer_len = 512;
241 cpt.cam_data_ptr = (uint32_t)data;
242 cpt.cam_sense_len = sizeof(sense);
243 cpt.cam_sense_ptr = (uint32_t)&sense;
244 cdb->ata_pass_thru.opcode = SC_ATA_PT16;
245 cdb->ata_pass_thru.protocol = ATA_PROTO_PIO_DATA_IN;
246 cdb->ata_pass_thru.flags = ATA_FLG_T_DIR|ATA_FLG_TLEN_STPSIU;
247 cdb->ata_pass_thru.command = ATA_IDENTIFY_DEVICE;
248 break;
249 case PIDENTIFY:
250 cpt.cam_flags = CAM_DIR_IN;
251 cpt.cam_cdb_len = 16;
252 cpt.cam_dxfer_len = 512;
253 cpt.cam_data_ptr = (uint32_t)data;
254 cpt.cam_sense_len = sizeof(sense);
255 cpt.cam_sense_ptr = (uint32_t)&sense;
256 cdb->ata_pass_thru.opcode = SC_ATA_PT16;
257 cdb->ata_pass_thru.protocol = ATA_PROTO_PIO_DATA_IN;
258 cdb->ata_pass_thru.flags = ATA_FLG_T_DIR|ATA_FLG_TLEN_STPSIU;
259 cdb->ata_pass_thru.command = ATA_IDENTIFY_PACKET_DEVICE;
260 break;
261 case ENABLE:
262 cpt.cam_flags = CAM_DIR_NONE;
263 cpt.cam_cdb_len = 16;
264 cpt.cam_sense_len = sizeof(sense);
265 cpt.cam_sense_ptr = (uint32_t)&sense;
266 cdb->ata_pass_thru.opcode = SC_ATA_PT16;
267 cdb->ata_pass_thru.protocol = ATA_PROTO_DATA_NONE;
268 cdb->ata_pass_thru.command = ATA_SMART_CMD;
269 cdb->ata_pass_thru.features = ATA_SMART_ENABLE;
270 cdb->ata_pass_thru.lba_mid = ATA_SMART_LBA_MID_SIG;
271 cdb->ata_pass_thru.lba_high = ATA_SMART_LBA_HI_SIG;
272 break;
273 case DISABLE:
274 cpt.cam_flags = CAM_DIR_NONE;
275 cpt.cam_cdb_len = 16;
276 cpt.cam_sense_len = sizeof(sense);
277 cpt.cam_sense_ptr = (uint32_t)&sense;
278 cdb->ata_pass_thru.opcode = SC_ATA_PT16;
279 cdb->ata_pass_thru.protocol = ATA_PROTO_DATA_NONE;
280 cdb->ata_pass_thru.command = ATA_SMART_CMD;
281 cdb->ata_pass_thru.features = ATA_SMART_DISABLE;
282 cdb->ata_pass_thru.lba_mid = ATA_SMART_LBA_MID_SIG;
283 cdb->ata_pass_thru.lba_high = ATA_SMART_LBA_HI_SIG;
284 break;
285 case AUTO_OFFLINE:
286 // NOTE: According to ATAPI 4 and UP, this command is obsolete
287 cpt.cam_flags = CAM_DIR_NONE;
288 cpt.cam_cdb_len = 16;
289 cpt.cam_sense_len = sizeof(sense);
290 cpt.cam_sense_ptr = (uint32_t)&sense;
291 cdb->ata_pass_thru.opcode = SC_ATA_PT16;
292 cdb->ata_pass_thru.protocol = ATA_PROTO_DATA_NONE;
293 cdb->ata_pass_thru.command = ATA_SMART_CMD;
294 cdb->ata_pass_thru.features = ATA_SMART_AUTO_OFFLINE;
295 cdb->ata_pass_thru.lba_low = select;
296 cdb->ata_pass_thru.lba_mid = ATA_SMART_LBA_MID_SIG;
297 cdb->ata_pass_thru.lba_high = ATA_SMART_LBA_HI_SIG;
298 break;
299 case AUTOSAVE:
300 cpt.cam_flags = CAM_DIR_NONE;
301 cpt.cam_cdb_len = 16;
302 cpt.cam_sense_len = sizeof(sense);
303 cpt.cam_sense_ptr = (uint32_t)&sense;
304 cdb->ata_pass_thru.opcode = SC_ATA_PT16;
305 cdb->ata_pass_thru.protocol = ATA_PROTO_DATA_NONE;
306 cdb->ata_pass_thru.command = ATA_SMART_CMD;
307 cdb->ata_pass_thru.features = ATA_SMART_AUTOSAVE;
308 cdb->ata_pass_thru.sector_count= select;
309 cdb->ata_pass_thru.lba_mid = ATA_SMART_LBA_MID_SIG;
310 cdb->ata_pass_thru.lba_high = ATA_SMART_LBA_HI_SIG;
311 break;
312 case IMMEDIATE_OFFLINE:
313 // NOTE: According to ATAPI 4 and UP, this command is obsolete
314 cpt.cam_flags = CAM_DIR_NONE;
315 cpt.cam_cdb_len = 16;
316 cpt.cam_sense_len = sizeof(sense);
317 cpt.cam_sense_ptr = (uint32_t)&sense;
318 cdb->ata_pass_thru.opcode = SC_ATA_PT16;
319 cdb->ata_pass_thru.protocol = ATA_PROTO_DATA_NONE;
320 cdb->ata_pass_thru.command = ATA_SMART_CMD;
321 cdb->ata_pass_thru.features = ATA_SMART_IMMEDIATE_OFFLINE;
322 cdb->ata_pass_thru.lba_low = select;
323 cdb->ata_pass_thru.lba_mid = ATA_SMART_LBA_MID_SIG;
324 cdb->ata_pass_thru.lba_high = ATA_SMART_LBA_HI_SIG;
325 break;
326 case STATUS_CHECK:
327 // same command, no HDIO in NetBSD
328 case STATUS:
329 cpt.cam_flags = CAM_DIR_NONE;
330 cpt.cam_cdb_len = 16;
331 cpt.cam_sense_len = sizeof(sense);
332 cpt.cam_sense_ptr = (uint32_t)&sense;
333 cdb->ata_pass_thru.opcode = SC_ATA_PT16;
334 cdb->ata_pass_thru.protocol = ATA_PROTO_DATA_NONE;
335 cdb->ata_pass_thru.flags = ATA_FLG_CK_COND;
336 cdb->ata_pass_thru.command = ATA_SMART_CMD;
337 cdb->ata_pass_thru.features = ATA_SMART_STATUS;
338 cdb->ata_pass_thru.lba_mid = ATA_SMART_LBA_MID_SIG;
339 cdb->ata_pass_thru.lba_high = ATA_SMART_LBA_HI_SIG;
340 break;
341 case CHECK_POWER_MODE:
342 cpt.cam_flags = CAM_DIR_NONE;
343 cpt.cam_cdb_len = 16;
344 cpt.cam_sense_len = sizeof(sense);
345 cpt.cam_sense_ptr = (uint32_t)&sense;
346 cdb->ata_pass_thru.opcode = SC_ATA_PT16;
347 cdb->ata_pass_thru.protocol = ATA_PROTO_DATA_NONE;
348 cdb->ata_pass_thru.flags = ATA_FLG_CK_COND;
349 cdb->ata_pass_thru.command = ATA_CHECK_POWER_MODE;
350 break;
351 default:
352 pout("Unrecognized command %d in ata_command_interface()\n", command);
353 errno=ENOSYS;
354 return(-1);
355 }
356 // execute now
357 if((status=ata_pass_thru(fd,&cpt))==EOK)
358 {
359 rc=status==EOK?0:-1;
360 if(cpt.cam_status!=CAM_REQ_CMP)
361 {
362 ata_interpret_sense(&cpt,&sense,&status,0);
363 if(command==STATUS||command==STATUS_CHECK)
364 rc=((sense.desc.lba_high<<8)|sense.desc.lba_mid)==ATA_SMART_SIG?0:1;
365 }
366 }
367 if(command==CHECK_POWER_MODE)
368 data[0]=cdb->ata_pass_thru.sector_count;
369 // finish
370 return(rc);
371 }
372 //----------------------------------------------------------------------------------------------
373 int marvell_command_interface(int fd, smart_command_set command, int select, char *data)
374 {
375 ARGUSED(fd);
376 ARGUSED(command);
377 ARGUSED(select);
378 ARGUSED(data);
379 unsupported();
380 return -1;
381 }
382 //----------------------------------------------------------------------------------------------
383 int highpoint_command_interface(int fd, smart_command_set command, int select, char *data)
384 {
385 ARGUSED(fd);
386 ARGUSED(command);
387 ARGUSED(select);
388 ARGUSED(data);
389 unsupported();
390 return -1;
391 }
392 //----------------------------------------------------------------------------------------------
393 // Interface to ATA devices behind 3ware escalade/apache RAID
394 // controller cards. Same description as ata_command_interface()
395 // above except that 0 <= disknum <= 15 specifies the ATA disk
396 // attached to the controller, and controller_type specifies the
397 // precise type of 3ware controller. See os_linux.c
398 int escalade_command_interface(int fd,int disknum,int controller_type,smart_command_set command,int select,char *data)
399 {
400 ARGUSED(fd);
401 ARGUSED(disknum);
402 ARGUSED(controller_type);
403 ARGUSED(command);
404 ARGUSED(select);
405 ARGUSED(data);
406
407 unsupported();
408 return -1;
409 }
410
411 int areca_command_interface(int fd,int disknum,smart_command_set command,int select,char *data)
412 {
413 ARGUSED(fd);
414 ARGUSED(disknum);
415 ARGUSED(command);
416 ARGUSED(select);
417 ARGUSED(data);
418
419 unsupported();
420 return -1;
421 }
422 //----------------------------------------------------------------------------------------------
423 #include <errno.h>
424 // Interface to SCSI devices. See os_linux.c
425 int do_scsi_cmnd_io(int fd,struct scsi_cmnd_io * iop,int report)
426 {
427 ARGUSED(fd);
428 ARGUSED(iop);
429 ARGUSED(report);
430 unsupported();
431 return -ENOSYS;
432 }
433 //----------------------------------------------------------------------------------------------
434 //----------------------------------------------------------------------------------------------
435 static int ata_sense_data(void *sdata,int *error,int *key,int *asc,int *ascq)
436 {
437 SCSI_SENSE *sf;
438 SCSI_SENSE_DESCRIPTOR *sd;
439 sf=(SCSI_SENSE *)sdata;
440 sd=(SCSI_SENSE_DESCRIPTOR *)sdata;
441 *error=sf->error;
442 if(*error & SENSE_DATA_FMT_DESCRIPTOR)
443 {
444 *key=sd->sense & SK_MSK;
445 *asc=sd->asc;
446 *ascq=sd->ascq;
447 }
448 else
449 {
450 *key=sf->sense & SK_MSK;
451 *asc=sf->asc;
452 *ascq=sf->ascq;
453 }
454 return(CAM_SUCCESS);
455 }
456 //----------------------------------------------------------------------------------------------
457 static int ata_interpret_sense(struct cam_pass_thru *cpt,void *sense,int *status,int rcount)
458 {
459 int retry;
460 int key;
461 int asc;
462 int ascq;
463 int error;
464 *status=EIO;
465 retry=CAM_TRUE;
466 if(cpt->cam_status&CAM_AUTOSNS_VALID)
467 {
468 ata_sense_data(sense,&error,&key,&asc,&ascq);
469 switch(key)
470 {
471 case SK_NO_SENSE: // No sense data (no error)
472 retry=CAM_FALSE;
473 *status=EOK;
474 break;
475 case SK_RECOVERED: // Recovered error
476 switch(asc)
477 {
478 case ASC_ATA_PASS_THRU:
479 switch(ascq)
480 {
481 case ASCQ_ATA_PASS_THRU_INFO_AVAIL:
482 break;
483 default:
484 break;
485 }
486 break;
487 default:
488 break;
489 }
490 retry=CAM_FALSE;
491 *status=EOK;
492 break;
493 case SK_NOT_RDY: // Device not ready
494 *status=EAGAIN;
495 switch(asc)
496 {
497 case ASC_NOT_READY:
498 switch(ascq)
499 {
500 case ASCQ_BECOMING_READY:
501 case ASCQ_CAUSE_NOT_REPORTABLE:
502 default:
503 retry=CAM_FALSE;
504 break;
505 }
506 break;
507 case ASC_MEDIA_NOT_PRESENT:
508 *status=ENXIO;
509 retry=CAM_FALSE;
510 break;
511 }
512 break;
513 case SK_MEDIUM: // Medium error
514 case SK_HARDWARE: // Hardware error
515 retry=CAM_FALSE;
516 *status=EIO;
517 break;
518 case SK_ILLEGAL: // Illegal Request (bad command)
519 retry=CAM_FALSE;
520 *status=EINVAL;
521 break;
522 case SK_UNIT_ATN: // Unit Attention
523 switch(asc)
524 {
525 case ASC_MEDIUM_CHANGED:
526 *status=ESTALE;
527 retry=CAM_FALSE;
528 break;
529 case ASC_BUS_RESET:
530 break;
531 }
532 break;
533 case SK_DATA_PROT: // Data Protect
534 retry=CAM_FALSE;
535 *status=EROFS;
536 break;
537 case SK_VENDOR: // Vendor Specific
538 case SK_CPY_ABORT: // Copy Aborted
539 retry=CAM_FALSE;
540 *status=EIO;
541 break;
542 case SK_CMD_ABORT: // Aborted Command
543 retry=CAM_FALSE;
544 *status=ECANCELED;
545 break;
546 case SK_EQUAL: // Equal
547 case SK_VOL_OFL: // Volume Overflow
548 case SK_MISCMP: // Miscompare
549 case SK_RESERVED: // Reserved
550 break;
551 }
552 if(*status==EOK)
553 {
554 switch(cpt->cam_status&CAM_STATUS_MASK)
555 {
556 case CAM_REQ_CMP_ERR: // CCB request completed with an err
557 retry=CAM_FALSE;
558 *status=EIO;
559 break;
560 case CAM_BUSY: // CAM subsystem is busy
561 *status=EAGAIN;
562 break;
563 case CAM_REQ_INVALID: // CCB request is invalid
564 case CAM_PATH_INVALID: // Path ID supplied is invalid
565 case CAM_DEV_NOT_THERE: // SCSI device not installed/there
566 case CAM_SEL_TIMEOUT: // Target selection timeout
567 case CAM_LUN_INVALID: // LUN supplied is invalid
568 case CAM_TID_INVALID: // Target ID supplied is invalid
569 retry=CAM_FALSE;
570 *status=ENXIO;
571 break;
572 case CAM_CMD_TIMEOUT: // Command timeout
573 *status=rcount?EAGAIN:EIO;
574 break;
575 case CAM_MSG_REJECT_REC: // Message reject received
576 case CAM_SCSI_BUS_RESET: // SCSI bus reset sent/received
577 case CAM_UNCOR_PARITY: // Uncorrectable parity err occurred
578 case CAM_AUTOSENSE_FAIL: // Autosense: Request sense cmd fail
579 case CAM_NO_HBA: // No HBA detected Error
580 case CAM_DATA_RUN_ERR: // Data overrun/underrun error
581 retry=CAM_FALSE;
582 *status=EIO;
583 break;
584 case CAM_UNEXP_BUSFREE: // Unexpected BUS free
585 case CAM_SEQUENCE_FAIL: // Target bus phase sequence failure
586 *status=EIO;
587 break;
588 case CAM_PROVIDE_FAIL: // Unable to provide requ. capability
589 retry=CAM_FALSE;
590 *status=ENOTTY;
591 break;
592 case CAM_CCB_LEN_ERR: // CCB length supplied is inadequate
593 case CAM_BDR_SENT: // A SCSI BDR msg was sent to target
594 case CAM_REQ_TERMIO: // CCB request terminated by the host
595 case CAM_FUNC_NOTAVAIL: // The requ. func is not available
596 case CAM_NO_NEXUS: // Nexus is not established
597 case CAM_IID_INVALID: // The initiator ID is invalid
598 case CAM_CDB_RECVD: // The SCSI CDB has been received
599 retry=CAM_FALSE;
600 *status=EIO;
601 break;
602 case CAM_SCSI_BUSY: // SCSI bus busy
603 *status=EAGAIN;
604 break;
605 }
606 }
607 }
608 return(retry);
609 }
610 //----------------------------------------------------------------------------------------------
611 static int ata_pass_thru(int fd,struct cam_pass_thru *pcpt)
612 {
613 int icnt;
614 int status;
615 iov_t iov[3];
616 struct cam_pass_thru cpt;
617 cpt=*pcpt;
618 icnt=1;
619 SETIOV(&iov[0],&cpt,sizeof(cpt));
620 cpt.cam_timeout=cpt.cam_timeout?cpt.cam_timeout:CAM_TIME_DEFAULT;
621 if(cpt.cam_sense_len)
622 {
623 SETIOV(&iov[1],(void *)cpt.cam_sense_ptr,cpt.cam_sense_len);
624 cpt.cam_sense_ptr=sizeof(cpt);
625 icnt++;
626 }
627 if(cpt.cam_dxfer_len)
628 {
629 SETIOV(&iov[2],(void *)cpt.cam_data_ptr,cpt.cam_dxfer_len);
630 cpt.cam_data_ptr=(paddr_t)sizeof(cpt)+cpt.cam_sense_len;
631 icnt++;
632 }
633 if((status=devctlv(fd,DCMD_CAM_PASS_THRU,icnt,icnt,iov,iov,NULL)))
634 pout("ata_pass_thru devctl: %s\n",strerror(status));
635 pcpt->cam_status=cpt.cam_status;
636 pcpt->cam_scsi_status=cpt.cam_scsi_status;
637 return(status);
638 }
639 //----------------------------------------------------------------------------------------------