|
smartmontools SVN Rev 3317
Utility to control and monitor storage systems with "S.M.A.R.T."
|
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 }
1.7.4