File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / smartmontools / scsiata.cpp
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 01:17:35 2013 UTC (10 years, 10 months ago) by misho
Branches: smartmontools, elwix, MAIN
CVS tags: v6_2, v6_1p0, v6_1, HEAD
6.1

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

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