File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / smartmontools / os_qnxnto.cpp
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 14 07:54:03 2013 UTC (10 years, 8 months ago) by misho
Branches: smartmontools, elwix, MAIN
CVS tags: v6_2, HEAD
v 6.2

    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"
   16: #include <errno.h>
   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.
   22: const char *os_XXXX_c_cvsid="$Id: os_qnxnto.cpp,v 1.1.1.3 2013/10/14 07:54:03 misho Exp $" \
   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;
   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: 
   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);
   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: //----------------------------------------------------------------------------------------------
  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:    {
  573:     SETIOV(&iov[1],(void *)cpt.cam_sense_ptr,cpt.cam_sense_len);
  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: //----------------------------------------------------------------------------------------------
  590: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>