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