3 // This is needed for the various HAVE_* macros and PROJECT_* macros.
6 // These are needed to define prototypes and structures for the
7 // functions defined below
13 // This is to include whatever structures and prototypes you define in
15 #include "os_qnxnto.h"
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,v 1.3 2008/06/12 21:46:31 ballen4705 Exp $" \
22 ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_QNXNTO_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID
;
25 // This is here to prevent compiler warnings for unused arguments of
27 #define ARGUSED(x) ((void)(x))
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)
38 #include <sys/utsname.h>
40 //----------------------------------------------------------------------------------------------
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
;
51 extern unsigned char debugmode
;
52 unsigned char savedebugmode
=debugmode
;
55 struct utsname ostype
;
57 osname
=ostype
.sysname
;
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",
69 debugmode
=savedebugmode
;
75 // End of the 'unsupported()' block that you should eliminate.
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
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"
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"
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";
113 int guess_device_type (const char* dev_name
)
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
))
121 if(len
<=dev_prefix_len
)
122 return(CONTROLLER_UNKNOWN
);
124 dev_name
+= dev_prefix_len
;
126 if(!strncmp(net_dev_ata_disk
,dev_name
,strlen(net_dev_ata_disk
)))
127 return(CONTROLLER_ATA
);
128 return(CONTROLLER_UNKNOWN
);
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
) {
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
)
152 if(!strcmp(type
, "ATA"))
153 return(open(pathname
,O_RDWR
|O_NONBLOCK
));
158 // Like close(). Acts only on integer handles returned by
159 // deviceopen() above.
160 int deviceclose(int fd
)
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
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
)
182 struct cam_pass_thru cpt
;
186 memset(&cpt
,0x00,sizeof(struct cam_pass_thru
));
187 cdb
=(CDB
*)cpt
.cam_cdb
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
331 // same command, no HDIO in NetBSD
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
;
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
;
356 pout("Unrecognized command %d in ata_command_interface()\n", command
);
361 if((status
=ata_pass_thru(fd
,&cpt
))==EOK
)
364 if(cpt
.cam_status
!=CAM_REQ_CMP
)
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;
371 if(command
==CHECK_POWER_MODE
)
372 data
[0]=cdb
->ata_pass_thru
.sector_count
;
376 //----------------------------------------------------------------------------------------------
377 int marvell_command_interface(int fd
, smart_command_set command
, int select
, char *data
)
386 //----------------------------------------------------------------------------------------------
387 int highpoint_command_interface(int fd
, smart_command_set command
, int select
, char *data
)
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
)
406 ARGUSED(controller_type
);
415 int areca_command_interface(int fd
,int disknum
,smart_command_set command
,int select
,char *data
)
426 //----------------------------------------------------------------------------------------------
428 // Interface to SCSI devices. See os_linux.c
429 int do_scsi_cmnd_io(int fd
,struct scsi_cmnd_io
* iop
,int report
)
437 //----------------------------------------------------------------------------------------------
438 //----------------------------------------------------------------------------------------------
439 static int ata_sense_data(void *sdata
,int *error
,int *key
,int *asc
,int *ascq
)
442 SCSI_SENSE_DESCRIPTOR
*sd
;
443 sf
=(SCSI_SENSE
*)sdata
;
444 sd
=(SCSI_SENSE_DESCRIPTOR
*)sdata
;
446 if(*error
& SENSE_DATA_FMT_DESCRIPTOR
)
448 *key
=sd
->sense
& SK_MSK
;
454 *key
=sf
->sense
& SK_MSK
;
460 //----------------------------------------------------------------------------------------------
461 static int ata_interpret_sense(struct cam_pass_thru
*cpt
,void *sense
,int *status
,int rcount
)
470 if(cpt
->cam_status
&CAM_AUTOSNS_VALID
)
472 ata_sense_data(sense
,&error
,&key
,&asc
,&ascq
);
475 case SK_NO_SENSE
: // No sense data (no error)
479 case SK_RECOVERED
: // Recovered error
482 case ASC_ATA_PASS_THRU
:
485 case ASCQ_ATA_PASS_THRU_INFO_AVAIL
:
497 case SK_NOT_RDY
: // Device not ready
504 case ASCQ_BECOMING_READY
:
505 case ASCQ_CAUSE_NOT_REPORTABLE
:
511 case ASC_MEDIA_NOT_PRESENT
:
517 case SK_MEDIUM
: // Medium error
518 case SK_HARDWARE
: // Hardware error
522 case SK_ILLEGAL
: // Illegal Request (bad command)
526 case SK_UNIT_ATN
: // Unit Attention
529 case ASC_MEDIUM_CHANGED
:
537 case SK_DATA_PROT
: // Data Protect
541 case SK_VENDOR
: // Vendor Specific
542 case SK_CPY_ABORT
: // Copy Aborted
546 case SK_CMD_ABORT
: // Aborted Command
550 case SK_EQUAL
: // Equal
551 case SK_VOL_OFL
: // Volume Overflow
552 case SK_MISCMP
: // Miscompare
553 case SK_RESERVED
: // Reserved
558 switch(cpt
->cam_status
&CAM_STATUS_MASK
)
560 case CAM_REQ_CMP_ERR
: // CCB request completed with an err
564 case CAM_BUSY
: // CAM subsystem is busy
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
576 case CAM_CMD_TIMEOUT
: // Command timeout
577 *status
=rcount
?EAGAIN
:EIO
;
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
588 case CAM_UNEXP_BUSFREE
: // Unexpected BUS free
589 case CAM_SEQUENCE_FAIL
: // Target bus phase sequence failure
592 case CAM_PROVIDE_FAIL
: // Unable to provide requ. capability
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
606 case CAM_SCSI_BUSY
: // SCSI bus busy
614 //----------------------------------------------------------------------------------------------
615 static int ata_pass_thru(int fd
,struct cam_pass_thru
*pcpt
)
620 struct cam_pass_thru cpt
;
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
)
627 SETIOV(&iov
[1],cpt
.cam_sense_ptr
,cpt
.cam_sense_len
);
628 cpt
.cam_sense_ptr
=sizeof(cpt
);
631 if(cpt
.cam_dxfer_len
)
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
;
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
;
643 //----------------------------------------------------------------------------------------------