Annotation of embedaddon/smartmontools/os_qnxnto.cpp, revision 1.1.1.3
1.1 misho 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"
1.1.1.2 misho 16: #include <errno.h>
1.1 misho 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.
1.1.1.3 ! misho 22: const char *os_XXXX_c_cvsid="$Id: os_qnxnto.cpp 3806 2013-03-29 20:17:03Z chrfranke $" \
1.1 misho 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: //----------------------------------------------------------------------------------------------
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>