smartmontools SVN Rev 3317
Utility to control and monitor storage systems with "S.M.A.R.T."
os_qnxnto.cpp
Go to the documentation of this file.
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 //----------------------------------------------------------------------------------------------