Annotation of embedaddon/smartmontools/os_freebsd.cpp, revision 1.1.1.2

1.1       misho       1: /*
                      2:  * os_freebsd.c
                      3:  *
                      4:  * Home page of code is: http://smartmontools.sourceforge.net
                      5:  *
                      6:  * Copyright (C) 2003-10 Eduard Martinescu <smartmontools-support@lists.sourceforge.net>
                      7:  *
                      8:  * This program is free software; you can redistribute it and/or modify
                      9:  * it under the terms of the GNU General Public License as published by
                     10:  * the Free Software Foundation; either version 2, or (at your option)
                     11:  * any later version.
                     12:  *
                     13:  * You should have received a copy of the GNU General Public License
                     14:  * (for example COPYING); if not, write to the Free
                     15:  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     16:  */
                     17: 
                     18: #include <stdio.h>
                     19: #include <sys/types.h>
                     20: #include <dirent.h>
                     21: #include <fcntl.h>
                     22: #include <err.h>
                     23: #include <errno.h>
                     24: #include <camlib.h>
                     25: #include <cam/scsi/scsi_message.h>
                     26: #include <cam/scsi/scsi_pass.h>
                     27: #if defined(__DragonFly__)
                     28: #include <sys/nata.h>
                     29: #else
                     30: #include <sys/ata.h>
                     31: #endif
                     32: #include <sys/stat.h>
                     33: #include <unistd.h>
                     34: #include <glob.h>
                     35: #include <stddef.h>
                     36: #include <paths.h>
                     37: #include <sys/utsname.h>
                     38: 
                     39: #include "config.h"
                     40: #include "int64.h"
                     41: #include "atacmds.h"
                     42: #include "scsicmds.h"
                     43: #include "cciss.h"
                     44: #include "utility.h"
                     45: #include "os_freebsd.h"
                     46: 
                     47: #include "dev_interface.h"
                     48: #include "dev_ata_cmd_set.h"
                     49: 
                     50: #define USBDEV "/dev/usb"
                     51: #if defined(__FreeBSD_version)
                     52: 
                     53: // This way we define one variable for the GNU/kFreeBSD and FreeBSD 
                     54: #define FREEBSDVER __FreeBSD_version
                     55: #else
                     56: #define FREEBSDVER __FreeBSD_kernel_version
                     57: #endif
                     58: 
                     59: #if (FREEBSDVER >= 800000)
                     60: #include <libusb20_desc.h>
                     61: #include <libusb20.h>
                     62: #elif defined(__DragonFly__)
                     63: #include <bus/usb/usb.h>
                     64: #include <bus/usb/usbhid.h>
                     65: #else
                     66: #include <dev/usb/usb.h>
                     67: #include <dev/usb/usbhid.h>
                     68: #endif
                     69: 
                     70: #define CONTROLLER_3WARE_9000_CHAR      0x01
                     71: #define CONTROLLER_3WARE_678K_CHAR      0x02
                     72: 
                     73: #ifndef PATHINQ_SETTINGS_SIZE
                     74: #define PATHINQ_SETTINGS_SIZE   128
                     75: #endif
                     76: 
1.1.1.2 ! misho      77: const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 3565 2012-06-19 20:37:05Z chrfranke $" \
1.1       misho      78: ATACMDS_H_CVSID CCISS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
                     79: 
                     80: #define NO_RETURN 0
                     81: #define BAD_SMART 1
                     82: #define NO_DISK_3WARE 2
                     83: #define BAD_KERNEL 3
                     84: #define MAX_MSG 3
                     85: 
                     86: // Utility function for printing warnings
                     87: void printwarning(int msgNo, const char* extra) {
                     88:   static int printed[] = {0,0,0,0};
                     89:   static const char* message[]={
                     90:     "The SMART RETURN STATUS return value (smartmontools -H option/Directive)\n can not be retrieved with this version of ATAng, please do not rely on this value\nYou should update to at least 5.2\n",
                     91: 
                     92:     "Error SMART Status command failed\nPlease get assistance from \n" PACKAGE_HOMEPAGE "\nRegister values returned from SMART Status command are:\n",
                     93: 
                     94:     "You must specify a DISK # for 3ware drives with -d 3ware,<n> where <n> begins with 1 for first disk drive\n",
                     95: 
                     96:     "ATA support is not provided for this kernel version. Please ugrade to a recent 5-CURRENT kernel (post 09/01/2003 or so)\n"
                     97:   };
                     98: 
                     99:   if (msgNo >= 0 && msgNo <= MAX_MSG) {
                    100:     if (!printed[msgNo]) {
                    101:       printed[msgNo] = 1;
                    102:       pout("%s", message[msgNo]);
                    103:       if (extra)
                    104:         pout("%s",extra);
                    105:     }
                    106:   }
                    107:   return;
                    108: }
                    109: 
                    110: // Interface to ATA devices behind 3ware escalade RAID controller cards.  See os_linux.c
                    111: 
                    112: #define BUFFER_LEN_678K_CHAR ( sizeof(struct twe_usercommand) ) // 520
                    113: #define BUFFER_LEN_9000_CHAR ( sizeof(TW_OSLI_IOCTL_NO_DATA_BUF) + sizeof(TWE_Command) ) // 2048
                    114: #define TW_IOCTL_BUFFER_SIZE ( MAX(BUFFER_LEN_678K_CHAR, BUFFER_LEN_9000_CHAR) )
                    115: 
                    116: #ifndef ATA_DEVICE
                    117: #define ATA_DEVICE "/dev/ata"
                    118: #endif
                    119: 
                    120: #define ARGUSED(x) ((void)(x))
                    121: 
                    122: // global variable holding byte count of allocated memory
                    123: long long bytes;
                    124: 
                    125: /////////////////////////////////////////////////////////////////////////////
                    126: 
                    127: namespace os_freebsd { // No need to publish anything, name provided for Doxygen
                    128: 
                    129: /////////////////////////////////////////////////////////////////////////////
                    130: /// Implement shared open/close routines with old functions.
                    131: 
                    132: class freebsd_smart_device
                    133: : virtual public /*implements*/ smart_device
                    134: {
                    135: public:
                    136:   explicit freebsd_smart_device(const char * mode)
                    137:     : smart_device(never_called),
                    138:       m_fd(-1), m_mode(mode) { }
                    139: 
                    140:   virtual ~freebsd_smart_device() throw();
                    141: 
                    142:   virtual bool is_open() const;
                    143: 
                    144:   virtual bool open();
                    145: 
                    146:   virtual bool close();
                    147: 
                    148: protected:
                    149:   /// Return filedesc for derived classes.
                    150:   int get_fd() const
                    151:     { return m_fd; }
                    152: 
                    153:   void set_fd(int fd)
                    154:     { m_fd = fd; }
                    155: 
                    156: private:
                    157:   int m_fd; ///< filedesc, -1 if not open.
                    158:   const char * m_mode; ///< Mode string for deviceopen().
                    159: };
                    160: 
                    161: #ifdef __GLIBC__
                    162: static inline void * reallocf(void *ptr, size_t size) {
                    163:    void *rv = realloc(ptr, size);
                    164:    if((rv == NULL) && (size != 0))
                    165:      free(ptr);
                    166:    return rv;
                    167:    }
                    168: #endif
                    169: 
                    170: freebsd_smart_device::~freebsd_smart_device() throw()
                    171: {
                    172:   if (m_fd >= 0)
                    173:     os_freebsd::freebsd_smart_device::close();
                    174: }
                    175: 
                    176: // migration from the old_style 
                    177: unsigned char m_controller_type;
                    178: unsigned char m_controller_port; 
                    179: 
                    180: // examples for smartctl
                    181: static const char  smartctl_examples[] =
                    182:    "=================================================== SMARTCTL EXAMPLES =====\n\n"
                    183:          "  smartctl -a /dev/ad0                       (Prints all SMART information)\n\n"
                    184:          "  smartctl --smart=on --offlineauto=on --saveauto=on /dev/ad0\n"
                    185:          "                                              (Enables SMART on first disk)\n\n"
                    186:          "  smartctl -t long /dev/ad0              (Executes extended disk self-test)\n\n"
                    187:          "  smartctl --attributes --log=selftest --quietmode=errorsonly /dev/ad0\n"
                    188:          "                                      (Prints Self-Test & Attribute errors)\n"
                    189:          "                                      (Prints Self-Test & Attribute errors)\n\n"
                    190:          "  smartctl -a --device=3ware,2 /dev/twa0\n"
                    191:          "  smartctl -a --device=3ware,2 /dev/twe0\n"
                    192:          "                              (Prints all SMART information for ATA disk on\n"
                    193:          "                                 third port of first 3ware RAID controller)\n"
                    194:   "  smartctl -a --device=cciss,0 /dev/ciss0\n"
                    195:          "                              (Prints all SMART information for first disk \n"
                    196:          "                               on Common Interface for SCSI-3 Support driver)\n"
1.1.1.2 ! misho     197:   "  smartctl -a --device=areca,3/1 /dev/arcmsr0\n"
        !           198:          "                              (Prints all SMART information for 3rd disk in the 1st enclosure \n"
1.1       misho     199:          "                               on first ARECA RAID controller)\n"
                    200: 
                    201:          ;
                    202: 
                    203: bool freebsd_smart_device::is_open() const
                    204: {
                    205:   return (m_fd >= 0);
                    206: }
                    207: 
                    208: 
                    209: bool freebsd_smart_device::open()
                    210: {
                    211:   const char *dev = get_dev_name();
                    212:   if ((m_fd = ::open(dev,O_RDONLY))<0) {
                    213:     set_err(errno);
                    214:     return false;
                    215:   }
                    216:   return true;
                    217: }
                    218: 
                    219: bool freebsd_smart_device::close()
                    220: {
                    221:   int failed = 0;
                    222:   // close device, if open
                    223:   if (is_open())
                    224:     failed=::close(get_fd());
                    225: 
                    226:   set_fd(-1);
                    227: 
                    228:   if(failed) return false;
                    229:     else return true;
                    230: }
                    231: 
                    232: /////////////////////////////////////////////////////////////////////////////
                    233: /// Implement standard ATA support
                    234: 
                    235: class freebsd_ata_device
                    236: : public /*implements*/ ata_device,
                    237:   public /*extends*/ freebsd_smart_device
                    238: {
                    239: public:
                    240:   freebsd_ata_device(smart_interface * intf, const char * dev_name, const char * req_type);
                    241:   virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
                    242: 
                    243: protected:
                    244:   virtual int do_cmd(struct ata_ioc_request* request, bool is_48bit_cmd);
                    245: };
                    246: 
                    247: freebsd_ata_device::freebsd_ata_device(smart_interface * intf, const char * dev_name, const char * req_type)
                    248: : smart_device(intf, dev_name, "ata", req_type),
                    249:   freebsd_smart_device("ATA")
                    250: {
                    251: }
                    252: 
                    253: int freebsd_ata_device::do_cmd( struct ata_ioc_request* request, bool is_48bit_cmd)
                    254: {
                    255:   int fd = get_fd();
                    256:   ARGUSED(is_48bit_cmd); // no support for 48 bit commands in the IOCATAREQUEST
                    257:   return ioctl(fd, IOCATAREQUEST, request);
                    258: }
                    259: 
                    260: 
                    261: 
                    262: bool freebsd_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
                    263: {
                    264:   bool ata_48bit = false; // no ata_48bit_support via IOCATAREQUEST
                    265:   if(!strcmp("atacam",get_dev_type())) // enable for atacam interface
                    266:     ata_48bit = true;
                    267: 
                    268:   if (!ata_cmd_is_ok(in,
                    269:     true,  // data_out_support
                    270:     true,  // multi_sector_support
                    271:     ata_48bit) 
                    272:     ) 
                    273:     return false;
                    274: 
                    275:   struct ata_ioc_request request;
                    276:   bzero(&request,sizeof(struct ata_ioc_request));
                    277: 
                    278:   request.timeout=SCSI_TIMEOUT_DEFAULT;
                    279:   request.u.ata.command=in.in_regs.command;
                    280:   request.u.ata.feature=in.in_regs.features;
                    281: 
                    282:   request.u.ata.count = in.in_regs.sector_count_16;
                    283:   request.u.ata.lba = in.in_regs.lba_48;
                    284: 
                    285:   switch (in.direction) {
                    286:     case ata_cmd_in::no_data:  
                    287:       request.flags=ATA_CMD_CONTROL;
                    288:       break;
                    289:     case ata_cmd_in::data_in:  
                    290:       request.flags=ATA_CMD_READ | ATA_CMD_CONTROL;
                    291:       request.data=(char *)in.buffer;
                    292:       request.count=in.size;
                    293:       break;
                    294:     case ata_cmd_in::data_out: 
                    295:       request.flags=ATA_CMD_WRITE | ATA_CMD_CONTROL;
                    296:       request.data=(char *)in.buffer;
                    297:       request.count=in.size;
                    298:       break;
                    299:     default:
                    300:       return set_err(ENOSYS);
                    301:   }
                    302: 
                    303:   clear_err();
                    304:   errno = 0;
                    305:   if (do_cmd(&request, in.in_regs.is_48bit_cmd()))
                    306:       return set_err(errno);
                    307:   if (request.error)
                    308:       return set_err(EIO, "request failed, error code 0x%02x", request.error);
                    309: 
                    310:   out.out_regs.error = request.error;
                    311:   out.out_regs.sector_count_16 = request.u.ata.count;
                    312:   out.out_regs.lba_48 = request.u.ata.lba;
                    313: 
                    314: 
                    315:   // Command specific processing
                    316:   if (in.in_regs.command == ATA_SMART_CMD
                    317:        && in.in_regs.features == ATA_SMART_STATUS
                    318:        && in.out_needed.lba_high)
                    319:   {
                    320:     unsigned const char normal_lo=0x4f, normal_hi=0xc2;
                    321:     unsigned const char failed_lo=0xf4, failed_hi=0x2c;
                    322: 
                    323:     // Cyl low and Cyl high unchanged means "Good SMART status"
                    324:     if (!(out.out_regs.lba_mid==normal_lo && out.out_regs.lba_high==normal_hi)
                    325:     // These values mean "Bad SMART status"
                    326:         && !(out.out_regs.lba_mid==failed_lo && out.out_regs.lba_high==failed_hi))
                    327: 
                    328:     {
                    329:       // We haven't gotten output that makes sense; print out some debugging info
                    330:       char buf[512];
                    331:       sprintf(buf,"CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
                    332:         (int)request.u.ata.command,
                    333:         (int)request.u.ata.feature,
                    334:         (int)request.u.ata.count,
                    335:         (int)((request.u.ata.lba) & 0xff),
                    336:         (int)((request.u.ata.lba>>8) & 0xff),
                    337:         (int)((request.u.ata.lba>>16) & 0xff),
                    338:         (int)request.error);
                    339:       printwarning(BAD_SMART,buf);
                    340:       out.out_regs.lba_high = failed_hi; 
                    341:       out.out_regs.lba_mid = failed_lo;
                    342:     }
                    343:   }
                    344: 
                    345:   return true;
                    346: }
                    347: 
                    348: #if FREEBSDVER > 800100
                    349: class freebsd_atacam_device : public freebsd_ata_device
                    350: {
                    351: public:
                    352:   freebsd_atacam_device(smart_interface * intf, const char * dev_name, const char * req_type)
                    353:   : smart_device(intf, dev_name, "atacam", req_type), freebsd_ata_device(intf, dev_name, req_type)
                    354:   {}
                    355:   
                    356:   virtual bool open();
                    357:   virtual bool close();
                    358:   
                    359: protected:
                    360:   int m_fd;
                    361:   struct cam_device *m_camdev;
                    362: 
                    363:   virtual int do_cmd( struct ata_ioc_request* request , bool is_48bit_cmd);
                    364: };
                    365: 
                    366: bool freebsd_atacam_device::open(){
                    367:   const char *dev = get_dev_name();
                    368:   
                    369:   if ((m_camdev = cam_open_device(dev, O_RDWR)) == NULL) {
                    370:     set_err(errno);
                    371:     return false;
                    372:   }
                    373:   set_fd(m_camdev->fd);
                    374:   return true;
                    375: }
                    376: 
                    377: bool freebsd_atacam_device::close(){
                    378:   cam_close_device(m_camdev);
                    379:   set_fd(-1);
                    380:   return true;
                    381: }
                    382: 
                    383: int freebsd_atacam_device::do_cmd( struct ata_ioc_request* request, bool is_48bit_cmd)
                    384: {
                    385:   union ccb ccb;
                    386:   int camflags;
                    387: 
                    388:   memset(&ccb, 0, sizeof(ccb));
                    389: 
                    390:   if (request->count == 0)
                    391:     camflags = CAM_DIR_NONE;
                    392:   else if (request->flags & ATA_CMD_READ)
                    393:     camflags = CAM_DIR_IN;
                    394:   else
                    395:     camflags = CAM_DIR_OUT;
                    396:   if(is_48bit_cmd)
                    397:     camflags |= CAM_ATAIO_48BIT;
                    398: 
                    399:   cam_fill_ataio(&ccb.ataio,
                    400:                  0,
                    401:                  NULL,
                    402:                  camflags,
                    403:                  MSG_SIMPLE_Q_TAG,
                    404:                  (u_int8_t*)request->data,
                    405:                  request->count,
                    406:                  request->timeout * 1000); // timeout in seconds
                    407: 
                    408:   ccb.ataio.cmd.flags = CAM_ATAIO_NEEDRESULT;
                    409:   // ata_28bit_cmd
                    410:   ccb.ataio.cmd.command = request->u.ata.command;
                    411:   ccb.ataio.cmd.features = request->u.ata.feature;
                    412:   ccb.ataio.cmd.lba_low = request->u.ata.lba;
                    413:   ccb.ataio.cmd.lba_mid = request->u.ata.lba >> 8;
                    414:   ccb.ataio.cmd.lba_high = request->u.ata.lba >> 16;
                    415:   // ata_48bit cmd
                    416:   ccb.ataio.cmd.lba_low_exp = request->u.ata.lba >> 24;
                    417:   ccb.ataio.cmd.lba_mid_exp = request->u.ata.lba >> 32;
                    418:   ccb.ataio.cmd.lba_high_exp = request->u.ata.lba >> 40;
                    419:   ccb.ataio.cmd.device = 0x40 | ((request->u.ata.lba >> 24) & 0x0f);
                    420:   ccb.ataio.cmd.sector_count = request->u.ata.count;
                    421:   ccb.ataio.cmd.sector_count_exp = request->u.ata.count  >> 8;;
                    422: 
                    423:   ccb.ccb_h.flags |= CAM_DEV_QFRZDIS;
                    424: 
                    425:   if (cam_send_ccb(m_camdev, &ccb) < 0) {
                    426:     err(1, "cam_send_ccb");
                    427:     return -1;
                    428:   }
                    429: 
                    430:   if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
                    431:     cam_error_print(m_camdev, &ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
                    432:     return -1;
                    433:   }
                    434: 
                    435:   request->u.ata.lba =
                    436:     ((u_int64_t)(ccb.ataio.res.lba_low)) |
                    437:     ((u_int64_t)(ccb.ataio.res.lba_mid) << 8) |
                    438:     ((u_int64_t)(ccb.ataio.res.lba_high) << 16) |
                    439:     ((u_int64_t)(ccb.ataio.res.lba_low_exp) << 24) |
                    440:     ((u_int64_t)(ccb.ataio.res.lba_mid_exp) << 32) |
                    441:     ((u_int64_t)(ccb.ataio.res.lba_high_exp) << 40);
                    442: 
                    443:   request->u.ata.count = ccb.ataio.res.sector_count | (ccb.ataio.res.sector_count_exp << 8);
                    444:   request->error = ccb.ataio.res.error;
                    445: 
                    446:   return 0;
                    447: }
                    448: 
                    449: #endif
                    450: 
                    451: /////////////////////////////////////////////////////////////////////////////
                    452: /// Implement AMCC/3ware RAID support with old functions
                    453: 
                    454: class freebsd_escalade_device
                    455: : public /*implements*/ ata_device_with_command_set,
                    456:   public /*extends*/ freebsd_smart_device
                    457: {
                    458: public:
                    459:   freebsd_escalade_device(smart_interface * intf, const char * dev_name,
                    460:     int escalade_type, int disknum);
                    461: 
                    462: protected:
                    463:   virtual int ata_command_interface(smart_command_set command, int select, char * data);
                    464:   virtual bool open();
                    465: 
                    466: private:
                    467:   int m_escalade_type; ///< Type string for escalade_command_interface().
                    468:   int m_disknum; ///< Disk number.
                    469: };
                    470: 
                    471: freebsd_escalade_device::freebsd_escalade_device(smart_interface * intf, const char * dev_name,
                    472:     int escalade_type, int disknum)
                    473: : smart_device(intf, dev_name, "3ware", "3ware"),
                    474:   freebsd_smart_device(
                    475:     escalade_type==CONTROLLER_3WARE_9000_CHAR ? "ATA_3WARE_9000" :
                    476:     escalade_type==CONTROLLER_3WARE_678K_CHAR ? "ATA_3WARE_678K" :
                    477:     /*             CONTROLLER_3WARE_678K     */ "ATA"             ),
                    478:   m_escalade_type(escalade_type), m_disknum(disknum)
                    479: {
                    480:   set_info().info_name = strprintf("%s [3ware_disk_%02d]", dev_name, disknum);
                    481: }
                    482: 
                    483: bool freebsd_escalade_device::open()
                    484: {
                    485:   const char *dev = get_dev_name();
                    486:   int fd;
                    487:   
                    488:   if ((fd = ::open(dev,O_RDWR))<0) {
                    489:     set_err(errno);
                    490:     return false;
                    491:   }
                    492:   set_fd(fd);
                    493:   return true;
                    494: }
                    495: 
                    496: int freebsd_escalade_device::ata_command_interface(smart_command_set command, int select, char * data)
                    497: {
                    498:   // to hold true file descriptor
                    499:   int fd = get_fd();
                    500: 
                    501:   // return value and buffer for ioctl()
                    502:   int  ioctlreturn, readdata=0;
                    503:   struct twe_usercommand* cmd_twe = NULL;
                    504:   TW_OSLI_IOCTL_NO_DATA_BUF* cmd_twa = NULL;
                    505:   TWE_Command_ATA* ata = NULL;
                    506: 
                    507:   // Used by both the SCSI and char interfaces
                    508:   char ioctl_buffer[TW_IOCTL_BUFFER_SIZE];
                    509: 
                    510:   if (m_disknum < 0) {
                    511:     printwarning(NO_DISK_3WARE,NULL);
                    512:     return -1;
                    513:   }
                    514: 
                    515:   memset(ioctl_buffer, 0, TW_IOCTL_BUFFER_SIZE);
                    516: 
                    517:   if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) {
                    518:     cmd_twa = (TW_OSLI_IOCTL_NO_DATA_BUF*)ioctl_buffer;
                    519:     cmd_twa->pdata = ((TW_OSLI_IOCTL_WITH_PAYLOAD*)cmd_twa)->payload.data_buf;
                    520:     cmd_twa->driver_pkt.buffer_length = 512;
                    521:     ata = (TWE_Command_ATA*)&cmd_twa->cmd_pkt.command.cmd_pkt_7k;
                    522:   } else if (m_escalade_type==CONTROLLER_3WARE_678K_CHAR) {
                    523:     cmd_twe = (struct twe_usercommand*)ioctl_buffer;
                    524:     ata = &cmd_twe->tu_command.ata;
                    525:   } else {
                    526:     pout("Unrecognized escalade_type %d in freebsd_3ware_command_interface(disk %d)\n"
                    527:       "Please contact " PACKAGE_BUGREPORT "\n", m_escalade_type, m_disknum);
                    528:     errno=ENOSYS;
                    529:     return -1;
                    530:   }
                    531: 
                    532:   ata->opcode = TWE_OP_ATA_PASSTHROUGH;
                    533: 
                    534:   // Same for (almost) all commands - but some reset below
                    535:   ata->request_id    = 0xFF;
                    536:   ata->unit          = m_disknum;
                    537:   ata->status        = 0;           
                    538:   ata->flags         = 0x1;
                    539:   ata->drive_head    = 0x0;
                    540:   ata->sector_num    = 0;
                    541: 
                    542:   // All SMART commands use this CL/CH signature.  These are magic
                    543:   // values from the ATA specifications.
                    544:   ata->cylinder_lo   = 0x4F;
                    545:   ata->cylinder_hi   = 0xC2;
                    546: 
                    547:   // SMART ATA COMMAND REGISTER value
                    548:   ata->command       = ATA_SMART_CMD;
                    549: 
                    550:   // Is this a command that reads or returns 512 bytes?
                    551:   // passthru->param values are:
                    552:   // 0x0 - non data command without TFR write check,
                    553:   // 0x8 - non data command with TFR write check,
                    554:   // 0xD - data command that returns data to host from device
                    555:   // 0xF - data command that writes data from host to device
                    556:   // passthru->size values are 0x5 for non-data and 0x07 for data
                    557:   if (command == READ_VALUES     ||
                    558:       command == READ_THRESHOLDS ||
                    559:       command == READ_LOG        ||
                    560:       command == IDENTIFY        ||
                    561:       command == WRITE_LOG ) 
                    562:   {
                    563:     readdata=1;
                    564:     if (m_escalade_type==CONTROLLER_3WARE_678K_CHAR) {
                    565:       cmd_twe->tu_data = data;
                    566:       cmd_twe->tu_size = 512;
                    567:     }
                    568:     ata->sgl_offset = 0x5;
                    569:     ata->size         = 0x5;
                    570:     ata->param        = 0xD;
                    571:     ata->sector_count = 0x1;
                    572:     // For 64-bit to work correctly, up the size of the command packet
                    573:     // in dwords by 1 to account for the 64-bit single sgl 'address'
                    574:     // field. Note that this doesn't agree with the typedefs but it's
                    575:     // right (agree with kernel driver behavior/typedefs).
                    576:     //if (sizeof(long)==8)
                    577:     //  ata->size++;
                    578:   }
                    579:   else {
                    580:     // Non data command -- but doesn't use large sector 
                    581:     // count register values.  
                    582:     ata->sgl_offset = 0x0;
                    583:     ata->size         = 0x5;
                    584:     ata->param        = 0x8;
                    585:     ata->sector_count = 0x0;
                    586:   }
                    587: 
                    588:   // Now set ATA registers depending upon command
                    589:   switch (command){
                    590:   case CHECK_POWER_MODE:
                    591:     ata->command     = ATA_CHECK_POWER_MODE;
                    592:     ata->features    = 0;
                    593:     ata->cylinder_lo = 0;
                    594:     ata->cylinder_hi = 0;
                    595:     break;
                    596:   case READ_VALUES:
                    597:     ata->features = ATA_SMART_READ_VALUES;
                    598:     break;
                    599:   case READ_THRESHOLDS:
                    600:     ata->features = ATA_SMART_READ_THRESHOLDS;
                    601:     break;
                    602:   case READ_LOG:
                    603:     ata->features = ATA_SMART_READ_LOG_SECTOR;
                    604:     // log number to return
                    605:     ata->sector_num  = select;
                    606:     break;
                    607:   case WRITE_LOG:
                    608:     readdata=0;
                    609:     ata->features     = ATA_SMART_WRITE_LOG_SECTOR;
                    610:     ata->sector_count = 1;
                    611:     ata->sector_num   = select;
                    612:     ata->param        = 0xF;  // PIO data write
                    613:     break;
                    614:   case IDENTIFY:
                    615:     // ATA IDENTIFY DEVICE
                    616:     ata->command     = ATA_IDENTIFY_DEVICE;
                    617:     ata->features    = 0;
                    618:     ata->cylinder_lo = 0;
                    619:     ata->cylinder_hi = 0;
                    620:     break;
                    621:   case PIDENTIFY:
                    622:     // 3WARE controller can NOT have packet device internally
                    623:     pout("WARNING - NO DEVICE FOUND ON 3WARE CONTROLLER (disk %d)\n", m_disknum);
                    624:     errno=ENODEV;
                    625:     return -1;
                    626:   case ENABLE:
                    627:     ata->features = ATA_SMART_ENABLE;
                    628:     break;
                    629:   case DISABLE:
                    630:     ata->features = ATA_SMART_DISABLE;
                    631:     break;
                    632:   case AUTO_OFFLINE:
                    633:     ata->features     = ATA_SMART_AUTO_OFFLINE;
                    634:     // Enable or disable?
                    635:     ata->sector_count = select;
                    636:     break;
                    637:   case AUTOSAVE:
                    638:     ata->features     = ATA_SMART_AUTOSAVE;
                    639:     // Enable or disable?
                    640:     ata->sector_count = select;
                    641:     break;
                    642:   case IMMEDIATE_OFFLINE:
                    643:     ata->features    = ATA_SMART_IMMEDIATE_OFFLINE;
                    644:     // What test type to run?
                    645:     ata->sector_num  = select;
                    646:     break;
                    647:   case STATUS_CHECK:
                    648:     ata->features = ATA_SMART_STATUS;
                    649:     break;
                    650:   case STATUS:
                    651:     // This is JUST to see if SMART is enabled, by giving SMART status
                    652:     // command. But it doesn't say if status was good, or failing.
                    653:     // See below for the difference.
                    654:     ata->features = ATA_SMART_STATUS;
                    655:     break;
                    656:   default:
                    657:     pout("Unrecognized command %d in freebsd_3ware_command_interface(disk %d)\n"
                    658:          "Please contact " PACKAGE_BUGREPORT "\n", command, m_disknum);
                    659:     errno=ENOSYS;
                    660:     return -1;
                    661:   }
                    662: 
                    663:   // Now send the command down through an ioctl()
                    664:   if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) {
                    665:     ioctlreturn=ioctl(fd,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa);
                    666:   } else {
                    667:     ioctlreturn=ioctl(fd,TWEIO_COMMAND,cmd_twe);
                    668:   }
                    669: 
                    670:   // Deal with the different error cases
                    671:   if (ioctlreturn) {
                    672:     if (!errno)
                    673:       errno=EIO;
                    674:     return -1;
                    675:   }
                    676: 
                    677:   // See if the ATA command failed.  Now that we have returned from
                    678:   // the ioctl() call, if passthru is valid, then:
                    679:   // - ata->status contains the 3ware controller STATUS
                    680:   // - ata->command contains the ATA STATUS register
                    681:   // - ata->features contains the ATA ERROR register
                    682:   //
                    683:   // Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS
                    684:   // If bit 0 (error bit) is set, then ATA ERROR register is valid.
                    685:   // While we *might* decode the ATA ERROR register, at the moment it
                    686:   // doesn't make much sense: we don't care in detail why the error
                    687:   // happened.
                    688: 
                    689:   if (ata->status || (ata->command & 0x21)) {
                    690:     pout("Command failed, ata.status=(0x%2.2x), ata.command=(0x%2.2x), ata.flags=(0x%2.2x)\n",ata->status,ata->command,ata->flags);
                    691:     errno=EIO;
                    692:     return -1;
                    693:   }
                    694: 
                    695:   // If this is a read data command, copy data to output buffer
                    696:   if (readdata) {
                    697:     if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR)
                    698:       memcpy(data, cmd_twa->pdata, 512);
                    699:   }
                    700: 
                    701:   // For STATUS_CHECK, we need to check register values
                    702:   if (command==STATUS_CHECK) {
                    703: 
                    704:     // To find out if the SMART RETURN STATUS is good or failing, we
                    705:     // need to examine the values of the Cylinder Low and Cylinder
                    706:     // High Registers.
                    707: 
                    708:     unsigned short cyl_lo=ata->cylinder_lo;
                    709:     unsigned short cyl_hi=ata->cylinder_hi;
                    710: 
                    711:     // If values in Cyl-LO and Cyl-HI are unchanged, SMART status is good.
                    712:     if (cyl_lo==0x4F && cyl_hi==0xC2)
                    713:       return 0;
                    714: 
                    715:     // If values in Cyl-LO and Cyl-HI are as follows, SMART status is FAIL
                    716:     if (cyl_lo==0xF4 && cyl_hi==0x2C)
                    717:       return 1;
                    718: 
                    719:       errno=EIO;
                    720:       return -1;
                    721:   }
                    722: 
                    723:   // copy sector count register (one byte!) to return data
                    724:   if (command==CHECK_POWER_MODE)
                    725:     *data=*(char *)&(ata->sector_count);
                    726: 
                    727:   // look for nonexistent devices/ports
                    728:   if (command==IDENTIFY && !nonempty(data, 512)) {
                    729:     errno=ENODEV;
                    730:     return -1;
                    731:   }
                    732: 
                    733:   return 0;
                    734: }
                    735: 
                    736: 
                    737: /////////////////////////////////////////////////////////////////////////////
                    738: /// Implement Highpoint RAID support with old functions
                    739: 
                    740: class freebsd_highpoint_device
                    741: : public /*implements*/ ata_device_with_command_set,
                    742:   public /*extends*/ freebsd_smart_device
                    743: {
                    744: public:
                    745:   freebsd_highpoint_device(smart_interface * intf, const char * dev_name,
                    746:     unsigned char controller, unsigned char channel, unsigned char port);
                    747: 
                    748: protected:
                    749:   virtual int ata_command_interface(smart_command_set command, int select, char * data);
                    750:   virtual bool open();
                    751: 
                    752: private:
                    753:   unsigned char m_hpt_data[3]; ///< controller/channel/port
                    754: };
                    755: 
                    756: 
                    757: freebsd_highpoint_device::freebsd_highpoint_device(smart_interface * intf, const char * dev_name,
                    758:   unsigned char controller, unsigned char channel, unsigned char port)
                    759: : smart_device(intf, dev_name, "hpt", "hpt"),
                    760:   freebsd_smart_device("ATA")
                    761: {
                    762:   m_hpt_data[0] = controller; m_hpt_data[1] = channel; m_hpt_data[2] = port;
                    763:   set_info().info_name = strprintf("%s [hpt_disk_%u/%u/%u]", dev_name, m_hpt_data[0], m_hpt_data[1], m_hpt_data[2]);
                    764: }
                    765: 
                    766: bool freebsd_highpoint_device::open()
                    767: {
                    768:   const char *dev = get_dev_name();
                    769:   int fd;
                    770:   
                    771:   if ((fd = ::open(dev,O_RDWR))<0) {
                    772:     set_err(errno);
                    773:     return false;
                    774:   }
                    775:   set_fd(fd);
                    776:   return true;
                    777: }
                    778: 
                    779: int freebsd_highpoint_device::ata_command_interface(smart_command_set command, int select, char * data)
                    780: {
                    781:   int fd=get_fd(); 
                    782:   int ids[2];
                    783:   HPT_IOCTL_PARAM param;
                    784:   HPT_CHANNEL_INFO_V2 info;
                    785:   unsigned char* buff[512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER)];
                    786:   PHPT_PASS_THROUGH_HEADER pide_pt_hdr, pide_pt_hdr_out;
                    787: 
                    788:   // get internal deviceid
                    789:   ids[0] = m_hpt_data[0] - 1;
                    790:   ids[1] = m_hpt_data[1] - 1;
                    791: 
                    792:   memset(&param, 0, sizeof(HPT_IOCTL_PARAM));
                    793: 
                    794:   param.magic = HPT_IOCTL_MAGIC;
                    795:   param.ctrl_code = HPT_IOCTL_GET_CHANNEL_INFO_V2;
                    796:   param.in = (unsigned char *)ids;
                    797:   param.in_size = sizeof(unsigned int) * 2;
                    798:   param.out = (unsigned char *)&info;
                    799:   param.out_size = sizeof(HPT_CHANNEL_INFO_V2);
                    800: 
                    801:   if (m_hpt_data[2]==1) {
                    802:     param.ctrl_code = HPT_IOCTL_GET_CHANNEL_INFO;
                    803:     param.out_size = sizeof(HPT_CHANNEL_INFO);
                    804:   }
                    805:   if (ioctl(fd, HPT_DO_IOCONTROL, &param)!=0 ||
                    806:       info.devices[m_hpt_data[2]-1]==0) {
                    807:     return -1;
                    808:   }
                    809: 
                    810:   // perform smart action
                    811:   memset(buff, 0, 512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER));
                    812:   pide_pt_hdr = (PHPT_PASS_THROUGH_HEADER)buff;
                    813: 
                    814:   pide_pt_hdr->lbamid = 0x4f;
                    815:   pide_pt_hdr->lbahigh = 0xc2;
                    816:   pide_pt_hdr->command = ATA_SMART_CMD;
                    817:   pide_pt_hdr->id = info.devices[m_hpt_data[2] - 1];
                    818: 
                    819:   switch (command){
                    820:   case READ_VALUES:
                    821:     pide_pt_hdr->feature=ATA_SMART_READ_VALUES;
                    822:     pide_pt_hdr->protocol=HPT_READ;
                    823:     break;
                    824:   case READ_THRESHOLDS:
                    825:     pide_pt_hdr->feature=ATA_SMART_READ_THRESHOLDS;
                    826:     pide_pt_hdr->protocol=HPT_READ;
                    827:     break;
                    828:   case READ_LOG:
                    829:     pide_pt_hdr->feature=ATA_SMART_READ_LOG_SECTOR;
                    830:     pide_pt_hdr->lbalow=select;
                    831:     pide_pt_hdr->protocol=HPT_READ;
                    832:     break;
                    833:   case IDENTIFY:
                    834:     pide_pt_hdr->command=ATA_IDENTIFY_DEVICE;
                    835:     pide_pt_hdr->protocol=HPT_READ;
                    836:     break;
                    837:   case ENABLE:
                    838:     pide_pt_hdr->feature=ATA_SMART_ENABLE;
                    839:     break;
                    840:   case DISABLE:
                    841:     pide_pt_hdr->feature=ATA_SMART_DISABLE;
                    842:     break;
                    843:   case AUTO_OFFLINE:
                    844:     pide_pt_hdr->feature=ATA_SMART_AUTO_OFFLINE;
                    845:     pide_pt_hdr->sectorcount=select;
                    846:     break;
                    847:   case AUTOSAVE:
                    848:     pide_pt_hdr->feature=ATA_SMART_AUTOSAVE;
                    849:     pide_pt_hdr->sectorcount=select;
                    850:     break;
                    851:   case IMMEDIATE_OFFLINE:
                    852:     pide_pt_hdr->feature=ATA_SMART_IMMEDIATE_OFFLINE;
                    853:     pide_pt_hdr->lbalow=select;
                    854:     break;
                    855:   case STATUS_CHECK:
                    856:   case STATUS:
                    857:     pide_pt_hdr->feature=ATA_SMART_STATUS;
                    858:     break;
                    859:   case CHECK_POWER_MODE:
                    860:     pide_pt_hdr->command=ATA_CHECK_POWER_MODE;
                    861:     break;
                    862:   case WRITE_LOG:
                    863:     memcpy(buff+sizeof(HPT_PASS_THROUGH_HEADER), data, 512);
                    864:     pide_pt_hdr->feature=ATA_SMART_WRITE_LOG_SECTOR;
                    865:     pide_pt_hdr->lbalow=select;
                    866:     pide_pt_hdr->protocol=HPT_WRITE;
                    867:     break;
                    868:   default:
                    869:     pout("Unrecognized command %d in highpoint_command_interface()\n"
                    870:          "Please contact " PACKAGE_BUGREPORT "\n", command);
                    871:     errno=ENOSYS;
                    872:     return -1;
                    873:   }
                    874:   if (pide_pt_hdr->protocol!=0) {
                    875:     pide_pt_hdr->sectors = 1;
                    876:     pide_pt_hdr->sectorcount = 1;
                    877:   }
                    878: 
                    879:   memset(&param, 0, sizeof(HPT_IOCTL_PARAM));
                    880: 
                    881:   param.magic = HPT_IOCTL_MAGIC;
                    882:   param.ctrl_code = HPT_IOCTL_IDE_PASS_THROUGH;
                    883:   param.in = (unsigned char *)buff;
                    884:   param.in_size = sizeof(HPT_PASS_THROUGH_HEADER) + (pide_pt_hdr->protocol==HPT_READ ? 0 : pide_pt_hdr->sectors * 512);
                    885:   param.out = (unsigned char *)buff+param.in_size;
                    886:   param.out_size = sizeof(HPT_PASS_THROUGH_HEADER) + (pide_pt_hdr->protocol==HPT_READ ? pide_pt_hdr->sectors * 512 : 0);
                    887: 
                    888:   pide_pt_hdr_out = (PHPT_PASS_THROUGH_HEADER)param.out;
                    889: 
                    890:   if ((ioctl(fd, HPT_DO_IOCONTROL, &param)!=0) ||
                    891:       (pide_pt_hdr_out->command & 1)) {
                    892:     return -1;
                    893:   }
                    894: 
                    895:   if (command==STATUS_CHECK)
                    896:   {
                    897:     unsigned const char normal_lo=0x4f, normal_hi=0xc2;
                    898:     unsigned const char failed_lo=0xf4, failed_hi=0x2c;
                    899:     unsigned char low,high;
                    900: 
                    901:     high = pide_pt_hdr_out->lbahigh;
                    902:     low = pide_pt_hdr_out->lbamid;
                    903: 
                    904:     // Cyl low and Cyl high unchanged means "Good SMART status"
                    905:     if (low==normal_lo && high==normal_hi)
                    906:       return 0;
                    907: 
                    908:     // These values mean "Bad SMART status"
                    909:     if (low==failed_lo && high==failed_hi)
                    910:       return 1;
                    911: 
                    912:     // We haven't gotten output that makes sense; print out some debugging info
                    913:     char buf[512];
                    914:     sprintf(buf,"CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
                    915:             (int)pide_pt_hdr_out->command,
                    916:             (int)pide_pt_hdr_out->feature,
                    917:             (int)pide_pt_hdr_out->sectorcount,
                    918:             (int)pide_pt_hdr_out->lbalow,
                    919:             (int)pide_pt_hdr_out->lbamid,
                    920:             (int)pide_pt_hdr_out->lbahigh,
                    921:             (int)pide_pt_hdr_out->sectors);
                    922:     printwarning(BAD_SMART,buf);
                    923:   }
                    924:   else if (command==CHECK_POWER_MODE)
                    925:     data[0] = pide_pt_hdr_out->sectorcount & 0xff;
                    926:   else if (pide_pt_hdr->protocol==HPT_READ)
                    927:     memcpy(data, (unsigned char *)buff + 2 * sizeof(HPT_PASS_THROUGH_HEADER), 
                    928:       pide_pt_hdr->sectors * 512);
                    929:   return 0;
                    930: }
                    931: 
                    932: 
                    933: /////////////////////////////////////////////////////////////////////////////
1.1.1.2 ! misho     934: /// Standard SCSI support
1.1       misho     935: 
                    936: class freebsd_scsi_device
                    937: : public /*implements*/ scsi_device,
                    938:   public /*extends*/ freebsd_smart_device
                    939: {
                    940: public:
                    941:   freebsd_scsi_device(smart_interface * intf, const char * dev_name, const char * req_type);
                    942: 
                    943:   virtual smart_device * autodetect_open();
                    944: 
                    945:   virtual bool scsi_pass_through(scsi_cmnd_io * iop);
                    946:   
                    947:   virtual bool open();
                    948: 
                    949:   virtual bool close();
                    950:   
                    951: private:
                    952:   int m_fd;
                    953:   struct cam_device *m_camdev;
                    954: };
                    955: 
                    956: bool freebsd_scsi_device::open(){
                    957:   const char *dev = get_dev_name();
                    958:   
                    959:   if ((m_camdev = cam_open_device(dev, O_RDWR)) == NULL) {
                    960:     set_err(errno);
                    961:     return false;
                    962:   }
                    963:   set_fd(m_camdev->fd);
                    964:   return true;
                    965: }
                    966: 
                    967: bool freebsd_scsi_device::close(){
                    968:   cam_close_device(m_camdev);
                    969:   set_fd(-1);
                    970:   return true;
                    971: }
                    972: 
                    973: freebsd_scsi_device::freebsd_scsi_device(smart_interface * intf,
                    974:   const char * dev_name, const char * req_type)
                    975: : smart_device(intf, dev_name, "scsi", req_type),
                    976:   freebsd_smart_device("SCSI")
                    977: {
                    978: }
                    979: 
                    980: 
                    981: bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io * iop)
                    982: {
                    983:   int report=scsi_debugmode;
                    984:   union ccb *ccb;
                    985: 
                    986:   if (report > 0) {
                    987:     unsigned int k;
                    988:     const unsigned char * ucp = iop->cmnd;
                    989:     const char * np;
                    990: 
                    991:     np = scsi_get_opcode_name(ucp[0]);
                    992:     pout(" [%s: ", np ? np : "<unknown opcode>");
                    993:     for (k = 0; k < iop->cmnd_len; ++k)
                    994:       pout("%02x ", ucp[k]);
                    995:     if ((report > 1) && 
                    996:       (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) {
                    997:     int trunc = (iop->dxfer_len > 256) ? 1 : 0;
                    998: 
                    999:     pout("]\n  Outgoing data, len=%d%s:\n", (int)iop->dxfer_len,
                   1000:       (trunc ? " [only first 256 bytes shown]" : ""));
                   1001:     dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
                   1002:       }
                   1003:       else
                   1004:         pout("]");
                   1005:   }
                   1006: 
                   1007:   if(m_camdev==NULL) {
                   1008:     warnx("error: camdev=0!");
                   1009:     return -ENOTTY;
                   1010:   }
                   1011: 
                   1012:   if (!(ccb = cam_getccb(m_camdev))) {
                   1013:     warnx("error allocating ccb");
                   1014:     return -ENOMEM;
                   1015:   }
1.1.1.2 ! misho    1016:   // mfi SAT layer is known to be buggy
        !          1017:   if(!strcmp("mfi",m_camdev->sim_name)) {
        !          1018:     if (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 || iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16) { 
        !          1019:       // Controller does not return ATA output registers in SAT sense data
        !          1020:       if (iop->cmnd[2] & (1 << 5)) // chk_cond
        !          1021:         return set_err(ENOSYS, "ATA return descriptor not supported by controller firmware");
        !          1022:     }
        !          1023:     // SMART WRITE LOG SECTOR causing media errors
        !          1024:     if ((iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16 && iop->cmnd[14] == ATA_SMART_CMD 
        !          1025:         && iop->cmnd[3]==0 && iop->cmnd[4] == ATA_SMART_WRITE_LOG_SECTOR) || 
        !          1026:         (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 && iop->cmnd[9] == ATA_SMART_CMD &&
        !          1027:         iop->cmnd[3] == ATA_SMART_WRITE_LOG_SECTOR)) 
        !          1028:       return set_err(ENOSYS, "SMART WRITE LOG SECTOR command is not supported by controller firmware"); 
        !          1029:   }
1.1       misho    1030: 
                   1031:   // clear out structure, except for header that was filled in for us
                   1032:   bzero(&(&ccb->ccb_h)[1],
                   1033:     sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
                   1034: 
                   1035:   cam_fill_csio(&ccb->csio,
                   1036:     /*retrires*/ 1,
                   1037:     /*cbfcnp*/ NULL,
                   1038:     /* flags */ (iop->dxfer_dir == DXFER_NONE ? CAM_DIR_NONE :(iop->dxfer_dir == DXFER_FROM_DEVICE ? CAM_DIR_IN : CAM_DIR_OUT)),
                   1039:     /* tagaction */ MSG_SIMPLE_Q_TAG,
                   1040:     /* dataptr */ iop->dxferp,
                   1041:     /* datalen */ iop->dxfer_len,
                   1042:     /* senselen */ iop->max_sense_len,
                   1043:     /* cdblen */ iop->cmnd_len,
                   1044:     /* timout (converted to seconds) */ iop->timeout*1000);
                   1045:   memcpy(ccb->csio.cdb_io.cdb_bytes,iop->cmnd,iop->cmnd_len);
                   1046: 
                   1047:   if (cam_send_ccb(m_camdev,ccb) < 0) {
                   1048:     warn("error sending SCSI ccb");
                   1049:     cam_error_print(m_camdev,ccb,CAM_ESF_ALL,CAM_EPF_ALL,stderr);
                   1050:     cam_freeccb(ccb);
                   1051:     return -EIO;
                   1052:   }
                   1053: 
                   1054:   if (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_SCSI_STATUS_ERROR)) {
                   1055:     cam_error_print(m_camdev,ccb,CAM_ESF_ALL,CAM_EPF_ALL,stderr);
                   1056:     cam_freeccb(ccb);
                   1057:     return -EIO;
                   1058:   }
                   1059: 
                   1060:   if (iop->sensep) {
1.1.1.2 ! misho    1061:     iop->resp_sense_len = ccb->csio.sense_len - ccb->csio.sense_resid;
        !          1062:     memcpy(iop->sensep,&(ccb->csio.sense_data),iop->resp_sense_len);
1.1       misho    1063:   }
                   1064: 
                   1065:   iop->scsi_status = ccb->csio.scsi_status;
                   1066: 
                   1067:   cam_freeccb(ccb);
                   1068: 
                   1069:   if (report > 0) {
                   1070:     int trunc;
                   1071: 
                   1072:     pout("  status=0\n");
                   1073:     trunc = (iop->dxfer_len > 256) ? 1 : 0;
                   1074: 
                   1075:     pout("  Incoming data, len=%d%s:\n", (int)iop->dxfer_len,
                   1076:       (trunc ? " [only first 256 bytes shown]" : ""));
                   1077:     dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
                   1078:   }
                   1079: 
                   1080:   return true;
                   1081: }
                   1082: 
                   1083: 
                   1084: /////////////////////////////////////////////////////////////////////////////
                   1085: /// Areca RAID support
                   1086: 
                   1087: class freebsd_areca_device
                   1088: : public /*implements*/ ata_device,
                   1089:   public /*extends*/ freebsd_smart_device
                   1090: {
                   1091: public:
1.1.1.2 ! misho    1092:   freebsd_areca_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
1.1       misho    1093: 
                   1094: protected:
                   1095:   virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); 
                   1096: 
                   1097: private:
                   1098:   int m_disknum; ///< Disk number.
1.1.1.2 ! misho    1099:   int m_encnum;
1.1       misho    1100: };
                   1101: 
                   1102: 
                   1103: // PURPOSE
                   1104: //   This is an interface routine meant to isolate the OS dependent
                   1105: //   parts of the code, and to provide a debugging interface.  Each
                   1106: //   different port and OS needs to provide it's own interface.  This
                   1107: //   is the linux interface to the Areca "arcmsr" driver.  It allows ATA
                   1108: //   commands to be passed through the SCSI driver.
                   1109: // DETAILED DESCRIPTION OF ARGUMENTS
                   1110: //   fd: is the file descriptor provided by open()
                   1111: //   disknum is the disk number (0 to 15) in the RAID array
                   1112: //   command: defines the different operations.
                   1113: //   select: additional input data if needed (which log, which type of
                   1114: //           self-test).
                   1115: //   data:   location to write output data, if needed (512 bytes).
                   1116: //   Note: not all commands use all arguments.
                   1117: // RETURN VALUES
                   1118: //  -1 if the command failed
                   1119: //   0 if the command succeeded,
                   1120: //   STATUS_CHECK routine: 
                   1121: //  -1 if the command failed
                   1122: //   0 if the command succeeded and disk SMART status is "OK"
                   1123: //   1 if the command succeeded and disk SMART status is "FAILING"
                   1124: 
                   1125: 
                   1126: /*FunctionCode*/
                   1127: #define FUNCTION_READ_RQBUFFER                 0x0801
                   1128: #define FUNCTION_WRITE_WQBUFFER                0x0802
                   1129: #define FUNCTION_CLEAR_RQBUFFER                0x0803
                   1130: #define FUNCTION_CLEAR_WQBUFFER                0x0804
                   1131: 
                   1132: /* ARECA IO CONTROL CODE*/
                   1133: #define ARCMSR_IOCTL_READ_RQBUFFER           _IOWR('F', FUNCTION_READ_RQBUFFER, sSRB_BUFFER)
                   1134: #define ARCMSR_IOCTL_WRITE_WQBUFFER          _IOWR('F', FUNCTION_WRITE_WQBUFFER, sSRB_BUFFER)
                   1135: #define ARCMSR_IOCTL_CLEAR_RQBUFFER          _IOWR('F', FUNCTION_CLEAR_RQBUFFER, sSRB_BUFFER)
                   1136: #define ARCMSR_IOCTL_CLEAR_WQBUFFER          _IOWR('F', FUNCTION_CLEAR_WQBUFFER, sSRB_BUFFER)
                   1137: #define ARECA_SIG_STR                                                  "ARCMSR"
                   1138: 
                   1139: 
                   1140: 
                   1141: // The SRB_IO_CONTROL & SRB_BUFFER structures are used to communicate(to/from) to areca driver
                   1142: typedef struct _SRB_IO_CONTROL
                   1143: {
                   1144:        unsigned int HeaderLength;
                   1145:        unsigned char Signature[8];
                   1146:        unsigned int Timeout;
                   1147:        unsigned int ControlCode;
                   1148:        unsigned int ReturnCode;
                   1149:        unsigned int Length;
                   1150: } sSRB_IO_CONTROL;
                   1151: 
                   1152: typedef struct _SRB_BUFFER
                   1153: {
                   1154:        sSRB_IO_CONTROL srbioctl;
                   1155:        unsigned char   ioctldatabuffer[1032]; // the buffer to put the command data to/from firmware
                   1156: } sSRB_BUFFER;
                   1157: 
                   1158: 
                   1159: // For debugging areca code
                   1160: 
                   1161: static void areca_dumpdata(unsigned char *block, int len)
                   1162: {
                   1163:        int ln = (len / 16) + 1;         // total line#
                   1164:        unsigned char c;
                   1165:        int pos = 0;
                   1166: 
                   1167:        printf(" Address = %p, Length = (0x%x)%d\n", block, len, len);
                   1168:        printf("      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F      ASCII      \n");
                   1169:        printf("=====================================================================\n");
                   1170: 
                   1171:        for ( int l = 0; l < ln && len; l++ )
                   1172:        {
                   1173:                // printf the line# and the HEX data
                   1174:                // if a line data length < 16 then append the space to the tail of line to reach 16 chars
                   1175:                printf("%02X | ", l);
                   1176:                for ( pos = 0; pos < 16 && len; pos++, len-- )
                   1177:                {
                   1178:                        c = block[l*16+pos];    
                   1179:                        printf("%02X ", c);
                   1180:                }
                   1181: 
                   1182:                if ( pos < 16 )
                   1183:                {
                   1184:                        for ( int loop = pos; loop < 16; loop++ )
                   1185:                        {
                   1186:                                printf("   ");
                   1187:                        }
                   1188:                }
                   1189: 
                   1190:                // print ASCII char
                   1191:                for ( int loop = 0; loop < pos; loop++ )
                   1192:                {
                   1193:                        c = block[l*16+loop];
                   1194:                        if ( c >= 0x20 && c <= 0x7F )
                   1195:                        {
                   1196:                                printf("%c", c);
                   1197:                        }
                   1198:                        else
                   1199:                        {
                   1200:                                printf(".");
                   1201:                        }
                   1202:                }
                   1203:                printf("\n");
                   1204:        }   
                   1205:        printf("=====================================================================\n");
                   1206: }
                   1207: 
                   1208: 
                   1209: static int arcmsr_command_handler(int fd, unsigned long arcmsr_cmd, unsigned char *data, int data_len, void *ext_data /* reserved for further use */)
                   1210: {
                   1211:        ARGUSED(ext_data);
                   1212: 
                   1213:        int ioctlreturn = 0;
                   1214:        sSRB_BUFFER sBuf;
                   1215: 
                   1216:        unsigned char *areca_return_packet;
                   1217:        int total = 0;
                   1218:        int expected = -1;
                   1219:        unsigned char return_buff[2048];
                   1220:        unsigned char *ptr = &return_buff[0];
                   1221:        memset(return_buff, 0, sizeof(return_buff));
                   1222: 
                   1223:        memset((unsigned char *)&sBuf, 0, sizeof(sBuf));
                   1224: 
                   1225: 
                   1226:        sBuf.srbioctl.HeaderLength = sizeof(sSRB_IO_CONTROL);   
                   1227:        memcpy(sBuf.srbioctl.Signature, ARECA_SIG_STR, strlen(ARECA_SIG_STR));
                   1228:        sBuf.srbioctl.Timeout = 10000;      
                   1229:        sBuf.srbioctl.ControlCode = ARCMSR_IOCTL_READ_RQBUFFER;
                   1230: 
                   1231:        switch ( arcmsr_cmd )
                   1232:        {
                   1233:        // command for writing data to driver
                   1234:        case ARCMSR_IOCTL_WRITE_WQBUFFER:   
                   1235:                if ( data && data_len )
                   1236:                {
                   1237:                        sBuf.srbioctl.Length = data_len;    
                   1238:                        memcpy((unsigned char *)sBuf.ioctldatabuffer, (unsigned char *)data, data_len);
                   1239:                }
                   1240:                // commands for clearing related buffer of driver
                   1241:        case ARCMSR_IOCTL_CLEAR_RQBUFFER:
                   1242:        case ARCMSR_IOCTL_CLEAR_WQBUFFER:
                   1243:                break;
                   1244:                // command for reading data from driver
                   1245:        case ARCMSR_IOCTL_READ_RQBUFFER:    
                   1246:                break;
                   1247:        default:
                   1248:                // unknown arcmsr commands
                   1249:                return -1;
                   1250:        }
                   1251: 
                   1252: 
                   1253:        while ( 1 )
                   1254:        {
                   1255:                ioctlreturn = ioctl(fd,arcmsr_cmd,&sBuf);
                   1256:                if ( ioctlreturn  )
                   1257:                {
                   1258:                        // errors found
                   1259:                        break;
                   1260:                }
                   1261: 
                   1262:                if ( arcmsr_cmd != ARCMSR_IOCTL_READ_RQBUFFER )
                   1263:                {
                   1264:                        // if succeeded, just returns the length of outgoing data
                   1265:                        return data_len;
                   1266:                }
                   1267: 
                   1268:                if ( sBuf.srbioctl.Length )
                   1269:                {
                   1270:                        if(ata_debugmode)
                   1271:                            areca_dumpdata(&sBuf.ioctldatabuffer[0], sBuf.srbioctl.Length);
                   1272:                        memcpy(ptr, &sBuf.ioctldatabuffer[0], sBuf.srbioctl.Length);
                   1273:                        ptr += sBuf.srbioctl.Length;
                   1274:                        total += sBuf.srbioctl.Length;
                   1275:                        // the returned bytes enough to compute payload length ?
                   1276:                        if ( expected < 0 && total >= 5 )
                   1277:                        {
                   1278:                                areca_return_packet = (unsigned char *)&return_buff[0];
                   1279:                                if ( areca_return_packet[0] == 0x5E && 
                   1280:                                         areca_return_packet[1] == 0x01 && 
                   1281:                                         areca_return_packet[2] == 0x61 )
                   1282:                                {
                   1283:                                        // valid header, let's compute the returned payload length,
                   1284:                                        // we expected the total length is 
                   1285:                                        // payload + 3 bytes header + 2 bytes length + 1 byte checksum
                   1286:                                        expected = areca_return_packet[4] * 256 + areca_return_packet[3] + 6;
                   1287:                                }
                   1288:                        }
                   1289: 
                   1290:                        if ( total >= 7 && total >= expected )
                   1291:                        {
                   1292:                                //printf("total bytes received = %d, expected length = %d\n", total, expected);
                   1293: 
                   1294:                                // ------ Okay! we received enough --------
                   1295:                                break;
                   1296:                        }
                   1297:                }
                   1298:        }
                   1299: 
                   1300:        // Deal with the different error cases
                   1301:        if ( ioctlreturn )
                   1302:        {
                   1303:                pout("ioctl write buffer failed code = %x\n", ioctlreturn);
                   1304:                return -2;
                   1305:        }
                   1306: 
                   1307: 
                   1308:        if ( data )
                   1309:        {
                   1310:                memcpy(data, return_buff, total);
                   1311:        }
                   1312: 
                   1313:        return total;
                   1314: }
                   1315: 
                   1316: 
1.1.1.2 ! misho    1317: freebsd_areca_device::freebsd_areca_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
1.1       misho    1318: : smart_device(intf, dev_name, "areca", "areca"),
                   1319:   freebsd_smart_device("ATA"),
1.1.1.2 ! misho    1320:   m_disknum(disknum),
        !          1321:   m_encnum(encnum)
1.1       misho    1322: {
1.1.1.2 ! misho    1323:   set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
1.1       misho    1324: }
                   1325: 
                   1326: // Areca RAID Controller
                   1327: // int freebsd_areca_device::ata_command_interface(smart_command_set command, int select, char * data)
                   1328: bool freebsd_areca_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) 
                   1329: {
                   1330: if (!ata_cmd_is_ok(in, 
                   1331:     true, // data_out_support 
                   1332:     false, // TODO: multi_sector_support 
                   1333:     true) // ata_48bit_support 
                   1334:     )
                   1335:     return false; 
                   1336: 
                   1337:        // ATA input registers
                   1338:        typedef struct _ATA_INPUT_REGISTERS
                   1339:        {
                   1340:                unsigned char features;
                   1341:                unsigned char sector_count;
                   1342:                unsigned char sector_number;
                   1343:                unsigned char cylinder_low; 
                   1344:                unsigned char cylinder_high;    
                   1345:                unsigned char device_head;  
                   1346:                unsigned char command;      
                   1347:                unsigned char reserved[8];
                   1348:                unsigned char data[512]; // [in/out] buffer for outgoing/incoming data
                   1349:        } sATA_INPUT_REGISTERS;
                   1350: 
                   1351:        // ATA output registers
                   1352:        // Note: The output registers is re-sorted for areca internal use only
                   1353:        typedef struct _ATA_OUTPUT_REGISTERS
                   1354:        {
                   1355:                unsigned char error;
                   1356:                unsigned char status;
                   1357:                unsigned char sector_count;
                   1358:                unsigned char sector_number;
                   1359:                unsigned char cylinder_low; 
                   1360:                unsigned char cylinder_high;
                   1361:        }sATA_OUTPUT_REGISTERS;
                   1362: 
                   1363:        // Areca packet format for outgoing:
                   1364:        // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
                   1365:        // B[3~4] : 2 bytes command length + variant data length, little endian
                   1366:        // B[5]   : 1 bytes areca defined command code, ATA passthrough command code is 0x1c
                   1367:        // B[6~last-1] : variant bytes payload data
                   1368:        // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
                   1369:        // 
                   1370:        // 
                   1371:        //   header 3 bytes  length 2 bytes   cmd 1 byte    payload data x bytes  cs 1 byte 
                   1372:        // +--------------------------------------------------------------------------------+
                   1373:        // + 0x5E 0x01 0x61 |   0x00 0x00   |     0x1c   | .................... |   0x00    |
                   1374:        // +--------------------------------------------------------------------------------+
                   1375:        // 
                   1376: 
                   1377:        //Areca packet format for incoming:
                   1378:        // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
                   1379:        // B[3~4] : 2 bytes payload length, little endian
                   1380:        // B[5~last-1] : variant bytes returned payload data
                   1381:        // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
                   1382:        // 
                   1383:        // 
                   1384:        //   header 3 bytes  length 2 bytes   payload data x bytes  cs 1 byte 
                   1385:        // +-------------------------------------------------------------------+
                   1386:        // + 0x5E 0x01 0x61 |   0x00 0x00   | .................... |   0x00    |
                   1387:        // +-------------------------------------------------------------------+
                   1388:        unsigned char    areca_packet[640];
                   1389:        int areca_packet_len = sizeof(areca_packet);
                   1390:        unsigned char cs = 0;   
                   1391: 
                   1392:        sATA_INPUT_REGISTERS *ata_cmd;
                   1393: 
                   1394:        // For debugging
                   1395:        memset(areca_packet, 0, areca_packet_len);
                   1396: 
                   1397:        // ----- BEGIN TO SETUP HEADERS -------
                   1398:        areca_packet[0] = 0x5E;
                   1399:        areca_packet[1] = 0x01;
                   1400:        areca_packet[2] = 0x61;
                   1401:        areca_packet[3] = (unsigned char)((areca_packet_len - 6) & 0xff);
                   1402:        areca_packet[4] = (unsigned char)(((areca_packet_len - 6) >> 8) & 0xff);
                   1403:        areca_packet[5] = 0x1c; // areca defined code for ATA passthrough command
                   1404: 
                   1405:        // ----- BEGIN TO SETUP PAYLOAD DATA -----
                   1406:        memcpy(&areca_packet[7], "SmrT", 4);    // areca defined password
                   1407:        ata_cmd = (sATA_INPUT_REGISTERS *)&areca_packet[12];
                   1408: 
                   1409:        // Set registers
                   1410:         {
                   1411:            const ata_in_regs_48bit & r = in.in_regs;
                   1412:            ata_cmd->features     = r.features_16;
                   1413:            ata_cmd->sector_count  = r.sector_count_16;
                   1414:            ata_cmd->sector_number = r.lba_low_16;
                   1415:            ata_cmd->cylinder_low  = r.lba_mid_16;
                   1416:            ata_cmd->cylinder_high = r.lba_high_16;
                   1417:            ata_cmd->device_head   = r.device;
                   1418:            ata_cmd->command      = r.command;
                   1419:        }
                   1420:        bool readdata = false; 
                   1421:        if (in.direction == ata_cmd_in::data_in) { 
                   1422:            readdata = true;
                   1423:            // the command will read data
                   1424:            areca_packet[6] = 0x13;
                   1425:        }
                   1426:        else if ( in.direction == ata_cmd_in::no_data )
                   1427:        {
                   1428:                // the commands will return no data
                   1429:                areca_packet[6] = 0x15;
                   1430:        }
                   1431:        else if (in.direction == ata_cmd_in::data_out) 
                   1432:        {
                   1433:                // the commands will write data
                   1434:                memcpy(ata_cmd->data, in.buffer, in.size);
                   1435:                areca_packet[6] = 0x14;
                   1436:        }
                   1437:        else {
                   1438:            // COMMAND NOT SUPPORTED VIA ARECA IOCTL INTERFACE
                   1439:            return set_err(ENOTSUP, "DATA OUT not supported for this Areca controller type");
                   1440:        }
                   1441: 
1.1.1.2 ! misho    1442:        areca_packet[11] = m_disknum - 1;               // disk #
        !          1443:        areca_packet[19] = m_encnum - 1;                // enc#
1.1       misho    1444: 
                   1445:        // ----- BEGIN TO SETUP CHECKSUM -----
                   1446:        for ( int loop = 3; loop < areca_packet_len - 1; loop++ )
                   1447:        {
                   1448:                cs += areca_packet[loop]; 
                   1449:        }
                   1450:        areca_packet[areca_packet_len-1] = cs;
                   1451: 
                   1452:        // ----- BEGIN TO SEND TO ARECA DRIVER ------
                   1453:        int expected = 0;       
                   1454:        unsigned char return_buff[2048];
                   1455:        memset(return_buff, 0, sizeof(return_buff));
                   1456: 
                   1457:        expected = arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_CLEAR_RQBUFFER, NULL, 0, NULL);
                   1458:         if (expected==-3) {
                   1459:            return set_err(EIO);
                   1460:        }
                   1461: 
                   1462:        expected = arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_CLEAR_WQBUFFER, NULL, 0, NULL);
                   1463:        expected = arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_WRITE_WQBUFFER, areca_packet, areca_packet_len, NULL);
                   1464:        if ( expected > 0 )
                   1465:        {
                   1466:                expected = arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_READ_RQBUFFER, return_buff, sizeof(return_buff), NULL);
                   1467:        }
                   1468:        if ( expected < 0 )
                   1469:        {
                   1470:                return -1;
                   1471:        }
                   1472: 
                   1473:        // ----- VERIFY THE CHECKSUM -----
                   1474:        cs = 0;
                   1475:        for ( int loop = 3; loop < expected - 1; loop++ )
                   1476:        {
                   1477:                cs += return_buff[loop]; 
                   1478:        }
                   1479: 
                   1480:        if ( return_buff[expected - 1] != cs )
                   1481:        {
                   1482:                return set_err(EIO);
                   1483:        }
                   1484: 
                   1485:        sATA_OUTPUT_REGISTERS *ata_out = (sATA_OUTPUT_REGISTERS *)&return_buff[5] ;
                   1486:        if ( ata_out->status )
                   1487:        {
                   1488:                if ( in.in_regs.command == ATA_IDENTIFY_DEVICE
                   1489:                 && !nonempty((unsigned char *)in.buffer, in.size)) 
                   1490:                 {
                   1491:                    return set_err(ENODEV, "No drive on port %d", m_disknum);
                   1492:                 } 
                   1493:        }
                   1494: 
                   1495:        // returns with data
                   1496:        if (readdata)
                   1497:        {
                   1498:                memcpy(in.buffer, &return_buff[7], in.size); 
                   1499:        }
                   1500: 
                   1501:        // Return register values
                   1502:        {
                   1503:            ata_out_regs_48bit & r = out.out_regs;
                   1504:            r.error           = ata_out->error;
                   1505:            r.sector_count_16 = ata_out->sector_count;
                   1506:            r.lba_low_16      = ata_out->sector_number;
                   1507:            r.lba_mid_16      = ata_out->cylinder_low;
                   1508:            r.lba_high_16     = ata_out->cylinder_high;
                   1509:            r.status          = ata_out->status;
                   1510:        }
                   1511:        return true;
                   1512: }
                   1513: 
                   1514: 
                   1515: 
                   1516: /////////////////////////////////////////////////////////////////////////////
                   1517: /// Implement CCISS RAID support with old functions
                   1518: 
                   1519: class freebsd_cciss_device
                   1520: : public /*implements*/ scsi_device,
                   1521:   public /*extends*/ freebsd_smart_device
                   1522: {
                   1523: public:
                   1524:   freebsd_cciss_device(smart_interface * intf, const char * name, unsigned char disknum);
                   1525: 
                   1526:   virtual bool scsi_pass_through(scsi_cmnd_io * iop);
                   1527:   virtual bool open();
                   1528: 
                   1529: private:
                   1530:   unsigned char m_disknum; ///< Disk number.
                   1531: };
                   1532: 
                   1533: bool freebsd_cciss_device::open()
                   1534: {
                   1535:   const char *dev = get_dev_name();
                   1536:   int fd;
                   1537:   if ((fd = ::open(dev,O_RDWR))<0) {
                   1538:     set_err(errno);
                   1539:     return false;
                   1540:   }
                   1541:   set_fd(fd);
                   1542:   return true;
                   1543: }
                   1544: 
                   1545: freebsd_cciss_device::freebsd_cciss_device(smart_interface * intf,
                   1546:   const char * dev_name, unsigned char disknum)
                   1547: : smart_device(intf, dev_name, "cciss", "cciss"),
                   1548:   freebsd_smart_device("SCSI"),
                   1549:   m_disknum(disknum)
                   1550: {
                   1551:   set_info().info_name = strprintf("%s [cciss_disk_%02d]", dev_name, disknum);
                   1552: }
                   1553: 
                   1554: bool freebsd_cciss_device::scsi_pass_through(scsi_cmnd_io * iop)
                   1555: {
                   1556:   int status = cciss_io_interface(get_fd(), m_disknum, iop, scsi_debugmode);
                   1557:   if (status < 0)
                   1558:       return set_err(-status);
                   1559:   return true;
                   1560:   // not reached
                   1561:   return true;
                   1562: }
                   1563: 
                   1564: 
                   1565: /////////////////////////////////////////////////////////////////////////////
                   1566: /// SCSI open with autodetection support
                   1567: 
                   1568: smart_device * freebsd_scsi_device::autodetect_open()
                   1569: {
                   1570:   // Open device
                   1571:   if (!open())
                   1572:     return this;
                   1573: 
                   1574:   // No Autodetection if device type was specified by user
                   1575:   if (*get_req_type())
                   1576:     return this;
                   1577: 
                   1578:   // The code below is based on smartd.cpp:SCSIFilterKnown()
                   1579: 
                   1580:   // Get INQUIRY
                   1581:   unsigned char req_buff[64] = {0, };
                   1582:   int req_len = 36;
                   1583:   if (scsiStdInquiry(this, req_buff, req_len)) {
                   1584:     // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices
                   1585:     // watch this spot ... other devices could lock up here
                   1586:     req_len = 64;
                   1587:     if (scsiStdInquiry(this, req_buff, req_len)) {
                   1588:       // device doesn't like INQUIRY commands
                   1589:       close();
                   1590:       set_err(EIO, "INQUIRY failed");
                   1591:       return this;
                   1592:     }
                   1593:   }
                   1594: 
                   1595:   int avail_len = req_buff[4] + 5;
                   1596:   int len = (avail_len < req_len ? avail_len : req_len);
                   1597:   if (len < 36)
                   1598:     return this;
                   1599: 
                   1600:   // Use INQUIRY to detect type
                   1601: 
                   1602:   // 3ware ?
                   1603:   if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4)) {
                   1604:     close();
                   1605:     set_err(EINVAL, "AMCC/3ware controller, please try adding '-d 3ware,N',\n"
                   1606:                     "you may need to replace %s with /dev/twaN or /dev/tweN", get_dev_name());
                   1607:     return this;
                   1608:   }
                   1609: 
1.1.1.2 ! misho    1610:   // SAT or USB, skip MFI controllers because of bugs
1.1       misho    1611:   {
                   1612:     smart_device * newdev = smi()->autodetect_sat_device(this, req_buff, len);
1.1.1.2 ! misho    1613:     if (newdev) {
1.1       misho    1614:       // NOTE: 'this' is now owned by '*newdev'
1.1.1.2 ! misho    1615:       if(!strcmp("mfi",m_camdev->sim_name)) {
        !          1616:         newdev->close();
        !          1617:         newdev->set_err(ENOSYS, "SATA device detected,\n"
        !          1618:           "MegaRAID SAT layer is reportedly buggy, use '-d sat' to try anyhow");
        !          1619:       }
1.1       misho    1620:       return newdev;
1.1.1.2 ! misho    1621:     }
1.1       misho    1622:   }
                   1623: 
                   1624:   // Nothing special found
                   1625:   return this;
                   1626: }
                   1627: 
                   1628: 
                   1629: /////////////////////////////////////////////////////////////////////////////
                   1630: /// Implement platform interface with old functions.
                   1631: 
                   1632: class freebsd_smart_interface
                   1633: : public /*implements*/ smart_interface
                   1634: {
                   1635: public:
                   1636:   virtual std::string get_os_version_str();
                   1637: 
                   1638:   virtual std::string get_app_examples(const char * appname);
                   1639: 
                   1640:   virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
                   1641:     const char * pattern = 0);
                   1642: 
                   1643: protected:
                   1644:   virtual ata_device * get_ata_device(const char * name, const char * type);
                   1645: 
                   1646: #if FREEBSDVER > 800100
                   1647:   virtual ata_device * get_atacam_device(const char * name, const char * type);
                   1648: #endif
                   1649: 
                   1650:   virtual scsi_device * get_scsi_device(const char * name, const char * type);
                   1651: 
                   1652:   virtual smart_device * autodetect_smart_device(const char * name);
                   1653: 
                   1654:   virtual smart_device * get_custom_smart_device(const char * name, const char * type);
                   1655: 
                   1656:   virtual std::string get_valid_custom_dev_types_str();
                   1657: };
                   1658: 
                   1659: 
                   1660: //////////////////////////////////////////////////////////////////////
                   1661: 
                   1662: std::string freebsd_smart_interface::get_os_version_str()
                   1663: {
                   1664:   struct utsname osname;
                   1665:   uname(&osname);
                   1666:   return strprintf("%s %s %s", osname.sysname, osname.release, osname.machine);
                   1667: }
                   1668: 
                   1669: std::string freebsd_smart_interface::get_app_examples(const char * appname)
                   1670: {
                   1671:   if (!strcmp(appname, "smartctl"))
                   1672:     return smartctl_examples;
                   1673:   return "";
                   1674: }
                   1675: 
                   1676: ata_device * freebsd_smart_interface::get_ata_device(const char * name, const char * type)
                   1677: {
                   1678:   return new freebsd_ata_device(this, name, type);
                   1679: }
                   1680: 
                   1681: #if FREEBSDVER > 800100
                   1682: ata_device * freebsd_smart_interface::get_atacam_device(const char * name, const char * type)
                   1683: {
                   1684:   return new freebsd_atacam_device(this, name, type);
                   1685: }
                   1686: #endif
                   1687: 
                   1688: scsi_device * freebsd_smart_interface::get_scsi_device(const char * name, const char * type)
                   1689: {
                   1690:   return new freebsd_scsi_device(this, name, type);
                   1691: }
                   1692: 
                   1693: // we are using CAM subsystem XPT enumerator to found all CAM (scsi/usb/ada/...)
                   1694: // devices on system despite of it's names
                   1695: //
                   1696: // If any errors occur, leave errno set as it was returned by the
                   1697: // system call, and return <0.
                   1698: //
                   1699: // arguments: 
                   1700: // names: resulting array
                   1701: // show_all - export duplicate device name or not
                   1702: //
                   1703: // Return values:
                   1704: // -1:   error
                   1705: // >=0: number of discovered devices
                   1706: 
                   1707: bool get_dev_names_cam(std::vector<std::string> & names, bool show_all)
                   1708: {
                   1709:   int fd;
                   1710:   if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
                   1711:     if (errno == ENOENT) /* There are no CAM device on this computer */
                   1712:       return 0;
                   1713:     int serrno = errno;
                   1714:     pout("%s control device couldn't opened: %s\n", XPT_DEVICE, strerror(errno));
                   1715:     errno = serrno;
                   1716:     return false;
                   1717:   }
                   1718: 
                   1719:   union ccb ccb;
                   1720:   bzero(&ccb, sizeof(union ccb));
                   1721: 
                   1722:   ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
                   1723:   ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
                   1724:   ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
                   1725: 
                   1726:   ccb.ccb_h.func_code = XPT_DEV_MATCH;
                   1727:   int bufsize = sizeof(struct dev_match_result) * MAX_NUM_DEV;
                   1728:   ccb.cdm.match_buf_len = bufsize;
                   1729:   // TODO: Use local buffer instead of malloc() if possible
                   1730:   ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
                   1731:   bzero(ccb.cdm.matches,bufsize); // clear ccb.cdm.matches structure
                   1732:   
                   1733:   if (ccb.cdm.matches == NULL) {
                   1734:     close(fd);
                   1735:     throw std::bad_alloc();
                   1736:   }
                   1737:   ccb.cdm.num_matches = 0;
                   1738:   ccb.cdm.num_patterns = 0;
                   1739:   ccb.cdm.pattern_buf_len = 0;
                   1740: 
                   1741:   /*
                   1742:    * We do the ioctl multiple times if necessary, in case there are
                   1743:    * more than MAX_NUM_DEV nodes in the EDT.
                   1744:    */
                   1745:   int skip_device = 0, skip_bus = 0, changed = 0; // TODO: bool
                   1746:   std::string devname;
                   1747:   do {
                   1748:     if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
                   1749:       int serrno = errno;
                   1750:       pout("error sending CAMIOCOMMAND ioctl: %s\n", strerror(errno));
                   1751:       free(ccb.cdm.matches);
                   1752:       close(fd);
                   1753:       errno = serrno;
                   1754:       return false;
                   1755:     }
                   1756: 
                   1757:     if ((ccb.ccb_h.status != CAM_REQ_CMP)
                   1758:       || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
                   1759:       && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
                   1760:       pout("got CAM error %#x, CDM error %d\n", ccb.ccb_h.status, ccb.cdm.status);
                   1761:       free(ccb.cdm.matches);
                   1762:       close(fd);
                   1763:       errno = ENXIO;
                   1764:       return false;
                   1765:     }
                   1766: 
                   1767:     for (unsigned i = 0; i < ccb.cdm.num_matches; i++) {
                   1768:       struct bus_match_result *bus_result;
                   1769:       struct device_match_result *dev_result;
                   1770:       struct periph_match_result *periph_result;
                   1771: 
                   1772:       if (ccb.cdm.matches[i].type == DEV_MATCH_BUS) {
                   1773:         bus_result = &ccb.cdm.matches[i].result.bus_result;
                   1774: 
1.1.1.2 ! misho    1775:         if (strcmp(bus_result->dev_name,"xpt") == 0) /* skip XPT bus at all */
1.1       misho    1776:         skip_bus = 1;
                   1777:         else
                   1778:           skip_bus = 0;
                   1779:         changed = 1;
                   1780:       } else if (ccb.cdm.matches[i].type == DEV_MATCH_DEVICE) {
                   1781:         dev_result = &ccb.cdm.matches[i].result.device_result;
                   1782: 
                   1783:         if (dev_result->flags & DEV_RESULT_UNCONFIGURED || skip_bus == 1)
                   1784:           skip_device = 1;
                   1785:         else
                   1786:           skip_device = 0;
                   1787:         
                   1788:         //        /* Shall we skip non T_DIRECT devices ? */
                   1789:         //        if (dev_result->inq_data.device != T_DIRECT)
                   1790:         //          skip_device = 1;
                   1791:         changed = 1;
                   1792:       } else if (ccb.cdm.matches[i].type == DEV_MATCH_PERIPH && 
                   1793:           (skip_device == 0 || show_all)) { 
                   1794:         /* One device may be populated as many peripherals (pass0 & da0 for example). 
                   1795:         * We are searching for latest name
                   1796:         */
                   1797:         periph_result =  &ccb.cdm.matches[i].result.periph_result;
                   1798:         devname = strprintf("%s%s%d", _PATH_DEV, periph_result->periph_name, periph_result->unit_number);
                   1799:         changed = 0;
                   1800:       };
                   1801:       if ((changed == 1 || show_all) && !devname.empty()) {
                   1802:         names.push_back(devname);
                   1803:         devname.erase();
                   1804:         changed = 0;
                   1805:       };
                   1806:     }
                   1807: 
                   1808:   } while ((ccb.ccb_h.status == CAM_REQ_CMP) && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
                   1809: 
                   1810:   if (!devname.empty())
                   1811:     names.push_back(devname);
                   1812: 
                   1813:   free(ccb.cdm.matches);
                   1814:   close(fd);
                   1815:   return true;
                   1816: }
                   1817: 
                   1818: // we are using ATA subsystem enumerator to found all ATA devices on system
                   1819: // despite of it's names
                   1820: //
                   1821: // If any errors occur, leave errno set as it was returned by the
                   1822: // system call, and return <0.
                   1823: 
                   1824: // Return values:
                   1825: // -1:   error
                   1826: // >=0: number of discovered devices
                   1827: int get_dev_names_ata(char*** names) {
                   1828:   struct ata_ioc_devices devices;
                   1829:   int fd=-1,maxchannel,serrno=-1,n=0;
                   1830:   char **mp = NULL;
                   1831: 
                   1832:   *names=NULL;
                   1833: 
                   1834:   if ((fd = open(ATA_DEVICE, O_RDWR)) < 0) {
                   1835:     if (errno == ENOENT) /* There are no ATA device on this computer */
                   1836:       return 0;
                   1837:     serrno = errno;
                   1838:     pout("%s control device can't be opened: %s\n", ATA_DEVICE, strerror(errno));
                   1839:     n = -1;
                   1840:     goto end;
                   1841:   };
                   1842: 
                   1843:   if (ioctl(fd, IOCATAGMAXCHANNEL, &maxchannel) < 0) {
                   1844:     serrno = errno;
                   1845:     pout("ioctl(IOCATAGMAXCHANNEL) on /dev/ata failed: %s\n", strerror(errno));
                   1846:     n = -1;
                   1847:     goto end;
                   1848:   };
                   1849: 
                   1850:   // allocate space for up to MAX_NUM_DEV number of ATA devices
                   1851:   mp =  (char **)calloc(MAX_NUM_DEV, sizeof(char*));
                   1852:   if (mp == NULL) {
                   1853:     serrno=errno;
                   1854:     pout("Out of memory constructing scan device list (on line %d)\n", __LINE__);
                   1855:     n = -1;
                   1856:     goto end;
                   1857:   };
                   1858: 
                   1859:   for (devices.channel = 0; devices.channel < maxchannel && n < MAX_NUM_DEV; devices.channel++) {
                   1860:     int j;
                   1861: 
                   1862:     if (ioctl(fd, IOCATADEVICES, &devices) < 0) {
                   1863:       if (errno == ENXIO)
                   1864:         continue; /* such channel not exist */
                   1865:       pout("ioctl(IOCATADEVICES) on %s channel %d failed: %s\n", ATA_DEVICE, devices.channel, strerror(errno));
                   1866:       n = -1;
                   1867:       goto end;
                   1868:     };
                   1869:     for (j=0;j<=1 && n<MAX_NUM_DEV;j++) {
                   1870:       if (devices.name[j][0] != '\0') {
                   1871:         asprintf(mp+n, "%s%s", _PATH_DEV, devices.name[j]);
                   1872:         if (mp[n] == NULL) {
                   1873:           pout("Out of memory constructing scan ATA device list (on line %d)\n", __LINE__);
                   1874:           n = -1;
                   1875:           goto end;
                   1876:         };
                   1877:         bytes+=1+strlen(mp[n]);
                   1878:         n++;
                   1879:       };
                   1880:     };
                   1881:   };  
                   1882:   mp = (char **)reallocf(mp,n*(sizeof (char*))); // shrink to correct size
                   1883:   if (mp == NULL && n > 0 ) { // reallocf never fail for size=0, but may return NULL
                   1884:     serrno=errno;
                   1885:     pout("Out of memory constructing scan device list (on line %d)\n", __LINE__);
                   1886:     n = -1;
                   1887:     goto end;
                   1888:   };
                   1889:   bytes += (n)*(sizeof(char*)); // and set allocated byte count
                   1890: 
                   1891: end:
                   1892:   if (fd>=0)
                   1893:     close(fd);
                   1894:   if (n <= 0) {
                   1895:     free(mp);
                   1896:     mp = NULL;
                   1897:   }
                   1898: 
                   1899:   *names=mp;
                   1900: 
                   1901:   if (serrno>-1)
                   1902:     errno=serrno;
                   1903:   return n;
                   1904: }
                   1905: 
                   1906: 
                   1907: 
                   1908: bool freebsd_smart_interface::scan_smart_devices(smart_device_list & devlist,
                   1909:   const char * type, const char * pattern /*= 0*/)
                   1910: {
                   1911:   if (pattern) {
                   1912:     set_err(EINVAL, "DEVICESCAN with pattern not implemented yet");
                   1913:     return false;
                   1914:   }
                   1915: 
                   1916:   // Make namelists
                   1917:   char * * atanames = 0; int numata = 0;
                   1918:   if (!type || !strcmp(type, "ata")) {
                   1919:     numata = get_dev_names_ata(&atanames);
                   1920:     if (numata < 0) {
                   1921:       set_err(ENOMEM);
                   1922:       return false;
                   1923:     }
                   1924:   }
                   1925: 
                   1926:   std::vector<std::string> scsinames;
                   1927:   if (!type || !strcmp(type, "scsi")) { // do not export duplicated names
                   1928:     if (!get_dev_names_cam(scsinames, false)) {
                   1929:       set_err(errno);
                   1930:       return false;
                   1931:     }
                   1932:   }
                   1933: 
                   1934:   // Add to devlist
                   1935:   int i;
                   1936:   if (type==NULL)
                   1937:     type="";
                   1938:   for (i = 0; i < numata; i++) {
                   1939:     ata_device * atadev = get_ata_device(atanames[i], type);
                   1940:     if (atadev)
                   1941:       devlist.push_back(atadev);
                   1942:     free(atanames[i]);
                   1943:   }
                   1944:   if(numata) free(atanames);
                   1945: 
                   1946:   for (i = 0; i < (int)scsinames.size(); i++) {
                   1947:     if(!*type) { // try USB autodetection if no type specified
                   1948:       smart_device * smartdev = autodetect_smart_device(scsinames[i].c_str());
                   1949:       if(smartdev)
                   1950:         devlist.push_back(smartdev);
                   1951:     }
                   1952:     else {
                   1953:       scsi_device * scsidev = get_scsi_device(scsinames[i].c_str(), type);
                   1954:       if (scsidev)
                   1955:         devlist.push_back(scsidev);
                   1956:     }
                   1957:   }
                   1958:   return true;
                   1959: }
                   1960: 
                   1961: 
                   1962: #if (FREEBSDVER < 800000) // without this build fail on FreeBSD 8
                   1963: static char done[USB_MAX_DEVICES];
                   1964: 
                   1965: static int usbdevinfo(int f, int a, int rec, int busno, unsigned short & vendor_id,
                   1966:   unsigned short & product_id, unsigned short & version)
                   1967: { 
                   1968: 
                   1969:   struct usb_device_info di;
                   1970:   int e, p, i;
                   1971:   char devname[256];
                   1972: 
                   1973:   snprintf(devname, sizeof(devname),"umass%d",busno);
                   1974: 
                   1975:   di.udi_addr = a;
                   1976:   e = ioctl(f, USB_DEVICEINFO, &di);
                   1977:   if (e) {
                   1978:     if (errno != ENXIO)
                   1979:       printf("addr %d: I/O error\n", a);
                   1980:     return 0;
                   1981:   }
                   1982:   done[a] = 1;
                   1983: 
                   1984:   // list devices
                   1985:   for (i = 0; i < USB_MAX_DEVNAMES; i++) {
                   1986:     if (di.udi_devnames[i][0]) {
                   1987:       if(strcmp(di.udi_devnames[i],devname)==0) {
                   1988:         // device found!
                   1989:         vendor_id = di.udi_vendorNo;
                   1990:         product_id = di.udi_productNo;
                   1991:         version = di.udi_releaseNo;
                   1992:         return 1;
                   1993:         // FIXME
                   1994:       }
                   1995:     }
                   1996:   }
                   1997:   if (!rec)
                   1998:     return 0;
                   1999:   for (p = 0; p < di.udi_nports; p++) {
                   2000:     int s = di.udi_ports[p];
                   2001:     if (s >= USB_MAX_DEVICES) {
                   2002:       continue;
                   2003:     }
                   2004:     if (s == 0)
                   2005:       printf("addr 0 should never happen!\n");
                   2006:     else {
                   2007:       if(usbdevinfo(f, s, 1, busno, vendor_id, product_id, version)) return 1;
                   2008:     }
                   2009:   }
                   2010:   return 0;
                   2011: }
                   2012: #endif
                   2013: 
                   2014: 
                   2015: static int usbdevlist(int busno,unsigned short & vendor_id,
                   2016:   unsigned short & product_id, unsigned short & version)
                   2017: {
                   2018: #if (FREEBSDVER >= 800000) // libusb2 interface
                   2019:   struct libusb20_device *pdev = NULL;
                   2020:   struct libusb20_backend *pbe;
                   2021:   uint32_t matches = 0;
                   2022:   char buf[128]; // do not change!
                   2023:   char devname[128];
                   2024:   uint8_t n;
                   2025:   struct LIBUSB20_DEVICE_DESC_DECODED *pdesc;
                   2026: 
                   2027:   pbe = libusb20_be_alloc_default();
                   2028: 
                   2029:   while ((pdev = libusb20_be_device_foreach(pbe, pdev))) {
                   2030:     matches++;
                   2031: 
                   2032:     if (libusb20_dev_open(pdev, 0)) {
                   2033:       warnx("libusb20_dev_open: could not open device");
                   2034:       return 0;
                   2035:     }
                   2036: 
                   2037:     pdesc=libusb20_dev_get_device_desc(pdev);
                   2038: 
                   2039:     snprintf(devname, sizeof(devname),"umass%d:",busno);
                   2040:     for (n = 0; n != 255; n++) {
                   2041:       if (libusb20_dev_get_iface_desc(pdev, n, buf, sizeof(buf)))
                   2042:         break;
                   2043:       if (buf[0] == 0)
                   2044:         continue;
                   2045:       if(strncmp(buf,devname,strlen(devname))==0){
                   2046:         // found!
                   2047:         vendor_id = pdesc->idVendor;
                   2048:         product_id = pdesc->idProduct;
                   2049:         version = pdesc->bcdDevice;
                   2050:         libusb20_dev_close(pdev);
                   2051:         libusb20_be_free(pbe);
                   2052:         return 1;
                   2053:       }
                   2054:     }
                   2055: 
                   2056:     libusb20_dev_close(pdev);
                   2057:   }
                   2058: 
                   2059:   if (matches == 0) {
                   2060:     printf("No device match or lack of permissions.\n");
                   2061:   }
                   2062: 
                   2063:   libusb20_be_free(pbe);
                   2064: 
                   2065:   return false;
                   2066: #else // freebsd < 8.0 USB stack, ioctl interface
                   2067: 
                   2068:   int  i, f, a, rc;
                   2069:   char buf[50];
                   2070:   int ncont;
                   2071: 
                   2072:   for (ncont = 0, i = 0; i < 10; i++) {
                   2073:     snprintf(buf, sizeof(buf), "%s%d", USBDEV, i);
                   2074:     f = open(buf, O_RDONLY);
                   2075:     if (f >= 0) {
                   2076:       memset(done, 0, sizeof done);
                   2077:       for (a = 1; a < USB_MAX_DEVICES; a++) {
                   2078:         if (!done[a]) {
                   2079:           rc = usbdevinfo(f, a, 1, busno,vendor_id, product_id, version);
                   2080:           if(rc) return 1;
                   2081:         }
                   2082: 
                   2083:       }
                   2084:       close(f);
                   2085:     } else {
                   2086:       if (errno == ENOENT || errno == ENXIO)
                   2087:         continue;
                   2088:       warn("%s", buf);
                   2089:     }
                   2090:     ncont++;
                   2091:   }
                   2092:   return 0;
                   2093: #endif
                   2094: }
                   2095: 
                   2096: smart_device * freebsd_smart_interface::autodetect_smart_device(const char * name)
                   2097: {
                   2098:   unsigned short vendor_id = 0, product_id = 0, version = 0;
                   2099:   struct cam_device *cam_dev;
                   2100:   union ccb ccb;
                   2101:   int bus=-1;
                   2102:   int i,c;
                   2103:   int len;
1.1.1.2 ! misho    2104:   const char * test_name = name;
1.1       misho    2105: 
                   2106:   // if dev_name null, or string length zero
                   2107:   if (!name || !(len = strlen(name)))
                   2108:     return 0;
                   2109: 
1.1.1.2 ! misho    2110:   // Dereference symlinks
        !          2111:   struct stat st;
        !          2112:   std::string pathbuf;
        !          2113:   if (!lstat(name, &st) && S_ISLNK(st.st_mode)) {
        !          2114:     char * p = realpath(name, (char *)0);
        !          2115:     if (p) {
        !          2116:       pathbuf = p;
        !          2117:       free(p);
        !          2118:       test_name = pathbuf.c_str();
        !          2119:     }
        !          2120:   }
        !          2121: 
1.1       misho    2122:   // check ATA bus
                   2123:   char * * atanames = 0; int numata = 0;
                   2124:   numata = get_dev_names_ata(&atanames);
                   2125:   if (numata > 0) {
                   2126:     // check ATA/ATAPI devices
                   2127:     for (i = 0; i < numata; i++) {
1.1.1.2 ! misho    2128:       if(!strcmp(atanames[i],test_name)) {
1.1       misho    2129:         for (c = i; c < numata; c++) free(atanames[c]);
                   2130:         free(atanames);
1.1.1.2 ! misho    2131:         return new freebsd_ata_device(this, test_name, "");
1.1       misho    2132:       }
                   2133:       else free(atanames[i]);
                   2134:     }
                   2135:     if(numata) free(atanames);
                   2136:   }
                   2137:   else {
                   2138:     if (numata < 0)
                   2139:       pout("Unable to get ATA device list\n");
                   2140:   }
                   2141: 
                   2142:   // check CAM
                   2143:   std::vector<std::string> scsinames;
                   2144:   if (!get_dev_names_cam(scsinames, true))
                   2145:     pout("Unable to get CAM device list\n");
                   2146:   else if (!scsinames.empty()) {
                   2147:     // check all devices on CAM bus
                   2148:     for (i = 0; i < (int)scsinames.size(); i++) {
1.1.1.2 ! misho    2149:       if(strcmp(scsinames[i].c_str(), test_name)==0)
1.1       misho    2150:       { // our disk device is CAM
1.1.1.2 ! misho    2151:         if ((cam_dev = cam_open_device(test_name, O_RDWR)) == NULL) {
1.1       misho    2152:           // open failure
                   2153:           set_err(errno);
                   2154:           return 0;
                   2155:         }
                   2156:         // zero the payload
                   2157:         bzero(&(&ccb.ccb_h)[1], PATHINQ_SETTINGS_SIZE);
                   2158:         ccb.ccb_h.func_code = XPT_PATH_INQ; // send PATH_INQ to the device
                   2159:         if (ioctl(cam_dev->fd, CAMIOCOMMAND, &ccb) == -1) {
                   2160:           warn("Get Transfer Settings CCB failed\n"
                   2161:             "%s", strerror(errno));
                   2162:           cam_close_device(cam_dev);
                   2163:           return 0;
                   2164:         }
                   2165:         // now check if we are working with USB device, see umass.c
                   2166:         if(strcmp(ccb.cpi.dev_name,"umass-sim") == 0) { // USB device found
                   2167:           usbdevlist(bus,vendor_id, product_id, version);
                   2168:           int bus=ccb.cpi.unit_number; // unit_number will match umass number
                   2169:           cam_close_device(cam_dev);
                   2170:           if(usbdevlist(bus,vendor_id, product_id, version)){
                   2171:             const char * usbtype = get_usb_dev_type_by_id(vendor_id, product_id, version);
                   2172:             if (usbtype)
1.1.1.2 ! misho    2173:               return get_sat_device(usbtype, new freebsd_scsi_device(this, test_name, ""));
1.1       misho    2174:           }
                   2175:           return 0;
                   2176:         }
                   2177: #if FREEBSDVER > 800100
                   2178:         // check if we have ATA device connected to CAM (ada)
                   2179:         if(ccb.cpi.protocol == PROTO_ATA){
                   2180:           cam_close_device(cam_dev);
1.1.1.2 ! misho    2181:           return new freebsd_atacam_device(this, test_name, "");
1.1       misho    2182:         }
                   2183: #endif
                   2184:         // close cam device, we don`t need it anymore
                   2185:         cam_close_device(cam_dev);
                   2186:         // handle as usual scsi
1.1.1.2 ! misho    2187:         return new freebsd_scsi_device(this, test_name, "");      
1.1       misho    2188:       }
                   2189:     }
                   2190:   }
                   2191:   // device is LSI raid supported by mfi driver
1.1.1.2 ! misho    2192:   if(!strncmp("/dev/mfid", test_name, strlen("/dev/mfid")))
1.1       misho    2193:     set_err(EINVAL, "To monitor disks on LSI RAID load mfip.ko module and run 'smartctl -a /dev/passX' to show SMART information");
                   2194:   // device type unknown
                   2195:   return 0;
                   2196: }
                   2197: 
                   2198: 
                   2199: smart_device * freebsd_smart_interface::get_custom_smart_device(const char * name, const char * type)
                   2200: {
                   2201:   // 3Ware ?
                   2202:   static const char * fbsd_dev_twe_ctrl = "/dev/twe";
                   2203:   static const char * fbsd_dev_twa_ctrl = "/dev/twa";
                   2204:   int disknum = -1, n1 = -1, n2 = -1, contr = -1;
                   2205: 
                   2206:   if (sscanf(type, "3ware,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
                   2207:     if (n2 != (int)strlen(type)) {
                   2208:       set_err(EINVAL, "Option -d 3ware,N requires N to be a non-negative integer");
                   2209:       return 0;
                   2210:     }
                   2211:     if (!(0 <= disknum && disknum <= 127)) {
                   2212:       set_err(EINVAL, "Option -d 3ware,N (N=%d) must have 0 <= N <= 127", disknum);
                   2213:       return 0;
                   2214:     }
                   2215: 
                   2216:     // guess 3ware device type based on device name
                   2217:     if (!strncmp(fbsd_dev_twa_ctrl, name, strlen(fbsd_dev_twa_ctrl))){
                   2218:       contr=CONTROLLER_3WARE_9000_CHAR;
                   2219:     }
                   2220:     if (!strncmp(fbsd_dev_twe_ctrl, name, strlen(fbsd_dev_twe_ctrl))){
                   2221:       contr=CONTROLLER_3WARE_678K_CHAR;
                   2222:     }
                   2223: 
                   2224:     if(contr == -1){
                   2225:       set_err(EINVAL, "3ware controller type unknown, use %sX or %sX devices", 
                   2226:         fbsd_dev_twe_ctrl, fbsd_dev_twa_ctrl);
                   2227:       return 0;
                   2228:     }
                   2229:     return new freebsd_escalade_device(this, name, contr, disknum);
                   2230:   } 
                   2231: 
                   2232:   // Highpoint ?
                   2233:   int controller = -1, channel = -1; disknum = 1;
                   2234:   n1 = n2 = -1; int n3 = -1;
                   2235:   if (sscanf(type, "hpt,%n%d/%d%n/%d%n", &n1, &controller, &channel, &n2, &disknum, &n3) >= 2 || n1 == 4) {
                   2236:     int len = strlen(type);
                   2237:     if (!(n2 == len || n3 == len)) {
                   2238:       set_err(EINVAL, "Option '-d hpt,L/M/N' supports 2-3 items");
                   2239:       return 0;
                   2240:     }
                   2241:     if (!(1 <= controller && controller <= 8)) {
                   2242:       set_err(EINVAL, "Option '-d hpt,L/M/N' invalid controller id L supplied");
                   2243:       return 0;
                   2244:     }
                   2245:     if (!(1 <= channel && channel <= 16)) {
                   2246:       set_err(EINVAL, "Option '-d hpt,L/M/N' invalid channel number M supplied");
                   2247:       return 0;
                   2248:     }
                   2249:     if (!(1 <= disknum && disknum <= 15)) {
                   2250:       set_err(EINVAL, "Option '-d hpt,L/M/N' invalid pmport number N supplied");
                   2251:       return 0;
                   2252:     }
                   2253:     return new freebsd_highpoint_device(this, name, controller, channel, disknum);
                   2254:   }
                   2255: 
                   2256:   // CCISS ?
                   2257:   disknum = n1 = n2 = -1;
                   2258:   if (sscanf(type, "cciss,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
                   2259:     if (n2 != (int)strlen(type)) {
                   2260:       set_err(EINVAL, "Option -d cciss,N requires N to be a non-negative integer");
                   2261:       return 0;
                   2262:     }
                   2263:     if (!(0 <= disknum && disknum <= 127)) {
                   2264:       set_err(EINVAL, "Option -d cciss,N (N=%d) must have 0 <= N <= 127", disknum);
                   2265:       return 0;
                   2266:     }
1.1.1.2 ! misho    2267:     return get_sat_device("sat,auto", new freebsd_cciss_device(this, name, disknum));
1.1       misho    2268:   }
                   2269: #if FREEBSDVER > 800100
                   2270:   // adaX devices ?
                   2271:   if(!strcmp(type,"atacam"))
                   2272:     return new freebsd_atacam_device(this, name, "");
                   2273: #endif
                   2274:   // Areca?
                   2275:   disknum = n1 = n2 = -1;
1.1.1.2 ! misho    2276:   int encnum = 1;
        !          2277:   if (sscanf(type, "areca,%n%d/%d%n", &n1, &disknum, &encnum, &n2) >= 1 || n1 == 6) {
        !          2278:     if (!(1 <= disknum && disknum <= 128)) {
        !          2279:       set_err(EINVAL, "Option -d areca,N/E (N=%d) must have 1 <= N <= 128", disknum);
1.1       misho    2280:       return 0;
                   2281:     }
1.1.1.2 ! misho    2282:     if (!(1 <= encnum && encnum <= 8)) {
        !          2283:       set_err(EINVAL, "Option -d areca,N/E (E=%d) must have 1 <= E <= 8", encnum);
1.1       misho    2284:       return 0;
                   2285:     }
                   2286:     return new freebsd_areca_device(this, name, disknum);
                   2287:   }
                   2288: 
                   2289:   return 0;
                   2290: }
                   2291: 
                   2292: std::string freebsd_smart_interface::get_valid_custom_dev_types_str()
                   2293: {
1.1.1.2 ! misho    2294:   return "3ware,N, hpt,L/M/N, cciss,N, areca,N/E"
1.1       misho    2295: #if FREEBSDVER > 800100
                   2296:   ", atacam"
                   2297: #endif
                   2298:   ;
                   2299: }
                   2300: 
                   2301: } // namespace
                   2302: 
                   2303: /////////////////////////////////////////////////////////////////////////////
                   2304: /// Initialize platform interface and register with smi()
                   2305: 
                   2306: void smart_interface::init()
                   2307: {
                   2308:   static os_freebsd::freebsd_smart_interface the_interface;
                   2309:   smart_interface::set(&the_interface);
                   2310: }

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