smartmontools SVN Rev 3317
Utility to control and monitor storage systems with "S.M.A.R.T."
scsiata.cpp
Go to the documentation of this file.
00001 /*
00002  * scsiata.cpp
00003  *
00004  * Home page of code is: http://smartmontools.sourceforge.net
00005  *
00006  * Copyright (C) 2006-12 Douglas Gilbert <dgilbert@interlog.com>
00007  * Copyright (C) 2009-13 Christian Franke <smartmontools-support@lists.sourceforge.net>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2, or (at your option)
00012  * any later version.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * (for example COPYING); if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00017  *
00018  * The code in this file is based on the SCSI to ATA Translation (SAT)
00019  * draft found at http://www.t10.org . The original draft used for this
00020  * code is sat-r08.pdf which is not too far away from becoming a
00021  * standard. The SAT commands of interest to smartmontools are the
00022  * ATA PASS THROUGH SCSI (16) and ATA PASS THROUGH SCSI (12) defined in
00023  * section 12 of that document.
00024  *
00025  * sat-r09.pdf is the most recent, easily accessible draft prior to the
00026  * original SAT standard (ANSI INCITS 431-2007). By mid-2009 the second
00027  * version of the SAT standard (SAT-2) is nearing standardization. In
00028  * their wisdom an incompatible change has been introduced in draft
00029  * sat2r08a.pdf in the area of the ATA RETURN DESCRIPTOR. A new "fixed
00030  * format" ATA RETURN buffer has been defined (sat2r08b.pdf section
00031  * 12.2.7) for the case when DSENSE=0 in the Control mode page.
00032  * Unfortunately this is the normal case. If the change stands our
00033  * code will need to be extended for this case.
00034  *
00035  * With more transports "hiding" SATA disks (and other S-ATAPI devices)
00036  * behind a SCSI command set, accessing special features like SMART
00037  * information becomes a challenge. The SAT standard offers ATA PASS
00038  * THROUGH commands for special usages. Note that the SAT layer may
00039  * be inside a generic OS layer (e.g. libata in linux), in a host
00040  * adapter (HA or HBA) firmware, or somewhere on the interconnect
00041  * between the host computer and the SATA devices (e.g. a RAID made
00042  * of SATA disks and the RAID talks "SCSI" to the host computer).
00043  * Note that in the latter case, this code does not solve the
00044  * addressing issue (i.e. which SATA disk to address behind the logical
00045  * SCSI (RAID) interface).
00046  * 
00047  */
00048 
00049 #include <stdio.h>
00050 #include <string.h>
00051 #include <stdlib.h>
00052 #include <ctype.h>
00053 #include <errno.h>
00054 
00055 #include "config.h"
00056 #include "int64.h"
00057 #include "scsicmds.h"
00058 #include "atacmds.h" // ataReadHDIdentity()
00059 #include "knowndrives.h" // lookup_usb_device()
00060 #include "utility.h"
00061 #include "dev_interface.h"
00062 #include "dev_ata_cmd_set.h" // ata_device_with_command_set
00063 #include "dev_tunnelled.h" // tunnelled_device<>
00064 
00065 const char * scsiata_cpp_cvsid = "$Id: scsiata.cpp 3741 2013-01-02 17:06:54Z chrfranke $";
00066 
00067 /* This is a slightly stretched SCSI sense "descriptor" format header.
00068    The addition is to allow the 0x70 and 0x71 response codes. The idea
00069    is to place the salient data of both "fixed" and "descriptor" sense
00070    format into one structure to ease application processing.
00071    The original sense buffer should be kept around for those cases
00072    in which more information is required (e.g. the LBA of a MEDIUM ERROR). */
00073 /// Abridged SCSI sense data
00074 struct sg_scsi_sense_hdr {
00075     unsigned char response_code; /* permit: 0x0, 0x70, 0x71, 0x72, 0x73 */
00076     unsigned char sense_key;
00077     unsigned char asc;
00078     unsigned char ascq;
00079     unsigned char byte4;
00080     unsigned char byte5;
00081     unsigned char byte6;
00082     unsigned char additional_length;
00083 };
00084 
00085 /* Maps the salient data from a sense buffer which is in either fixed or
00086    descriptor format into a structure mimicking a descriptor format
00087    header (i.e. the first 8 bytes of sense descriptor format).
00088    If zero response code returns 0. Otherwise returns 1 and if 'sshp' is
00089    non-NULL then zero all fields and then set the appropriate fields in
00090    that structure. sshp::additional_length is always 0 for response
00091    codes 0x70 and 0x71 (fixed format). */
00092 static int sg_scsi_normalize_sense(const unsigned char * sensep, int sb_len,
00093                                    struct sg_scsi_sense_hdr * sshp);
00094 
00095 #define SAT_ATA_PASSTHROUGH_12LEN 12
00096 #define SAT_ATA_PASSTHROUGH_16LEN 16
00097 
00098 #define DEF_SAT_ATA_PASSTHRU_SIZE 16
00099 #define ATA_RETURN_DESCRIPTOR 9
00100 
00101 
00102 namespace sat { // no need to publish anything, name provided for Doxygen
00103 
00104 /// SAT support.
00105 /// Implements ATA by tunnelling through SCSI.
00106 
00107 class sat_device
00108 : public tunnelled_device<
00109     /*implements*/ ata_device
00110     /*by tunnelling through a*/, scsi_device
00111   >,
00112   virtual public /*implements*/ scsi_device
00113 {
00114 public:
00115   sat_device(smart_interface * intf, scsi_device * scsidev,
00116     const char * req_type, int passthrulen = 0, bool enable_auto = false);
00117 
00118   virtual ~sat_device() throw();
00119 
00120   virtual smart_device * autodetect_open();
00121 
00122   virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
00123 
00124   virtual bool scsi_pass_through(scsi_cmnd_io * iop);
00125 
00126 private:
00127   int m_passthrulen;
00128   bool m_enable_auto;
00129 };
00130 
00131 
00132 sat_device::sat_device(smart_interface * intf, scsi_device * scsidev,
00133   const char * req_type, int passthrulen /* = 0 */, bool enable_auto /* = false */)
00134 : smart_device(intf, scsidev->get_dev_name(),
00135     (enable_auto ? "sat,auto" : "sat"), req_type),
00136   tunnelled_device<ata_device, scsi_device>(scsidev),
00137   m_passthrulen(passthrulen),
00138   m_enable_auto(enable_auto)
00139 {
00140   if (enable_auto)
00141     hide_ata(); // Start as SCSI, switch to ATA in autodetect_open()
00142   else
00143     hide_scsi(); // ATA always
00144   if (strcmp(scsidev->get_dev_type(), "scsi"))
00145     set_info().dev_type += strprintf("+%s", scsidev->get_dev_type());
00146 
00147   set_info().info_name = strprintf("%s [%sSAT]", scsidev->get_info_name(),
00148                                    (enable_auto ? "SCSI/" : ""));
00149 }
00150 
00151 sat_device::~sat_device() throw()
00152 {
00153 }
00154 
00155 
00156 // cdb[0]: ATA PASS THROUGH (16) SCSI command opcode byte (0x85)
00157 // cdb[1]: multiple_count, protocol + extend
00158 // cdb[2]: offline, ck_cond, t_dir, byte_block + t_length
00159 // cdb[3]: features (15:8)
00160 // cdb[4]: features (7:0)
00161 // cdb[5]: sector_count (15:8)
00162 // cdb[6]: sector_count (7:0)
00163 // cdb[7]: lba_low (15:8)
00164 // cdb[8]: lba_low (7:0)
00165 // cdb[9]: lba_mid (15:8)
00166 // cdb[10]: lba_mid (7:0)
00167 // cdb[11]: lba_high (15:8)
00168 // cdb[12]: lba_high (7:0)
00169 // cdb[13]: device
00170 // cdb[14]: (ata) command
00171 // cdb[15]: control (SCSI, leave as zero)
00172 //
00173 // 24 bit lba (from MSB): cdb[12] cdb[10] cdb[8]
00174 // 48 bit lba (from MSB): cdb[11] cdb[9] cdb[7] cdb[12] cdb[10] cdb[8]
00175 //
00176 //
00177 // cdb[0]: ATA PASS THROUGH (12) SCSI command opcode byte (0xa1)
00178 // cdb[1]: multiple_count, protocol + extend
00179 // cdb[2]: offline, ck_cond, t_dir, byte_block + t_length
00180 // cdb[3]: features (7:0)
00181 // cdb[4]: sector_count (7:0)
00182 // cdb[5]: lba_low (7:0)
00183 // cdb[6]: lba_mid (7:0)
00184 // cdb[7]: lba_high (7:0)
00185 // cdb[8]: device
00186 // cdb[9]: (ata) command
00187 // cdb[10]: reserved
00188 // cdb[11]: control (SCSI, leave as zero)
00189 //
00190 //
00191 // ATA Return Descriptor (component of descriptor sense data)
00192 // des[0]: descriptor code (0x9)
00193 // des[1]: additional descriptor length (0xc)
00194 // des[2]: extend (bit 0)
00195 // des[3]: error
00196 // des[4]: sector_count (15:8)
00197 // des[5]: sector_count (7:0)
00198 // des[6]: lba_low (15:8)
00199 // des[7]: lba_low (7:0)
00200 // des[8]: lba_mid (15:8)
00201 // des[9]: lba_mid (7:0)
00202 // des[10]: lba_high (15:8)
00203 // des[11]: lba_high (7:0)
00204 // des[12]: device
00205 // des[13]: status
00206 
00207 
00208 
00209 // PURPOSE
00210 //   This interface routine takes ATA SMART commands and packages
00211 //   them in the SAT-defined ATA PASS THROUGH SCSI commands. There are
00212 //   two available SCSI commands: a 12 byte and 16 byte variant; the
00213 //   one used is chosen via this->m_passthrulen .
00214 // DETAILED DESCRIPTION OF ARGUMENTS
00215 //   device: is the file descriptor provided by (a SCSI dvice type) open()
00216 //   command: defines the different ATA operations.
00217 //   select: additional input data if needed (which log, which type of
00218 //           self-test).
00219 //   data:   location to write output data, if needed (512 bytes).
00220 //     Note: not all commands use all arguments.
00221 // RETURN VALUES
00222 //  -1 if the command failed
00223 //   0 if the command succeeded,
00224 //   STATUS_CHECK routine: 
00225 //  -1 if the command failed
00226 //   0 if the command succeeded and disk SMART status is "OK"
00227 //   1 if the command succeeded and disk SMART status is "FAILING"
00228 
00229 bool sat_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
00230 {
00231   if (!ata_cmd_is_supported(in,
00232     ata_device::supports_data_out |
00233     ata_device::supports_output_regs |
00234     ata_device::supports_multi_sector |
00235     ata_device::supports_48bit,
00236     "SAT")
00237   )
00238     return false;
00239 
00240     struct scsi_cmnd_io io_hdr;
00241     struct scsi_sense_disect sinfo;
00242     struct sg_scsi_sense_hdr ssh;
00243     unsigned char cdb[SAT_ATA_PASSTHROUGH_16LEN];
00244     unsigned char sense[32];
00245     const unsigned char * ardp;
00246     int status, ard_len, have_sense;
00247     int extend = 0;
00248     int ck_cond = 0;    /* set to 1 to read register(s) back */
00249     int protocol = 3;   /* non-data */
00250     int t_dir = 1;      /* 0 -> to device, 1 -> from device */
00251     int byte_block = 1; /* 0 -> bytes, 1 -> 512 byte blocks */
00252     int t_length = 0;   /* 0 -> no data transferred */
00253     int passthru_size = DEF_SAT_ATA_PASSTHRU_SIZE;
00254 
00255     memset(cdb, 0, sizeof(cdb));
00256     memset(sense, 0, sizeof(sense));
00257 
00258     // Set data direction
00259     // TODO: This works only for commands where sector_count holds count!
00260     switch (in.direction) {
00261       case ata_cmd_in::no_data:
00262         break;
00263       case ata_cmd_in::data_in:
00264         protocol = 4;  // PIO data-in
00265         t_length = 2;  // sector_count holds count
00266         break;
00267       case ata_cmd_in::data_out:
00268         protocol = 5;  // PIO data-out
00269         t_length = 2;  // sector_count holds count
00270         t_dir = 0;     // to device
00271         break;
00272       default:
00273         return set_err(EINVAL, "sat_device::ata_pass_through: invalid direction=%d",
00274             (int)in.direction);
00275     }
00276 
00277     // Check condition if any output register needed
00278     if (in.out_needed.is_set())
00279         ck_cond = 1;
00280 
00281     if ((SAT_ATA_PASSTHROUGH_12LEN == m_passthrulen) ||
00282         (SAT_ATA_PASSTHROUGH_16LEN == m_passthrulen))
00283         passthru_size = m_passthrulen;
00284 
00285     // Set extend bit on 48-bit ATA command
00286     if (in.in_regs.is_48bit_cmd()) {
00287       if (passthru_size != SAT_ATA_PASSTHROUGH_16LEN)
00288         return set_err(ENOSYS, "48-bit ATA commands require SAT ATA PASS-THROUGH (16)");
00289       extend = 1;
00290     }
00291 
00292     cdb[0] = (SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ?
00293              SAT_ATA_PASSTHROUGH_12 : SAT_ATA_PASSTHROUGH_16;
00294 
00295     cdb[1] = (protocol << 1) | extend;
00296     cdb[2] = (ck_cond << 5) | (t_dir << 3) |
00297              (byte_block << 2) | t_length;
00298 
00299     if (passthru_size == SAT_ATA_PASSTHROUGH_12LEN) {
00300         // ATA PASS-THROUGH (12)
00301         const ata_in_regs & lo = in.in_regs;
00302         cdb[3] = lo.features;
00303         cdb[4] = lo.sector_count;
00304         cdb[5] = lo.lba_low;
00305         cdb[6] = lo.lba_mid;
00306         cdb[7] = lo.lba_high;
00307         cdb[8] = lo.device;
00308         cdb[9] = lo.command;
00309     }
00310     else {
00311         // ATA PASS-THROUGH (16)
00312         const ata_in_regs & lo = in.in_regs;
00313         const ata_in_regs & hi = in.in_regs.prev;
00314         // Note: all 'in.in_regs.prev.*' are always zero for 28-bit commands
00315         cdb[ 3] = hi.features;
00316         cdb[ 4] = lo.features;
00317         cdb[ 5] = hi.sector_count;
00318         cdb[ 6] = lo.sector_count;
00319         cdb[ 7] = hi.lba_low;
00320         cdb[ 8] = lo.lba_low;
00321         cdb[ 9] = hi.lba_mid;
00322         cdb[10] = lo.lba_mid;
00323         cdb[11] = hi.lba_high;
00324         cdb[12] = lo.lba_high;
00325         cdb[13] = lo.device;
00326         cdb[14] = lo.command;
00327     }
00328 
00329     memset(&io_hdr, 0, sizeof(io_hdr));
00330     if (0 == t_length) {
00331         io_hdr.dxfer_dir = DXFER_NONE;
00332         io_hdr.dxfer_len = 0;
00333     } else if (t_dir) {         /* from device */
00334         io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
00335         io_hdr.dxfer_len = in.size;
00336         io_hdr.dxferp = (unsigned char *)in.buffer;
00337         memset(in.buffer, 0, in.size); // prefill with zeroes
00338     } else {                    /* to device */
00339         io_hdr.dxfer_dir = DXFER_TO_DEVICE;
00340         io_hdr.dxfer_len = in.size;
00341         io_hdr.dxferp = (unsigned char *)in.buffer;
00342     }
00343     io_hdr.cmnd = cdb;
00344     io_hdr.cmnd_len = passthru_size;
00345     io_hdr.sensep = sense;
00346     io_hdr.max_sense_len = sizeof(sense);
00347     io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
00348 
00349     scsi_device * scsidev = get_tunnel_dev();
00350     if (!scsidev->scsi_pass_through(&io_hdr)) {
00351         if (scsi_debugmode > 0)
00352             pout("sat_device::ata_pass_through: scsi_pass_through() failed, "
00353                  "errno=%d [%s]\n", scsidev->get_errno(), scsidev->get_errmsg());
00354         return set_err(scsidev->get_err());
00355     }
00356     ardp = NULL;
00357     ard_len = 0;
00358     have_sense = sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len,
00359                                          &ssh);
00360     if (have_sense) {
00361         /* look for SAT ATA Return Descriptor */
00362         ardp = sg_scsi_sense_desc_find(io_hdr.sensep,
00363                                        io_hdr.resp_sense_len,
00364                                        ATA_RETURN_DESCRIPTOR);
00365         if (ardp) {
00366             ard_len = ardp[1] + 2;
00367             if (ard_len < 12)
00368                 ard_len = 12;
00369             else if (ard_len > 14)
00370                 ard_len = 14;
00371         }
00372         scsi_do_sense_disect(&io_hdr, &sinfo);
00373         status = scsiSimpleSenseFilter(&sinfo);
00374         if (0 != status) {
00375             if (scsi_debugmode > 0) {
00376                 pout("sat_device::ata_pass_through: scsi error: %s\n",
00377                      scsiErrString(status));
00378                 if (ardp && (scsi_debugmode > 1)) {
00379                     pout("Values from ATA Return Descriptor are:\n");
00380                     dStrHex((const char *)ardp, ard_len, 1);
00381                 }
00382             }
00383             if (t_dir && (t_length > 0) && (in.direction == ata_cmd_in::data_in))
00384                 memset(in.buffer, 0, in.size);
00385             return set_err(EIO, "scsi error %s", scsiErrString(status));
00386         }
00387     }
00388     if (ck_cond) {     /* expecting SAT specific sense data */
00389         if (have_sense) {
00390             if (ardp) {
00391                 if (scsi_debugmode > 1) {
00392                     pout("Values from ATA Return Descriptor are:\n");
00393                     dStrHex((const char *)ardp, ard_len, 1);
00394                 }
00395                 // Set output registers
00396                 ata_out_regs & lo = out.out_regs;
00397                 lo.error        = ardp[ 3];
00398                 lo.sector_count = ardp[ 5];
00399                 lo.lba_low      = ardp[ 7];
00400                 lo.lba_mid      = ardp[ 9];
00401                 lo.lba_high     = ardp[11];
00402                 lo.device       = ardp[12];
00403                 lo.status       = ardp[13];
00404                 if (in.in_regs.is_48bit_cmd()) {
00405                     ata_out_regs & hi = out.out_regs.prev;
00406                     hi.sector_count = ardp[ 4];
00407                     hi.lba_low      = ardp[ 6];
00408                     hi.lba_mid      = ardp[ 8];
00409                     hi.lba_high     = ardp[10];
00410                 }
00411             }
00412         }
00413         if (ardp == NULL)
00414             ck_cond = 0;       /* not the type of sense data expected */
00415     }
00416     if (0 == ck_cond) {
00417         if (have_sense) {
00418             if ((ssh.response_code >= 0x72) &&
00419                 ((SCSI_SK_NO_SENSE == ssh.sense_key) ||
00420                  (SCSI_SK_RECOVERED_ERR == ssh.sense_key)) &&
00421                 (0 == ssh.asc) &&
00422                 (SCSI_ASCQ_ATA_PASS_THROUGH == ssh.ascq)) {
00423                 if (ardp) {
00424                     if (scsi_debugmode > 0) {
00425                         pout("Values from ATA Return Descriptor are:\n");
00426                         dStrHex((const char *)ardp, ard_len, 1);
00427                     }
00428                     return set_err(EIO, "SAT command failed");
00429                 }
00430             }
00431         }
00432     }
00433     return true;
00434 }
00435 
00436 bool sat_device::scsi_pass_through(scsi_cmnd_io * iop)
00437 {
00438   scsi_device * scsidev = get_tunnel_dev();
00439   if (!scsidev->scsi_pass_through(iop)) {
00440     set_err(scsidev->get_err());
00441     return false;
00442   }
00443   return true;
00444 }
00445 
00446 smart_device * sat_device::autodetect_open()
00447 {
00448   if (!open() || !m_enable_auto)
00449     return this;
00450 
00451   scsi_device * scsidev = get_tunnel_dev();
00452 
00453   unsigned char inqdata[36] = {0, };
00454   if (scsiStdInquiry(scsidev, inqdata, sizeof(inqdata))) {
00455       smart_device::error_info err = scsidev->get_err();
00456       close();
00457       set_err(err.no, "INQUIRY [SAT]: %s", err.msg.c_str());
00458       return this;
00459   }
00460 
00461   // Check for SAT "VENDOR"
00462   int inqsize = inqdata[4] + 5;
00463   bool sat = (inqsize >= 36 && !memcmp(inqdata + 8, "ATA     ", 8));
00464 
00465   // Change interface
00466   hide_ata(!sat);
00467   hide_scsi(sat);
00468 
00469   set_info().dev_type = (sat ? "sat" : scsidev->get_dev_type());
00470   set_info().info_name = strprintf("%s [%s]", scsidev->get_info_name(),
00471                                    (sat ? "SAT" : "SCSI"));
00472   return this;
00473 }
00474 
00475 } // namespace
00476 
00477 /////////////////////////////////////////////////////////////////////////////
00478 
00479 /* Attempt an IDENTIFY DEVICE ATA command via SATL when packet_interface
00480    is false otherwise attempt IDENTIFY PACKET DEVICE. If successful
00481    return true, else false */
00482 
00483 static bool has_sat_pass_through(ata_device * dev, bool packet_interface = false)
00484 {
00485     /* Note:  malloc() ensures the read buffer lands on a single
00486        page.  This avoids some bugs seen on LSI controlers under
00487        FreeBSD */
00488     char *data = (char *)malloc(512);
00489     ata_cmd_in in;
00490     in.in_regs.command = (packet_interface ? ATA_IDENTIFY_PACKET_DEVICE : ATA_IDENTIFY_DEVICE);
00491     in.set_data_in(data, 1);
00492     bool ret = dev->ata_pass_through(in);
00493     free(data);
00494     return ret;
00495 }
00496 
00497 /////////////////////////////////////////////////////////////////////////////
00498 
00499 /* Next two functions are borrowed from sg_lib.c in the sg3_utils
00500    package. Same copyrght owner, same license as this file. */
00501 static int sg_scsi_normalize_sense(const unsigned char * sensep, int sb_len,
00502                                    struct sg_scsi_sense_hdr * sshp)
00503 {
00504     if (sshp)
00505         memset(sshp, 0, sizeof(struct sg_scsi_sense_hdr));
00506     if ((NULL == sensep) || (0 == sb_len) || (0x70 != (0x70 & sensep[0])))
00507         return 0;
00508     if (sshp) {
00509         sshp->response_code = (0x7f & sensep[0]);
00510         if (sshp->response_code >= 0x72) {  /* descriptor format */
00511             if (sb_len > 1)
00512                 sshp->sense_key = (0xf & sensep[1]);
00513             if (sb_len > 2)
00514                 sshp->asc = sensep[2];
00515             if (sb_len > 3)
00516                 sshp->ascq = sensep[3];
00517             if (sb_len > 7)
00518                 sshp->additional_length = sensep[7];
00519         } else {                              /* fixed format */
00520             if (sb_len > 2)
00521                 sshp->sense_key = (0xf & sensep[2]);
00522             if (sb_len > 7) {
00523                 sb_len = (sb_len < (sensep[7] + 8)) ? sb_len :
00524                                                       (sensep[7] + 8);
00525                 if (sb_len > 12)
00526                     sshp->asc = sensep[12];
00527                 if (sb_len > 13)
00528                     sshp->ascq = sensep[13];
00529             }
00530         }
00531     }
00532     return 1;
00533 }
00534 
00535 
00536 // Call scsi_pass_through and check sense.
00537 // TODO: Provide as member function of class scsi_device (?)
00538 static bool scsi_pass_through_and_check(scsi_device * scsidev,  scsi_cmnd_io * iop,
00539                                         const char * msg = "")
00540 {
00541   // Provide sense buffer
00542   unsigned char sense[32] = {0, };
00543   iop->sensep = sense;
00544   iop->max_sense_len = sizeof(sense);
00545   iop->timeout = SCSI_TIMEOUT_DEFAULT;
00546 
00547   // Run cmd
00548   if (!scsidev->scsi_pass_through(iop)) {
00549     if (scsi_debugmode > 0)
00550       pout("%sscsi_pass_through() failed, errno=%d [%s]\n",
00551            msg, scsidev->get_errno(), scsidev->get_errmsg());
00552     return false;
00553   }
00554 
00555   // Check sense
00556   scsi_sense_disect sinfo;
00557   scsi_do_sense_disect(iop, &sinfo);
00558   int err = scsiSimpleSenseFilter(&sinfo);
00559   if (err) {
00560     if (scsi_debugmode > 0)
00561       pout("%sscsi error: %s\n", msg, scsiErrString(err));
00562     return scsidev->set_err(EIO, "scsi error %s", scsiErrString(err));
00563   }
00564 
00565   return true;
00566 }
00567 
00568 
00569 /////////////////////////////////////////////////////////////////////////////
00570 
00571 namespace sat {
00572 
00573 /// Cypress USB Brigde support.
00574 
00575 class usbcypress_device
00576 : public tunnelled_device<
00577     /*implements*/ ata_device_with_command_set
00578     /*by tunnelling through a*/, scsi_device
00579   >
00580 {
00581 public:
00582   usbcypress_device(smart_interface * intf, scsi_device * scsidev,
00583     const char * req_type, unsigned char signature);
00584 
00585   virtual ~usbcypress_device() throw();
00586 
00587 protected:
00588   virtual int ata_command_interface(smart_command_set command, int select, char * data);
00589 
00590   unsigned char m_signature;
00591 };
00592 
00593 
00594 usbcypress_device::usbcypress_device(smart_interface * intf, scsi_device * scsidev,
00595   const char * req_type, unsigned char signature)
00596 : smart_device(intf, scsidev->get_dev_name(), "sat", req_type),
00597   tunnelled_device<ata_device_with_command_set, scsi_device>(scsidev),
00598   m_signature(signature)
00599 {
00600   set_info().info_name = strprintf("%s [USB Cypress]", scsidev->get_info_name());
00601 }
00602 
00603 usbcypress_device::~usbcypress_device() throw()
00604 {
00605 }
00606 
00607 
00608 /* see cy7c68300c_8.pdf for more information */
00609 #define USBCYPRESS_PASSTHROUGH_LEN 16
00610 int usbcypress_device::ata_command_interface(smart_command_set command, int select, char *data)
00611 {
00612     struct scsi_cmnd_io io_hdr;
00613     unsigned char cdb[USBCYPRESS_PASSTHROUGH_LEN];
00614     unsigned char sense[32];
00615     int copydata = 0;
00616     int outlen = 0;
00617     int ck_cond = 0;    /* set to 1 to read register(s) back */
00618     int t_dir = 1;      /* 0 -> to device, 1 -> from device */
00619     int byte_block = 1; /* 0 -> bytes, 1 -> 512 byte blocks */
00620     int t_length = 0;   /* 0 -> no data transferred */
00621     int feature = 0;
00622     int ata_command = 0;
00623     int sector_count = 0;
00624     int lba_low = 0;
00625     int lba_mid = 0;
00626     int lba_high = 0;
00627     int passthru_size = USBCYPRESS_PASSTHROUGH_LEN;
00628 
00629     memset(cdb, 0, sizeof(cdb));
00630     memset(sense, 0, sizeof(sense));
00631 
00632     ata_command = ATA_SMART_CMD;
00633     switch (command) {
00634     case CHECK_POWER_MODE:
00635         ata_command = ATA_CHECK_POWER_MODE;
00636         ck_cond = 1;
00637         copydata = 1;
00638         break;
00639     case READ_VALUES:           /* READ DATA */
00640         feature = ATA_SMART_READ_VALUES;
00641         sector_count = 1;     /* one (512 byte) block */
00642         t_length = 2;   /* sector count holds count */
00643         copydata = 512;
00644         break;
00645     case READ_THRESHOLDS:       /* obsolete */
00646         feature = ATA_SMART_READ_THRESHOLDS;
00647         sector_count = 1;     /* one (512 byte) block */
00648         lba_low = 1;
00649         t_length = 2;   /* sector count holds count */
00650         copydata=512;
00651         break;
00652     case READ_LOG:
00653         feature = ATA_SMART_READ_LOG_SECTOR;
00654         sector_count = 1;     /* one (512 byte) block */
00655         lba_low = select;
00656         t_length = 2;   /* sector count holds count */
00657         copydata = 512;
00658         break;
00659     case WRITE_LOG:
00660         feature = ATA_SMART_WRITE_LOG_SECTOR;
00661         sector_count = 1;     /* one (512 byte) block */
00662         lba_low = select;
00663         t_length = 2;   /* sector count holds count */
00664         t_dir = 0;      /* to device */
00665         outlen = 512;
00666         break;
00667     case IDENTIFY:
00668         ata_command = ATA_IDENTIFY_DEVICE;
00669         sector_count = 1;     /* one (512 byte) block */
00670         t_length = 2;   /* sector count holds count */
00671         copydata = 512;
00672         break;
00673     case PIDENTIFY:
00674         ata_command = ATA_IDENTIFY_PACKET_DEVICE;
00675         sector_count = 1;     /* one (512 byte) block */
00676         t_length = 2;   /* sector count (7:0) holds count */
00677         copydata = 512;
00678         break;
00679     case ENABLE:
00680         feature = ATA_SMART_ENABLE;
00681         lba_low = 1;
00682         break;
00683     case DISABLE:
00684         feature = ATA_SMART_DISABLE;
00685         lba_low = 1;
00686         break;
00687     case STATUS:
00688         // this command only says if SMART is working.  It could be
00689         // replaced with STATUS_CHECK below.
00690         feature = ATA_SMART_STATUS;
00691         ck_cond = 1;
00692         break;
00693     case AUTO_OFFLINE:
00694         feature = ATA_SMART_AUTO_OFFLINE;
00695         sector_count = select;   // YET NOTE - THIS IS A NON-DATA COMMAND!!
00696         break;
00697     case AUTOSAVE:
00698         feature = ATA_SMART_AUTOSAVE;
00699         sector_count = select;   // YET NOTE - THIS IS A NON-DATA COMMAND!!
00700         break;
00701     case IMMEDIATE_OFFLINE:
00702         feature = ATA_SMART_IMMEDIATE_OFFLINE;
00703         lba_low = select;
00704         break;
00705     case STATUS_CHECK:
00706         // This command uses HDIO_DRIVE_TASK and has different syntax than
00707         // the other commands.
00708         feature = ATA_SMART_STATUS;      /* SMART RETURN STATUS */
00709         ck_cond = 1;
00710         break;
00711     default:
00712         pout("Unrecognized command %d in usbcypress_device::ata_command_interface()\n"
00713              "Please contact " PACKAGE_BUGREPORT "\n", command);
00714         errno=ENOSYS;
00715         return -1;
00716     }
00717     if (ATA_SMART_CMD == ata_command) {
00718         lba_mid = 0x4f;
00719         lba_high = 0xc2;
00720     }
00721 
00722     cdb[0] = m_signature; // bVSCBSignature : vendor-specific command
00723     cdb[1] = 0x24; // bVSCBSubCommand : 0x24 for ATACB
00724     cdb[2] = 0x0;
00725     if (ata_command == ATA_IDENTIFY_DEVICE || ata_command == ATA_IDENTIFY_PACKET_DEVICE)
00726         cdb[2] |= (1<<7); //set  IdentifyPacketDevice for these cmds
00727     cdb[3] = 0xff - (1<<0) - (1<<6); //features, sector count, lba low, lba med
00728                                      // lba high, command are valid
00729     cdb[4] = byte_block; //TransferBlockCount : 512
00730 
00731 
00732     cdb[6] = feature;
00733     cdb[7] = sector_count;
00734     cdb[8] = lba_low;
00735     cdb[9] = lba_mid;
00736     cdb[10] = lba_high;
00737     cdb[12] = ata_command;
00738 
00739     memset(&io_hdr, 0, sizeof(io_hdr));
00740     if (0 == t_length) {
00741         io_hdr.dxfer_dir = DXFER_NONE;
00742         io_hdr.dxfer_len = 0;
00743     } else if (t_dir) {         /* from device */
00744         io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
00745         io_hdr.dxfer_len = copydata;
00746         io_hdr.dxferp = (unsigned char *)data;
00747         memset(data, 0, copydata); /* prefill with zeroes */
00748     } else {                    /* to device */
00749         io_hdr.dxfer_dir = DXFER_TO_DEVICE;
00750         io_hdr.dxfer_len = outlen;
00751         io_hdr.dxferp = (unsigned char *)data;
00752     }
00753     io_hdr.cmnd = cdb;
00754     io_hdr.cmnd_len = passthru_size;
00755     io_hdr.sensep = sense;
00756     io_hdr.max_sense_len = sizeof(sense);
00757     io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
00758 
00759     scsi_device * scsidev = get_tunnel_dev();
00760     if (!scsidev->scsi_pass_through(&io_hdr)) {
00761         if (scsi_debugmode > 0)
00762             pout("usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
00763                  "errno=%d [%s]\n", scsidev->get_errno(), scsidev->get_errmsg());
00764         set_err(scsidev->get_err());
00765         return -1;
00766     }
00767 
00768     // if there is a sense the command failed or the
00769     // device doesn't support usbcypress
00770     if (io_hdr.scsi_status == SCSI_STATUS_CHECK_CONDITION && 
00771             sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len, NULL)) {
00772         return -1;
00773     }
00774     if (ck_cond) {
00775         unsigned char ardp[8];
00776         int ard_len = 8;
00777         /* XXX this is racy if there other scsi command between
00778          * the first usbcypress command and this one
00779          */
00780         //pout("If you got strange result, please retry without traffic on the disc\n");
00781         /* we use the same command as before, but we set
00782          * * the read taskfile bit, for not executing usbcypress command,
00783          * * but reading register selected in srb->cmnd[4]
00784          */
00785         cdb[2] = (1<<0); /* ask read taskfile */
00786         memset(sense, 0, sizeof(sense));
00787 
00788         /* transfert 8 bytes */
00789         memset(&io_hdr, 0, sizeof(io_hdr));
00790         io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
00791         io_hdr.dxfer_len = ard_len;
00792         io_hdr.dxferp = (unsigned char *)ardp;
00793         memset(ardp, 0, ard_len); /* prefill with zeroes */
00794 
00795         io_hdr.cmnd = cdb;
00796         io_hdr.cmnd_len = passthru_size;
00797         io_hdr.sensep = sense;
00798         io_hdr.max_sense_len = sizeof(sense);
00799         io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
00800 
00801 
00802         if (!scsidev->scsi_pass_through(&io_hdr)) {
00803             if (scsi_debugmode > 0)
00804                 pout("usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
00805                      "errno=%d [%s]\n", scsidev->get_errno(), scsidev->get_errmsg());
00806             set_err(scsidev->get_err());
00807             return -1;
00808         }
00809         // if there is a sense the command failed or the
00810         // device doesn't support usbcypress
00811         if (io_hdr.scsi_status == SCSI_STATUS_CHECK_CONDITION && 
00812                 sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len, NULL)) {
00813             return -1;
00814         }
00815 
00816 
00817         if (scsi_debugmode > 1) {
00818             pout("Values from ATA Return Descriptor are:\n");
00819             dStrHex((const char *)ardp, ard_len, 1);
00820         }
00821 
00822         if (ATA_CHECK_POWER_MODE == ata_command)
00823             data[0] = ardp[2];      /* sector count (0:7) */
00824         else if (STATUS_CHECK == command) {
00825             if ((ardp[4] == 0x4f) && (ardp[5] == 0xc2))
00826                 return 0;    /* GOOD smart status */
00827             if ((ardp[4] == 0xf4) && (ardp[5] == 0x2c))
00828                 return 1;    // smart predicting failure, "bad" status
00829             // We haven't gotten output that makes sense so
00830             // print out some debugging info
00831             syserror("Error SMART Status command failed");
00832             pout("This may be due to a race in usbcypress\n");
00833             pout("Retry without other disc access\n");
00834             pout("Please get assistance from " PACKAGE_HOMEPAGE "\n");
00835             pout("Values from ATA Return Descriptor are:\n");
00836             dStrHex((const char *)ardp, ard_len, 1);
00837             return -1;
00838         }
00839     }
00840     return 0;
00841 }
00842 
00843 #if 0 // Not used, see autodetect_sat_device() below.
00844 static int isprint_string(const char *s)
00845 {
00846     while (*s) {
00847         if (isprint(*s) == 0)
00848             return 0;
00849         s++;
00850     }
00851     return 1;
00852 }
00853 
00854 /* Attempt an IDENTIFY DEVICE ATA or IDENTIFY PACKET DEVICE command
00855    If successful return 1, else 0 */
00856 // TODO: Combine with has_sat_pass_through above
00857 static int has_usbcypress_pass_through(ata_device * atadev, const char *manufacturer, const char *product)
00858 {
00859     struct ata_identify_device drive;
00860     char model[40], serial[20], firm[8];
00861 
00862     /* issue the command and do a checksum if possible */
00863     if (ataReadHDIdentity(atadev, &drive) < 0)
00864         return 0;
00865 
00866     /* check if model string match, revision doesn't work for me */
00867     format_ata_string(model, drive.model, 40);
00868     if (*model == 0 || isprint_string(model) == 0)
00869         return 0;
00870 
00871     if (manufacturer && strncmp(manufacturer, model, 8))
00872         pout("manufacturer doesn't match in pass_through test\n");
00873     if (product &&
00874             strlen(model) > 8 && strncmp(product, model+8, strlen(model)-8))
00875         pout("product doesn't match in pass_through test\n");
00876 
00877     /* check serial */
00878     format_ata_string(serial, drive.serial_no, 20);
00879     if (isprint_string(serial) == 0)
00880         return 0;
00881     format_ata_string(firm, drive.fw_rev, 8);
00882     if (isprint_string(firm) == 0)
00883         return 0;
00884     return 1;
00885 }
00886 #endif
00887 
00888 /////////////////////////////////////////////////////////////////////////////
00889 
00890 /// JMicron USB Bridge support.
00891 
00892 class usbjmicron_device
00893 : public tunnelled_device<
00894     /*implements*/ ata_device,
00895     /*by tunnelling through a*/ scsi_device
00896   >
00897 {
00898 public:
00899   usbjmicron_device(smart_interface * intf, scsi_device * scsidev,
00900                     const char * req_type, bool prolific,
00901                     bool ata_48bit_support, int port);
00902 
00903   virtual ~usbjmicron_device() throw();
00904 
00905   virtual bool open();
00906 
00907   virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
00908 
00909 private:
00910   bool get_registers(unsigned short addr, unsigned char * buf, unsigned short size);
00911 
00912   bool m_prolific;
00913   bool m_ata_48bit_support;
00914   int m_port;
00915 };
00916 
00917 
00918 usbjmicron_device::usbjmicron_device(smart_interface * intf, scsi_device * scsidev,
00919                                      const char * req_type, bool prolific,
00920                                      bool ata_48bit_support, int port)
00921 : smart_device(intf, scsidev->get_dev_name(), "usbjmicron", req_type),
00922   tunnelled_device<ata_device, scsi_device>(scsidev),
00923   m_prolific(prolific), m_ata_48bit_support(ata_48bit_support),
00924   m_port(port >= 0 || !prolific ? port : 0)
00925 {
00926   set_info().info_name = strprintf("%s [USB JMicron]", scsidev->get_info_name());
00927 }
00928 
00929 usbjmicron_device::~usbjmicron_device() throw()
00930 {
00931 }
00932 
00933 
00934 bool usbjmicron_device::open()
00935 {
00936   // Open USB first
00937   if (!tunnelled_device<ata_device, scsi_device>::open())
00938     return false;
00939 
00940   // Detect port if not specified
00941   if (m_port < 0) {
00942     unsigned char regbuf[1] = {0};
00943     if (!get_registers(0x720f, regbuf, sizeof(regbuf))) {
00944       close();
00945       return false;
00946     }
00947 
00948     switch (regbuf[0] & 0x44) {
00949       case 0x04:
00950         m_port = 0; break;
00951       case 0x40:
00952         m_port = 1; break;
00953       case 0x44:
00954         close();
00955         return set_err(EINVAL, "Two devices connected, try '-d usbjmicron,[01]'");
00956       default:
00957         close();
00958         return set_err(ENODEV, "No device connected");
00959     }
00960   }
00961 
00962   return true;
00963 }
00964 
00965 
00966 bool usbjmicron_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
00967 {
00968   if (!ata_cmd_is_supported(in,
00969     ata_device::supports_data_out |
00970     ata_device::supports_smart_status |
00971     (m_ata_48bit_support ? ata_device::supports_48bit_hi_null : 0),
00972     "JMicron")
00973   )
00974     return false;
00975 
00976   if (m_port < 0)
00977     return set_err(EIO, "Unknown JMicron port");
00978 
00979   scsi_cmnd_io io_hdr;
00980   memset(&io_hdr, 0, sizeof(io_hdr));
00981 
00982   bool rwbit = true;
00983   unsigned char smart_status = 0;
00984 
00985   bool is_smart_status = (   in.in_regs.command  == ATA_SMART_CMD
00986                           && in.in_regs.features == ATA_SMART_STATUS);
00987 
00988   if (is_smart_status && in.out_needed.is_set()) {
00989     io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
00990     io_hdr.dxfer_len = 1;
00991     io_hdr.dxferp = &smart_status;
00992   }
00993   else switch (in.direction) {
00994     case ata_cmd_in::no_data:
00995       io_hdr.dxfer_dir = DXFER_NONE;
00996       break;
00997     case ata_cmd_in::data_in:
00998       io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
00999       io_hdr.dxfer_len = in.size;
01000       io_hdr.dxferp = (unsigned char *)in.buffer;
01001       memset(in.buffer, 0, in.size);
01002       break;
01003     case ata_cmd_in::data_out:
01004       io_hdr.dxfer_dir = DXFER_TO_DEVICE;
01005       io_hdr.dxfer_len = in.size;
01006       io_hdr.dxferp = (unsigned char *)in.buffer;
01007       rwbit = false;
01008       break;
01009     default:
01010       return set_err(EINVAL);
01011   }
01012 
01013   // Build pass through command
01014   unsigned char cdb[14];
01015   cdb[ 0] = 0xdf;
01016   cdb[ 1] = (rwbit ? 0x10 : 0x00);
01017   cdb[ 2] = 0x00;
01018   cdb[ 3] = (unsigned char)(io_hdr.dxfer_len >> 8);
01019   cdb[ 4] = (unsigned char)(io_hdr.dxfer_len     );
01020   cdb[ 5] = in.in_regs.features;
01021   cdb[ 6] = in.in_regs.sector_count;
01022   cdb[ 7] = in.in_regs.lba_low;
01023   cdb[ 8] = in.in_regs.lba_mid;
01024   cdb[ 9] = in.in_regs.lba_high;
01025   cdb[10] = in.in_regs.device | (m_port == 0 ? 0xa0 : 0xb0);
01026   cdb[11] = in.in_regs.command;
01027   // Prolific PL3507
01028   cdb[12] = 0x06;
01029   cdb[13] = 0x7b;
01030 
01031   io_hdr.cmnd = cdb;
01032   io_hdr.cmnd_len = (!m_prolific ? 12 : 14);
01033 
01034   scsi_device * scsidev = get_tunnel_dev();
01035   if (!scsi_pass_through_and_check(scsidev, &io_hdr,
01036          "usbjmicron_device::ata_pass_through: "))
01037     return set_err(scsidev->get_err());
01038 
01039   if (in.out_needed.is_set()) {
01040     if (is_smart_status) {
01041       switch (smart_status) {
01042         case 0x01: case 0xc2:
01043           out.out_regs.lba_high = 0xc2;
01044           out.out_regs.lba_mid = 0x4f;
01045           break;
01046         case 0x00: case 0x2c:
01047           out.out_regs.lba_high = 0x2c;
01048           out.out_regs.lba_mid = 0xf4;
01049           break;
01050       }
01051     }
01052 
01053 #if 0 // Not needed for SMART STATUS, see also notes below
01054     else {
01055       // Read ATA output registers
01056       // NOTE: The register addresses are not valid for some older chip revisions
01057       // NOTE: There is a small race condition here!
01058       unsigned char regbuf[16] = {0, };
01059       if (!get_registers((m_port == 0 ? 0x8000 : 0x9000), regbuf, sizeof(regbuf)))
01060         return false;
01061 
01062       out.out_regs.sector_count = regbuf[ 0];
01063       out.out_regs.lba_mid      = regbuf[ 4];
01064       out.out_regs.lba_low      = regbuf[ 6];
01065       out.out_regs.device       = regbuf[ 9];
01066       out.out_regs.lba_high     = regbuf[10];
01067       out.out_regs.error        = regbuf[13];
01068       out.out_regs.status       = regbuf[14];
01069     }
01070 #endif
01071   }
01072 
01073   return true;
01074 }
01075 
01076 bool usbjmicron_device::get_registers(unsigned short addr,
01077                                       unsigned char * buf, unsigned short size)
01078 {
01079   unsigned char cdb[14];
01080   cdb[ 0] = 0xdf;
01081   cdb[ 1] = 0x10;
01082   cdb[ 2] = 0x00;
01083   cdb[ 3] = (unsigned char)(size >> 8);
01084   cdb[ 4] = (unsigned char)(size     );
01085   cdb[ 5] = 0x00;
01086   cdb[ 6] = (unsigned char)(addr >> 8);
01087   cdb[ 7] = (unsigned char)(addr     );
01088   cdb[ 8] = 0x00;
01089   cdb[ 9] = 0x00;
01090   cdb[10] = 0x00;
01091   cdb[11] = 0xfd;
01092   // Prolific PL3507
01093   cdb[12] = 0x06;
01094   cdb[13] = 0x7b;
01095 
01096   scsi_cmnd_io io_hdr;
01097   memset(&io_hdr, 0, sizeof(io_hdr));
01098   io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
01099   io_hdr.dxfer_len = size;
01100   io_hdr.dxferp = buf;
01101   io_hdr.cmnd = cdb;
01102   io_hdr.cmnd_len = sizeof(cdb);
01103   io_hdr.cmnd_len = (!m_prolific ? 12 : 14);
01104 
01105   scsi_device * scsidev = get_tunnel_dev();
01106   if (!scsi_pass_through_and_check(scsidev, &io_hdr,
01107          "usbjmicron_device::get_registers: "))
01108     return set_err(scsidev->get_err());
01109 
01110   return true;
01111 }
01112 
01113 
01114 /////////////////////////////////////////////////////////////////////////////
01115 
01116 /// SunplusIT USB Bridge support.
01117 
01118 class usbsunplus_device
01119 : public tunnelled_device<
01120     /*implements*/ ata_device,
01121     /*by tunnelling through a*/ scsi_device
01122   >
01123 {
01124 public:
01125   usbsunplus_device(smart_interface * intf, scsi_device * scsidev,
01126                     const char * req_type);
01127 
01128   virtual ~usbsunplus_device() throw();
01129 
01130   virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
01131 };
01132 
01133 
01134 usbsunplus_device::usbsunplus_device(smart_interface * intf, scsi_device * scsidev,
01135                                      const char * req_type)
01136 : smart_device(intf, scsidev->get_dev_name(), "usbsunplus", req_type),
01137   tunnelled_device<ata_device, scsi_device>(scsidev)
01138 {
01139   set_info().info_name = strprintf("%s [USB Sunplus]", scsidev->get_info_name());
01140 }
01141 
01142 usbsunplus_device::~usbsunplus_device() throw()
01143 {
01144 }
01145 
01146 bool usbsunplus_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
01147 {
01148   if (!ata_cmd_is_supported(in,
01149     ata_device::supports_data_out |
01150     ata_device::supports_output_regs |
01151     ata_device::supports_48bit,
01152     "Sunplus")
01153   )
01154     return false;
01155 
01156   scsi_cmnd_io io_hdr;
01157   unsigned char cdb[12];
01158 
01159   if (in.in_regs.is_48bit_cmd()) {
01160     // Set "previous" registers
01161     memset(&io_hdr, 0, sizeof(io_hdr));
01162     io_hdr.dxfer_dir = DXFER_NONE;
01163 
01164     cdb[ 0] = 0xf8;
01165     cdb[ 1] = 0x00;
01166     cdb[ 2] = 0x23; // Subcommand: Pass through presetting
01167     cdb[ 3] = 0x00;
01168     cdb[ 4] = 0x00;
01169     cdb[ 5] = in.in_regs.prev.features;
01170     cdb[ 6] = in.in_regs.prev.sector_count;
01171     cdb[ 7] = in.in_regs.prev.lba_low;
01172     cdb[ 8] = in.in_regs.prev.lba_mid;
01173     cdb[ 9] = in.in_regs.prev.lba_high;
01174     cdb[10] = 0x00;
01175     cdb[11] = 0x00;
01176 
01177     io_hdr.cmnd = cdb;
01178     io_hdr.cmnd_len = sizeof(cdb);
01179 
01180     scsi_device * scsidev = get_tunnel_dev();
01181     if (!scsi_pass_through_and_check(scsidev, &io_hdr,
01182            "usbsunplus_device::scsi_pass_through (presetting): "))
01183       return set_err(scsidev->get_err());
01184   }
01185 
01186   // Run Pass through command
01187   memset(&io_hdr, 0, sizeof(io_hdr));
01188   unsigned char protocol;
01189   switch (in.direction) {
01190     case ata_cmd_in::no_data:
01191       io_hdr.dxfer_dir = DXFER_NONE;
01192       protocol = 0x00;
01193       break;
01194     case ata_cmd_in::data_in:
01195       io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
01196       io_hdr.dxfer_len = in.size;
01197       io_hdr.dxferp = (unsigned char *)in.buffer;
01198       memset(in.buffer, 0, in.size);
01199       protocol = 0x10;
01200       break;
01201     case ata_cmd_in::data_out:
01202       io_hdr.dxfer_dir = DXFER_TO_DEVICE;
01203       io_hdr.dxfer_len = in.size;
01204       io_hdr.dxferp = (unsigned char *)in.buffer;
01205       protocol = 0x11;
01206       break;
01207     default:
01208       return set_err(EINVAL);
01209   }
01210 
01211   cdb[ 0] = 0xf8;
01212   cdb[ 1] = 0x00;
01213   cdb[ 2] = 0x22; // Subcommand: Pass through
01214   cdb[ 3] = protocol;
01215   cdb[ 4] = (unsigned char)(io_hdr.dxfer_len >> 9);
01216   cdb[ 5] = in.in_regs.features;
01217   cdb[ 6] = in.in_regs.sector_count;
01218   cdb[ 7] = in.in_regs.lba_low;
01219   cdb[ 8] = in.in_regs.lba_mid;
01220   cdb[ 9] = in.in_regs.lba_high;
01221   cdb[10] = in.in_regs.device | 0xa0;
01222   cdb[11] = in.in_regs.command;
01223 
01224   io_hdr.cmnd = cdb;
01225   io_hdr.cmnd_len = sizeof(cdb);
01226 
01227   scsi_device * scsidev = get_tunnel_dev();
01228   if (!scsi_pass_through_and_check(scsidev, &io_hdr,
01229          "usbsunplus_device::scsi_pass_through: "))
01230     // Returns sense key 0x03 (medium error) on ATA command error
01231     return set_err(scsidev->get_err());
01232 
01233   if (in.out_needed.is_set()) {
01234     // Read ATA output registers
01235     unsigned char regbuf[8] = {0, };
01236     memset(&io_hdr, 0, sizeof(io_hdr));
01237     io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
01238     io_hdr.dxfer_len = sizeof(regbuf);
01239     io_hdr.dxferp = regbuf;
01240 
01241     cdb[ 0] = 0xf8;
01242     cdb[ 1] = 0x00;
01243     cdb[ 2] = 0x21; // Subcommand: Get status
01244     memset(cdb+3, 0, sizeof(cdb)-3);
01245     io_hdr.cmnd = cdb;
01246     io_hdr.cmnd_len = sizeof(cdb);
01247 
01248     if (!scsi_pass_through_and_check(scsidev, &io_hdr,
01249            "usbsunplus_device::scsi_pass_through (get registers): "))
01250       return set_err(scsidev->get_err());
01251 
01252     out.out_regs.error        = regbuf[1];
01253     out.out_regs.sector_count = regbuf[2];
01254     out.out_regs.lba_low      = regbuf[3];
01255     out.out_regs.lba_mid      = regbuf[4];
01256     out.out_regs.lba_high     = regbuf[5];
01257     out.out_regs.device       = regbuf[6];
01258     out.out_regs.status       = regbuf[7];
01259   }
01260 
01261   return true;
01262 }
01263 
01264 
01265 } // namespace
01266 
01267 using namespace sat;
01268 
01269 
01270 /////////////////////////////////////////////////////////////////////////////
01271 
01272 // Return ATA->SCSI filter for SAT or USB.
01273 
01274 ata_device * smart_interface::get_sat_device(const char * type, scsi_device * scsidev)
01275 {
01276   if (!strncmp(type, "sat", 3)) {
01277     const char * t = type + 3;
01278     bool enable_auto = false;
01279     if (!strncmp(t, ",auto", 5)) {
01280       t += 5;
01281       enable_auto = true;
01282     }
01283     int ptlen = 0, n = -1;
01284     if (*t && !(sscanf(t, ",%d%n", &ptlen, &n) == 1 && n == (int)strlen(t)
01285                 && (ptlen == 0 || ptlen == 12 || ptlen == 16))) {
01286       set_err(EINVAL, "Option '-d sat[,auto][,N]' requires N to be 0, 12 or 16");
01287       return 0;
01288     }
01289     return new sat_device(this, scsidev, type, ptlen, enable_auto);
01290   }
01291 
01292   else if (!strncmp(type, "usbcypress", 10)) {
01293     unsigned signature = 0x24; int n1 = -1, n2 = -1;
01294     if (!(((sscanf(type, "usbcypress%n,0x%x%n", &n1, &signature, &n2) == 1 && n2 == (int)strlen(type)) || n1 == (int)strlen(type))
01295           && signature <= 0xff)) {
01296       set_err(EINVAL, "Option '-d usbcypress,<n>' requires <n> to be "
01297                       "an hexadecimal number between 0x0 and 0xff");
01298       return 0;
01299     }
01300     return new usbcypress_device(this, scsidev, type, signature);
01301   }
01302 
01303   else if (!strncmp(type, "usbjmicron", 10)) {
01304     const char * t = type + 10;
01305     bool prolific = false;
01306     if (!strncmp(t, ",p", 2)) {
01307       t += 2;
01308       prolific = true;
01309     }
01310     bool ata_48bit_support = false;
01311     if (!strncmp(t, ",x", 2)) {
01312       t += 2;
01313       ata_48bit_support = true;
01314     }
01315     int port = -1, n = -1;
01316     if (*t && !(  (sscanf(t, ",%d%n", &port, &n) == 1
01317                 && n == (int)strlen(t) && 0 <= port && port <= 1))) {
01318       set_err(EINVAL, "Option '-d usbjmicron[,p][,x],<n>' requires <n> to be 0 or 1");
01319       return 0;
01320     }
01321     return new usbjmicron_device(this, scsidev, type, prolific, ata_48bit_support, port);
01322   }
01323 
01324   else if (!strcmp(type, "usbsunplus")) {
01325     return new usbsunplus_device(this, scsidev, type);
01326   }
01327 
01328   else {
01329     set_err(EINVAL, "Unknown USB device type '%s'", type);
01330     return 0;
01331   }
01332 }
01333 
01334 // Try to detect a SAT device behind a SCSI interface.
01335 
01336 ata_device * smart_interface::autodetect_sat_device(scsi_device * scsidev,
01337   const unsigned char * inqdata, unsigned inqsize)
01338 {
01339   if (!scsidev->is_open())
01340     return 0;
01341 
01342   // SAT ?
01343   if (inqdata && inqsize >= 36 && !memcmp(inqdata + 8, "ATA     ", 8)) { // TODO: Linux-specific?
01344     ata_device_auto_ptr atadev( new sat_device(this, scsidev, "") , scsidev);
01345     if (has_sat_pass_through(atadev.get()))
01346       return atadev.release(); // Detected SAT
01347   }
01348 
01349   return 0;
01350 }
01351 
01352 
01353 /////////////////////////////////////////////////////////////////////////////
01354 // USB device type detection
01355 
01356 // Format USB ID for error messages
01357 static std::string format_usb_id(int vendor_id, int product_id, int version)
01358 {
01359   if (version >= 0)
01360     return strprintf("[0x%04x:0x%04x (0x%03x)]", vendor_id, product_id, version);
01361   else
01362     return strprintf("[0x%04x:0x%04x]", vendor_id, product_id);
01363 }
01364 
01365 // Get type name for USB device with known VENDOR:PRODUCT ID.
01366 const char * smart_interface::get_usb_dev_type_by_id(int vendor_id, int product_id,
01367                                                      int version /*= -1*/)
01368 {
01369   usb_dev_info info, info2;
01370   int n = lookup_usb_device(vendor_id, product_id, version, info, info2);
01371 
01372   if (n <= 0) {
01373     set_err(EINVAL, "Unknown USB bridge %s",
01374             format_usb_id(vendor_id, product_id, version).c_str());
01375     return 0;
01376   }
01377 
01378   if (n > 1) {
01379     set_err(EINVAL, "USB bridge %s type is ambiguous: '%s' or '%s'",
01380             format_usb_id(vendor_id, product_id, version).c_str(),
01381             (!info.usb_type.empty()  ? info.usb_type.c_str()  : "[unsupported]"),
01382             (!info2.usb_type.empty() ? info2.usb_type.c_str() : "[unsupported]"));
01383     return 0;
01384   }
01385 
01386   if (info.usb_type.empty()) {
01387     set_err(ENOSYS, "Unsupported USB bridge %s",
01388             format_usb_id(vendor_id, product_id, version).c_str());
01389     return 0;
01390   }
01391 
01392   // TODO: change return type to std::string
01393   static std::string type;
01394   type = info.usb_type;
01395   return type.c_str();
01396 }