File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / smartmontools / scsiata.cpp
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:36:45 2012 UTC (11 years, 9 months ago) by misho
Branches: smartmontools, elwix, MAIN
CVS tags: v5_43, HEAD
smartmontools

    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-12 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
   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: 
   65: const char * scsiata_cpp_cvsid = "$Id: scsiata.cpp,v 1.1.1.2 2012/10/09 09:36:45 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: /* 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
  117:   >,
  118:   virtual public /*implements*/ scsi_device
  119: {
  120: public:
  121:   sat_device(smart_interface * intf, scsi_device * scsidev,
  122:     const char * req_type, int passthrulen = 0, bool enable_auto = false);
  123: 
  124:   virtual ~sat_device() throw();
  125: 
  126:   virtual smart_device * autodetect_open();
  127: 
  128:   virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
  129: 
  130:   virtual bool scsi_pass_through(scsi_cmnd_io * iop);
  131: 
  132: private:
  133:   int m_passthrulen;
  134:   bool m_enable_auto;
  135: };
  136: 
  137: 
  138: sat_device::sat_device(smart_interface * intf, scsi_device * scsidev,
  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),
  142:   tunnelled_device<ata_device, scsi_device>(scsidev),
  143:   m_passthrulen(passthrulen),
  144:   m_enable_auto(enable_auto)
  145: {
  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/" : ""));
  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: 
  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: 
  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)) {
 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");
 1310:       return 0;
 1311:     }
 1312:     return new sat_device(this, scsidev, type, ptlen, enable_auto);
 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>