]>
Commit | Line | Data |
---|---|---|
a23d5117 GI |
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" | |
ee38a438 | 16 | #include <errno.h> |
a23d5117 GI |
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. | |
ee38a438 | 22 | const char *os_XXXX_c_cvsid="$Id: os_qnxnto.cpp 3806 2013-03-29 20:17:03Z chrfranke $" \ |
a23d5117 GI |
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; | |
a23d5117 GI |
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 | ||
a23d5117 GI |
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); | |
a23d5117 GI |
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 | //---------------------------------------------------------------------------------------------- | |
a23d5117 GI |
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 | { | |
e9583e0c | 573 | SETIOV(&iov[1],(void *)cpt.cam_sense_ptr,cpt.cam_sense_len); |
a23d5117 GI |
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 | //---------------------------------------------------------------------------------------------- |