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