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

1.1       misho       1: /*
                      2:  * scsiata.cpp
                      3:  *
                      4:  * Home page of code is: http://smartmontools.sourceforge.net
                      5:  *
1.1.1.2 ! misho       6:  * Copyright (C) 2006-12 Douglas Gilbert <dgilbert@interlog.com>
        !             7:  * Copyright (C) 2009-12 Christian Franke <smartmontools-support@lists.sourceforge.net>
1.1       misho       8:  *
                      9:  * This program is free software; you can redistribute it and/or modify
                     10:  * it under the terms of the GNU General Public License as published by
                     11:  * the Free Software Foundation; either version 2, or (at your option)
                     12:  * any later version.
                     13:  *
                     14:  * You should have received a copy of the GNU General Public License
                     15:  * (for example COPYING); if not, write to the Free
                     16:  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     17:  *
                     18:  * The code in this file is based on the SCSI to ATA Translation (SAT)
                     19:  * draft found at http://www.t10.org . The original draft used for this
                     20:  * code is sat-r08.pdf which is not too far away from becoming a
                     21:  * standard. The SAT commands of interest to smartmontools are the
                     22:  * ATA PASS THROUGH SCSI (16) and ATA PASS THROUGH SCSI (12) defined in
                     23:  * section 12 of that document.
                     24:  *
                     25:  * sat-r09.pdf is the most recent, easily accessible draft prior to the
                     26:  * original SAT standard (ANSI INCITS 431-2007). By mid-2009 the second
                     27:  * version of the SAT standard (SAT-2) is nearing standardization. In
                     28:  * their wisdom an incompatible change has been introduced in draft
                     29:  * sat2r08a.pdf in the area of the ATA RETURN DESCRIPTOR. A new "fixed
                     30:  * format" ATA RETURN buffer has been defined (sat2r08b.pdf section
                     31:  * 12.2.7) for the case when DSENSE=0 in the Control mode page.
                     32:  * Unfortunately this is the normal case. If the change stands our
                     33:  * code will need to be extended for this case.
                     34:  *
                     35:  * With more transports "hiding" SATA disks (and other S-ATAPI devices)
                     36:  * behind a SCSI command set, accessing special features like SMART
                     37:  * information becomes a challenge. The SAT standard offers ATA PASS
                     38:  * THROUGH commands for special usages. Note that the SAT layer may
                     39:  * be inside a generic OS layer (e.g. libata in linux), in a host
                     40:  * adapter (HA or HBA) firmware, or somewhere on the interconnect
                     41:  * between the host computer and the SATA devices (e.g. a RAID made
                     42:  * of SATA disks and the RAID talks "SCSI" to the host computer).
                     43:  * Note that in the latter case, this code does not solve the
                     44:  * addressing issue (i.e. which SATA disk to address behind the logical
                     45:  * SCSI (RAID) interface).
                     46:  * 
                     47:  */
                     48: 
                     49: #include <stdio.h>
                     50: #include <string.h>
                     51: #include <stdlib.h>
                     52: #include <ctype.h>
                     53: #include <errno.h>
                     54: 
                     55: #include "config.h"
                     56: #include "int64.h"
                     57: #include "scsicmds.h"
                     58: #include "atacmds.h" // ataReadHDIdentity()
                     59: #include "knowndrives.h" // lookup_usb_device()
                     60: #include "utility.h"
                     61: #include "dev_interface.h"
                     62: #include "dev_ata_cmd_set.h" // ata_device_with_command_set
                     63: #include "dev_tunnelled.h" // tunnelled_device<>
                     64: 
1.1.1.2 ! misho      65: const char * scsiata_cpp_cvsid = "$Id: scsiata.cpp 3519 2012-03-06 20:01:44Z chrfranke $";
1.1       misho      66: 
                     67: /* This is a slightly stretched SCSI sense "descriptor" format header.
                     68:    The addition is to allow the 0x70 and 0x71 response codes. The idea
                     69:    is to place the salient data of both "fixed" and "descriptor" sense
                     70:    format into one structure to ease application processing.
                     71:    The original sense buffer should be kept around for those cases
                     72:    in which more information is required (e.g. the LBA of a MEDIUM ERROR). */
                     73: /// Abridged SCSI sense data
                     74: struct sg_scsi_sense_hdr {
                     75:     unsigned char response_code; /* permit: 0x0, 0x70, 0x71, 0x72, 0x73 */
                     76:     unsigned char sense_key;
                     77:     unsigned char asc;
                     78:     unsigned char ascq;
                     79:     unsigned char byte4;
                     80:     unsigned char byte5;
                     81:     unsigned char byte6;
                     82:     unsigned char additional_length;
                     83: };
                     84: 
                     85: /* Maps the salient data from a sense buffer which is in either fixed or
                     86:    descriptor format into a structure mimicking a descriptor format
                     87:    header (i.e. the first 8 bytes of sense descriptor format).
                     88:    If zero response code returns 0. Otherwise returns 1 and if 'sshp' is
                     89:    non-NULL then zero all fields and then set the appropriate fields in
                     90:    that structure. sshp::additional_length is always 0 for response
                     91:    codes 0x70 and 0x71 (fixed format). */
                     92: static int sg_scsi_normalize_sense(const unsigned char * sensep, int sb_len,
                     93:                                    struct sg_scsi_sense_hdr * sshp);
                     94: 
                     95: /* Attempt to find the first SCSI sense data descriptor that matches the
                     96:    given 'desc_type'. If found return pointer to start of sense data
                     97:    descriptor; otherwise (including fixed format sense data) returns NULL. */
                     98: static const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep,
                     99:                                                      int sense_len, int desc_type);
                    100: 
                    101: #define SAT_ATA_PASSTHROUGH_12LEN 12
                    102: #define SAT_ATA_PASSTHROUGH_16LEN 16
                    103: 
                    104: #define DEF_SAT_ATA_PASSTHRU_SIZE 16
                    105: #define ATA_RETURN_DESCRIPTOR 9
                    106: 
                    107: 
                    108: namespace sat { // no need to publish anything, name provided for Doxygen
                    109: 
                    110: /// SAT support.
                    111: /// Implements ATA by tunnelling through SCSI.
                    112: 
                    113: class sat_device
                    114: : public tunnelled_device<
                    115:     /*implements*/ ata_device
                    116:     /*by tunnelling through a*/, scsi_device
1.1.1.2 ! misho     117:   >,
        !           118:   virtual public /*implements*/ scsi_device
1.1       misho     119: {
                    120: public:
                    121:   sat_device(smart_interface * intf, scsi_device * scsidev,
1.1.1.2 ! misho     122:     const char * req_type, int passthrulen = 0, bool enable_auto = false);
1.1       misho     123: 
                    124:   virtual ~sat_device() throw();
                    125: 
1.1.1.2 ! misho     126:   virtual smart_device * autodetect_open();
        !           127: 
1.1       misho     128:   virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
                    129: 
1.1.1.2 ! misho     130:   virtual bool scsi_pass_through(scsi_cmnd_io * iop);
        !           131: 
1.1       misho     132: private:
                    133:   int m_passthrulen;
1.1.1.2 ! misho     134:   bool m_enable_auto;
1.1       misho     135: };
                    136: 
                    137: 
                    138: sat_device::sat_device(smart_interface * intf, scsi_device * scsidev,
1.1.1.2 ! misho     139:   const char * req_type, int passthrulen /* = 0 */, bool enable_auto /* = false */)
        !           140: : smart_device(intf, scsidev->get_dev_name(),
        !           141:     (enable_auto ? "sat,auto" : "sat"), req_type),
1.1       misho     142:   tunnelled_device<ata_device, scsi_device>(scsidev),
1.1.1.2 ! misho     143:   m_passthrulen(passthrulen),
        !           144:   m_enable_auto(enable_auto)
1.1       misho     145: {
1.1.1.2 ! misho     146:   if (enable_auto)
        !           147:     hide_ata(); // Start as SCSI, switch to ATA in autodetect_open()
        !           148:   else
        !           149:     hide_scsi(); // ATA always
        !           150: 
        !           151:   set_info().info_name = strprintf("%s [%sSAT]", scsidev->get_info_name(),
        !           152:                                    (enable_auto ? "SCSI/" : ""));
1.1       misho     153: }
                    154: 
                    155: sat_device::~sat_device() throw()
                    156: {
                    157: }
                    158: 
                    159: 
                    160: // cdb[0]: ATA PASS THROUGH (16) SCSI command opcode byte (0x85)
                    161: // cdb[1]: multiple_count, protocol + extend
                    162: // cdb[2]: offline, ck_cond, t_dir, byte_block + t_length
                    163: // cdb[3]: features (15:8)
                    164: // cdb[4]: features (7:0)
                    165: // cdb[5]: sector_count (15:8)
                    166: // cdb[6]: sector_count (7:0)
                    167: // cdb[7]: lba_low (15:8)
                    168: // cdb[8]: lba_low (7:0)
                    169: // cdb[9]: lba_mid (15:8)
                    170: // cdb[10]: lba_mid (7:0)
                    171: // cdb[11]: lba_high (15:8)
                    172: // cdb[12]: lba_high (7:0)
                    173: // cdb[13]: device
                    174: // cdb[14]: (ata) command
                    175: // cdb[15]: control (SCSI, leave as zero)
                    176: //
                    177: // 24 bit lba (from MSB): cdb[12] cdb[10] cdb[8]
                    178: // 48 bit lba (from MSB): cdb[11] cdb[9] cdb[7] cdb[12] cdb[10] cdb[8]
                    179: //
                    180: //
                    181: // cdb[0]: ATA PASS THROUGH (12) SCSI command opcode byte (0xa1)
                    182: // cdb[1]: multiple_count, protocol + extend
                    183: // cdb[2]: offline, ck_cond, t_dir, byte_block + t_length
                    184: // cdb[3]: features (7:0)
                    185: // cdb[4]: sector_count (7:0)
                    186: // cdb[5]: lba_low (7:0)
                    187: // cdb[6]: lba_mid (7:0)
                    188: // cdb[7]: lba_high (7:0)
                    189: // cdb[8]: device
                    190: // cdb[9]: (ata) command
                    191: // cdb[10]: reserved
                    192: // cdb[11]: control (SCSI, leave as zero)
                    193: //
                    194: //
                    195: // ATA Return Descriptor (component of descriptor sense data)
                    196: // des[0]: descriptor code (0x9)
                    197: // des[1]: additional descriptor length (0xc)
                    198: // des[2]: extend (bit 0)
                    199: // des[3]: error
                    200: // des[4]: sector_count (15:8)
                    201: // des[5]: sector_count (7:0)
                    202: // des[6]: lba_low (15:8)
                    203: // des[7]: lba_low (7:0)
                    204: // des[8]: lba_mid (15:8)
                    205: // des[9]: lba_mid (7:0)
                    206: // des[10]: lba_high (15:8)
                    207: // des[11]: lba_high (7:0)
                    208: // des[12]: device
                    209: // des[13]: status
                    210: 
                    211: 
                    212: 
                    213: // PURPOSE
                    214: //   This interface routine takes ATA SMART commands and packages
                    215: //   them in the SAT-defined ATA PASS THROUGH SCSI commands. There are
                    216: //   two available SCSI commands: a 12 byte and 16 byte variant; the
                    217: //   one used is chosen via this->m_passthrulen .
                    218: // DETAILED DESCRIPTION OF ARGUMENTS
                    219: //   device: is the file descriptor provided by (a SCSI dvice type) open()
                    220: //   command: defines the different ATA operations.
                    221: //   select: additional input data if needed (which log, which type of
                    222: //           self-test).
                    223: //   data:   location to write output data, if needed (512 bytes).
                    224: //     Note: not all commands use all arguments.
                    225: // RETURN VALUES
                    226: //  -1 if the command failed
                    227: //   0 if the command succeeded,
                    228: //   STATUS_CHECK routine: 
                    229: //  -1 if the command failed
                    230: //   0 if the command succeeded and disk SMART status is "OK"
                    231: //   1 if the command succeeded and disk SMART status is "FAILING"
                    232: 
                    233: bool sat_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
                    234: {
                    235:   if (!ata_cmd_is_ok(in,
                    236:     true, // data_out_support
                    237:     true, // multi_sector_support
                    238:     true) // ata_48bit_support
                    239:   )
                    240:     return false;
                    241: 
                    242:     struct scsi_cmnd_io io_hdr;
                    243:     struct scsi_sense_disect sinfo;
                    244:     struct sg_scsi_sense_hdr ssh;
                    245:     unsigned char cdb[SAT_ATA_PASSTHROUGH_16LEN];
                    246:     unsigned char sense[32];
                    247:     const unsigned char * ardp;
                    248:     int status, ard_len, have_sense;
                    249:     int extend = 0;
                    250:     int ck_cond = 0;    /* set to 1 to read register(s) back */
                    251:     int protocol = 3;   /* non-data */
                    252:     int t_dir = 1;      /* 0 -> to device, 1 -> from device */
                    253:     int byte_block = 1; /* 0 -> bytes, 1 -> 512 byte blocks */
                    254:     int t_length = 0;   /* 0 -> no data transferred */
                    255:     int passthru_size = DEF_SAT_ATA_PASSTHRU_SIZE;
                    256: 
                    257:     memset(cdb, 0, sizeof(cdb));
                    258:     memset(sense, 0, sizeof(sense));
                    259: 
                    260:     // Set data direction
                    261:     // TODO: This works only for commands where sector_count holds count!
                    262:     switch (in.direction) {
                    263:       case ata_cmd_in::no_data:
                    264:         break;
                    265:       case ata_cmd_in::data_in:
                    266:         protocol = 4;  // PIO data-in
                    267:         t_length = 2;  // sector_count holds count
                    268:         break;
                    269:       case ata_cmd_in::data_out:
                    270:         protocol = 5;  // PIO data-out
                    271:         t_length = 2;  // sector_count holds count
                    272:         t_dir = 0;     // to device
                    273:         break;
                    274:       default:
                    275:         return set_err(EINVAL, "sat_device::ata_pass_through: invalid direction=%d",
                    276:             (int)in.direction);
                    277:     }
                    278: 
                    279:     // Check condition if any output register needed
                    280:     if (in.out_needed.is_set())
                    281:         ck_cond = 1;
                    282: 
                    283:     if ((SAT_ATA_PASSTHROUGH_12LEN == m_passthrulen) ||
                    284:         (SAT_ATA_PASSTHROUGH_16LEN == m_passthrulen))
                    285:         passthru_size = m_passthrulen;
                    286: 
                    287:     // Set extend bit on 48-bit ATA command
                    288:     if (in.in_regs.is_48bit_cmd()) {
                    289:       if (passthru_size != SAT_ATA_PASSTHROUGH_16LEN)
                    290:         return set_err(ENOSYS, "48-bit ATA commands require SAT ATA PASS-THROUGH (16)");
                    291:       extend = 1;
                    292:     }
                    293: 
                    294:     cdb[0] = (SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ?
                    295:              SAT_ATA_PASSTHROUGH_12 : SAT_ATA_PASSTHROUGH_16;
                    296: 
                    297:     cdb[1] = (protocol << 1) | extend;
                    298:     cdb[2] = (ck_cond << 5) | (t_dir << 3) |
                    299:              (byte_block << 2) | t_length;
                    300: 
                    301:     if (passthru_size == SAT_ATA_PASSTHROUGH_12LEN) {
                    302:         // ATA PASS-THROUGH (12)
                    303:         const ata_in_regs & lo = in.in_regs;
                    304:         cdb[3] = lo.features;
                    305:         cdb[4] = lo.sector_count;
                    306:         cdb[5] = lo.lba_low;
                    307:         cdb[6] = lo.lba_mid;
                    308:         cdb[7] = lo.lba_high;
                    309:         cdb[8] = lo.device;
                    310:         cdb[9] = lo.command;
                    311:     }
                    312:     else {
                    313:         // ATA PASS-THROUGH (16)
                    314:         const ata_in_regs & lo = in.in_regs;
                    315:         const ata_in_regs & hi = in.in_regs.prev;
                    316:         // Note: all 'in.in_regs.prev.*' are always zero for 28-bit commands
                    317:         cdb[ 3] = hi.features;
                    318:         cdb[ 4] = lo.features;
                    319:         cdb[ 5] = hi.sector_count;
                    320:         cdb[ 6] = lo.sector_count;
                    321:         cdb[ 7] = hi.lba_low;
                    322:         cdb[ 8] = lo.lba_low;
                    323:         cdb[ 9] = hi.lba_mid;
                    324:         cdb[10] = lo.lba_mid;
                    325:         cdb[11] = hi.lba_high;
                    326:         cdb[12] = lo.lba_high;
                    327:         cdb[13] = lo.device;
                    328:         cdb[14] = lo.command;
                    329:     }
                    330: 
                    331:     memset(&io_hdr, 0, sizeof(io_hdr));
                    332:     if (0 == t_length) {
                    333:         io_hdr.dxfer_dir = DXFER_NONE;
                    334:         io_hdr.dxfer_len = 0;
                    335:     } else if (t_dir) {         /* from device */
                    336:         io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
                    337:         io_hdr.dxfer_len = in.size;
                    338:         io_hdr.dxferp = (unsigned char *)in.buffer;
                    339:         memset(in.buffer, 0, in.size); // prefill with zeroes
                    340:     } else {                    /* to device */
                    341:         io_hdr.dxfer_dir = DXFER_TO_DEVICE;
                    342:         io_hdr.dxfer_len = in.size;
                    343:         io_hdr.dxferp = (unsigned char *)in.buffer;
                    344:     }
                    345:     io_hdr.cmnd = cdb;
                    346:     io_hdr.cmnd_len = passthru_size;
                    347:     io_hdr.sensep = sense;
                    348:     io_hdr.max_sense_len = sizeof(sense);
                    349:     io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
                    350: 
                    351:     scsi_device * scsidev = get_tunnel_dev();
                    352:     if (!scsidev->scsi_pass_through(&io_hdr)) {
                    353:         if (scsi_debugmode > 0)
                    354:             pout("sat_device::ata_pass_through: scsi_pass_through() failed, "
                    355:                  "errno=%d [%s]\n", scsidev->get_errno(), scsidev->get_errmsg());
                    356:         return set_err(scsidev->get_err());
                    357:     }
                    358:     ardp = NULL;
                    359:     ard_len = 0;
                    360:     have_sense = sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len,
                    361:                                          &ssh);
                    362:     if (have_sense) {
                    363:         /* look for SAT ATA Return Descriptor */
                    364:         ardp = sg_scsi_sense_desc_find(io_hdr.sensep,
                    365:                                        io_hdr.resp_sense_len,
                    366:                                        ATA_RETURN_DESCRIPTOR);
                    367:         if (ardp) {
                    368:             ard_len = ardp[1] + 2;
                    369:             if (ard_len < 12)
                    370:                 ard_len = 12;
                    371:             else if (ard_len > 14)
                    372:                 ard_len = 14;
                    373:         }
                    374:         scsi_do_sense_disect(&io_hdr, &sinfo);
                    375:         status = scsiSimpleSenseFilter(&sinfo);
                    376:         if (0 != status) {
                    377:             if (scsi_debugmode > 0) {
                    378:                 pout("sat_device::ata_pass_through: scsi error: %s\n",
                    379:                      scsiErrString(status));
                    380:                 if (ardp && (scsi_debugmode > 1)) {
                    381:                     pout("Values from ATA Return Descriptor are:\n");
                    382:                     dStrHex((const char *)ardp, ard_len, 1);
                    383:                 }
                    384:             }
                    385:             if (t_dir && (t_length > 0) && (in.direction == ata_cmd_in::data_in))
                    386:                 memset(in.buffer, 0, in.size);
                    387:             return set_err(EIO, "scsi error %s", scsiErrString(status));
                    388:         }
                    389:     }
                    390:     if (ck_cond) {     /* expecting SAT specific sense data */
                    391:         if (have_sense) {
                    392:             if (ardp) {
                    393:                 if (scsi_debugmode > 1) {
                    394:                     pout("Values from ATA Return Descriptor are:\n");
                    395:                     dStrHex((const char *)ardp, ard_len, 1);
                    396:                 }
                    397:                 // Set output registers
                    398:                 ata_out_regs & lo = out.out_regs;
                    399:                 lo.error        = ardp[ 3];
                    400:                 lo.sector_count = ardp[ 5];
                    401:                 lo.lba_low      = ardp[ 7];
                    402:                 lo.lba_mid      = ardp[ 9];
                    403:                 lo.lba_high     = ardp[11];
                    404:                 lo.device       = ardp[12];
                    405:                 lo.status       = ardp[13];
                    406:                 if (in.in_regs.is_48bit_cmd()) {
                    407:                     ata_out_regs & hi = out.out_regs.prev;
                    408:                     hi.sector_count = ardp[ 4];
                    409:                     hi.lba_low      = ardp[ 6];
                    410:                     hi.lba_mid      = ardp[ 8];
                    411:                     hi.lba_high     = ardp[10];
                    412:                 }
                    413:             }
                    414:         }
                    415:         if (ardp == NULL)
                    416:             ck_cond = 0;       /* not the type of sense data expected */
                    417:     }
                    418:     if (0 == ck_cond) {
                    419:         if (have_sense) {
                    420:             if ((ssh.response_code >= 0x72) &&
                    421:                 ((SCSI_SK_NO_SENSE == ssh.sense_key) ||
                    422:                  (SCSI_SK_RECOVERED_ERR == ssh.sense_key)) &&
                    423:                 (0 == ssh.asc) &&
                    424:                 (SCSI_ASCQ_ATA_PASS_THROUGH == ssh.ascq)) {
                    425:                 if (ardp) {
                    426:                     if (scsi_debugmode > 0) {
                    427:                         pout("Values from ATA Return Descriptor are:\n");
                    428:                         dStrHex((const char *)ardp, ard_len, 1);
                    429:                     }
                    430:                     return set_err(EIO, "SAT command failed");
                    431:                 }
                    432:             }
                    433:         }
                    434:     }
                    435:     return true;
                    436: }
                    437: 
1.1.1.2 ! misho     438: bool sat_device::scsi_pass_through(scsi_cmnd_io * iop)
        !           439: {
        !           440:   scsi_device * scsidev = get_tunnel_dev();
        !           441:   if (!scsidev->scsi_pass_through(iop)) {
        !           442:     set_err(scsidev->get_err());
        !           443:     return false;
        !           444:   }
        !           445:   return true;
        !           446: }
        !           447: 
        !           448: smart_device * sat_device::autodetect_open()
        !           449: {
        !           450:   if (!open() || !m_enable_auto)
        !           451:     return this;
        !           452: 
        !           453:   scsi_device * scsidev = get_tunnel_dev();
        !           454: 
        !           455:   unsigned char inqdata[36] = {0, };
        !           456:   if (scsiStdInquiry(scsidev, inqdata, sizeof(inqdata))) {
        !           457:       smart_device::error_info err = scsidev->get_err();
        !           458:       close();
        !           459:       set_err(err.no, "INQUIRY [SAT]: %s", err.msg.c_str());
        !           460:       return this;
        !           461:   }
        !           462: 
        !           463:   // Check for SAT "VENDOR"
        !           464:   int inqsize = inqdata[4] + 5;
        !           465:   bool sat = (inqsize >= 36 && !memcmp(inqdata + 8, "ATA     ", 8));
        !           466: 
        !           467:   // Change interface
        !           468:   hide_ata(!sat);
        !           469:   hide_scsi(sat);
        !           470: 
        !           471:   set_info().dev_type = (sat ? "sat" : scsidev->get_dev_type());
        !           472:   set_info().info_name = strprintf("%s [%s]", scsidev->get_info_name(),
        !           473:                                    (sat ? "SAT" : "SCSI"));
        !           474:   return this;
        !           475: }
        !           476: 
1.1       misho     477: } // namespace
                    478: 
                    479: /////////////////////////////////////////////////////////////////////////////
                    480: 
                    481: /* Attempt an IDENTIFY DEVICE ATA command via SATL when packet_interface
                    482:    is false otherwise attempt IDENTIFY PACKET DEVICE. If successful
                    483:    return true, else false */
                    484: 
                    485: static bool has_sat_pass_through(ata_device * dev, bool packet_interface = false)
                    486: {
                    487:     /* Note:  malloc() ensures the read buffer lands on a single
                    488:        page.  This avoids some bugs seen on LSI controlers under
                    489:        FreeBSD */
                    490:     char *data = (char *)malloc(512);
                    491:     ata_cmd_in in;
                    492:     in.in_regs.command = (packet_interface ? ATA_IDENTIFY_PACKET_DEVICE : ATA_IDENTIFY_DEVICE);
                    493:     in.set_data_in(data, 1);
                    494:     bool ret = dev->ata_pass_through(in);
                    495:     free(data);
                    496:     return ret;
                    497: }
                    498: 
                    499: /////////////////////////////////////////////////////////////////////////////
                    500: 
                    501: /* Next two functions are borrowed from sg_lib.c in the sg3_utils
                    502:    package. Same copyrght owner, same license as this file. */
                    503: static int sg_scsi_normalize_sense(const unsigned char * sensep, int sb_len,
                    504:                                    struct sg_scsi_sense_hdr * sshp)
                    505: {
                    506:     if (sshp)
                    507:         memset(sshp, 0, sizeof(struct sg_scsi_sense_hdr));
                    508:     if ((NULL == sensep) || (0 == sb_len) || (0x70 != (0x70 & sensep[0])))
                    509:         return 0;
                    510:     if (sshp) {
                    511:         sshp->response_code = (0x7f & sensep[0]);
                    512:         if (sshp->response_code >= 0x72) {  /* descriptor format */
                    513:             if (sb_len > 1)
                    514:                 sshp->sense_key = (0xf & sensep[1]);
                    515:             if (sb_len > 2)
                    516:                 sshp->asc = sensep[2];
                    517:             if (sb_len > 3)
                    518:                 sshp->ascq = sensep[3];
                    519:             if (sb_len > 7)
                    520:                 sshp->additional_length = sensep[7];
                    521:         } else {                              /* fixed format */
                    522:             if (sb_len > 2)
                    523:                 sshp->sense_key = (0xf & sensep[2]);
                    524:             if (sb_len > 7) {
                    525:                 sb_len = (sb_len < (sensep[7] + 8)) ? sb_len :
                    526:                                                       (sensep[7] + 8);
                    527:                 if (sb_len > 12)
                    528:                     sshp->asc = sensep[12];
                    529:                 if (sb_len > 13)
                    530:                     sshp->ascq = sensep[13];
                    531:             }
                    532:         }
                    533:     }
                    534:     return 1;
                    535: }
                    536: 
                    537: 
                    538: static const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep,
                    539:                                                      int sense_len, int desc_type)
                    540: {
                    541:     int add_sen_len, add_len, desc_len, k;
                    542:     const unsigned char * descp;
                    543: 
                    544:     if ((sense_len < 8) || (0 == (add_sen_len = sensep[7])))
                    545:         return NULL;
                    546:     if ((sensep[0] < 0x72) || (sensep[0] > 0x73))
                    547:         return NULL;
                    548:     add_sen_len = (add_sen_len < (sense_len - 8)) ?
                    549:                          add_sen_len : (sense_len - 8);
                    550:     descp = &sensep[8];
                    551:     for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) {
                    552:         descp += desc_len;
                    553:         add_len = (k < (add_sen_len - 1)) ? descp[1]: -1;
                    554:         desc_len = add_len + 2;
                    555:         if (descp[0] == desc_type)
                    556:             return descp;
                    557:         if (add_len < 0) /* short descriptor ?? */
                    558:             break;
                    559:     }
                    560:     return NULL;
                    561: }
                    562: 
                    563: 
                    564: // Call scsi_pass_through and check sense.
                    565: // TODO: Provide as member function of class scsi_device (?)
                    566: static bool scsi_pass_through_and_check(scsi_device * scsidev,  scsi_cmnd_io * iop,
                    567:                                         const char * msg = "")
                    568: {
                    569:   // Provide sense buffer
                    570:   unsigned char sense[32] = {0, };
                    571:   iop->sensep = sense;
                    572:   iop->max_sense_len = sizeof(sense);
                    573:   iop->timeout = SCSI_TIMEOUT_DEFAULT;
                    574: 
                    575:   // Run cmd
                    576:   if (!scsidev->scsi_pass_through(iop)) {
                    577:     if (scsi_debugmode > 0)
                    578:       pout("%sscsi_pass_through() failed, errno=%d [%s]\n",
                    579:            msg, scsidev->get_errno(), scsidev->get_errmsg());
                    580:     return false;
                    581:   }
                    582: 
                    583:   // Check sense
                    584:   scsi_sense_disect sinfo;
                    585:   scsi_do_sense_disect(iop, &sinfo);
                    586:   int err = scsiSimpleSenseFilter(&sinfo);
                    587:   if (err) {
                    588:     if (scsi_debugmode > 0)
                    589:       pout("%sscsi error: %s\n", msg, scsiErrString(err));
                    590:     return scsidev->set_err(EIO, "scsi error %s", scsiErrString(err));
                    591:   }
                    592: 
                    593:   return true;
                    594: }
                    595: 
                    596: 
                    597: /////////////////////////////////////////////////////////////////////////////
                    598: 
                    599: namespace sat {
                    600: 
                    601: /// Cypress USB Brigde support.
                    602: 
                    603: class usbcypress_device
                    604: : public tunnelled_device<
                    605:     /*implements*/ ata_device_with_command_set
                    606:     /*by tunnelling through a*/, scsi_device
                    607:   >
                    608: {
                    609: public:
                    610:   usbcypress_device(smart_interface * intf, scsi_device * scsidev,
                    611:     const char * req_type, unsigned char signature);
                    612: 
                    613:   virtual ~usbcypress_device() throw();
                    614: 
                    615: protected:
                    616:   virtual int ata_command_interface(smart_command_set command, int select, char * data);
                    617: 
                    618:   unsigned char m_signature;
                    619: };
                    620: 
                    621: 
                    622: usbcypress_device::usbcypress_device(smart_interface * intf, scsi_device * scsidev,
                    623:   const char * req_type, unsigned char signature)
                    624: : smart_device(intf, scsidev->get_dev_name(), "sat", req_type),
                    625:   tunnelled_device<ata_device_with_command_set, scsi_device>(scsidev),
                    626:   m_signature(signature)
                    627: {
                    628:   set_info().info_name = strprintf("%s [USB Cypress]", scsidev->get_info_name());
                    629: }
                    630: 
                    631: usbcypress_device::~usbcypress_device() throw()
                    632: {
                    633: }
                    634: 
                    635: 
                    636: /* see cy7c68300c_8.pdf for more information */
                    637: #define USBCYPRESS_PASSTHROUGH_LEN 16
                    638: int usbcypress_device::ata_command_interface(smart_command_set command, int select, char *data)
                    639: {
                    640:     struct scsi_cmnd_io io_hdr;
                    641:     unsigned char cdb[USBCYPRESS_PASSTHROUGH_LEN];
                    642:     unsigned char sense[32];
                    643:     int copydata = 0;
                    644:     int outlen = 0;
                    645:     int ck_cond = 0;    /* set to 1 to read register(s) back */
                    646:     int t_dir = 1;      /* 0 -> to device, 1 -> from device */
                    647:     int byte_block = 1; /* 0 -> bytes, 1 -> 512 byte blocks */
                    648:     int t_length = 0;   /* 0 -> no data transferred */
                    649:     int feature = 0;
                    650:     int ata_command = 0;
                    651:     int sector_count = 0;
                    652:     int lba_low = 0;
                    653:     int lba_mid = 0;
                    654:     int lba_high = 0;
                    655:     int passthru_size = USBCYPRESS_PASSTHROUGH_LEN;
                    656: 
                    657:     memset(cdb, 0, sizeof(cdb));
                    658:     memset(sense, 0, sizeof(sense));
                    659: 
                    660:     ata_command = ATA_SMART_CMD;
                    661:     switch (command) {
                    662:     case CHECK_POWER_MODE:
                    663:         ata_command = ATA_CHECK_POWER_MODE;
                    664:         ck_cond = 1;
                    665:         copydata = 1;
                    666:         break;
                    667:     case READ_VALUES:           /* READ DATA */
                    668:         feature = ATA_SMART_READ_VALUES;
                    669:         sector_count = 1;     /* one (512 byte) block */
                    670:         t_length = 2;   /* sector count holds count */
                    671:         copydata = 512;
                    672:         break;
                    673:     case READ_THRESHOLDS:       /* obsolete */
                    674:         feature = ATA_SMART_READ_THRESHOLDS;
                    675:         sector_count = 1;     /* one (512 byte) block */
                    676:         lba_low = 1;
                    677:         t_length = 2;   /* sector count holds count */
                    678:         copydata=512;
                    679:         break;
                    680:     case READ_LOG:
                    681:         feature = ATA_SMART_READ_LOG_SECTOR;
                    682:         sector_count = 1;     /* one (512 byte) block */
                    683:         lba_low = select;
                    684:         t_length = 2;   /* sector count holds count */
                    685:         copydata = 512;
                    686:         break;
                    687:     case WRITE_LOG:
                    688:         feature = ATA_SMART_WRITE_LOG_SECTOR;
                    689:         sector_count = 1;     /* one (512 byte) block */
                    690:         lba_low = select;
                    691:         t_length = 2;   /* sector count holds count */
                    692:         t_dir = 0;      /* to device */
                    693:         outlen = 512;
                    694:         break;
                    695:     case IDENTIFY:
                    696:         ata_command = ATA_IDENTIFY_DEVICE;
                    697:         sector_count = 1;     /* one (512 byte) block */
                    698:         t_length = 2;   /* sector count holds count */
                    699:         copydata = 512;
                    700:         break;
                    701:     case PIDENTIFY:
                    702:         ata_command = ATA_IDENTIFY_PACKET_DEVICE;
                    703:         sector_count = 1;     /* one (512 byte) block */
                    704:         t_length = 2;   /* sector count (7:0) holds count */
                    705:         copydata = 512;
                    706:         break;
                    707:     case ENABLE:
                    708:         feature = ATA_SMART_ENABLE;
                    709:         lba_low = 1;
                    710:         break;
                    711:     case DISABLE:
                    712:         feature = ATA_SMART_DISABLE;
                    713:         lba_low = 1;
                    714:         break;
                    715:     case STATUS:
                    716:         // this command only says if SMART is working.  It could be
                    717:         // replaced with STATUS_CHECK below.
                    718:         feature = ATA_SMART_STATUS;
                    719:         ck_cond = 1;
                    720:         break;
                    721:     case AUTO_OFFLINE:
                    722:         feature = ATA_SMART_AUTO_OFFLINE;
                    723:         sector_count = select;   // YET NOTE - THIS IS A NON-DATA COMMAND!!
                    724:         break;
                    725:     case AUTOSAVE:
                    726:         feature = ATA_SMART_AUTOSAVE;
                    727:         sector_count = select;   // YET NOTE - THIS IS A NON-DATA COMMAND!!
                    728:         break;
                    729:     case IMMEDIATE_OFFLINE:
                    730:         feature = ATA_SMART_IMMEDIATE_OFFLINE;
                    731:         lba_low = select;
                    732:         break;
                    733:     case STATUS_CHECK:
                    734:         // This command uses HDIO_DRIVE_TASK and has different syntax than
                    735:         // the other commands.
                    736:         feature = ATA_SMART_STATUS;      /* SMART RETURN STATUS */
                    737:         ck_cond = 1;
                    738:         break;
                    739:     default:
                    740:         pout("Unrecognized command %d in usbcypress_device::ata_command_interface()\n"
                    741:              "Please contact " PACKAGE_BUGREPORT "\n", command);
                    742:         errno=ENOSYS;
                    743:         return -1;
                    744:     }
                    745:     if (ATA_SMART_CMD == ata_command) {
                    746:         lba_mid = 0x4f;
                    747:         lba_high = 0xc2;
                    748:     }
                    749: 
                    750:     cdb[0] = m_signature; // bVSCBSignature : vendor-specific command
                    751:     cdb[1] = 0x24; // bVSCBSubCommand : 0x24 for ATACB
                    752:     cdb[2] = 0x0;
                    753:     if (ata_command == ATA_IDENTIFY_DEVICE || ata_command == ATA_IDENTIFY_PACKET_DEVICE)
                    754:         cdb[2] |= (1<<7); //set  IdentifyPacketDevice for these cmds
                    755:     cdb[3] = 0xff - (1<<0) - (1<<6); //features, sector count, lba low, lba med
                    756:                                      // lba high, command are valid
                    757:     cdb[4] = byte_block; //TransferBlockCount : 512
                    758: 
                    759: 
                    760:     cdb[6] = feature;
                    761:     cdb[7] = sector_count;
                    762:     cdb[8] = lba_low;
                    763:     cdb[9] = lba_mid;
                    764:     cdb[10] = lba_high;
                    765:     cdb[12] = ata_command;
                    766: 
                    767:     memset(&io_hdr, 0, sizeof(io_hdr));
                    768:     if (0 == t_length) {
                    769:         io_hdr.dxfer_dir = DXFER_NONE;
                    770:         io_hdr.dxfer_len = 0;
                    771:     } else if (t_dir) {         /* from device */
                    772:         io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
                    773:         io_hdr.dxfer_len = copydata;
                    774:         io_hdr.dxferp = (unsigned char *)data;
                    775:         memset(data, 0, copydata); /* prefill with zeroes */
                    776:     } else {                    /* to device */
                    777:         io_hdr.dxfer_dir = DXFER_TO_DEVICE;
                    778:         io_hdr.dxfer_len = outlen;
                    779:         io_hdr.dxferp = (unsigned char *)data;
                    780:     }
                    781:     io_hdr.cmnd = cdb;
                    782:     io_hdr.cmnd_len = passthru_size;
                    783:     io_hdr.sensep = sense;
                    784:     io_hdr.max_sense_len = sizeof(sense);
                    785:     io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
                    786: 
                    787:     scsi_device * scsidev = get_tunnel_dev();
                    788:     if (!scsidev->scsi_pass_through(&io_hdr)) {
                    789:         if (scsi_debugmode > 0)
                    790:             pout("usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
                    791:                  "errno=%d [%s]\n", scsidev->get_errno(), scsidev->get_errmsg());
                    792:         set_err(scsidev->get_err());
                    793:         return -1;
                    794:     }
                    795: 
                    796:     // if there is a sense the command failed or the
                    797:     // device doesn't support usbcypress
                    798:     if (io_hdr.scsi_status == SCSI_STATUS_CHECK_CONDITION && 
                    799:             sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len, NULL)) {
                    800:         return -1;
                    801:     }
                    802:     if (ck_cond) {
                    803:         unsigned char ardp[8];
                    804:         int ard_len = 8;
                    805:         /* XXX this is racy if there other scsi command between
                    806:          * the first usbcypress command and this one
                    807:          */
                    808:         //pout("If you got strange result, please retry without traffic on the disc\n");
                    809:         /* we use the same command as before, but we set
                    810:          * * the read taskfile bit, for not executing usbcypress command,
                    811:          * * but reading register selected in srb->cmnd[4]
                    812:          */
                    813:         cdb[2] = (1<<0); /* ask read taskfile */
                    814:         memset(sense, 0, sizeof(sense));
                    815: 
                    816:         /* transfert 8 bytes */
                    817:         memset(&io_hdr, 0, sizeof(io_hdr));
                    818:         io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
                    819:         io_hdr.dxfer_len = ard_len;
                    820:         io_hdr.dxferp = (unsigned char *)ardp;
                    821:         memset(ardp, 0, ard_len); /* prefill with zeroes */
                    822: 
                    823:         io_hdr.cmnd = cdb;
                    824:         io_hdr.cmnd_len = passthru_size;
                    825:         io_hdr.sensep = sense;
                    826:         io_hdr.max_sense_len = sizeof(sense);
                    827:         io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
                    828: 
                    829: 
                    830:         if (!scsidev->scsi_pass_through(&io_hdr)) {
                    831:             if (scsi_debugmode > 0)
                    832:                 pout("usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
                    833:                      "errno=%d [%s]\n", scsidev->get_errno(), scsidev->get_errmsg());
                    834:             set_err(scsidev->get_err());
                    835:             return -1;
                    836:         }
                    837:         // if there is a sense the command failed or the
                    838:         // device doesn't support usbcypress
                    839:         if (io_hdr.scsi_status == SCSI_STATUS_CHECK_CONDITION && 
                    840:                 sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len, NULL)) {
                    841:             return -1;
                    842:         }
                    843: 
                    844: 
                    845:         if (scsi_debugmode > 1) {
                    846:             pout("Values from ATA Return Descriptor are:\n");
                    847:             dStrHex((const char *)ardp, ard_len, 1);
                    848:         }
                    849: 
                    850:         if (ATA_CHECK_POWER_MODE == ata_command)
                    851:             data[0] = ardp[2];      /* sector count (0:7) */
                    852:         else if (STATUS_CHECK == command) {
                    853:             if ((ardp[4] == 0x4f) && (ardp[5] == 0xc2))
                    854:                 return 0;    /* GOOD smart status */
                    855:             if ((ardp[4] == 0xf4) && (ardp[5] == 0x2c))
                    856:                 return 1;    // smart predicting failure, "bad" status
                    857:             // We haven't gotten output that makes sense so
                    858:             // print out some debugging info
                    859:             syserror("Error SMART Status command failed");
                    860:             pout("This may be due to a race in usbcypress\n");
                    861:             pout("Retry without other disc access\n");
                    862:             pout("Please get assistance from " PACKAGE_HOMEPAGE "\n");
                    863:             pout("Values from ATA Return Descriptor are:\n");
                    864:             dStrHex((const char *)ardp, ard_len, 1);
                    865:             return -1;
                    866:         }
                    867:     }
                    868:     return 0;
                    869: }
                    870: 
                    871: #if 0 // Not used, see autodetect_sat_device() below.
                    872: static int isprint_string(const char *s)
                    873: {
                    874:     while (*s) {
                    875:         if (isprint(*s) == 0)
                    876:             return 0;
                    877:         s++;
                    878:     }
                    879:     return 1;
                    880: }
                    881: 
                    882: /* Attempt an IDENTIFY DEVICE ATA or IDENTIFY PACKET DEVICE command
                    883:    If successful return 1, else 0 */
                    884: // TODO: Combine with has_sat_pass_through above
                    885: static int has_usbcypress_pass_through(ata_device * atadev, const char *manufacturer, const char *product)
                    886: {
                    887:     struct ata_identify_device drive;
                    888:     char model[40], serial[20], firm[8];
                    889: 
                    890:     /* issue the command and do a checksum if possible */
                    891:     if (ataReadHDIdentity(atadev, &drive) < 0)
                    892:         return 0;
                    893: 
                    894:     /* check if model string match, revision doesn't work for me */
                    895:     format_ata_string(model, drive.model, 40);
                    896:     if (*model == 0 || isprint_string(model) == 0)
                    897:         return 0;
                    898: 
                    899:     if (manufacturer && strncmp(manufacturer, model, 8))
                    900:         pout("manufacturer doesn't match in pass_through test\n");
                    901:     if (product &&
                    902:             strlen(model) > 8 && strncmp(product, model+8, strlen(model)-8))
                    903:         pout("product doesn't match in pass_through test\n");
                    904: 
                    905:     /* check serial */
                    906:     format_ata_string(serial, drive.serial_no, 20);
                    907:     if (isprint_string(serial) == 0)
                    908:         return 0;
                    909:     format_ata_string(firm, drive.fw_rev, 8);
                    910:     if (isprint_string(firm) == 0)
                    911:         return 0;
                    912:     return 1;
                    913: }
                    914: #endif
                    915: 
                    916: /////////////////////////////////////////////////////////////////////////////
                    917: 
                    918: /// JMicron USB Bridge support.
                    919: 
                    920: class usbjmicron_device
                    921: : public tunnelled_device<
                    922:     /*implements*/ ata_device,
                    923:     /*by tunnelling through a*/ scsi_device
                    924:   >
                    925: {
                    926: public:
                    927:   usbjmicron_device(smart_interface * intf, scsi_device * scsidev,
                    928:                     const char * req_type, bool ata_48bit_support, int port);
                    929: 
                    930:   virtual ~usbjmicron_device() throw();
                    931: 
                    932:   virtual bool open();
                    933: 
                    934:   virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
                    935: 
                    936: private:
                    937:   bool get_registers(unsigned short addr, unsigned char * buf, unsigned short size);
                    938: 
                    939:   bool m_ata_48bit_support;
                    940:   int m_port;
                    941: };
                    942: 
                    943: 
                    944: usbjmicron_device::usbjmicron_device(smart_interface * intf, scsi_device * scsidev,
                    945:                                      const char * req_type, bool ata_48bit_support, int port)
                    946: : smart_device(intf, scsidev->get_dev_name(), "usbjmicron", req_type),
                    947:   tunnelled_device<ata_device, scsi_device>(scsidev),
                    948:   m_ata_48bit_support(ata_48bit_support), m_port(port)
                    949: {
                    950:   set_info().info_name = strprintf("%s [USB JMicron]", scsidev->get_info_name());
                    951: }
                    952: 
                    953: usbjmicron_device::~usbjmicron_device() throw()
                    954: {
                    955: }
                    956: 
                    957: 
                    958: bool usbjmicron_device::open()
                    959: {
                    960:   // Open USB first
                    961:   if (!tunnelled_device<ata_device, scsi_device>::open())
                    962:     return false;
                    963: 
                    964:   // Detect port if not specified
                    965:   if (m_port < 0) {
                    966:     unsigned char regbuf[1] = {0};
                    967:     if (!get_registers(0x720f, regbuf, sizeof(regbuf))) {
                    968:       close();
                    969:       return false;
                    970:     }
                    971: 
                    972:     switch (regbuf[0] & 0x44) {
                    973:       case 0x04:
                    974:         m_port = 0; break;
                    975:       case 0x40:
                    976:         m_port = 1; break;
                    977:       case 0x44:
                    978:         close();
                    979:         return set_err(EINVAL, "Two devices connected, try '-d usbjmicron,[01]'");
                    980:       default:
                    981:         close();
                    982:         return set_err(ENODEV, "No device connected");
                    983:     }
                    984:   }
                    985: 
                    986:   return true;
                    987: }
                    988: 
                    989: 
                    990: bool usbjmicron_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
                    991: {
                    992:   if (!ata_cmd_is_ok(in,
                    993:     true,  // data_out_support
                    994:     false, // !multi_sector_support
                    995:     m_ata_48bit_support) // limited, see below
                    996:   )
                    997:     return false;
                    998: 
                    999:   bool is_smart_status = (   in.in_regs.command  == ATA_SMART_CMD
                   1000:                           && in.in_regs.features == ATA_SMART_STATUS);
                   1001: 
                   1002:   // Support output registers for SMART STATUS
                   1003:   if (in.out_needed.is_set() && !is_smart_status)
                   1004:     return set_err(ENOSYS, "ATA output registers not supported");
                   1005: 
                   1006:   // Support 48-bit commands with zero high bytes
                   1007:   if (in.in_regs.is_real_48bit_cmd())
                   1008:     return set_err(ENOSYS, "48-bit ATA commands not fully supported");
                   1009: 
                   1010:   if (m_port < 0)
                   1011:     return set_err(EIO, "Unknown JMicron port");
                   1012: 
                   1013:   scsi_cmnd_io io_hdr;
                   1014:   memset(&io_hdr, 0, sizeof(io_hdr));
                   1015: 
                   1016:   bool rwbit = true;
                   1017:   unsigned char smart_status = 0;
                   1018: 
                   1019:   if (is_smart_status && in.out_needed.is_set()) {
                   1020:     io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
                   1021:     io_hdr.dxfer_len = 1;
                   1022:     io_hdr.dxferp = &smart_status;
                   1023:   }
                   1024:   else switch (in.direction) {
                   1025:     case ata_cmd_in::no_data:
                   1026:       io_hdr.dxfer_dir = DXFER_NONE;
                   1027:       break;
                   1028:     case ata_cmd_in::data_in:
                   1029:       io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
                   1030:       io_hdr.dxfer_len = in.size;
                   1031:       io_hdr.dxferp = (unsigned char *)in.buffer;
                   1032:       memset(in.buffer, 0, in.size);
                   1033:       break;
                   1034:     case ata_cmd_in::data_out:
                   1035:       io_hdr.dxfer_dir = DXFER_TO_DEVICE;
                   1036:       io_hdr.dxfer_len = in.size;
                   1037:       io_hdr.dxferp = (unsigned char *)in.buffer;
                   1038:       rwbit = false;
                   1039:       break;
                   1040:     default:
                   1041:       return set_err(EINVAL);
                   1042:   }
                   1043: 
                   1044:   // Build pass through command
                   1045:   unsigned char cdb[12];
                   1046:   cdb[ 0] = 0xdf;
                   1047:   cdb[ 1] = (rwbit ? 0x10 : 0x00);
                   1048:   cdb[ 2] = 0x00;
                   1049:   cdb[ 3] = (unsigned char)(io_hdr.dxfer_len >> 8);
                   1050:   cdb[ 4] = (unsigned char)(io_hdr.dxfer_len     );
                   1051:   cdb[ 5] = in.in_regs.features;
                   1052:   cdb[ 6] = in.in_regs.sector_count;
                   1053:   cdb[ 7] = in.in_regs.lba_low;
                   1054:   cdb[ 8] = in.in_regs.lba_mid;
                   1055:   cdb[ 9] = in.in_regs.lba_high;
                   1056:   cdb[10] = in.in_regs.device | (m_port == 0 ? 0xa0 : 0xb0);
                   1057:   cdb[11] = in.in_regs.command;
                   1058: 
                   1059:   io_hdr.cmnd = cdb;
                   1060:   io_hdr.cmnd_len = sizeof(cdb);
                   1061: 
                   1062:   scsi_device * scsidev = get_tunnel_dev();
                   1063:   if (!scsi_pass_through_and_check(scsidev, &io_hdr,
                   1064:          "usbjmicron_device::ata_pass_through: "))
                   1065:     return set_err(scsidev->get_err());
                   1066: 
                   1067:   if (in.out_needed.is_set()) {
                   1068:     if (is_smart_status) {
                   1069:       switch (smart_status) {
                   1070:         case 0x01: case 0xc2:
                   1071:           out.out_regs.lba_high = 0xc2;
                   1072:           out.out_regs.lba_mid = 0x4f;
                   1073:           break;
                   1074:         case 0x00: case 0x2c:
                   1075:           out.out_regs.lba_high = 0x2c;
                   1076:           out.out_regs.lba_mid = 0xf4;
                   1077:           break;
                   1078:       }
                   1079:     }
                   1080: 
                   1081: #if 0 // Not needed for SMART STATUS, see also notes below
                   1082:     else {
                   1083:       // Read ATA output registers
                   1084:       // NOTE: The register addresses are not valid for some older chip revisions
                   1085:       // NOTE: There is a small race condition here!
                   1086:       unsigned char regbuf[16] = {0, };
                   1087:       if (!get_registers((m_port == 0 ? 0x8000 : 0x9000), regbuf, sizeof(regbuf)))
                   1088:         return false;
                   1089: 
                   1090:       out.out_regs.sector_count = regbuf[ 0];
                   1091:       out.out_regs.lba_mid      = regbuf[ 4];
                   1092:       out.out_regs.lba_low      = regbuf[ 6];
                   1093:       out.out_regs.device       = regbuf[ 9];
                   1094:       out.out_regs.lba_high     = regbuf[10];
                   1095:       out.out_regs.error        = regbuf[13];
                   1096:       out.out_regs.status       = regbuf[14];
                   1097:     }
                   1098: #endif
                   1099:   }
                   1100: 
                   1101:   return true;
                   1102: }
                   1103: 
                   1104: bool usbjmicron_device::get_registers(unsigned short addr,
                   1105:                                       unsigned char * buf, unsigned short size)
                   1106: {
                   1107:   unsigned char cdb[12];
                   1108:   cdb[ 0] = 0xdf;
                   1109:   cdb[ 1] = 0x10;
                   1110:   cdb[ 2] = 0x00;
                   1111:   cdb[ 3] = (unsigned char)(size >> 8);
                   1112:   cdb[ 4] = (unsigned char)(size     );
                   1113:   cdb[ 5] = 0x00;
                   1114:   cdb[ 6] = (unsigned char)(addr >> 8);
                   1115:   cdb[ 7] = (unsigned char)(addr     );
                   1116:   cdb[ 8] = 0x00;
                   1117:   cdb[ 9] = 0x00;
                   1118:   cdb[10] = 0x00;
                   1119:   cdb[11] = 0xfd;
                   1120: 
                   1121:   scsi_cmnd_io io_hdr;
                   1122:   memset(&io_hdr, 0, sizeof(io_hdr));
                   1123:   io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
                   1124:   io_hdr.dxfer_len = size;
                   1125:   io_hdr.dxferp = buf;
                   1126:   io_hdr.cmnd = cdb;
                   1127:   io_hdr.cmnd_len = sizeof(cdb);
                   1128: 
                   1129:   scsi_device * scsidev = get_tunnel_dev();
                   1130:   if (!scsi_pass_through_and_check(scsidev, &io_hdr,
                   1131:          "usbjmicron_device::get_registers: "))
                   1132:     return set_err(scsidev->get_err());
                   1133: 
                   1134:   return true;
                   1135: }
                   1136: 
                   1137: 
                   1138: /////////////////////////////////////////////////////////////////////////////
                   1139: 
                   1140: /// SunplusIT USB Bridge support.
                   1141: 
                   1142: class usbsunplus_device
                   1143: : public tunnelled_device<
                   1144:     /*implements*/ ata_device,
                   1145:     /*by tunnelling through a*/ scsi_device
                   1146:   >
                   1147: {
                   1148: public:
                   1149:   usbsunplus_device(smart_interface * intf, scsi_device * scsidev,
                   1150:                     const char * req_type);
                   1151: 
                   1152:   virtual ~usbsunplus_device() throw();
                   1153: 
                   1154:   virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
                   1155: };
                   1156: 
                   1157: 
                   1158: usbsunplus_device::usbsunplus_device(smart_interface * intf, scsi_device * scsidev,
                   1159:                                      const char * req_type)
                   1160: : smart_device(intf, scsidev->get_dev_name(), "usbsunplus", req_type),
                   1161:   tunnelled_device<ata_device, scsi_device>(scsidev)
                   1162: {
                   1163:   set_info().info_name = strprintf("%s [USB Sunplus]", scsidev->get_info_name());
                   1164: }
                   1165: 
                   1166: usbsunplus_device::~usbsunplus_device() throw()
                   1167: {
                   1168: }
                   1169: 
                   1170: bool usbsunplus_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
                   1171: {
                   1172:   if (!ata_cmd_is_ok(in,
                   1173:     true,  // data_out_support
                   1174:     false, // !multi_sector_support
                   1175:     true)  // ata_48bit_support
                   1176:   )
                   1177:     return false;
                   1178: 
                   1179:   scsi_cmnd_io io_hdr;
                   1180:   unsigned char cdb[12];
                   1181: 
                   1182:   if (in.in_regs.is_48bit_cmd()) {
                   1183:     // Set "previous" registers
                   1184:     memset(&io_hdr, 0, sizeof(io_hdr));
                   1185:     io_hdr.dxfer_dir = DXFER_NONE;
                   1186: 
                   1187:     cdb[ 0] = 0xf8;
                   1188:     cdb[ 1] = 0x00;
                   1189:     cdb[ 2] = 0x23; // Subcommand: Pass through presetting
                   1190:     cdb[ 3] = 0x00;
                   1191:     cdb[ 4] = 0x00;
                   1192:     cdb[ 5] = in.in_regs.prev.features;
                   1193:     cdb[ 6] = in.in_regs.prev.sector_count;
                   1194:     cdb[ 7] = in.in_regs.prev.lba_low;
                   1195:     cdb[ 8] = in.in_regs.prev.lba_mid;
                   1196:     cdb[ 9] = in.in_regs.prev.lba_high;
                   1197:     cdb[10] = 0x00;
                   1198:     cdb[11] = 0x00;
                   1199: 
                   1200:     io_hdr.cmnd = cdb;
                   1201:     io_hdr.cmnd_len = sizeof(cdb);
                   1202: 
                   1203:     scsi_device * scsidev = get_tunnel_dev();
                   1204:     if (!scsi_pass_through_and_check(scsidev, &io_hdr,
                   1205:            "usbsunplus_device::scsi_pass_through (presetting): "))
                   1206:       return set_err(scsidev->get_err());
                   1207:   }
                   1208: 
                   1209:   // Run Pass through command
                   1210:   memset(&io_hdr, 0, sizeof(io_hdr));
                   1211:   unsigned char protocol;
                   1212:   switch (in.direction) {
                   1213:     case ata_cmd_in::no_data:
                   1214:       io_hdr.dxfer_dir = DXFER_NONE;
                   1215:       protocol = 0x00;
                   1216:       break;
                   1217:     case ata_cmd_in::data_in:
                   1218:       io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
                   1219:       io_hdr.dxfer_len = in.size;
                   1220:       io_hdr.dxferp = (unsigned char *)in.buffer;
                   1221:       memset(in.buffer, 0, in.size);
                   1222:       protocol = 0x10;
                   1223:       break;
                   1224:     case ata_cmd_in::data_out:
                   1225:       io_hdr.dxfer_dir = DXFER_TO_DEVICE;
                   1226:       io_hdr.dxfer_len = in.size;
                   1227:       io_hdr.dxferp = (unsigned char *)in.buffer;
                   1228:       protocol = 0x11;
                   1229:       break;
                   1230:     default:
                   1231:       return set_err(EINVAL);
                   1232:   }
                   1233: 
                   1234:   cdb[ 0] = 0xf8;
                   1235:   cdb[ 1] = 0x00;
                   1236:   cdb[ 2] = 0x22; // Subcommand: Pass through
                   1237:   cdb[ 3] = protocol;
                   1238:   cdb[ 4] = (unsigned char)(io_hdr.dxfer_len >> 9);
                   1239:   cdb[ 5] = in.in_regs.features;
                   1240:   cdb[ 6] = in.in_regs.sector_count;
                   1241:   cdb[ 7] = in.in_regs.lba_low;
                   1242:   cdb[ 8] = in.in_regs.lba_mid;
                   1243:   cdb[ 9] = in.in_regs.lba_high;
                   1244:   cdb[10] = in.in_regs.device | 0xa0;
                   1245:   cdb[11] = in.in_regs.command;
                   1246: 
                   1247:   io_hdr.cmnd = cdb;
                   1248:   io_hdr.cmnd_len = sizeof(cdb);
                   1249: 
                   1250:   scsi_device * scsidev = get_tunnel_dev();
                   1251:   if (!scsi_pass_through_and_check(scsidev, &io_hdr,
                   1252:          "usbsunplus_device::scsi_pass_through: "))
                   1253:     // Returns sense key 0x03 (medium error) on ATA command error
                   1254:     return set_err(scsidev->get_err());
                   1255: 
                   1256:   if (in.out_needed.is_set()) {
                   1257:     // Read ATA output registers
                   1258:     unsigned char regbuf[8] = {0, };
                   1259:     memset(&io_hdr, 0, sizeof(io_hdr));
                   1260:     io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
                   1261:     io_hdr.dxfer_len = sizeof(regbuf);
                   1262:     io_hdr.dxferp = regbuf;
                   1263: 
                   1264:     cdb[ 0] = 0xf8;
                   1265:     cdb[ 1] = 0x00;
                   1266:     cdb[ 2] = 0x21; // Subcommand: Get status
                   1267:     memset(cdb+3, 0, sizeof(cdb)-3);
                   1268:     io_hdr.cmnd = cdb;
                   1269:     io_hdr.cmnd_len = sizeof(cdb);
                   1270: 
                   1271:     if (!scsi_pass_through_and_check(scsidev, &io_hdr,
                   1272:            "usbsunplus_device::scsi_pass_through (get registers): "))
                   1273:       return set_err(scsidev->get_err());
                   1274: 
                   1275:     out.out_regs.error        = regbuf[1];
                   1276:     out.out_regs.sector_count = regbuf[2];
                   1277:     out.out_regs.lba_low      = regbuf[3];
                   1278:     out.out_regs.lba_mid      = regbuf[4];
                   1279:     out.out_regs.lba_high     = regbuf[5];
                   1280:     out.out_regs.device       = regbuf[6];
                   1281:     out.out_regs.status       = regbuf[7];
                   1282:   }
                   1283: 
                   1284:   return true;
                   1285: }
                   1286: 
                   1287: 
                   1288: } // namespace
                   1289: 
                   1290: using namespace sat;
                   1291: 
                   1292: 
                   1293: /////////////////////////////////////////////////////////////////////////////
                   1294: 
                   1295: // Return ATA->SCSI filter for SAT or USB.
                   1296: 
                   1297: ata_device * smart_interface::get_sat_device(const char * type, scsi_device * scsidev)
                   1298: {
                   1299:   if (!strncmp(type, "sat", 3)) {
1.1.1.2 ! misho    1300:     const char * t = type + 3;
        !          1301:     bool enable_auto = false;
        !          1302:     if (!strncmp(t, ",auto", 5)) {
        !          1303:       t += 5;
        !          1304:       enable_auto = true;
        !          1305:     }
        !          1306:     int ptlen = 0, n = -1;
        !          1307:     if (*t && !(sscanf(t, ",%d%n", &ptlen, &n) == 1 && n == (int)strlen(t)
        !          1308:                 && (ptlen == 0 || ptlen == 12 || ptlen == 16))) {
        !          1309:       set_err(EINVAL, "Option '-d sat[,auto][,N]' requires N to be 0, 12 or 16");
1.1       misho    1310:       return 0;
                   1311:     }
1.1.1.2 ! misho    1312:     return new sat_device(this, scsidev, type, ptlen, enable_auto);
1.1       misho    1313:   }
                   1314: 
                   1315:   else if (!strncmp(type, "usbcypress", 10)) {
                   1316:     unsigned signature = 0x24; int n1 = -1, n2 = -1;
                   1317:     if (!(((sscanf(type, "usbcypress%n,0x%x%n", &n1, &signature, &n2) == 1 && n2 == (int)strlen(type)) || n1 == (int)strlen(type))
                   1318:           && signature <= 0xff)) {
                   1319:       set_err(EINVAL, "Option '-d usbcypress,<n>' requires <n> to be "
                   1320:                       "an hexadecimal number between 0x0 and 0xff");
                   1321:       return 0;
                   1322:     }
                   1323:     return new usbcypress_device(this, scsidev, type, signature);
                   1324:   }
                   1325: 
                   1326:   else if (!strncmp(type, "usbjmicron", 10)) {
                   1327:     const char * t = type + 10;
                   1328:     bool ata_48bit_support = false;
                   1329:     if (!strncmp(t, ",x", 2)) {
                   1330:       t += 2;
                   1331:       ata_48bit_support = true;
                   1332:     }
                   1333:     int port = -1, n = -1;
                   1334:     if (*t && !(  (sscanf(t, ",%d%n", &port, &n) == 1
                   1335:                 && n == (int)strlen(t) && 0 <= port && port <= 1))) {
                   1336:       set_err(EINVAL, "Option '-d usbmicron[,x],<n>' requires <n> to be 0 or 1");
                   1337:       return 0;
                   1338:     }
                   1339:     return new usbjmicron_device(this, scsidev, type, ata_48bit_support, port);
                   1340:   }
                   1341: 
                   1342:   else if (!strcmp(type, "usbsunplus")) {
                   1343:     return new usbsunplus_device(this, scsidev, type);
                   1344:   }
                   1345: 
                   1346:   else {
                   1347:     set_err(EINVAL, "Unknown USB device type '%s'", type);
                   1348:     return 0;
                   1349:   }
                   1350: }
                   1351: 
                   1352: // Try to detect a SAT device behind a SCSI interface.
                   1353: 
                   1354: ata_device * smart_interface::autodetect_sat_device(scsi_device * scsidev,
                   1355:   const unsigned char * inqdata, unsigned inqsize)
                   1356: {
                   1357:   if (!scsidev->is_open())
                   1358:     return 0;
                   1359: 
                   1360:   // SAT ?
                   1361:   if (inqdata && inqsize >= 36 && !memcmp(inqdata + 8, "ATA     ", 8)) { // TODO: Linux-specific?
                   1362:     ata_device_auto_ptr atadev( new sat_device(this, scsidev, "") , scsidev);
                   1363:     if (has_sat_pass_through(atadev.get()))
                   1364:       return atadev.release(); // Detected SAT
                   1365:   }
                   1366: 
                   1367:   return 0;
                   1368: }
                   1369: 
                   1370: 
                   1371: /////////////////////////////////////////////////////////////////////////////
                   1372: // USB device type detection
                   1373: 
                   1374: // Format USB ID for error messages
                   1375: static std::string format_usb_id(int vendor_id, int product_id, int version)
                   1376: {
                   1377:   if (version >= 0)
                   1378:     return strprintf("[0x%04x:0x%04x (0x%03x)]", vendor_id, product_id, version);
                   1379:   else
                   1380:     return strprintf("[0x%04x:0x%04x]", vendor_id, product_id);
                   1381: }
                   1382: 
                   1383: // Get type name for USB device with known VENDOR:PRODUCT ID.
                   1384: const char * smart_interface::get_usb_dev_type_by_id(int vendor_id, int product_id,
                   1385:                                                      int version /*= -1*/)
                   1386: {
                   1387:   usb_dev_info info, info2;
                   1388:   int n = lookup_usb_device(vendor_id, product_id, version, info, info2);
                   1389: 
                   1390:   if (n <= 0) {
                   1391:     set_err(EINVAL, "Unknown USB bridge %s",
                   1392:             format_usb_id(vendor_id, product_id, version).c_str());
                   1393:     return 0;
                   1394:   }
                   1395: 
                   1396:   if (n > 1) {
                   1397:     set_err(EINVAL, "USB bridge %s type is ambiguous: '%s' or '%s'",
                   1398:             format_usb_id(vendor_id, product_id, version).c_str(),
                   1399:             (!info.usb_type.empty()  ? info.usb_type.c_str()  : "[unsupported]"),
                   1400:             (!info2.usb_type.empty() ? info2.usb_type.c_str() : "[unsupported]"));
                   1401:     return 0;
                   1402:   }
                   1403: 
                   1404:   if (info.usb_type.empty()) {
                   1405:     set_err(ENOSYS, "Unsupported USB bridge %s",
                   1406:             format_usb_id(vendor_id, product_id, version).c_str());
                   1407:     return 0;
                   1408:   }
                   1409: 
                   1410:   // TODO: change return type to std::string
                   1411:   static std::string type;
                   1412:   type = info.usb_type;
                   1413:   return type.c_str();
                   1414: }

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