|
smartmontools SVN Rev 3317
Utility to control and monitor storage systems with "S.M.A.R.T."
|
00001 00002 00003 // This is needed for the various HAVE_* macros and PROJECT_* macros. 00004 #include "config.h" 00005 00006 // These are needed to define prototypes and structures for the 00007 // functions defined below 00008 #include "int64.h" 00009 #include "atacmds.h" 00010 #include "scsicmds.h" 00011 #include "utility.h" 00012 00013 // This is to include whatever structures and prototypes you define in 00014 // os_generic.h 00015 #include "os_qnxnto.h" 00016 #include <errno.h> 00017 00018 // Needed by '-V' option (CVS versioning) of smartd/smartctl. You 00019 // should have one *_H_CVSID macro appearing below for each file 00020 // appearing with #include "*.h" above. Please list these (below) in 00021 // alphabetic/dictionary order. 00022 const char *os_XXXX_c_cvsid="$Id: os_qnxnto.cpp 3806 2013-03-29 20:17:03Z chrfranke $" \ 00023 ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_QNXNTO_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID; 00024 00025 00026 // This is here to prevent compiler warnings for unused arguments of 00027 // functions. 00028 #define ARGUSED(x) ((void)(x)) 00029 00030 // Please eliminate the following block: both the #include and 00031 // the 'unsupported()' function. They are only here to warn 00032 // unsuspecting users that their Operating System is not supported! If 00033 // you wish, you can use a similar warning mechanism for any of the 00034 // functions in this file that you can not (or choose not to) 00035 // implement. 00036 00037 00038 #ifdef HAVE_UNAME 00039 #include <sys/utsname.h> 00040 #endif 00041 //---------------------------------------------------------------------------------------------- 00042 // private Functions 00043 static int ata_sense_data(void *sdata,int *error,int *key,int *asc,int *ascq); 00044 static int ata_interpret_sense(struct cam_pass_thru *cpt,void *sense,int *status,int rcount); 00045 static int ata_pass_thru(int fd,struct cam_pass_thru *pcpt); 00046 //---------------------------------------------------------------------------------------------- 00047 static void unsupported(){ 00048 static int warninggiven; 00049 00050 if (!warninggiven) { 00051 char *osname; 00052 00053 #ifdef HAVE_UNAME 00054 struct utsname ostype; 00055 uname(&ostype); 00056 osname=ostype.sysname; 00057 #else 00058 osname="host's"; 00059 #endif 00060 00061 pout("\n" 00062 "############################################################################\n" 00063 "WARNING: smartmontools has not been ported to the %s Operating System.\n" 00064 "Please see the files os_generic.cpp and os_generic.h for porting instructions.\n" 00065 "############################################################################\n\n", 00066 osname); 00067 warninggiven=1; 00068 } 00069 00070 return; 00071 } 00072 // End of the 'unsupported()' block that you should eliminate. 00073 00074 00075 // print examples for smartctl. You should modify this function so 00076 // that the device paths are sensible for your OS, and to eliminate 00077 // unsupported commands (eg, 3ware controllers). 00078 void print_smartctl_examples(){ 00079 printf("=================================================== SMARTCTL EXAMPLES =====\n\n"); 00080 #ifdef HAVE_GETOPT_LONG 00081 printf( 00082 " smartctl -a /dev/hd0 (Prints all SMART information)\n\n" 00083 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/hd0\n" 00084 " (Enables SMART on first disk)\n\n" 00085 " smartctl -t long /dev/hd0 (Executes extended disk self-test)\n\n" 00086 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/hd0\n" 00087 " (Prints Self-Test & Attribute errors)\n" 00088 " smartctl -a --device=3ware,2 /dev/sda\n" 00089 " (Prints all SMART info for 3rd ATA disk on 3ware RAID controller)\n" 00090 ); 00091 #else 00092 printf( 00093 " smartctl -a /dev/hd0 (Prints all SMART information)\n" 00094 " smartctl -s on -o on -S on /dev/hd0 (Enables SMART on first disk)\n" 00095 " smartctl -t long /dev/hd0 (Executes extended disk self-test)\n" 00096 " smartctl -A -l selftest -q errorsonly /dev/hd0\n" 00097 " (Prints Self-Test & Attribute errors)\n" 00098 " smartctl -a -d 3ware,2 /dev/sda\n" 00099 " (Prints all SMART info for 3rd ATA disk on 3ware RAID controller)\n" 00100 ); 00101 #endif 00102 return; 00103 } 00104 00105 // tries to guess device type given the name (a path). See utility.h 00106 // for return values. 00107 static const char *net_dev_prefix = "/dev/"; 00108 static const char *net_dev_ata_disk = "hd"; 00109 00110 int guess_device_type (const char* dev_name) 00111 { 00112 int len,dev_prefix_len; 00113 dev_prefix_len=strlen(net_dev_prefix); 00114 if(!dev_name||!(len=strlen(dev_name))) 00115 return(CONTROLLER_UNKNOWN); 00116 if (!strncmp(net_dev_prefix,dev_name,dev_prefix_len)) 00117 { 00118 if(len<=dev_prefix_len) 00119 return(CONTROLLER_UNKNOWN); 00120 else 00121 dev_name += dev_prefix_len; 00122 } 00123 if(!strncmp(net_dev_ata_disk,dev_name,strlen(net_dev_ata_disk))) 00124 return(CONTROLLER_ATA); 00125 return(CONTROLLER_UNKNOWN); 00126 } 00127 00128 // makes a list of ATA or SCSI devices for the DEVICESCAN directive of 00129 // smartd. Returns number N of devices, or -1 if out of 00130 // memory. Allocates N+1 arrays: one of N pointers (devlist); the 00131 // other N arrays each contain null-terminated character strings. In 00132 // the case N==0, no arrays are allocated because the array of 0 00133 // pointers has zero length, equivalent to calling malloc(0). 00134 int make_device_names (char*** devlist, const char* name) { 00135 ARGUSED(devlist); 00136 ARGUSED(name); 00137 unsupported(); 00138 return 0; 00139 } 00140 00141 // Like open(). Return non-negative integer handle, only used by the 00142 // functions below. type=="ATA" or "SCSI". If you need to store 00143 // extra information about your devices, create a private internal 00144 // array within this file (see os_freebsd.cpp for an example). If you 00145 // can not open the device (permission denied, does not exist, etc) 00146 // set errno as open() does and return <0. 00147 int deviceopen(const char *pathname, char *type) 00148 { 00149 if(!strcmp(type, "ATA")) 00150 return(open(pathname,O_RDWR|O_NONBLOCK)); 00151 else 00152 return(-1); 00153 } 00154 00155 // Like close(). Acts only on integer handles returned by 00156 // deviceopen() above. 00157 int deviceclose(int fd) 00158 { 00159 return(close(fd)); 00160 } 00161 //---------------------------------------------------------------------------------------------- 00162 // Interface to ATA devices. See os_linux.cpp for the cannonical example. 00163 // DETAILED DESCRIPTION OF ARGUMENTS 00164 // device: is the integer handle provided by deviceopen() 00165 // command: defines the different operations, see atacmds.h 00166 // select: additional input data IF NEEDED (which log, which type of 00167 // self-test). 00168 // data: location to write output data, IF NEEDED (1 or 512 bytes). 00169 // Note: not all commands use all arguments. 00170 // RETURN VALUES (for all commands BUT command==STATUS_CHECK) 00171 // -1 if the command failed 00172 // 0 if the command succeeded, 00173 // RETURN VALUES if command==STATUS_CHECK 00174 // -1 if the command failed OR the disk SMART status can't be determined 00175 // 0 if the command succeeded and disk SMART status is "OK" 00176 // 1 if the command succeeded and disk SMART status is "FAILING" 00177 int ata_command_interface(int fd,smart_command_set command,int select,char *data) 00178 { 00179 struct cam_pass_thru cpt; 00180 ATA_SENSE sense; 00181 CDB *cdb; 00182 int status,rc; 00183 memset(&cpt,0x00,sizeof(struct cam_pass_thru)); 00184 cdb=(CDB *)cpt.cam_cdb; 00185 rc=-1; 00186 switch(command) 00187 { 00188 case READ_VALUES: 00189 cpt.cam_flags = CAM_DIR_IN; 00190 cpt.cam_cdb_len = 16; 00191 cpt.cam_dxfer_len = 512; 00192 cpt.cam_data_ptr = (uint32_t)data; 00193 cpt.cam_sense_len = sizeof(sense); 00194 cpt.cam_sense_ptr = (uint32_t)&sense; 00195 cdb->ata_pass_thru.opcode = SC_ATA_PT16; 00196 cdb->ata_pass_thru.protocol = ATA_PROTO_PIO_DATA_IN; 00197 cdb->ata_pass_thru.flags = ATA_FLG_T_DIR|ATA_FLG_TLEN_STPSIU; 00198 cdb->ata_pass_thru.command = ATA_SMART_CMD; 00199 cdb->ata_pass_thru.features = ATA_SMART_READ_VALUES; 00200 cdb->ata_pass_thru.lba_mid = ATA_SMART_LBA_MID_SIG; 00201 cdb->ata_pass_thru.lba_high = ATA_SMART_LBA_HI_SIG; 00202 break; 00203 case READ_THRESHOLDS: 00204 cpt.cam_flags = CAM_DIR_IN; 00205 cpt.cam_cdb_len = 16; 00206 cpt.cam_dxfer_len = 512; 00207 cpt.cam_data_ptr = (uint32_t)data; 00208 cpt.cam_sense_len = sizeof(sense); 00209 cpt.cam_sense_ptr = (uint32_t)&sense; 00210 cdb->ata_pass_thru.opcode = SC_ATA_PT16; 00211 cdb->ata_pass_thru.protocol = ATA_PROTO_PIO_DATA_IN; 00212 cdb->ata_pass_thru.flags = ATA_FLG_T_DIR|ATA_FLG_TLEN_STPSIU; 00213 cdb->ata_pass_thru.command = ATA_SMART_CMD; 00214 cdb->ata_pass_thru.features = ATA_SMART_READ_THRESHOLDS; 00215 cdb->ata_pass_thru.lba_mid = ATA_SMART_LBA_MID_SIG; 00216 cdb->ata_pass_thru.lba_high = ATA_SMART_LBA_HI_SIG; 00217 break; 00218 case READ_LOG: 00219 cpt.cam_flags = CAM_DIR_IN; 00220 cpt.cam_cdb_len = 16; 00221 cpt.cam_dxfer_len = 512; 00222 cpt.cam_data_ptr = (uint32_t)data; 00223 cpt.cam_sense_len = sizeof(sense); 00224 cpt.cam_sense_ptr = (uint32_t)&sense; 00225 cdb->ata_pass_thru.opcode = SC_ATA_PT16; 00226 cdb->ata_pass_thru.protocol = ATA_PROTO_PIO_DATA_IN; 00227 cdb->ata_pass_thru.flags = ATA_FLG_T_DIR|ATA_FLG_TLEN_STPSIU; 00228 cdb->ata_pass_thru.command = ATA_SMART_CMD; 00229 cdb->ata_pass_thru.features = ATA_SMART_READ_LOG_SECTOR; 00230 cdb->ata_pass_thru.sector_count= 1; 00231 cdb->ata_pass_thru.lba_low = select; 00232 cdb->ata_pass_thru.lba_mid = ATA_SMART_LBA_MID_SIG; 00233 cdb->ata_pass_thru.lba_high = ATA_SMART_LBA_HI_SIG; 00234 break; 00235 case WRITE_LOG: 00236 return(-1); 00237 break; 00238 case IDENTIFY: 00239 cpt.cam_flags = CAM_DIR_IN; 00240 cpt.cam_cdb_len = 16; 00241 cpt.cam_dxfer_len = 512; 00242 cpt.cam_data_ptr = (uint32_t)data; 00243 cpt.cam_sense_len = sizeof(sense); 00244 cpt.cam_sense_ptr = (uint32_t)&sense; 00245 cdb->ata_pass_thru.opcode = SC_ATA_PT16; 00246 cdb->ata_pass_thru.protocol = ATA_PROTO_PIO_DATA_IN; 00247 cdb->ata_pass_thru.flags = ATA_FLG_T_DIR|ATA_FLG_TLEN_STPSIU; 00248 cdb->ata_pass_thru.command = ATA_IDENTIFY_DEVICE; 00249 break; 00250 case PIDENTIFY: 00251 cpt.cam_flags = CAM_DIR_IN; 00252 cpt.cam_cdb_len = 16; 00253 cpt.cam_dxfer_len = 512; 00254 cpt.cam_data_ptr = (uint32_t)data; 00255 cpt.cam_sense_len = sizeof(sense); 00256 cpt.cam_sense_ptr = (uint32_t)&sense; 00257 cdb->ata_pass_thru.opcode = SC_ATA_PT16; 00258 cdb->ata_pass_thru.protocol = ATA_PROTO_PIO_DATA_IN; 00259 cdb->ata_pass_thru.flags = ATA_FLG_T_DIR|ATA_FLG_TLEN_STPSIU; 00260 cdb->ata_pass_thru.command = ATA_IDENTIFY_PACKET_DEVICE; 00261 break; 00262 case ENABLE: 00263 cpt.cam_flags = CAM_DIR_NONE; 00264 cpt.cam_cdb_len = 16; 00265 cpt.cam_sense_len = sizeof(sense); 00266 cpt.cam_sense_ptr = (uint32_t)&sense; 00267 cdb->ata_pass_thru.opcode = SC_ATA_PT16; 00268 cdb->ata_pass_thru.protocol = ATA_PROTO_DATA_NONE; 00269 cdb->ata_pass_thru.command = ATA_SMART_CMD; 00270 cdb->ata_pass_thru.features = ATA_SMART_ENABLE; 00271 cdb->ata_pass_thru.lba_mid = ATA_SMART_LBA_MID_SIG; 00272 cdb->ata_pass_thru.lba_high = ATA_SMART_LBA_HI_SIG; 00273 break; 00274 case DISABLE: 00275 cpt.cam_flags = CAM_DIR_NONE; 00276 cpt.cam_cdb_len = 16; 00277 cpt.cam_sense_len = sizeof(sense); 00278 cpt.cam_sense_ptr = (uint32_t)&sense; 00279 cdb->ata_pass_thru.opcode = SC_ATA_PT16; 00280 cdb->ata_pass_thru.protocol = ATA_PROTO_DATA_NONE; 00281 cdb->ata_pass_thru.command = ATA_SMART_CMD; 00282 cdb->ata_pass_thru.features = ATA_SMART_DISABLE; 00283 cdb->ata_pass_thru.lba_mid = ATA_SMART_LBA_MID_SIG; 00284 cdb->ata_pass_thru.lba_high = ATA_SMART_LBA_HI_SIG; 00285 break; 00286 case AUTO_OFFLINE: 00287 // NOTE: According to ATAPI 4 and UP, this command is obsolete 00288 cpt.cam_flags = CAM_DIR_NONE; 00289 cpt.cam_cdb_len = 16; 00290 cpt.cam_sense_len = sizeof(sense); 00291 cpt.cam_sense_ptr = (uint32_t)&sense; 00292 cdb->ata_pass_thru.opcode = SC_ATA_PT16; 00293 cdb->ata_pass_thru.protocol = ATA_PROTO_DATA_NONE; 00294 cdb->ata_pass_thru.command = ATA_SMART_CMD; 00295 cdb->ata_pass_thru.features = ATA_SMART_AUTO_OFFLINE; 00296 cdb->ata_pass_thru.lba_low = select; 00297 cdb->ata_pass_thru.lba_mid = ATA_SMART_LBA_MID_SIG; 00298 cdb->ata_pass_thru.lba_high = ATA_SMART_LBA_HI_SIG; 00299 break; 00300 case AUTOSAVE: 00301 cpt.cam_flags = CAM_DIR_NONE; 00302 cpt.cam_cdb_len = 16; 00303 cpt.cam_sense_len = sizeof(sense); 00304 cpt.cam_sense_ptr = (uint32_t)&sense; 00305 cdb->ata_pass_thru.opcode = SC_ATA_PT16; 00306 cdb->ata_pass_thru.protocol = ATA_PROTO_DATA_NONE; 00307 cdb->ata_pass_thru.command = ATA_SMART_CMD; 00308 cdb->ata_pass_thru.features = ATA_SMART_AUTOSAVE; 00309 cdb->ata_pass_thru.sector_count= select; 00310 cdb->ata_pass_thru.lba_mid = ATA_SMART_LBA_MID_SIG; 00311 cdb->ata_pass_thru.lba_high = ATA_SMART_LBA_HI_SIG; 00312 break; 00313 case IMMEDIATE_OFFLINE: 00314 // NOTE: According to ATAPI 4 and UP, this command is obsolete 00315 cpt.cam_flags = CAM_DIR_NONE; 00316 cpt.cam_cdb_len = 16; 00317 cpt.cam_sense_len = sizeof(sense); 00318 cpt.cam_sense_ptr = (uint32_t)&sense; 00319 cdb->ata_pass_thru.opcode = SC_ATA_PT16; 00320 cdb->ata_pass_thru.protocol = ATA_PROTO_DATA_NONE; 00321 cdb->ata_pass_thru.command = ATA_SMART_CMD; 00322 cdb->ata_pass_thru.features = ATA_SMART_IMMEDIATE_OFFLINE; 00323 cdb->ata_pass_thru.lba_low = select; 00324 cdb->ata_pass_thru.lba_mid = ATA_SMART_LBA_MID_SIG; 00325 cdb->ata_pass_thru.lba_high = ATA_SMART_LBA_HI_SIG; 00326 break; 00327 case STATUS_CHECK: 00328 // same command, no HDIO in NetBSD 00329 case STATUS: 00330 cpt.cam_flags = CAM_DIR_NONE; 00331 cpt.cam_cdb_len = 16; 00332 cpt.cam_sense_len = sizeof(sense); 00333 cpt.cam_sense_ptr = (uint32_t)&sense; 00334 cdb->ata_pass_thru.opcode = SC_ATA_PT16; 00335 cdb->ata_pass_thru.protocol = ATA_PROTO_DATA_NONE; 00336 cdb->ata_pass_thru.flags = ATA_FLG_CK_COND; 00337 cdb->ata_pass_thru.command = ATA_SMART_CMD; 00338 cdb->ata_pass_thru.features = ATA_SMART_STATUS; 00339 cdb->ata_pass_thru.lba_mid = ATA_SMART_LBA_MID_SIG; 00340 cdb->ata_pass_thru.lba_high = ATA_SMART_LBA_HI_SIG; 00341 break; 00342 case CHECK_POWER_MODE: 00343 cpt.cam_flags = CAM_DIR_NONE; 00344 cpt.cam_cdb_len = 16; 00345 cpt.cam_sense_len = sizeof(sense); 00346 cpt.cam_sense_ptr = (uint32_t)&sense; 00347 cdb->ata_pass_thru.opcode = SC_ATA_PT16; 00348 cdb->ata_pass_thru.protocol = ATA_PROTO_DATA_NONE; 00349 cdb->ata_pass_thru.flags = ATA_FLG_CK_COND; 00350 cdb->ata_pass_thru.command = ATA_CHECK_POWER_MODE; 00351 break; 00352 default: 00353 pout("Unrecognized command %d in ata_command_interface()\n", command); 00354 errno=ENOSYS; 00355 return(-1); 00356 } 00357 // execute now 00358 if((status=ata_pass_thru(fd,&cpt))==EOK) 00359 { 00360 rc=status==EOK?0:-1; 00361 if(cpt.cam_status!=CAM_REQ_CMP) 00362 { 00363 ata_interpret_sense(&cpt,&sense,&status,0); 00364 if(command==STATUS||command==STATUS_CHECK) 00365 rc=((sense.desc.lba_high<<8)|sense.desc.lba_mid)==ATA_SMART_SIG?0:1; 00366 } 00367 } 00368 if(command==CHECK_POWER_MODE) 00369 data[0]=cdb->ata_pass_thru.sector_count; 00370 // finish 00371 return(rc); 00372 } 00373 //---------------------------------------------------------------------------------------------- 00374 // Interface to SCSI devices. See os_linux.c 00375 int do_scsi_cmnd_io(int fd,struct scsi_cmnd_io * iop,int report) 00376 { 00377 ARGUSED(fd); 00378 ARGUSED(iop); 00379 ARGUSED(report); 00380 unsupported(); 00381 return -ENOSYS; 00382 } 00383 //---------------------------------------------------------------------------------------------- 00384 //---------------------------------------------------------------------------------------------- 00385 static int ata_sense_data(void *sdata,int *error,int *key,int *asc,int *ascq) 00386 { 00387 SCSI_SENSE *sf; 00388 SCSI_SENSE_DESCRIPTOR *sd; 00389 sf=(SCSI_SENSE *)sdata; 00390 sd=(SCSI_SENSE_DESCRIPTOR *)sdata; 00391 *error=sf->error; 00392 if(*error & SENSE_DATA_FMT_DESCRIPTOR) 00393 { 00394 *key=sd->sense & SK_MSK; 00395 *asc=sd->asc; 00396 *ascq=sd->ascq; 00397 } 00398 else 00399 { 00400 *key=sf->sense & SK_MSK; 00401 *asc=sf->asc; 00402 *ascq=sf->ascq; 00403 } 00404 return(CAM_SUCCESS); 00405 } 00406 //---------------------------------------------------------------------------------------------- 00407 static int ata_interpret_sense(struct cam_pass_thru *cpt,void *sense,int *status,int rcount) 00408 { 00409 int retry; 00410 int key; 00411 int asc; 00412 int ascq; 00413 int error; 00414 *status=EIO; 00415 retry=CAM_TRUE; 00416 if(cpt->cam_status&CAM_AUTOSNS_VALID) 00417 { 00418 ata_sense_data(sense,&error,&key,&asc,&ascq); 00419 switch(key) 00420 { 00421 case SK_NO_SENSE: // No sense data (no error) 00422 retry=CAM_FALSE; 00423 *status=EOK; 00424 break; 00425 case SK_RECOVERED: // Recovered error 00426 switch(asc) 00427 { 00428 case ASC_ATA_PASS_THRU: 00429 switch(ascq) 00430 { 00431 case ASCQ_ATA_PASS_THRU_INFO_AVAIL: 00432 break; 00433 default: 00434 break; 00435 } 00436 break; 00437 default: 00438 break; 00439 } 00440 retry=CAM_FALSE; 00441 *status=EOK; 00442 break; 00443 case SK_NOT_RDY: // Device not ready 00444 *status=EAGAIN; 00445 switch(asc) 00446 { 00447 case ASC_NOT_READY: 00448 switch(ascq) 00449 { 00450 case ASCQ_BECOMING_READY: 00451 case ASCQ_CAUSE_NOT_REPORTABLE: 00452 default: 00453 retry=CAM_FALSE; 00454 break; 00455 } 00456 break; 00457 case ASC_MEDIA_NOT_PRESENT: 00458 *status=ENXIO; 00459 retry=CAM_FALSE; 00460 break; 00461 } 00462 break; 00463 case SK_MEDIUM: // Medium error 00464 case SK_HARDWARE: // Hardware error 00465 retry=CAM_FALSE; 00466 *status=EIO; 00467 break; 00468 case SK_ILLEGAL: // Illegal Request (bad command) 00469 retry=CAM_FALSE; 00470 *status=EINVAL; 00471 break; 00472 case SK_UNIT_ATN: // Unit Attention 00473 switch(asc) 00474 { 00475 case ASC_MEDIUM_CHANGED: 00476 *status=ESTALE; 00477 retry=CAM_FALSE; 00478 break; 00479 case ASC_BUS_RESET: 00480 break; 00481 } 00482 break; 00483 case SK_DATA_PROT: // Data Protect 00484 retry=CAM_FALSE; 00485 *status=EROFS; 00486 break; 00487 case SK_VENDOR: // Vendor Specific 00488 case SK_CPY_ABORT: // Copy Aborted 00489 retry=CAM_FALSE; 00490 *status=EIO; 00491 break; 00492 case SK_CMD_ABORT: // Aborted Command 00493 retry=CAM_FALSE; 00494 *status=ECANCELED; 00495 break; 00496 case SK_EQUAL: // Equal 00497 case SK_VOL_OFL: // Volume Overflow 00498 case SK_MISCMP: // Miscompare 00499 case SK_RESERVED: // Reserved 00500 break; 00501 } 00502 if(*status==EOK) 00503 { 00504 switch(cpt->cam_status&CAM_STATUS_MASK) 00505 { 00506 case CAM_REQ_CMP_ERR: // CCB request completed with an err 00507 retry=CAM_FALSE; 00508 *status=EIO; 00509 break; 00510 case CAM_BUSY: // CAM subsystem is busy 00511 *status=EAGAIN; 00512 break; 00513 case CAM_REQ_INVALID: // CCB request is invalid 00514 case CAM_PATH_INVALID: // Path ID supplied is invalid 00515 case CAM_DEV_NOT_THERE: // SCSI device not installed/there 00516 case CAM_SEL_TIMEOUT: // Target selection timeout 00517 case CAM_LUN_INVALID: // LUN supplied is invalid 00518 case CAM_TID_INVALID: // Target ID supplied is invalid 00519 retry=CAM_FALSE; 00520 *status=ENXIO; 00521 break; 00522 case CAM_CMD_TIMEOUT: // Command timeout 00523 *status=rcount?EAGAIN:EIO; 00524 break; 00525 case CAM_MSG_REJECT_REC: // Message reject received 00526 case CAM_SCSI_BUS_RESET: // SCSI bus reset sent/received 00527 case CAM_UNCOR_PARITY: // Uncorrectable parity err occurred 00528 case CAM_AUTOSENSE_FAIL: // Autosense: Request sense cmd fail 00529 case CAM_NO_HBA: // No HBA detected Error 00530 case CAM_DATA_RUN_ERR: // Data overrun/underrun error 00531 retry=CAM_FALSE; 00532 *status=EIO; 00533 break; 00534 case CAM_UNEXP_BUSFREE: // Unexpected BUS free 00535 case CAM_SEQUENCE_FAIL: // Target bus phase sequence failure 00536 *status=EIO; 00537 break; 00538 case CAM_PROVIDE_FAIL: // Unable to provide requ. capability 00539 retry=CAM_FALSE; 00540 *status=ENOTTY; 00541 break; 00542 case CAM_CCB_LEN_ERR: // CCB length supplied is inadequate 00543 case CAM_BDR_SENT: // A SCSI BDR msg was sent to target 00544 case CAM_REQ_TERMIO: // CCB request terminated by the host 00545 case CAM_FUNC_NOTAVAIL: // The requ. func is not available 00546 case CAM_NO_NEXUS: // Nexus is not established 00547 case CAM_IID_INVALID: // The initiator ID is invalid 00548 case CAM_CDB_RECVD: // The SCSI CDB has been received 00549 retry=CAM_FALSE; 00550 *status=EIO; 00551 break; 00552 case CAM_SCSI_BUSY: // SCSI bus busy 00553 *status=EAGAIN; 00554 break; 00555 } 00556 } 00557 } 00558 return(retry); 00559 } 00560 //---------------------------------------------------------------------------------------------- 00561 static int ata_pass_thru(int fd,struct cam_pass_thru *pcpt) 00562 { 00563 int icnt; 00564 int status; 00565 iov_t iov[3]; 00566 struct cam_pass_thru cpt; 00567 cpt=*pcpt; 00568 icnt=1; 00569 SETIOV(&iov[0],&cpt,sizeof(cpt)); 00570 cpt.cam_timeout=cpt.cam_timeout?cpt.cam_timeout:CAM_TIME_DEFAULT; 00571 if(cpt.cam_sense_len) 00572 { 00573 SETIOV(&iov[1],(void *)cpt.cam_sense_ptr,cpt.cam_sense_len); 00574 cpt.cam_sense_ptr=sizeof(cpt); 00575 icnt++; 00576 } 00577 if(cpt.cam_dxfer_len) 00578 { 00579 SETIOV(&iov[2],(void *)cpt.cam_data_ptr,cpt.cam_dxfer_len); 00580 cpt.cam_data_ptr=(paddr_t)sizeof(cpt)+cpt.cam_sense_len; 00581 icnt++; 00582 } 00583 if((status=devctlv(fd,DCMD_CAM_PASS_THRU,icnt,icnt,iov,iov,NULL))) 00584 pout("ata_pass_thru devctl: %s\n",strerror(status)); 00585 pcpt->cam_status=cpt.cam_status; 00586 pcpt->cam_scsi_status=cpt.cam_scsi_status; 00587 return(status); 00588 } 00589 //----------------------------------------------------------------------------------------------
1.7.4