4 * Home page of code is: http://smartmontools.sourceforge.net
6 * Copyright (C) 2006-9 Douglas Gilbert <dougg@torque.net>
7 * Copyright (C) 2009 Christian Franke <smartmontools-support@lists.sourceforge.net>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
14 * You should have received a copy of the GNU General Public License
15 * (for example COPYING); if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 * The code in this file is based on the SCSI to ATA Translation (SAT)
19 * draft found at http://www.t10.org . The original draft used for this
20 * code is sat-r08.pdf which is not too far away from becoming a
21 * standard. The SAT commands of interest to smartmontools are the
22 * ATA PASS THROUGH SCSI (16) and ATA PASS THROUGH SCSI (12) defined in
23 * section 12 of that document.
25 * sat-r09.pdf is the most recent, easily accessible draft prior to the
26 * original SAT standard (ANSI INCITS 431-2007). By mid-2009 the second
27 * version of the SAT standard (SAT-2) is nearing standardization. In
28 * their wisdom an incompatible change has been introduced in draft
29 * sat2r08a.pdf in the area of the ATA RETURN DESCRIPTOR. A new "fixed
30 * format" ATA RETURN buffer has been defined (sat2r08b.pdf section
31 * 12.2.7) for the case when DSENSE=0 in the Control mode page.
32 * Unfortunately this is the normal case. If the change stands our
33 * code will need to be extended for this case.
35 * With more transports "hiding" SATA disks (and other S-ATAPI devices)
36 * behind a SCSI command set, accessing special features like SMART
37 * information becomes a challenge. The SAT standard offers ATA PASS
38 * THROUGH commands for special usages. Note that the SAT layer may
39 * be inside a generic OS layer (e.g. libata in linux), in a host
40 * adapter (HA or HBA) firmware, or somewhere on the interconnect
41 * between the host computer and the SATA devices (e.g. a RAID made
42 * of SATA disks and the RAID talks "SCSI" to the host computer).
43 * Note that in the latter case, this code does not solve the
44 * addressing issue (i.e. which SATA disk to address behind the logical
45 * SCSI (RAID) interface).
57 #include "atacmds.h" // ataReadHDIdentity()
59 #include "dev_interface.h"
60 #include "dev_ata_cmd_set.h" // ata_device_with_command_set
61 #include "dev_tunnelled.h" // tunnelled_device<>
63 const char * scsiata_cpp_cvsid
= "$Id: scsiata.cpp 2876 2009-08-20 22:53:18Z dlukes $";
65 /* for passing global control variables */
66 extern smartmonctrl
*con
;
68 /* This is a slightly stretched SCSI sense "descriptor" format header.
69 The addition is to allow the 0x70 and 0x71 response codes. The idea
70 is to place the salient data of both "fixed" and "descriptor" sense
71 format into one structure to ease application processing.
72 The original sense buffer should be kept around for those cases
73 in which more information is required (e.g. the LBA of a MEDIUM ERROR). */
74 /// Abridged SCSI sense data
75 struct sg_scsi_sense_hdr
{
76 unsigned char response_code
; /* permit: 0x0, 0x70, 0x71, 0x72, 0x73 */
77 unsigned char sense_key
;
83 unsigned char additional_length
;
86 /* Maps the salient data from a sense buffer which is in either fixed or
87 descriptor format into a structure mimicking a descriptor format
88 header (i.e. the first 8 bytes of sense descriptor format).
89 If zero response code returns 0. Otherwise returns 1 and if 'sshp' is
90 non-NULL then zero all fields and then set the appropriate fields in
91 that structure. sshp::additional_length is always 0 for response
92 codes 0x70 and 0x71 (fixed format). */
93 static int sg_scsi_normalize_sense(const unsigned char * sensep
, int sb_len
,
94 struct sg_scsi_sense_hdr
* sshp
);
96 /* Attempt to find the first SCSI sense data descriptor that matches the
97 given 'desc_type'. If found return pointer to start of sense data
98 descriptor; otherwise (including fixed format sense data) returns NULL. */
99 static const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep
,
100 int sense_len
, int desc_type
);
102 #define SAT_ATA_PASSTHROUGH_12LEN 12
103 #define SAT_ATA_PASSTHROUGH_16LEN 16
105 #define DEF_SAT_ATA_PASSTHRU_SIZE 16
106 #define ATA_RETURN_DESCRIPTOR 9
109 namespace sat
{ // no need to publish anything, name provided for Doxygen
112 /// Implements ATA by tunnelling through SCSI.
115 : public tunnelled_device
<
116 /*implements*/ ata_device
117 /*by tunnelling through a*/, scsi_device
121 sat_device(smart_interface
* intf
, scsi_device
* scsidev
,
122 const char * req_type
, int passthrulen
= 0);
124 virtual ~sat_device() throw();
126 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
133 sat_device::sat_device(smart_interface
* intf
, scsi_device
* scsidev
,
134 const char * req_type
, int passthrulen
/*= 0*/)
135 : smart_device(intf
, scsidev
->get_dev_name(), "sat", req_type
),
136 tunnelled_device
<ata_device
, scsi_device
>(scsidev
),
137 m_passthrulen(passthrulen
)
139 set_info().info_name
= strprintf("%s [SAT]", scsidev
->get_info_name());
142 sat_device::~sat_device() throw()
147 // cdb[0]: ATA PASS THROUGH (16) SCSI command opcode byte (0x85)
148 // cdb[1]: multiple_count, protocol + extend
149 // cdb[2]: offline, ck_cond, t_dir, byte_block + t_length
150 // cdb[3]: features (15:8)
151 // cdb[4]: features (7:0)
152 // cdb[5]: sector_count (15:8)
153 // cdb[6]: sector_count (7:0)
154 // cdb[7]: lba_low (15:8)
155 // cdb[8]: lba_low (7:0)
156 // cdb[9]: lba_mid (15:8)
157 // cdb[10]: lba_mid (7:0)
158 // cdb[11]: lba_high (15:8)
159 // cdb[12]: lba_high (7:0)
161 // cdb[14]: (ata) command
162 // cdb[15]: control (SCSI, leave as zero)
164 // 24 bit lba (from MSB): cdb[12] cdb[10] cdb[8]
165 // 48 bit lba (from MSB): cdb[11] cdb[9] cdb[7] cdb[12] cdb[10] cdb[8]
168 // cdb[0]: ATA PASS THROUGH (12) SCSI command opcode byte (0xa1)
169 // cdb[1]: multiple_count, protocol + extend
170 // cdb[2]: offline, ck_cond, t_dir, byte_block + t_length
171 // cdb[3]: features (7:0)
172 // cdb[4]: sector_count (7:0)
173 // cdb[5]: lba_low (7:0)
174 // cdb[6]: lba_mid (7:0)
175 // cdb[7]: lba_high (7:0)
177 // cdb[9]: (ata) command
179 // cdb[11]: control (SCSI, leave as zero)
182 // ATA Return Descriptor (component of descriptor sense data)
183 // des[0]: descriptor code (0x9)
184 // des[1]: additional descriptor length (0xc)
185 // des[2]: extend (bit 0)
187 // des[4]: sector_count (15:8)
188 // des[5]: sector_count (7:0)
189 // des[6]: lba_low (15:8)
190 // des[7]: lba_low (7:0)
191 // des[8]: lba_mid (15:8)
192 // des[9]: lba_mid (7:0)
193 // des[10]: lba_high (15:8)
194 // des[11]: lba_high (7:0)
201 // This interface routine takes ATA SMART commands and packages
202 // them in the SAT-defined ATA PASS THROUGH SCSI commands. There are
203 // two available SCSI commands: a 12 byte and 16 byte variant; the
204 // one used is chosen via this->m_passthrulen .
205 // DETAILED DESCRIPTION OF ARGUMENTS
206 // device: is the file descriptor provided by (a SCSI dvice type) open()
207 // command: defines the different ATA operations.
208 // select: additional input data if needed (which log, which type of
210 // data: location to write output data, if needed (512 bytes).
211 // Note: not all commands use all arguments.
213 // -1 if the command failed
214 // 0 if the command succeeded,
215 // STATUS_CHECK routine:
216 // -1 if the command failed
217 // 0 if the command succeeded and disk SMART status is "OK"
218 // 1 if the command succeeded and disk SMART status is "FAILING"
220 bool sat_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
222 if (!ata_cmd_is_ok(in
,
223 true, // data_out_support
224 true, // multi_sector_support
225 true) // ata_48bit_support
229 struct scsi_cmnd_io io_hdr
;
230 struct scsi_sense_disect sinfo
;
231 struct sg_scsi_sense_hdr ssh
;
232 unsigned char cdb
[SAT_ATA_PASSTHROUGH_16LEN
];
233 unsigned char sense
[32];
234 const unsigned char * ardp
;
235 int status
, ard_len
, have_sense
;
237 int ck_cond
= 0; /* set to 1 to read register(s) back */
238 int protocol
= 3; /* non-data */
239 int t_dir
= 1; /* 0 -> to device, 1 -> from device */
240 int byte_block
= 1; /* 0 -> bytes, 1 -> 512 byte blocks */
241 int t_length
= 0; /* 0 -> no data transferred */
242 int passthru_size
= DEF_SAT_ATA_PASSTHRU_SIZE
;
244 memset(cdb
, 0, sizeof(cdb
));
245 memset(sense
, 0, sizeof(sense
));
247 // Set data direction
248 // TODO: This works only for commands where sector_count holds count!
249 switch (in
.direction
) {
250 case ata_cmd_in::no_data
:
252 case ata_cmd_in::data_in
:
253 protocol
= 4; // PIO data-in
254 t_length
= 2; // sector_count holds count
256 case ata_cmd_in::data_out
:
257 protocol
= 5; // PIO data-out
258 t_length
= 2; // sector_count holds count
259 t_dir
= 0; // to device
262 return set_err(EINVAL
, "sat_device::ata_pass_through: invalid direction=%d",
266 // Check condition if any output register needed
267 if (in
.out_needed
.is_set())
270 if ((SAT_ATA_PASSTHROUGH_12LEN
== m_passthrulen
) ||
271 (SAT_ATA_PASSTHROUGH_16LEN
== m_passthrulen
))
272 passthru_size
= m_passthrulen
;
274 // Set extend bit on 48-bit ATA command
275 if (in
.in_regs
.is_48bit_cmd()) {
276 if (passthru_size
!= SAT_ATA_PASSTHROUGH_16LEN
)
277 return set_err(ENOSYS
, "48-bit ATA commands require SAT ATA PASS-THROUGH (16)");
281 cdb
[0] = (SAT_ATA_PASSTHROUGH_12LEN
== passthru_size
) ?
282 SAT_ATA_PASSTHROUGH_12
: SAT_ATA_PASSTHROUGH_16
;
284 cdb
[1] = (protocol
<< 1) | extend
;
285 cdb
[2] = (ck_cond
<< 5) | (t_dir
<< 3) |
286 (byte_block
<< 2) | t_length
;
288 if (passthru_size
== SAT_ATA_PASSTHROUGH_12LEN
) {
289 // ATA PASS-THROUGH (12)
290 const ata_in_regs
& lo
= in
.in_regs
;
291 cdb
[3] = lo
.features
;
292 cdb
[4] = lo
.sector_count
;
295 cdb
[7] = lo
.lba_high
;
300 // ATA PASS-THROUGH (16)
301 const ata_in_regs
& lo
= in
.in_regs
;
302 const ata_in_regs
& hi
= in
.in_regs
.prev
;
303 // Note: all 'in.in_regs.prev.*' are always zero for 28-bit commands
304 cdb
[ 3] = hi
.features
;
305 cdb
[ 4] = lo
.features
;
306 cdb
[ 5] = hi
.sector_count
;
307 cdb
[ 6] = lo
.sector_count
;
308 cdb
[ 7] = hi
.lba_low
;
309 cdb
[ 8] = lo
.lba_low
;
310 cdb
[ 9] = hi
.lba_mid
;
311 cdb
[10] = lo
.lba_mid
;
312 cdb
[11] = hi
.lba_high
;
313 cdb
[12] = lo
.lba_high
;
315 cdb
[14] = lo
.command
;
318 memset(&io_hdr
, 0, sizeof(io_hdr
));
320 io_hdr
.dxfer_dir
= DXFER_NONE
;
321 io_hdr
.dxfer_len
= 0;
322 } else if (t_dir
) { /* from device */
323 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
324 io_hdr
.dxfer_len
= in
.size
;
325 io_hdr
.dxferp
= (unsigned char *)in
.buffer
;
326 memset(in
.buffer
, 0, in
.size
); // prefill with zeroes
327 } else { /* to device */
328 io_hdr
.dxfer_dir
= DXFER_TO_DEVICE
;
329 io_hdr
.dxfer_len
= in
.size
;
330 io_hdr
.dxferp
= (unsigned char *)in
.buffer
;
333 io_hdr
.cmnd_len
= passthru_size
;
334 io_hdr
.sensep
= sense
;
335 io_hdr
.max_sense_len
= sizeof(sense
);
336 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
338 scsi_device
* scsidev
= get_tunnel_dev();
339 if (!scsidev
->scsi_pass_through(&io_hdr
)) {
340 if (con
->reportscsiioctl
> 0)
341 pout("sat_device::ata_pass_through: scsi_pass_through() failed, "
342 "errno=%d [%s]\n", scsidev
->get_errno(), scsidev
->get_errmsg());
343 return set_err(scsidev
->get_err());
347 have_sense
= sg_scsi_normalize_sense(io_hdr
.sensep
, io_hdr
.resp_sense_len
,
350 /* look for SAT ATA Return Descriptor */
351 ardp
= sg_scsi_sense_desc_find(io_hdr
.sensep
,
352 io_hdr
.resp_sense_len
,
353 ATA_RETURN_DESCRIPTOR
);
355 ard_len
= ardp
[1] + 2;
358 else if (ard_len
> 14)
361 scsi_do_sense_disect(&io_hdr
, &sinfo
);
362 status
= scsiSimpleSenseFilter(&sinfo
);
364 if (con
->reportscsiioctl
> 0) {
365 pout("sat_device::ata_pass_through: scsi error: %s\n",
366 scsiErrString(status
));
367 if (ardp
&& (con
->reportscsiioctl
> 1)) {
368 pout("Values from ATA Return Descriptor are:\n");
369 dStrHex((const char *)ardp
, ard_len
, 1);
372 if (t_dir
&& (t_length
> 0) && (in
.direction
== ata_cmd_in::data_in
))
373 memset(in
.buffer
, 0, in
.size
);
374 return set_err(EIO
, "scsi error %s", scsiErrString(status
));
377 if (ck_cond
) { /* expecting SAT specific sense data */
380 if (con
->reportscsiioctl
> 1) {
381 pout("Values from ATA Return Descriptor are:\n");
382 dStrHex((const char *)ardp
, ard_len
, 1);
384 // Set output registers
385 ata_out_regs
& lo
= out
.out_regs
;
387 lo
.sector_count
= ardp
[ 5];
388 lo
.lba_low
= ardp
[ 7];
389 lo
.lba_mid
= ardp
[ 9];
390 lo
.lba_high
= ardp
[11];
391 lo
.device
= ardp
[12];
392 lo
.status
= ardp
[13];
393 if (in
.in_regs
.is_48bit_cmd()) {
394 ata_out_regs
& hi
= out
.out_regs
.prev
;
395 hi
.sector_count
= ardp
[ 4];
396 hi
.lba_low
= ardp
[ 6];
397 hi
.lba_mid
= ardp
[ 8];
398 hi
.lba_high
= ardp
[10];
403 ck_cond
= 0; /* not the type of sense data expected */
407 if ((ssh
.response_code
>= 0x72) &&
408 ((SCSI_SK_NO_SENSE
== ssh
.sense_key
) ||
409 (SCSI_SK_RECOVERED_ERR
== ssh
.sense_key
)) &&
411 (SCSI_ASCQ_ATA_PASS_THROUGH
== ssh
.ascq
)) {
413 if (con
->reportscsiioctl
> 0) {
414 pout("Values from ATA Return Descriptor are:\n");
415 dStrHex((const char *)ardp
, ard_len
, 1);
417 return set_err(EIO
, "SAT command failed");
427 /////////////////////////////////////////////////////////////////////////////
429 /* Attempt an IDENTIFY DEVICE ATA command via SATL when packet_interface
430 is false otherwise attempt IDENTIFY PACKET DEVICE. If successful
431 return true, else false */
433 static bool has_sat_pass_through(ata_device
* dev
, bool packet_interface
= false)
436 in
.in_regs
.command
= (packet_interface
? ATA_IDENTIFY_PACKET_DEVICE
: ATA_IDENTIFY_DEVICE
);
438 in
.set_data_in(data
, 1);
439 return dev
->ata_pass_through(in
);
442 /////////////////////////////////////////////////////////////////////////////
444 /* Next two functions are borrowed from sg_lib.c in the sg3_utils
445 package. Same copyrght owner, same license as this file. */
446 static int sg_scsi_normalize_sense(const unsigned char * sensep
, int sb_len
,
447 struct sg_scsi_sense_hdr
* sshp
)
450 memset(sshp
, 0, sizeof(struct sg_scsi_sense_hdr
));
451 if ((NULL
== sensep
) || (0 == sb_len
) || (0x70 != (0x70 & sensep
[0])))
454 sshp
->response_code
= (0x7f & sensep
[0]);
455 if (sshp
->response_code
>= 0x72) { /* descriptor format */
457 sshp
->sense_key
= (0xf & sensep
[1]);
459 sshp
->asc
= sensep
[2];
461 sshp
->ascq
= sensep
[3];
463 sshp
->additional_length
= sensep
[7];
464 } else { /* fixed format */
466 sshp
->sense_key
= (0xf & sensep
[2]);
468 sb_len
= (sb_len
< (sensep
[7] + 8)) ? sb_len
:
471 sshp
->asc
= sensep
[12];
473 sshp
->ascq
= sensep
[13];
481 static const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep
,
482 int sense_len
, int desc_type
)
484 int add_sen_len
, add_len
, desc_len
, k
;
485 const unsigned char * descp
;
487 if ((sense_len
< 8) || (0 == (add_sen_len
= sensep
[7])))
489 if ((sensep
[0] < 0x72) || (sensep
[0] > 0x73))
491 add_sen_len
= (add_sen_len
< (sense_len
- 8)) ?
492 add_sen_len
: (sense_len
- 8);
494 for (desc_len
= 0, k
= 0; k
< add_sen_len
; k
+= desc_len
) {
496 add_len
= (k
< (add_sen_len
- 1)) ? descp
[1]: -1;
497 desc_len
= add_len
+ 2;
498 if (descp
[0] == desc_type
)
500 if (add_len
< 0) /* short descriptor ?? */
507 // Call scsi_pass_through and check sense.
508 // TODO: Provide as member function of class scsi_device (?)
509 static bool scsi_pass_through_and_check(scsi_device
* scsidev
, scsi_cmnd_io
* iop
,
510 const char * msg
= "")
512 // Provide sense buffer
513 unsigned char sense
[32] = {0, };
515 iop
->max_sense_len
= sizeof(sense
);
516 iop
->timeout
= SCSI_TIMEOUT_DEFAULT
;
519 if (!scsidev
->scsi_pass_through(iop
)) {
520 if (con
->reportscsiioctl
> 0)
521 pout("%sscsi_pass_through() failed, errno=%d [%s]\n",
522 msg
, scsidev
->get_errno(), scsidev
->get_errmsg());
527 scsi_sense_disect sinfo
;
528 scsi_do_sense_disect(iop
, &sinfo
);
529 int err
= scsiSimpleSenseFilter(&sinfo
);
531 if (con
->reportscsiioctl
> 0)
532 pout("%sscsi error: %s\n", msg
, scsiErrString(err
));
533 return scsidev
->set_err(EIO
, "scsi error %s", scsiErrString(err
));
540 /////////////////////////////////////////////////////////////////////////////
544 /// Cypress USB Brigde support.
546 class usbcypress_device
547 : public tunnelled_device
<
548 /*implements*/ ata_device_with_command_set
549 /*by tunnelling through a*/, scsi_device
553 usbcypress_device(smart_interface
* intf
, scsi_device
* scsidev
,
554 const char * req_type
, unsigned char signature
);
556 virtual ~usbcypress_device() throw();
559 virtual int ata_command_interface(smart_command_set command
, int select
, char * data
);
561 unsigned char m_signature
;
565 usbcypress_device::usbcypress_device(smart_interface
* intf
, scsi_device
* scsidev
,
566 const char * req_type
, unsigned char signature
)
567 : smart_device(intf
, scsidev
->get_dev_name(), "sat", req_type
),
568 tunnelled_device
<ata_device_with_command_set
, scsi_device
>(scsidev
),
569 m_signature(signature
)
571 set_info().info_name
= strprintf("%s [USB Cypress]", scsidev
->get_info_name());
574 usbcypress_device::~usbcypress_device() throw()
579 /* see cy7c68300c_8.pdf for more information */
580 #define USBCYPRESS_PASSTHROUGH_LEN 16
581 int usbcypress_device::ata_command_interface(smart_command_set command
, int select
, char *data
)
583 struct scsi_cmnd_io io_hdr
;
584 unsigned char cdb
[USBCYPRESS_PASSTHROUGH_LEN
];
585 unsigned char sense
[32];
588 int ck_cond
= 0; /* set to 1 to read register(s) back */
589 int protocol
= 3; /* non-data */
590 int t_dir
= 1; /* 0 -> to device, 1 -> from device */
591 int byte_block
= 1; /* 0 -> bytes, 1 -> 512 byte blocks */
592 int t_length
= 0; /* 0 -> no data transferred */
595 int sector_count
= 0;
599 int passthru_size
= USBCYPRESS_PASSTHROUGH_LEN
;
601 memset(cdb
, 0, sizeof(cdb
));
602 memset(sense
, 0, sizeof(sense
));
604 ata_command
= ATA_SMART_CMD
;
606 case CHECK_POWER_MODE
:
607 ata_command
= ATA_CHECK_POWER_MODE
;
611 case READ_VALUES
: /* READ DATA */
612 feature
= ATA_SMART_READ_VALUES
;
613 sector_count
= 1; /* one (512 byte) block */
614 protocol
= 4; /* PIO data-in */
615 t_length
= 2; /* sector count holds count */
618 case READ_THRESHOLDS
: /* obsolete */
619 feature
= ATA_SMART_READ_THRESHOLDS
;
620 sector_count
= 1; /* one (512 byte) block */
622 protocol
= 4; /* PIO data-in */
623 t_length
= 2; /* sector count holds count */
627 feature
= ATA_SMART_READ_LOG_SECTOR
;
628 sector_count
= 1; /* one (512 byte) block */
630 protocol
= 4; /* PIO data-in */
631 t_length
= 2; /* sector count holds count */
635 feature
= ATA_SMART_WRITE_LOG_SECTOR
;
636 sector_count
= 1; /* one (512 byte) block */
638 protocol
= 5; /* PIO data-out */
639 t_length
= 2; /* sector count holds count */
640 t_dir
= 0; /* to device */
644 ata_command
= ATA_IDENTIFY_DEVICE
;
645 sector_count
= 1; /* one (512 byte) block */
646 protocol
= 4; /* PIO data-in */
647 t_length
= 2; /* sector count holds count */
651 ata_command
= ATA_IDENTIFY_PACKET_DEVICE
;
652 sector_count
= 1; /* one (512 byte) block */
653 protocol
= 4; /* PIO data-in */
654 t_length
= 2; /* sector count (7:0) holds count */
658 feature
= ATA_SMART_ENABLE
;
662 feature
= ATA_SMART_DISABLE
;
666 // this command only says if SMART is working. It could be
667 // replaced with STATUS_CHECK below.
668 feature
= ATA_SMART_STATUS
;
672 feature
= ATA_SMART_AUTO_OFFLINE
;
673 sector_count
= select
; // YET NOTE - THIS IS A NON-DATA COMMAND!!
676 feature
= ATA_SMART_AUTOSAVE
;
677 sector_count
= select
; // YET NOTE - THIS IS A NON-DATA COMMAND!!
679 case IMMEDIATE_OFFLINE
:
680 feature
= ATA_SMART_IMMEDIATE_OFFLINE
;
684 // This command uses HDIO_DRIVE_TASK and has different syntax than
685 // the other commands.
686 feature
= ATA_SMART_STATUS
; /* SMART RETURN STATUS */
690 pout("Unrecognized command %d in usbcypress_device::ata_command_interface()\n"
691 "Please contact " PACKAGE_BUGREPORT
"\n", command
);
695 if (ATA_SMART_CMD
== ata_command
) {
700 cdb
[0] = m_signature
; // bVSCBSignature : vendor-specific command
701 cdb
[1] = 0x24; // bVSCBSubCommand : 0x24 for ATACB
703 if (ata_command
== ATA_IDENTIFY_DEVICE
|| ata_command
== ATA_IDENTIFY_PACKET_DEVICE
)
704 cdb
[2] |= (1<<7); //set IdentifyPacketDevice for these cmds
705 cdb
[3] = 0xff - (1<<0) - (1<<6); //features, sector count, lba low, lba med
706 // lba high, command are valid
707 cdb
[4] = byte_block
; //TransferBlockCount : 512
711 cdb
[7] = sector_count
;
715 cdb
[12] = ata_command
;
717 memset(&io_hdr
, 0, sizeof(io_hdr
));
719 io_hdr
.dxfer_dir
= DXFER_NONE
;
720 io_hdr
.dxfer_len
= 0;
721 } else if (t_dir
) { /* from device */
722 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
723 io_hdr
.dxfer_len
= copydata
;
724 io_hdr
.dxferp
= (unsigned char *)data
;
725 memset(data
, 0, copydata
); /* prefill with zeroes */
726 } else { /* to device */
727 io_hdr
.dxfer_dir
= DXFER_TO_DEVICE
;
728 io_hdr
.dxfer_len
= outlen
;
729 io_hdr
.dxferp
= (unsigned char *)data
;
732 io_hdr
.cmnd_len
= passthru_size
;
733 io_hdr
.sensep
= sense
;
734 io_hdr
.max_sense_len
= sizeof(sense
);
735 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
737 scsi_device
* scsidev
= get_tunnel_dev();
738 if (!scsidev
->scsi_pass_through(&io_hdr
)) {
739 if (con
->reportscsiioctl
> 0)
740 pout("usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
741 "errno=%d [%s]\n", scsidev
->get_errno(), scsidev
->get_errmsg());
742 set_err(scsidev
->get_err());
746 // if there is a sense the command failed or the
747 // device doesn't support usbcypress
748 if (io_hdr
.scsi_status
== SCSI_STATUS_CHECK_CONDITION
&&
749 sg_scsi_normalize_sense(io_hdr
.sensep
, io_hdr
.resp_sense_len
, NULL
)) {
753 unsigned char ardp
[8];
755 /* XXX this is racy if there other scsi command between
756 * the first usbcypress command and this one
758 //pout("If you got strange result, please retry without traffic on the disc\n");
759 /* we use the same command as before, but we set
760 * * the read taskfile bit, for not executing usbcypress command,
761 * * but reading register selected in srb->cmnd[4]
763 cdb
[2] = (1<<0); /* ask read taskfile */
764 memset(sense
, 0, sizeof(sense
));
766 /* transfert 8 bytes */
767 memset(&io_hdr
, 0, sizeof(io_hdr
));
768 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
769 io_hdr
.dxfer_len
= ard_len
;
770 io_hdr
.dxferp
= (unsigned char *)ardp
;
771 memset(ardp
, 0, ard_len
); /* prefill with zeroes */
774 io_hdr
.cmnd_len
= passthru_size
;
775 io_hdr
.sensep
= sense
;
776 io_hdr
.max_sense_len
= sizeof(sense
);
777 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
780 if (!scsidev
->scsi_pass_through(&io_hdr
)) {
781 if (con
->reportscsiioctl
> 0)
782 pout("usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
783 "errno=%d [%s]\n", scsidev
->get_errno(), scsidev
->get_errmsg());
784 set_err(scsidev
->get_err());
787 // if there is a sense the command failed or the
788 // device doesn't support usbcypress
789 if (io_hdr
.scsi_status
== SCSI_STATUS_CHECK_CONDITION
&&
790 sg_scsi_normalize_sense(io_hdr
.sensep
, io_hdr
.resp_sense_len
, NULL
)) {
795 if (con
->reportscsiioctl
> 1) {
796 pout("Values from ATA Return Descriptor are:\n");
797 dStrHex((const char *)ardp
, ard_len
, 1);
800 if (ATA_CHECK_POWER_MODE
== ata_command
)
801 data
[0] = ardp
[2]; /* sector count (0:7) */
802 else if (STATUS_CHECK
== command
) {
803 if ((ardp
[4] == 0x4f) && (ardp
[5] == 0xc2))
804 return 0; /* GOOD smart status */
805 if ((ardp
[4] == 0xf4) && (ardp
[5] == 0x2c))
806 return 1; // smart predicting failure, "bad" status
807 // We haven't gotten output that makes sense so
808 // print out some debugging info
809 syserror("Error SMART Status command failed");
810 pout("This may be due to a race in usbcypress\n");
811 pout("Retry without other disc access\n");
812 pout("Please get assistance from " PACKAGE_HOMEPAGE
"\n");
813 pout("Values from ATA Return Descriptor are:\n");
814 dStrHex((const char *)ardp
, ard_len
, 1);
821 #if 0 // Not used, see autodetect_sat_device() below.
822 static int isprint_string(const char *s
)
825 if (isprint(*s
) == 0)
832 /* Attempt an IDENTIFY DEVICE ATA or IDENTIFY PACKET DEVICE command
833 If successful return 1, else 0 */
834 // TODO: Combine with has_sat_pass_through above
835 static int has_usbcypress_pass_through(ata_device
* atadev
, const char *manufacturer
, const char *product
)
837 struct ata_identify_device drive
;
838 char model
[40], serial
[20], firm
[8];
840 /* issue the command and do a checksum if possible */
841 if (ataReadHDIdentity(atadev
, &drive
) < 0)
844 /* check if model string match, revision doesn't work for me */
845 format_ata_string(model
, drive
.model
, 40);
846 if (*model
== 0 || isprint_string(model
) == 0)
849 if (manufacturer
&& strncmp(manufacturer
, model
, 8))
850 pout("manufacturer doesn't match in pass_through test\n");
852 strlen(model
) > 8 && strncmp(product
, model
+8, strlen(model
)-8))
853 pout("product doesn't match in pass_through test\n");
856 format_ata_string(serial
, drive
.serial_no
, 20);
857 if (isprint_string(serial
) == 0)
859 format_ata_string(firm
, drive
.fw_rev
, 8);
860 if (isprint_string(firm
) == 0)
866 /////////////////////////////////////////////////////////////////////////////
868 /// JMicron USB Bridge support.
870 class usbjmicron_device
871 : public tunnelled_device
<
872 /*implements*/ ata_device
,
873 /*by tunnelling through a*/ scsi_device
877 usbjmicron_device(smart_interface
* intf
, scsi_device
* scsidev
,
878 const char * req_type
, bool ata_48bit_support
, int port
);
880 virtual ~usbjmicron_device() throw();
884 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
887 bool get_registers(unsigned short addr
, unsigned char * buf
, unsigned short size
);
889 bool m_ata_48bit_support
;
894 usbjmicron_device::usbjmicron_device(smart_interface
* intf
, scsi_device
* scsidev
,
895 const char * req_type
, bool ata_48bit_support
, int port
)
896 : smart_device(intf
, scsidev
->get_dev_name(), "usbjmicron", req_type
),
897 tunnelled_device
<ata_device
, scsi_device
>(scsidev
),
898 m_ata_48bit_support(ata_48bit_support
), m_port(port
)
900 set_info().info_name
= strprintf("%s [USB JMicron]", scsidev
->get_info_name());
903 usbjmicron_device::~usbjmicron_device() throw()
908 bool usbjmicron_device::open()
911 if (!tunnelled_device
<ata_device
, scsi_device
>::open())
914 // Detect port if not specified
916 unsigned char regbuf
[1] = {0};
917 if (!get_registers(0x720f, regbuf
, sizeof(regbuf
))) {
922 switch (regbuf
[0] & 0x44) {
929 return set_err(EINVAL
, "Two devices connected, try '-d usbjmicron,[01]'");
932 return set_err(ENODEV
, "No device connected");
940 bool usbjmicron_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
942 if (!ata_cmd_is_ok(in
,
943 true, // data_out_support
944 false, // !multi_sector_support
945 m_ata_48bit_support
) // limited, see below
949 bool is_smart_status
= ( in
.in_regs
.command
== ATA_SMART_CMD
950 && in
.in_regs
.features
== ATA_SMART_STATUS
);
952 // Support output registers for SMART STATUS
953 if (in
.out_needed
.is_set() && !is_smart_status
)
954 return set_err(ENOSYS
, "ATA output registers not supported");
956 // Support 48-bit commands with zero high bytes
957 if (in
.in_regs
.is_real_48bit_cmd())
958 return set_err(ENOSYS
, "48-bit ATA commands not fully supported");
961 return set_err(EIO
, "Unknown JMicron port");
964 memset(&io_hdr
, 0, sizeof(io_hdr
));
967 unsigned char smart_status
= 0;
969 if (is_smart_status
&& in
.out_needed
.is_set()) {
970 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
971 io_hdr
.dxfer_len
= 1;
972 io_hdr
.dxferp
= &smart_status
;
974 else switch (in
.direction
) {
975 case ata_cmd_in::no_data
:
976 io_hdr
.dxfer_dir
= DXFER_NONE
;
978 case ata_cmd_in::data_in
:
979 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
980 io_hdr
.dxfer_len
= in
.size
;
981 io_hdr
.dxferp
= (unsigned char *)in
.buffer
;
982 memset(in
.buffer
, 0, in
.size
);
984 case ata_cmd_in::data_out
:
985 io_hdr
.dxfer_dir
= DXFER_TO_DEVICE
;
986 io_hdr
.dxfer_len
= in
.size
;
987 io_hdr
.dxferp
= (unsigned char *)in
.buffer
;
991 return set_err(EINVAL
);
994 // Build pass through command
995 unsigned char cdb
[12];
997 cdb
[ 1] = (rwbit
? 0x10 : 0x00);
999 cdb
[ 3] = (unsigned char)(io_hdr
.dxfer_len
>> 8);
1000 cdb
[ 4] = (unsigned char)(io_hdr
.dxfer_len
);
1001 cdb
[ 5] = in
.in_regs
.features
;
1002 cdb
[ 6] = in
.in_regs
.sector_count
;
1003 cdb
[ 7] = in
.in_regs
.lba_low
;
1004 cdb
[ 8] = in
.in_regs
.lba_mid
;
1005 cdb
[ 9] = in
.in_regs
.lba_high
;
1006 cdb
[10] = in
.in_regs
.device
| (m_port
== 0 ? 0xa0 : 0xb0);
1007 cdb
[11] = in
.in_regs
.command
;
1010 io_hdr
.cmnd_len
= sizeof(cdb
);
1012 scsi_device
* scsidev
= get_tunnel_dev();
1013 if (!scsi_pass_through_and_check(scsidev
, &io_hdr
,
1014 "usbjmicron_device::ata_pass_through: "))
1015 return set_err(scsidev
->get_err());
1017 if (in
.out_needed
.is_set()) {
1018 if (is_smart_status
) {
1019 switch (smart_status
) {
1020 case 0x01: case 0xc2:
1021 out
.out_regs
.lba_high
= 0xc2;
1022 out
.out_regs
.lba_mid
= 0x4f;
1024 case 0x00: case 0x2c:
1025 out
.out_regs
.lba_high
= 0x2c;
1026 out
.out_regs
.lba_mid
= 0xf4;
1031 #if 0 // Not needed for SMART STATUS, see also notes below
1033 // Read ATA output registers
1034 // NOTE: The register addresses are not valid for some older chip revisions
1035 // NOTE: There is a small race condition here!
1036 unsigned char regbuf
[16] = {0, };
1037 if (!get_registers((m_port
== 0 ? 0x8000 : 0x9000), regbuf
, sizeof(regbuf
)))
1040 out
.out_regs
.sector_count
= regbuf
[ 0];
1041 out
.out_regs
.lba_mid
= regbuf
[ 4];
1042 out
.out_regs
.lba_low
= regbuf
[ 6];
1043 out
.out_regs
.device
= regbuf
[ 9];
1044 out
.out_regs
.lba_high
= regbuf
[10];
1045 out
.out_regs
.error
= regbuf
[13];
1046 out
.out_regs
.status
= regbuf
[14];
1054 bool usbjmicron_device::get_registers(unsigned short addr
,
1055 unsigned char * buf
, unsigned short size
)
1057 unsigned char cdb
[12];
1061 cdb
[ 3] = (unsigned char)(size
>> 8);
1062 cdb
[ 4] = (unsigned char)(size
);
1064 cdb
[ 6] = (unsigned char)(addr
>> 8);
1065 cdb
[ 7] = (unsigned char)(addr
);
1071 scsi_cmnd_io io_hdr
;
1072 memset(&io_hdr
, 0, sizeof(io_hdr
));
1073 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
1074 io_hdr
.dxfer_len
= size
;
1075 io_hdr
.dxferp
= buf
;
1077 io_hdr
.cmnd_len
= sizeof(cdb
);
1079 scsi_device
* scsidev
= get_tunnel_dev();
1080 if (!scsi_pass_through_and_check(scsidev
, &io_hdr
,
1081 "usbjmicron_device::get_registers: "))
1082 return set_err(scsidev
->get_err());
1088 /////////////////////////////////////////////////////////////////////////////
1090 /// SunplusIT USB Bridge support.
1092 class usbsunplus_device
1093 : public tunnelled_device
<
1094 /*implements*/ ata_device
,
1095 /*by tunnelling through a*/ scsi_device
1099 usbsunplus_device(smart_interface
* intf
, scsi_device
* scsidev
,
1100 const char * req_type
);
1102 virtual ~usbsunplus_device() throw();
1104 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
1108 usbsunplus_device::usbsunplus_device(smart_interface
* intf
, scsi_device
* scsidev
,
1109 const char * req_type
)
1110 : smart_device(intf
, scsidev
->get_dev_name(), "usbsunplus", req_type
),
1111 tunnelled_device
<ata_device
, scsi_device
>(scsidev
)
1113 set_info().info_name
= strprintf("%s [USB Sunplus]", scsidev
->get_info_name());
1116 usbsunplus_device::~usbsunplus_device() throw()
1120 bool usbsunplus_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
1122 if (!ata_cmd_is_ok(in
,
1123 true, // data_out_support
1124 false, // !multi_sector_support
1125 true) // ata_48bit_support
1129 scsi_cmnd_io io_hdr
;
1130 unsigned char cdb
[12];
1132 if (in
.in_regs
.is_48bit_cmd()) {
1133 // Set "previous" registers
1134 memset(&io_hdr
, 0, sizeof(io_hdr
));
1135 io_hdr
.dxfer_dir
= DXFER_NONE
;
1139 cdb
[ 2] = 0x23; // Subcommand: Pass through presetting
1142 cdb
[ 5] = in
.in_regs
.prev
.features
;
1143 cdb
[ 6] = in
.in_regs
.prev
.sector_count
;
1144 cdb
[ 7] = in
.in_regs
.prev
.lba_low
;
1145 cdb
[ 8] = in
.in_regs
.prev
.lba_mid
;
1146 cdb
[ 9] = in
.in_regs
.prev
.lba_high
;
1151 io_hdr
.cmnd_len
= sizeof(cdb
);
1153 scsi_device
* scsidev
= get_tunnel_dev();
1154 if (!scsi_pass_through_and_check(scsidev
, &io_hdr
,
1155 "usbsunplus_device::scsi_pass_through (presetting): "))
1156 return set_err(scsidev
->get_err());
1159 // Run Pass through command
1160 memset(&io_hdr
, 0, sizeof(io_hdr
));
1161 unsigned char protocol
;
1162 switch (in
.direction
) {
1163 case ata_cmd_in::no_data
:
1164 io_hdr
.dxfer_dir
= DXFER_NONE
;
1167 case ata_cmd_in::data_in
:
1168 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
1169 io_hdr
.dxfer_len
= in
.size
;
1170 io_hdr
.dxferp
= (unsigned char *)in
.buffer
;
1171 memset(in
.buffer
, 0, in
.size
);
1174 case ata_cmd_in::data_out
:
1175 io_hdr
.dxfer_dir
= DXFER_TO_DEVICE
;
1176 io_hdr
.dxfer_len
= in
.size
;
1177 io_hdr
.dxferp
= (unsigned char *)in
.buffer
;
1181 return set_err(EINVAL
);
1186 cdb
[ 2] = 0x22; // Subcommand: Pass through
1188 cdb
[ 4] = (unsigned char)(io_hdr
.dxfer_len
>> 9);
1189 cdb
[ 5] = in
.in_regs
.features
;
1190 cdb
[ 6] = in
.in_regs
.sector_count
;
1191 cdb
[ 7] = in
.in_regs
.lba_low
;
1192 cdb
[ 8] = in
.in_regs
.lba_mid
;
1193 cdb
[ 9] = in
.in_regs
.lba_high
;
1194 cdb
[10] = in
.in_regs
.device
| 0xa0;
1195 cdb
[11] = in
.in_regs
.command
;
1198 io_hdr
.cmnd_len
= sizeof(cdb
);
1200 scsi_device
* scsidev
= get_tunnel_dev();
1201 if (!scsi_pass_through_and_check(scsidev
, &io_hdr
,
1202 "usbsunplus_device::scsi_pass_through: "))
1203 // Returns sense key 0x03 (medium error) on ATA command error
1204 return set_err(scsidev
->get_err());
1206 if (in
.out_needed
.is_set()) {
1207 // Read ATA output registers
1208 unsigned char regbuf
[8] = {0, };
1209 memset(&io_hdr
, 0, sizeof(io_hdr
));
1210 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
1211 io_hdr
.dxfer_len
= sizeof(regbuf
);
1212 io_hdr
.dxferp
= regbuf
;
1216 cdb
[ 2] = 0x21; // Subcommand: Get status
1217 memset(cdb
+3, 0, sizeof(cdb
)-3);
1219 io_hdr
.cmnd_len
= sizeof(cdb
);
1221 if (!scsi_pass_through_and_check(scsidev
, &io_hdr
,
1222 "usbsunplus_device::scsi_pass_through (get registers): "))
1223 return set_err(scsidev
->get_err());
1225 out
.out_regs
.error
= regbuf
[1];
1226 out
.out_regs
.sector_count
= regbuf
[2];
1227 out
.out_regs
.lba_low
= regbuf
[3];
1228 out
.out_regs
.lba_mid
= regbuf
[4];
1229 out
.out_regs
.lba_high
= regbuf
[5];
1230 out
.out_regs
.device
= regbuf
[6];
1231 out
.out_regs
.status
= regbuf
[7];
1240 using namespace sat
;
1243 /////////////////////////////////////////////////////////////////////////////
1245 // Return ATA->SCSI filter for SAT or USB.
1247 ata_device
* smart_interface::get_sat_device(const char * type
, scsi_device
* scsidev
)
1249 if (!strncmp(type
, "sat", 3)) {
1250 int ptlen
= 0, n1
= -1, n2
= -1;
1251 if (!(((sscanf(type
, "sat%n,%d%n", &n1
, &ptlen
, &n2
) == 1 && n2
== (int)strlen(type
)) || n1
== (int)strlen(type
))
1252 && (ptlen
== 0 || ptlen
== 12 || ptlen
== 16))) {
1253 set_err(EINVAL
, "Option '-d sat,<n>' requires <n> to be 0, 12 or 16");
1256 return new sat_device(this, scsidev
, type
, ptlen
);
1259 else if (!strncmp(type
, "usbcypress", 10)) {
1260 unsigned signature
= 0x24; int n1
= -1, n2
= -1;
1261 if (!(((sscanf(type
, "usbcypress%n,0x%x%n", &n1
, &signature
, &n2
) == 1 && n2
== (int)strlen(type
)) || n1
== (int)strlen(type
))
1262 && signature
<= 0xff)) {
1263 set_err(EINVAL
, "Option '-d usbcypress,<n>' requires <n> to be "
1264 "an hexadecimal number between 0x0 and 0xff");
1267 return new usbcypress_device(this, scsidev
, type
, signature
);
1270 else if (!strncmp(type
, "usbjmicron", 10)) {
1271 const char * t
= type
+ 10;
1272 bool ata_48bit_support
= false;
1273 if (!strncmp(t
, ",x", 2)) {
1275 ata_48bit_support
= true;
1277 int port
= -1, n
= -1;
1278 if (*t
&& !( (sscanf(t
, ",%d%n", &port
, &n
) == 1
1279 && n
== (int)strlen(t
) && 0 <= port
&& port
<= 1))) {
1280 set_err(EINVAL
, "Option '-d usbmicron[,x],<n>' requires <n> to be 0 or 1");
1283 return new usbjmicron_device(this, scsidev
, type
, ata_48bit_support
, port
);
1286 else if (!strcmp(type
, "usbsunplus")) {
1287 return new usbsunplus_device(this, scsidev
, type
);
1291 set_err(EINVAL
, "Unknown USB device type '%s'", type
);
1296 // Try to detect a SAT device behind a SCSI interface.
1298 ata_device
* smart_interface::autodetect_sat_device(scsi_device
* scsidev
,
1299 const unsigned char * inqdata
, unsigned inqsize
)
1301 if (!scsidev
->is_open())
1304 ata_device
* atadev
= 0;
1307 if (inqdata
&& inqsize
>= 36 && !memcmp(inqdata
+ 8, "ATA ", 8)) { // TODO: Linux-specific?
1308 atadev
= new sat_device(this, scsidev
, "");
1309 if (has_sat_pass_through(atadev
))
1310 return atadev
; // Detected SAT
1311 atadev
->release(scsidev
);
1315 /* The new usbcypress_device(this, scsidev, "", 0x24) sends vendor specific comand to non-cypress devices.
1316 * It's dangerous as other device may interpret such command as own valid vendor specific command.
1317 * I commented it out untill problem resolved
1322 atadev
= new usbcypress_device(this, scsidev
, "", 0x24);
1323 if (has_usbcypress_pass_through(atadev
,
1324 (inqdata
&& inqsize
>= 36 ? (const char*)inqdata
+ 8 : 0),
1325 (inqdata
&& inqsize
>= 36 ? (const char*)inqdata
+ 16 : 0) ))
1326 return atadev
; // Detected USB
1327 atadev
->release(scsidev
);
1334 atadev
->release(scsidev
);
1344 /////////////////////////////////////////////////////////////////////////////
1345 // USB device type detection
1347 struct usb_id_entry
{
1348 int vendor_id
, product_id
, version
;
1352 const char d_sat
[] = "sat";
1353 const char d_cypress
[] = "usbcypress";
1354 const char d_jmicron
[] = "usbjmicron";
1355 const char d_jmicron_x
[] = "usbjmicron,x";
1356 const char d_sunplus
[] = "usbsunplus";
1357 const char d_unsup
[] = "unsupported";
1359 // Map USB IDs -> '-d type' string
1360 const usb_id_entry usb_ids
[] = {
1361 { 0x04b4, 0x6830, 0x0001, d_unsup
}, // Cypress CY7C68300A (AT2)
1362 { 0x04b4, 0x6830, 0x0240, d_cypress
}, // Cypress CY7C68300B/C (AT2LP)
1363 //{ 0x04b4, 0x6831, -1, d_cypress }, // Cypress CY7C68310 (ISD-300LP)
1364 { 0x04fc, 0x0c15, 0xf615, d_sunplus
}, // SunPlus SPDIF215
1365 { 0x04fc, 0x0c25, 0x0103, d_sunplus
}, // SunPlus SPDIF225 (USB+SATA->SATA)
1366 { 0x059b, 0x0275, 0x0001, d_unsup
}, // Iomega MDHD500-U
1367 { 0x059f, 0x0651, -1, d_unsup
}, // LaCie hard disk (FA Porsche design)
1368 { 0x059f, 0x1018, -1, d_sat
}, // LaCie hard disk (Neil Poulton design)
1369 { 0x067b, 0x3507, 0x0001, d_unsup
}, // Prolific PL3507
1370 { 0x0930, 0x0b09, -1, d_sunplus
}, // Toshiba PX1396E-3T01 (similar to Dura Micro)
1371 { 0x0bc2, 0x2000, -1, d_sat
}, // Seagate FreeAgent Go
1372 { 0x0bc2, 0x2100, -1, d_sat
}, // Seagate FreeAgent Go
1373 { 0x0bc2, 0x3001, -1, d_sat
}, // Seagate FreeAgent Desk
1374 { 0x0c0b, 0xb159, 0x0103, d_sunplus
}, // Dura Micro (Sunplus USB-bridge)
1375 { 0x0d49, 0x7310, 0x0125, d_sat
}, // Maxtor OneTouch 4
1376 { 0x0d49, 0x7350, 0x0125, d_sat
}, // Maxtor OneTouch 4 Mini
1377 { 0x0d49, 0x7450, 0x0122, d_sat
}, // Maxtor Basics Portable
1378 { 0x1058, 0x0704, 0x0175, d_sat
}, // WD My Passport Essential
1379 { 0x1058, 0x0705, 0x0175, d_sat
}, // WD My Passport Elite
1380 { 0x1058, 0x0906, 0x0012, d_sat
}, // WD My Book ES
1381 { 0x1058, 0x1001, 0x0104, d_sat
}, // WD Elements Desktop
1382 { 0x1058, 0x1003, 0x0175, d_sat
}, // WD Elements Desktop WDE1UBK...
1383 { 0x1058, 0x1010, 0x0105, d_sat
}, // WD Elements
1384 { 0x1058, 0x1100, 0x0165, d_sat
}, // WD My Book Essential
1385 { 0x1058, 0x1102, 0x1028, d_sat
}, // WD My Book
1386 { 0x13fd, 0x1240, 0x0104, d_sat
}, // Initio ? (USB->SATA)
1387 { 0x13fd, 0x1340, 0x0208, d_sat
}, // Initio ? (USB+SATA->SATA)
1388 { 0x152d, 0x2329, 0x0100, d_jmicron
}, // JMicron JM20329 (USB->SATA)
1389 { 0x152d, 0x2336, 0x0100, d_jmicron_x
},// JMicron JM20336 (USB+SATA->SATA, USB->2xSATA)
1390 { 0x152d, 0x2338, 0x0100, d_jmicron
}, // JMicron JM20337/8 (USB->SATA+PATA, USB+SATA->PATA)
1391 { 0x152d, 0x2339, 0x0100, d_jmicron_x
},// JMicron JM20339 (USB->SATA)
1392 { 0x18a5, 0x0215, 0x0001, d_sat
}, // Verbatim FW/USB160 - Oxford OXUF934SSA-LQAG (USB+IEE1394->SATA)
1393 { 0x1bcf, 0x0c31, -1, d_sunplus
} // SunplusIT
1396 const unsigned num_usb_ids
= sizeof(usb_ids
)/sizeof(usb_ids
[0]);
1399 // Format USB ID for error messages
1400 static std::string
format_usb_id(int vendor_id
, int product_id
, int version
)
1403 return strprintf("[0x%04x:0x%04x (0x%03x)]", vendor_id
, product_id
, version
);
1405 return strprintf("[0x%04x:0x%04x]", vendor_id
, product_id
);
1408 // Get type name for USB device with known VENDOR:PRODUCT ID.
1409 const char * smart_interface::get_usb_dev_type_by_id(int vendor_id
, int product_id
,
1410 int version
/*= -1*/)
1412 const usb_id_entry
* entry
= 0;
1415 for (unsigned i
= 0; i
< num_usb_ids
; i
++) {
1416 const usb_id_entry
& e
= usb_ids
[i
];
1417 if (!(vendor_id
== e
.vendor_id
&& product_id
== e
.product_id
))
1420 // If two entries with same vendor:product ID have different
1421 // types, use version (if provided by OS) to select entry.
1422 bool s
= (version
>= 0 && version
== e
.version
);
1425 if (s
== state
&& e
.type
!= entry
->type
) {
1426 set_err(EINVAL
, "USB bridge %s type is ambiguous: '%s' or '%s'",
1427 format_usb_id(vendor_id
, product_id
, version
).c_str(),
1428 e
.type
, entry
->type
);
1439 set_err(EINVAL
, "Unknown USB bridge %s",
1440 format_usb_id(vendor_id
, product_id
, version
).c_str());
1443 if (entry
->type
== d_unsup
) {
1444 set_err(ENOSYS
, "Unsupported USB bridge %s",
1445 format_usb_id(vendor_id
, product_id
, version
).c_str());