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