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).
58 #include "atacmds.h" // ataReadHDIdentity()
60 #include "dev_interface.h"
61 #include "dev_ata_cmd_set.h" // ata_device_with_command_set
62 #include "dev_tunnelled.h" // tunnelled_device<>
64 const char * scsiata_cpp_cvsid
= "$Id: scsiata.cpp 2923 2009-09-24 20:10:38Z chrfranke $";
66 /* for passing global control variables */
67 extern smartmonctrl
*con
;
69 /* This is a slightly stretched SCSI sense "descriptor" format header.
70 The addition is to allow the 0x70 and 0x71 response codes. The idea
71 is to place the salient data of both "fixed" and "descriptor" sense
72 format into one structure to ease application processing.
73 The original sense buffer should be kept around for those cases
74 in which more information is required (e.g. the LBA of a MEDIUM ERROR). */
75 /// Abridged SCSI sense data
76 struct sg_scsi_sense_hdr
{
77 unsigned char response_code
; /* permit: 0x0, 0x70, 0x71, 0x72, 0x73 */
78 unsigned char sense_key
;
84 unsigned char additional_length
;
87 /* Maps the salient data from a sense buffer which is in either fixed or
88 descriptor format into a structure mimicking a descriptor format
89 header (i.e. the first 8 bytes of sense descriptor format).
90 If zero response code returns 0. Otherwise returns 1 and if 'sshp' is
91 non-NULL then zero all fields and then set the appropriate fields in
92 that structure. sshp::additional_length is always 0 for response
93 codes 0x70 and 0x71 (fixed format). */
94 static int sg_scsi_normalize_sense(const unsigned char * sensep
, int sb_len
,
95 struct sg_scsi_sense_hdr
* sshp
);
97 /* Attempt to find the first SCSI sense data descriptor that matches the
98 given 'desc_type'. If found return pointer to start of sense data
99 descriptor; otherwise (including fixed format sense data) returns NULL. */
100 static const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep
,
101 int sense_len
, int desc_type
);
103 #define SAT_ATA_PASSTHROUGH_12LEN 12
104 #define SAT_ATA_PASSTHROUGH_16LEN 16
106 #define DEF_SAT_ATA_PASSTHRU_SIZE 16
107 #define ATA_RETURN_DESCRIPTOR 9
110 namespace sat
{ // no need to publish anything, name provided for Doxygen
113 /// Implements ATA by tunnelling through SCSI.
116 : public tunnelled_device
<
117 /*implements*/ ata_device
118 /*by tunnelling through a*/, scsi_device
122 sat_device(smart_interface
* intf
, scsi_device
* scsidev
,
123 const char * req_type
, int passthrulen
= 0);
125 virtual ~sat_device() throw();
127 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
134 sat_device::sat_device(smart_interface
* intf
, scsi_device
* scsidev
,
135 const char * req_type
, int passthrulen
/*= 0*/)
136 : smart_device(intf
, scsidev
->get_dev_name(), "sat", req_type
),
137 tunnelled_device
<ata_device
, scsi_device
>(scsidev
),
138 m_passthrulen(passthrulen
)
140 set_info().info_name
= strprintf("%s [SAT]", scsidev
->get_info_name());
143 sat_device::~sat_device() throw()
148 // cdb[0]: ATA PASS THROUGH (16) SCSI command opcode byte (0x85)
149 // cdb[1]: multiple_count, protocol + extend
150 // cdb[2]: offline, ck_cond, t_dir, byte_block + t_length
151 // cdb[3]: features (15:8)
152 // cdb[4]: features (7:0)
153 // cdb[5]: sector_count (15:8)
154 // cdb[6]: sector_count (7:0)
155 // cdb[7]: lba_low (15:8)
156 // cdb[8]: lba_low (7:0)
157 // cdb[9]: lba_mid (15:8)
158 // cdb[10]: lba_mid (7:0)
159 // cdb[11]: lba_high (15:8)
160 // cdb[12]: lba_high (7:0)
162 // cdb[14]: (ata) command
163 // cdb[15]: control (SCSI, leave as zero)
165 // 24 bit lba (from MSB): cdb[12] cdb[10] cdb[8]
166 // 48 bit lba (from MSB): cdb[11] cdb[9] cdb[7] cdb[12] cdb[10] cdb[8]
169 // cdb[0]: ATA PASS THROUGH (12) SCSI command opcode byte (0xa1)
170 // cdb[1]: multiple_count, protocol + extend
171 // cdb[2]: offline, ck_cond, t_dir, byte_block + t_length
172 // cdb[3]: features (7:0)
173 // cdb[4]: sector_count (7:0)
174 // cdb[5]: lba_low (7:0)
175 // cdb[6]: lba_mid (7:0)
176 // cdb[7]: lba_high (7:0)
178 // cdb[9]: (ata) command
180 // cdb[11]: control (SCSI, leave as zero)
183 // ATA Return Descriptor (component of descriptor sense data)
184 // des[0]: descriptor code (0x9)
185 // des[1]: additional descriptor length (0xc)
186 // des[2]: extend (bit 0)
188 // des[4]: sector_count (15:8)
189 // des[5]: sector_count (7:0)
190 // des[6]: lba_low (15:8)
191 // des[7]: lba_low (7:0)
192 // des[8]: lba_mid (15:8)
193 // des[9]: lba_mid (7:0)
194 // des[10]: lba_high (15:8)
195 // des[11]: lba_high (7:0)
202 // This interface routine takes ATA SMART commands and packages
203 // them in the SAT-defined ATA PASS THROUGH SCSI commands. There are
204 // two available SCSI commands: a 12 byte and 16 byte variant; the
205 // one used is chosen via this->m_passthrulen .
206 // DETAILED DESCRIPTION OF ARGUMENTS
207 // device: is the file descriptor provided by (a SCSI dvice type) open()
208 // command: defines the different ATA operations.
209 // select: additional input data if needed (which log, which type of
211 // data: location to write output data, if needed (512 bytes).
212 // Note: not all commands use all arguments.
214 // -1 if the command failed
215 // 0 if the command succeeded,
216 // STATUS_CHECK routine:
217 // -1 if the command failed
218 // 0 if the command succeeded and disk SMART status is "OK"
219 // 1 if the command succeeded and disk SMART status is "FAILING"
221 bool sat_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
223 if (!ata_cmd_is_ok(in
,
224 true, // data_out_support
225 true, // multi_sector_support
226 true) // ata_48bit_support
230 struct scsi_cmnd_io io_hdr
;
231 struct scsi_sense_disect sinfo
;
232 struct sg_scsi_sense_hdr ssh
;
233 unsigned char cdb
[SAT_ATA_PASSTHROUGH_16LEN
];
234 unsigned char sense
[32];
235 const unsigned char * ardp
;
236 int status
, ard_len
, have_sense
;
238 int ck_cond
= 0; /* set to 1 to read register(s) back */
239 int protocol
= 3; /* non-data */
240 int t_dir
= 1; /* 0 -> to device, 1 -> from device */
241 int byte_block
= 1; /* 0 -> bytes, 1 -> 512 byte blocks */
242 int t_length
= 0; /* 0 -> no data transferred */
243 int passthru_size
= DEF_SAT_ATA_PASSTHRU_SIZE
;
245 memset(cdb
, 0, sizeof(cdb
));
246 memset(sense
, 0, sizeof(sense
));
248 // Set data direction
249 // TODO: This works only for commands where sector_count holds count!
250 switch (in
.direction
) {
251 case ata_cmd_in::no_data
:
253 case ata_cmd_in::data_in
:
254 protocol
= 4; // PIO data-in
255 t_length
= 2; // sector_count holds count
257 case ata_cmd_in::data_out
:
258 protocol
= 5; // PIO data-out
259 t_length
= 2; // sector_count holds count
260 t_dir
= 0; // to device
263 return set_err(EINVAL
, "sat_device::ata_pass_through: invalid direction=%d",
267 // Check condition if any output register needed
268 if (in
.out_needed
.is_set())
271 if ((SAT_ATA_PASSTHROUGH_12LEN
== m_passthrulen
) ||
272 (SAT_ATA_PASSTHROUGH_16LEN
== m_passthrulen
))
273 passthru_size
= m_passthrulen
;
275 // Set extend bit on 48-bit ATA command
276 if (in
.in_regs
.is_48bit_cmd()) {
277 if (passthru_size
!= SAT_ATA_PASSTHROUGH_16LEN
)
278 return set_err(ENOSYS
, "48-bit ATA commands require SAT ATA PASS-THROUGH (16)");
282 cdb
[0] = (SAT_ATA_PASSTHROUGH_12LEN
== passthru_size
) ?
283 SAT_ATA_PASSTHROUGH_12
: SAT_ATA_PASSTHROUGH_16
;
285 cdb
[1] = (protocol
<< 1) | extend
;
286 cdb
[2] = (ck_cond
<< 5) | (t_dir
<< 3) |
287 (byte_block
<< 2) | t_length
;
289 if (passthru_size
== SAT_ATA_PASSTHROUGH_12LEN
) {
290 // ATA PASS-THROUGH (12)
291 const ata_in_regs
& lo
= in
.in_regs
;
292 cdb
[3] = lo
.features
;
293 cdb
[4] = lo
.sector_count
;
296 cdb
[7] = lo
.lba_high
;
301 // ATA PASS-THROUGH (16)
302 const ata_in_regs
& lo
= in
.in_regs
;
303 const ata_in_regs
& hi
= in
.in_regs
.prev
;
304 // Note: all 'in.in_regs.prev.*' are always zero for 28-bit commands
305 cdb
[ 3] = hi
.features
;
306 cdb
[ 4] = lo
.features
;
307 cdb
[ 5] = hi
.sector_count
;
308 cdb
[ 6] = lo
.sector_count
;
309 cdb
[ 7] = hi
.lba_low
;
310 cdb
[ 8] = lo
.lba_low
;
311 cdb
[ 9] = hi
.lba_mid
;
312 cdb
[10] = lo
.lba_mid
;
313 cdb
[11] = hi
.lba_high
;
314 cdb
[12] = lo
.lba_high
;
316 cdb
[14] = lo
.command
;
319 memset(&io_hdr
, 0, sizeof(io_hdr
));
321 io_hdr
.dxfer_dir
= DXFER_NONE
;
322 io_hdr
.dxfer_len
= 0;
323 } else if (t_dir
) { /* from device */
324 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
325 io_hdr
.dxfer_len
= in
.size
;
326 io_hdr
.dxferp
= (unsigned char *)in
.buffer
;
327 memset(in
.buffer
, 0, in
.size
); // prefill with zeroes
328 } else { /* to device */
329 io_hdr
.dxfer_dir
= DXFER_TO_DEVICE
;
330 io_hdr
.dxfer_len
= in
.size
;
331 io_hdr
.dxferp
= (unsigned char *)in
.buffer
;
334 io_hdr
.cmnd_len
= passthru_size
;
335 io_hdr
.sensep
= sense
;
336 io_hdr
.max_sense_len
= sizeof(sense
);
337 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
339 scsi_device
* scsidev
= get_tunnel_dev();
340 if (!scsidev
->scsi_pass_through(&io_hdr
)) {
341 if (con
->reportscsiioctl
> 0)
342 pout("sat_device::ata_pass_through: scsi_pass_through() failed, "
343 "errno=%d [%s]\n", scsidev
->get_errno(), scsidev
->get_errmsg());
344 return set_err(scsidev
->get_err());
348 have_sense
= sg_scsi_normalize_sense(io_hdr
.sensep
, io_hdr
.resp_sense_len
,
351 /* look for SAT ATA Return Descriptor */
352 ardp
= sg_scsi_sense_desc_find(io_hdr
.sensep
,
353 io_hdr
.resp_sense_len
,
354 ATA_RETURN_DESCRIPTOR
);
356 ard_len
= ardp
[1] + 2;
359 else if (ard_len
> 14)
362 scsi_do_sense_disect(&io_hdr
, &sinfo
);
363 status
= scsiSimpleSenseFilter(&sinfo
);
365 if (con
->reportscsiioctl
> 0) {
366 pout("sat_device::ata_pass_through: scsi error: %s\n",
367 scsiErrString(status
));
368 if (ardp
&& (con
->reportscsiioctl
> 1)) {
369 pout("Values from ATA Return Descriptor are:\n");
370 dStrHex((const char *)ardp
, ard_len
, 1);
373 if (t_dir
&& (t_length
> 0) && (in
.direction
== ata_cmd_in::data_in
))
374 memset(in
.buffer
, 0, in
.size
);
375 return set_err(EIO
, "scsi error %s", scsiErrString(status
));
378 if (ck_cond
) { /* expecting SAT specific sense data */
381 if (con
->reportscsiioctl
> 1) {
382 pout("Values from ATA Return Descriptor are:\n");
383 dStrHex((const char *)ardp
, ard_len
, 1);
385 // Set output registers
386 ata_out_regs
& lo
= out
.out_regs
;
388 lo
.sector_count
= ardp
[ 5];
389 lo
.lba_low
= ardp
[ 7];
390 lo
.lba_mid
= ardp
[ 9];
391 lo
.lba_high
= ardp
[11];
392 lo
.device
= ardp
[12];
393 lo
.status
= ardp
[13];
394 if (in
.in_regs
.is_48bit_cmd()) {
395 ata_out_regs
& hi
= out
.out_regs
.prev
;
396 hi
.sector_count
= ardp
[ 4];
397 hi
.lba_low
= ardp
[ 6];
398 hi
.lba_mid
= ardp
[ 8];
399 hi
.lba_high
= ardp
[10];
404 ck_cond
= 0; /* not the type of sense data expected */
408 if ((ssh
.response_code
>= 0x72) &&
409 ((SCSI_SK_NO_SENSE
== ssh
.sense_key
) ||
410 (SCSI_SK_RECOVERED_ERR
== ssh
.sense_key
)) &&
412 (SCSI_ASCQ_ATA_PASS_THROUGH
== ssh
.ascq
)) {
414 if (con
->reportscsiioctl
> 0) {
415 pout("Values from ATA Return Descriptor are:\n");
416 dStrHex((const char *)ardp
, ard_len
, 1);
418 return set_err(EIO
, "SAT command failed");
428 /////////////////////////////////////////////////////////////////////////////
430 /* Attempt an IDENTIFY DEVICE ATA command via SATL when packet_interface
431 is false otherwise attempt IDENTIFY PACKET DEVICE. If successful
432 return true, else false */
434 static bool has_sat_pass_through(ata_device
* dev
, bool packet_interface
= false)
436 /* Note: malloc() ensures the read buffer lands on a single
437 page. This avoids some bugs seen on LSI controlers under
439 char *data
= (char *)malloc(512);
441 in
.in_regs
.command
= (packet_interface
? ATA_IDENTIFY_PACKET_DEVICE
: ATA_IDENTIFY_DEVICE
);
442 in
.set_data_in(data
, 1);
443 bool ret
= dev
->ata_pass_through(in
);
448 /////////////////////////////////////////////////////////////////////////////
450 /* Next two functions are borrowed from sg_lib.c in the sg3_utils
451 package. Same copyrght owner, same license as this file. */
452 static int sg_scsi_normalize_sense(const unsigned char * sensep
, int sb_len
,
453 struct sg_scsi_sense_hdr
* sshp
)
456 memset(sshp
, 0, sizeof(struct sg_scsi_sense_hdr
));
457 if ((NULL
== sensep
) || (0 == sb_len
) || (0x70 != (0x70 & sensep
[0])))
460 sshp
->response_code
= (0x7f & sensep
[0]);
461 if (sshp
->response_code
>= 0x72) { /* descriptor format */
463 sshp
->sense_key
= (0xf & sensep
[1]);
465 sshp
->asc
= sensep
[2];
467 sshp
->ascq
= sensep
[3];
469 sshp
->additional_length
= sensep
[7];
470 } else { /* fixed format */
472 sshp
->sense_key
= (0xf & sensep
[2]);
474 sb_len
= (sb_len
< (sensep
[7] + 8)) ? sb_len
:
477 sshp
->asc
= sensep
[12];
479 sshp
->ascq
= sensep
[13];
487 static const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep
,
488 int sense_len
, int desc_type
)
490 int add_sen_len
, add_len
, desc_len
, k
;
491 const unsigned char * descp
;
493 if ((sense_len
< 8) || (0 == (add_sen_len
= sensep
[7])))
495 if ((sensep
[0] < 0x72) || (sensep
[0] > 0x73))
497 add_sen_len
= (add_sen_len
< (sense_len
- 8)) ?
498 add_sen_len
: (sense_len
- 8);
500 for (desc_len
= 0, k
= 0; k
< add_sen_len
; k
+= desc_len
) {
502 add_len
= (k
< (add_sen_len
- 1)) ? descp
[1]: -1;
503 desc_len
= add_len
+ 2;
504 if (descp
[0] == desc_type
)
506 if (add_len
< 0) /* short descriptor ?? */
513 // Call scsi_pass_through and check sense.
514 // TODO: Provide as member function of class scsi_device (?)
515 static bool scsi_pass_through_and_check(scsi_device
* scsidev
, scsi_cmnd_io
* iop
,
516 const char * msg
= "")
518 // Provide sense buffer
519 unsigned char sense
[32] = {0, };
521 iop
->max_sense_len
= sizeof(sense
);
522 iop
->timeout
= SCSI_TIMEOUT_DEFAULT
;
525 if (!scsidev
->scsi_pass_through(iop
)) {
526 if (con
->reportscsiioctl
> 0)
527 pout("%sscsi_pass_through() failed, errno=%d [%s]\n",
528 msg
, scsidev
->get_errno(), scsidev
->get_errmsg());
533 scsi_sense_disect sinfo
;
534 scsi_do_sense_disect(iop
, &sinfo
);
535 int err
= scsiSimpleSenseFilter(&sinfo
);
537 if (con
->reportscsiioctl
> 0)
538 pout("%sscsi error: %s\n", msg
, scsiErrString(err
));
539 return scsidev
->set_err(EIO
, "scsi error %s", scsiErrString(err
));
546 /////////////////////////////////////////////////////////////////////////////
550 /// Cypress USB Brigde support.
552 class usbcypress_device
553 : public tunnelled_device
<
554 /*implements*/ ata_device_with_command_set
555 /*by tunnelling through a*/, scsi_device
559 usbcypress_device(smart_interface
* intf
, scsi_device
* scsidev
,
560 const char * req_type
, unsigned char signature
);
562 virtual ~usbcypress_device() throw();
565 virtual int ata_command_interface(smart_command_set command
, int select
, char * data
);
567 unsigned char m_signature
;
571 usbcypress_device::usbcypress_device(smart_interface
* intf
, scsi_device
* scsidev
,
572 const char * req_type
, unsigned char signature
)
573 : smart_device(intf
, scsidev
->get_dev_name(), "sat", req_type
),
574 tunnelled_device
<ata_device_with_command_set
, scsi_device
>(scsidev
),
575 m_signature(signature
)
577 set_info().info_name
= strprintf("%s [USB Cypress]", scsidev
->get_info_name());
580 usbcypress_device::~usbcypress_device() throw()
585 /* see cy7c68300c_8.pdf for more information */
586 #define USBCYPRESS_PASSTHROUGH_LEN 16
587 int usbcypress_device::ata_command_interface(smart_command_set command
, int select
, char *data
)
589 struct scsi_cmnd_io io_hdr
;
590 unsigned char cdb
[USBCYPRESS_PASSTHROUGH_LEN
];
591 unsigned char sense
[32];
594 int ck_cond
= 0; /* set to 1 to read register(s) back */
595 int protocol
= 3; /* non-data */
596 int t_dir
= 1; /* 0 -> to device, 1 -> from device */
597 int byte_block
= 1; /* 0 -> bytes, 1 -> 512 byte blocks */
598 int t_length
= 0; /* 0 -> no data transferred */
601 int sector_count
= 0;
605 int passthru_size
= USBCYPRESS_PASSTHROUGH_LEN
;
607 memset(cdb
, 0, sizeof(cdb
));
608 memset(sense
, 0, sizeof(sense
));
610 ata_command
= ATA_SMART_CMD
;
612 case CHECK_POWER_MODE
:
613 ata_command
= ATA_CHECK_POWER_MODE
;
617 case READ_VALUES
: /* READ DATA */
618 feature
= ATA_SMART_READ_VALUES
;
619 sector_count
= 1; /* one (512 byte) block */
620 protocol
= 4; /* PIO data-in */
621 t_length
= 2; /* sector count holds count */
624 case READ_THRESHOLDS
: /* obsolete */
625 feature
= ATA_SMART_READ_THRESHOLDS
;
626 sector_count
= 1; /* one (512 byte) block */
628 protocol
= 4; /* PIO data-in */
629 t_length
= 2; /* sector count holds count */
633 feature
= ATA_SMART_READ_LOG_SECTOR
;
634 sector_count
= 1; /* one (512 byte) block */
636 protocol
= 4; /* PIO data-in */
637 t_length
= 2; /* sector count holds count */
641 feature
= ATA_SMART_WRITE_LOG_SECTOR
;
642 sector_count
= 1; /* one (512 byte) block */
644 protocol
= 5; /* PIO data-out */
645 t_length
= 2; /* sector count holds count */
646 t_dir
= 0; /* to device */
650 ata_command
= ATA_IDENTIFY_DEVICE
;
651 sector_count
= 1; /* one (512 byte) block */
652 protocol
= 4; /* PIO data-in */
653 t_length
= 2; /* sector count holds count */
657 ata_command
= ATA_IDENTIFY_PACKET_DEVICE
;
658 sector_count
= 1; /* one (512 byte) block */
659 protocol
= 4; /* PIO data-in */
660 t_length
= 2; /* sector count (7:0) holds count */
664 feature
= ATA_SMART_ENABLE
;
668 feature
= ATA_SMART_DISABLE
;
672 // this command only says if SMART is working. It could be
673 // replaced with STATUS_CHECK below.
674 feature
= ATA_SMART_STATUS
;
678 feature
= ATA_SMART_AUTO_OFFLINE
;
679 sector_count
= select
; // YET NOTE - THIS IS A NON-DATA COMMAND!!
682 feature
= ATA_SMART_AUTOSAVE
;
683 sector_count
= select
; // YET NOTE - THIS IS A NON-DATA COMMAND!!
685 case IMMEDIATE_OFFLINE
:
686 feature
= ATA_SMART_IMMEDIATE_OFFLINE
;
690 // This command uses HDIO_DRIVE_TASK and has different syntax than
691 // the other commands.
692 feature
= ATA_SMART_STATUS
; /* SMART RETURN STATUS */
696 pout("Unrecognized command %d in usbcypress_device::ata_command_interface()\n"
697 "Please contact " PACKAGE_BUGREPORT
"\n", command
);
701 if (ATA_SMART_CMD
== ata_command
) {
706 cdb
[0] = m_signature
; // bVSCBSignature : vendor-specific command
707 cdb
[1] = 0x24; // bVSCBSubCommand : 0x24 for ATACB
709 if (ata_command
== ATA_IDENTIFY_DEVICE
|| ata_command
== ATA_IDENTIFY_PACKET_DEVICE
)
710 cdb
[2] |= (1<<7); //set IdentifyPacketDevice for these cmds
711 cdb
[3] = 0xff - (1<<0) - (1<<6); //features, sector count, lba low, lba med
712 // lba high, command are valid
713 cdb
[4] = byte_block
; //TransferBlockCount : 512
717 cdb
[7] = sector_count
;
721 cdb
[12] = ata_command
;
723 memset(&io_hdr
, 0, sizeof(io_hdr
));
725 io_hdr
.dxfer_dir
= DXFER_NONE
;
726 io_hdr
.dxfer_len
= 0;
727 } else if (t_dir
) { /* from device */
728 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
729 io_hdr
.dxfer_len
= copydata
;
730 io_hdr
.dxferp
= (unsigned char *)data
;
731 memset(data
, 0, copydata
); /* prefill with zeroes */
732 } else { /* to device */
733 io_hdr
.dxfer_dir
= DXFER_TO_DEVICE
;
734 io_hdr
.dxfer_len
= outlen
;
735 io_hdr
.dxferp
= (unsigned char *)data
;
738 io_hdr
.cmnd_len
= passthru_size
;
739 io_hdr
.sensep
= sense
;
740 io_hdr
.max_sense_len
= sizeof(sense
);
741 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
743 scsi_device
* scsidev
= get_tunnel_dev();
744 if (!scsidev
->scsi_pass_through(&io_hdr
)) {
745 if (con
->reportscsiioctl
> 0)
746 pout("usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
747 "errno=%d [%s]\n", scsidev
->get_errno(), scsidev
->get_errmsg());
748 set_err(scsidev
->get_err());
752 // if there is a sense the command failed or the
753 // device doesn't support usbcypress
754 if (io_hdr
.scsi_status
== SCSI_STATUS_CHECK_CONDITION
&&
755 sg_scsi_normalize_sense(io_hdr
.sensep
, io_hdr
.resp_sense_len
, NULL
)) {
759 unsigned char ardp
[8];
761 /* XXX this is racy if there other scsi command between
762 * the first usbcypress command and this one
764 //pout("If you got strange result, please retry without traffic on the disc\n");
765 /* we use the same command as before, but we set
766 * * the read taskfile bit, for not executing usbcypress command,
767 * * but reading register selected in srb->cmnd[4]
769 cdb
[2] = (1<<0); /* ask read taskfile */
770 memset(sense
, 0, sizeof(sense
));
772 /* transfert 8 bytes */
773 memset(&io_hdr
, 0, sizeof(io_hdr
));
774 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
775 io_hdr
.dxfer_len
= ard_len
;
776 io_hdr
.dxferp
= (unsigned char *)ardp
;
777 memset(ardp
, 0, ard_len
); /* prefill with zeroes */
780 io_hdr
.cmnd_len
= passthru_size
;
781 io_hdr
.sensep
= sense
;
782 io_hdr
.max_sense_len
= sizeof(sense
);
783 io_hdr
.timeout
= SCSI_TIMEOUT_DEFAULT
;
786 if (!scsidev
->scsi_pass_through(&io_hdr
)) {
787 if (con
->reportscsiioctl
> 0)
788 pout("usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
789 "errno=%d [%s]\n", scsidev
->get_errno(), scsidev
->get_errmsg());
790 set_err(scsidev
->get_err());
793 // if there is a sense the command failed or the
794 // device doesn't support usbcypress
795 if (io_hdr
.scsi_status
== SCSI_STATUS_CHECK_CONDITION
&&
796 sg_scsi_normalize_sense(io_hdr
.sensep
, io_hdr
.resp_sense_len
, NULL
)) {
801 if (con
->reportscsiioctl
> 1) {
802 pout("Values from ATA Return Descriptor are:\n");
803 dStrHex((const char *)ardp
, ard_len
, 1);
806 if (ATA_CHECK_POWER_MODE
== ata_command
)
807 data
[0] = ardp
[2]; /* sector count (0:7) */
808 else if (STATUS_CHECK
== command
) {
809 if ((ardp
[4] == 0x4f) && (ardp
[5] == 0xc2))
810 return 0; /* GOOD smart status */
811 if ((ardp
[4] == 0xf4) && (ardp
[5] == 0x2c))
812 return 1; // smart predicting failure, "bad" status
813 // We haven't gotten output that makes sense so
814 // print out some debugging info
815 syserror("Error SMART Status command failed");
816 pout("This may be due to a race in usbcypress\n");
817 pout("Retry without other disc access\n");
818 pout("Please get assistance from " PACKAGE_HOMEPAGE
"\n");
819 pout("Values from ATA Return Descriptor are:\n");
820 dStrHex((const char *)ardp
, ard_len
, 1);
827 #if 0 // Not used, see autodetect_sat_device() below.
828 static int isprint_string(const char *s
)
831 if (isprint(*s
) == 0)
838 /* Attempt an IDENTIFY DEVICE ATA or IDENTIFY PACKET DEVICE command
839 If successful return 1, else 0 */
840 // TODO: Combine with has_sat_pass_through above
841 static int has_usbcypress_pass_through(ata_device
* atadev
, const char *manufacturer
, const char *product
)
843 struct ata_identify_device drive
;
844 char model
[40], serial
[20], firm
[8];
846 /* issue the command and do a checksum if possible */
847 if (ataReadHDIdentity(atadev
, &drive
) < 0)
850 /* check if model string match, revision doesn't work for me */
851 format_ata_string(model
, drive
.model
, 40);
852 if (*model
== 0 || isprint_string(model
) == 0)
855 if (manufacturer
&& strncmp(manufacturer
, model
, 8))
856 pout("manufacturer doesn't match in pass_through test\n");
858 strlen(model
) > 8 && strncmp(product
, model
+8, strlen(model
)-8))
859 pout("product doesn't match in pass_through test\n");
862 format_ata_string(serial
, drive
.serial_no
, 20);
863 if (isprint_string(serial
) == 0)
865 format_ata_string(firm
, drive
.fw_rev
, 8);
866 if (isprint_string(firm
) == 0)
872 /////////////////////////////////////////////////////////////////////////////
874 /// JMicron USB Bridge support.
876 class usbjmicron_device
877 : public tunnelled_device
<
878 /*implements*/ ata_device
,
879 /*by tunnelling through a*/ scsi_device
883 usbjmicron_device(smart_interface
* intf
, scsi_device
* scsidev
,
884 const char * req_type
, bool ata_48bit_support
, int port
);
886 virtual ~usbjmicron_device() throw();
890 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
893 bool get_registers(unsigned short addr
, unsigned char * buf
, unsigned short size
);
895 bool m_ata_48bit_support
;
900 usbjmicron_device::usbjmicron_device(smart_interface
* intf
, scsi_device
* scsidev
,
901 const char * req_type
, bool ata_48bit_support
, int port
)
902 : smart_device(intf
, scsidev
->get_dev_name(), "usbjmicron", req_type
),
903 tunnelled_device
<ata_device
, scsi_device
>(scsidev
),
904 m_ata_48bit_support(ata_48bit_support
), m_port(port
)
906 set_info().info_name
= strprintf("%s [USB JMicron]", scsidev
->get_info_name());
909 usbjmicron_device::~usbjmicron_device() throw()
914 bool usbjmicron_device::open()
917 if (!tunnelled_device
<ata_device
, scsi_device
>::open())
920 // Detect port if not specified
922 unsigned char regbuf
[1] = {0};
923 if (!get_registers(0x720f, regbuf
, sizeof(regbuf
))) {
928 switch (regbuf
[0] & 0x44) {
935 return set_err(EINVAL
, "Two devices connected, try '-d usbjmicron,[01]'");
938 return set_err(ENODEV
, "No device connected");
946 bool usbjmicron_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
948 if (!ata_cmd_is_ok(in
,
949 true, // data_out_support
950 false, // !multi_sector_support
951 m_ata_48bit_support
) // limited, see below
955 bool is_smart_status
= ( in
.in_regs
.command
== ATA_SMART_CMD
956 && in
.in_regs
.features
== ATA_SMART_STATUS
);
958 // Support output registers for SMART STATUS
959 if (in
.out_needed
.is_set() && !is_smart_status
)
960 return set_err(ENOSYS
, "ATA output registers not supported");
962 // Support 48-bit commands with zero high bytes
963 if (in
.in_regs
.is_real_48bit_cmd())
964 return set_err(ENOSYS
, "48-bit ATA commands not fully supported");
967 return set_err(EIO
, "Unknown JMicron port");
970 memset(&io_hdr
, 0, sizeof(io_hdr
));
973 unsigned char smart_status
= 0;
975 if (is_smart_status
&& in
.out_needed
.is_set()) {
976 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
977 io_hdr
.dxfer_len
= 1;
978 io_hdr
.dxferp
= &smart_status
;
980 else switch (in
.direction
) {
981 case ata_cmd_in::no_data
:
982 io_hdr
.dxfer_dir
= DXFER_NONE
;
984 case ata_cmd_in::data_in
:
985 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
986 io_hdr
.dxfer_len
= in
.size
;
987 io_hdr
.dxferp
= (unsigned char *)in
.buffer
;
988 memset(in
.buffer
, 0, in
.size
);
990 case ata_cmd_in::data_out
:
991 io_hdr
.dxfer_dir
= DXFER_TO_DEVICE
;
992 io_hdr
.dxfer_len
= in
.size
;
993 io_hdr
.dxferp
= (unsigned char *)in
.buffer
;
997 return set_err(EINVAL
);
1000 // Build pass through command
1001 unsigned char cdb
[12];
1003 cdb
[ 1] = (rwbit
? 0x10 : 0x00);
1005 cdb
[ 3] = (unsigned char)(io_hdr
.dxfer_len
>> 8);
1006 cdb
[ 4] = (unsigned char)(io_hdr
.dxfer_len
);
1007 cdb
[ 5] = in
.in_regs
.features
;
1008 cdb
[ 6] = in
.in_regs
.sector_count
;
1009 cdb
[ 7] = in
.in_regs
.lba_low
;
1010 cdb
[ 8] = in
.in_regs
.lba_mid
;
1011 cdb
[ 9] = in
.in_regs
.lba_high
;
1012 cdb
[10] = in
.in_regs
.device
| (m_port
== 0 ? 0xa0 : 0xb0);
1013 cdb
[11] = in
.in_regs
.command
;
1016 io_hdr
.cmnd_len
= sizeof(cdb
);
1018 scsi_device
* scsidev
= get_tunnel_dev();
1019 if (!scsi_pass_through_and_check(scsidev
, &io_hdr
,
1020 "usbjmicron_device::ata_pass_through: "))
1021 return set_err(scsidev
->get_err());
1023 if (in
.out_needed
.is_set()) {
1024 if (is_smart_status
) {
1025 switch (smart_status
) {
1026 case 0x01: case 0xc2:
1027 out
.out_regs
.lba_high
= 0xc2;
1028 out
.out_regs
.lba_mid
= 0x4f;
1030 case 0x00: case 0x2c:
1031 out
.out_regs
.lba_high
= 0x2c;
1032 out
.out_regs
.lba_mid
= 0xf4;
1037 #if 0 // Not needed for SMART STATUS, see also notes below
1039 // Read ATA output registers
1040 // NOTE: The register addresses are not valid for some older chip revisions
1041 // NOTE: There is a small race condition here!
1042 unsigned char regbuf
[16] = {0, };
1043 if (!get_registers((m_port
== 0 ? 0x8000 : 0x9000), regbuf
, sizeof(regbuf
)))
1046 out
.out_regs
.sector_count
= regbuf
[ 0];
1047 out
.out_regs
.lba_mid
= regbuf
[ 4];
1048 out
.out_regs
.lba_low
= regbuf
[ 6];
1049 out
.out_regs
.device
= regbuf
[ 9];
1050 out
.out_regs
.lba_high
= regbuf
[10];
1051 out
.out_regs
.error
= regbuf
[13];
1052 out
.out_regs
.status
= regbuf
[14];
1060 bool usbjmicron_device::get_registers(unsigned short addr
,
1061 unsigned char * buf
, unsigned short size
)
1063 unsigned char cdb
[12];
1067 cdb
[ 3] = (unsigned char)(size
>> 8);
1068 cdb
[ 4] = (unsigned char)(size
);
1070 cdb
[ 6] = (unsigned char)(addr
>> 8);
1071 cdb
[ 7] = (unsigned char)(addr
);
1077 scsi_cmnd_io io_hdr
;
1078 memset(&io_hdr
, 0, sizeof(io_hdr
));
1079 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
1080 io_hdr
.dxfer_len
= size
;
1081 io_hdr
.dxferp
= buf
;
1083 io_hdr
.cmnd_len
= sizeof(cdb
);
1085 scsi_device
* scsidev
= get_tunnel_dev();
1086 if (!scsi_pass_through_and_check(scsidev
, &io_hdr
,
1087 "usbjmicron_device::get_registers: "))
1088 return set_err(scsidev
->get_err());
1094 /////////////////////////////////////////////////////////////////////////////
1096 /// SunplusIT USB Bridge support.
1098 class usbsunplus_device
1099 : public tunnelled_device
<
1100 /*implements*/ ata_device
,
1101 /*by tunnelling through a*/ scsi_device
1105 usbsunplus_device(smart_interface
* intf
, scsi_device
* scsidev
,
1106 const char * req_type
);
1108 virtual ~usbsunplus_device() throw();
1110 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
1114 usbsunplus_device::usbsunplus_device(smart_interface
* intf
, scsi_device
* scsidev
,
1115 const char * req_type
)
1116 : smart_device(intf
, scsidev
->get_dev_name(), "usbsunplus", req_type
),
1117 tunnelled_device
<ata_device
, scsi_device
>(scsidev
)
1119 set_info().info_name
= strprintf("%s [USB Sunplus]", scsidev
->get_info_name());
1122 usbsunplus_device::~usbsunplus_device() throw()
1126 bool usbsunplus_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
1128 if (!ata_cmd_is_ok(in
,
1129 true, // data_out_support
1130 false, // !multi_sector_support
1131 true) // ata_48bit_support
1135 scsi_cmnd_io io_hdr
;
1136 unsigned char cdb
[12];
1138 if (in
.in_regs
.is_48bit_cmd()) {
1139 // Set "previous" registers
1140 memset(&io_hdr
, 0, sizeof(io_hdr
));
1141 io_hdr
.dxfer_dir
= DXFER_NONE
;
1145 cdb
[ 2] = 0x23; // Subcommand: Pass through presetting
1148 cdb
[ 5] = in
.in_regs
.prev
.features
;
1149 cdb
[ 6] = in
.in_regs
.prev
.sector_count
;
1150 cdb
[ 7] = in
.in_regs
.prev
.lba_low
;
1151 cdb
[ 8] = in
.in_regs
.prev
.lba_mid
;
1152 cdb
[ 9] = in
.in_regs
.prev
.lba_high
;
1157 io_hdr
.cmnd_len
= sizeof(cdb
);
1159 scsi_device
* scsidev
= get_tunnel_dev();
1160 if (!scsi_pass_through_and_check(scsidev
, &io_hdr
,
1161 "usbsunplus_device::scsi_pass_through (presetting): "))
1162 return set_err(scsidev
->get_err());
1165 // Run Pass through command
1166 memset(&io_hdr
, 0, sizeof(io_hdr
));
1167 unsigned char protocol
;
1168 switch (in
.direction
) {
1169 case ata_cmd_in::no_data
:
1170 io_hdr
.dxfer_dir
= DXFER_NONE
;
1173 case ata_cmd_in::data_in
:
1174 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
1175 io_hdr
.dxfer_len
= in
.size
;
1176 io_hdr
.dxferp
= (unsigned char *)in
.buffer
;
1177 memset(in
.buffer
, 0, in
.size
);
1180 case ata_cmd_in::data_out
:
1181 io_hdr
.dxfer_dir
= DXFER_TO_DEVICE
;
1182 io_hdr
.dxfer_len
= in
.size
;
1183 io_hdr
.dxferp
= (unsigned char *)in
.buffer
;
1187 return set_err(EINVAL
);
1192 cdb
[ 2] = 0x22; // Subcommand: Pass through
1194 cdb
[ 4] = (unsigned char)(io_hdr
.dxfer_len
>> 9);
1195 cdb
[ 5] = in
.in_regs
.features
;
1196 cdb
[ 6] = in
.in_regs
.sector_count
;
1197 cdb
[ 7] = in
.in_regs
.lba_low
;
1198 cdb
[ 8] = in
.in_regs
.lba_mid
;
1199 cdb
[ 9] = in
.in_regs
.lba_high
;
1200 cdb
[10] = in
.in_regs
.device
| 0xa0;
1201 cdb
[11] = in
.in_regs
.command
;
1204 io_hdr
.cmnd_len
= sizeof(cdb
);
1206 scsi_device
* scsidev
= get_tunnel_dev();
1207 if (!scsi_pass_through_and_check(scsidev
, &io_hdr
,
1208 "usbsunplus_device::scsi_pass_through: "))
1209 // Returns sense key 0x03 (medium error) on ATA command error
1210 return set_err(scsidev
->get_err());
1212 if (in
.out_needed
.is_set()) {
1213 // Read ATA output registers
1214 unsigned char regbuf
[8] = {0, };
1215 memset(&io_hdr
, 0, sizeof(io_hdr
));
1216 io_hdr
.dxfer_dir
= DXFER_FROM_DEVICE
;
1217 io_hdr
.dxfer_len
= sizeof(regbuf
);
1218 io_hdr
.dxferp
= regbuf
;
1222 cdb
[ 2] = 0x21; // Subcommand: Get status
1223 memset(cdb
+3, 0, sizeof(cdb
)-3);
1225 io_hdr
.cmnd_len
= sizeof(cdb
);
1227 if (!scsi_pass_through_and_check(scsidev
, &io_hdr
,
1228 "usbsunplus_device::scsi_pass_through (get registers): "))
1229 return set_err(scsidev
->get_err());
1231 out
.out_regs
.error
= regbuf
[1];
1232 out
.out_regs
.sector_count
= regbuf
[2];
1233 out
.out_regs
.lba_low
= regbuf
[3];
1234 out
.out_regs
.lba_mid
= regbuf
[4];
1235 out
.out_regs
.lba_high
= regbuf
[5];
1236 out
.out_regs
.device
= regbuf
[6];
1237 out
.out_regs
.status
= regbuf
[7];
1246 using namespace sat
;
1249 /////////////////////////////////////////////////////////////////////////////
1251 // Return ATA->SCSI filter for SAT or USB.
1253 ata_device
* smart_interface::get_sat_device(const char * type
, scsi_device
* scsidev
)
1255 if (!strncmp(type
, "sat", 3)) {
1256 int ptlen
= 0, n1
= -1, n2
= -1;
1257 if (!(((sscanf(type
, "sat%n,%d%n", &n1
, &ptlen
, &n2
) == 1 && n2
== (int)strlen(type
)) || n1
== (int)strlen(type
))
1258 && (ptlen
== 0 || ptlen
== 12 || ptlen
== 16))) {
1259 set_err(EINVAL
, "Option '-d sat,<n>' requires <n> to be 0, 12 or 16");
1262 return new sat_device(this, scsidev
, type
, ptlen
);
1265 else if (!strncmp(type
, "usbcypress", 10)) {
1266 unsigned signature
= 0x24; int n1
= -1, n2
= -1;
1267 if (!(((sscanf(type
, "usbcypress%n,0x%x%n", &n1
, &signature
, &n2
) == 1 && n2
== (int)strlen(type
)) || n1
== (int)strlen(type
))
1268 && signature
<= 0xff)) {
1269 set_err(EINVAL
, "Option '-d usbcypress,<n>' requires <n> to be "
1270 "an hexadecimal number between 0x0 and 0xff");
1273 return new usbcypress_device(this, scsidev
, type
, signature
);
1276 else if (!strncmp(type
, "usbjmicron", 10)) {
1277 const char * t
= type
+ 10;
1278 bool ata_48bit_support
= false;
1279 if (!strncmp(t
, ",x", 2)) {
1281 ata_48bit_support
= true;
1283 int port
= -1, n
= -1;
1284 if (*t
&& !( (sscanf(t
, ",%d%n", &port
, &n
) == 1
1285 && n
== (int)strlen(t
) && 0 <= port
&& port
<= 1))) {
1286 set_err(EINVAL
, "Option '-d usbmicron[,x],<n>' requires <n> to be 0 or 1");
1289 return new usbjmicron_device(this, scsidev
, type
, ata_48bit_support
, port
);
1292 else if (!strcmp(type
, "usbsunplus")) {
1293 return new usbsunplus_device(this, scsidev
, type
);
1297 set_err(EINVAL
, "Unknown USB device type '%s'", type
);
1302 // Try to detect a SAT device behind a SCSI interface.
1304 ata_device
* smart_interface::autodetect_sat_device(scsi_device
* scsidev
,
1305 const unsigned char * inqdata
, unsigned inqsize
)
1307 if (!scsidev
->is_open())
1310 ata_device
* atadev
= 0;
1313 if (inqdata
&& inqsize
>= 36 && !memcmp(inqdata
+ 8, "ATA ", 8)) { // TODO: Linux-specific?
1314 atadev
= new sat_device(this, scsidev
, "");
1315 if (has_sat_pass_through(atadev
))
1316 return atadev
; // Detected SAT
1317 atadev
->release(scsidev
);
1321 /* The new usbcypress_device(this, scsidev, "", 0x24) sends vendor specific comand to non-cypress devices.
1322 * It's dangerous as other device may interpret such command as own valid vendor specific command.
1323 * I commented it out untill problem resolved
1328 atadev
= new usbcypress_device(this, scsidev
, "", 0x24);
1329 if (has_usbcypress_pass_through(atadev
,
1330 (inqdata
&& inqsize
>= 36 ? (const char*)inqdata
+ 8 : 0),
1331 (inqdata
&& inqsize
>= 36 ? (const char*)inqdata
+ 16 : 0) ))
1332 return atadev
; // Detected USB
1333 atadev
->release(scsidev
);
1340 atadev
->release(scsidev
);
1350 /////////////////////////////////////////////////////////////////////////////
1351 // USB device type detection
1353 struct usb_id_entry
{
1354 int vendor_id
, product_id
, version
;
1358 const char d_sat
[] = "sat";
1359 const char d_cypress
[] = "usbcypress";
1360 const char d_jmicron
[] = "usbjmicron";
1361 const char d_jmicron_x
[] = "usbjmicron,x";
1362 const char d_sunplus
[] = "usbsunplus";
1363 const char d_unsup
[] = "unsupported";
1365 // Map USB IDs -> '-d type' string
1366 const usb_id_entry usb_ids
[] = {
1368 { 0x04b4, 0x6830, 0x0001, d_unsup
}, // Cypress CY7C68300A (AT2)
1369 { 0x04b4, 0x6830, 0x0240, d_cypress
}, // Cypress CY7C68300B/C (AT2LP)
1370 //{ 0x04b4, 0x6831, -1, d_cypress }, // Cypress CY7C68310 (ISD-300LP)
1372 { 0x04cf, 0x8818, 0xb007, d_unsup
}, // Myson Century CS8818
1374 { 0x04fc, 0x0c15, 0xf615, d_sunplus
}, // SunPlus SPDIF215
1375 { 0x04fc, 0x0c25, 0x0103, d_sunplus
}, // SunPlus SPDIF225 (USB+SATA->SATA)
1377 { 0x059b, 0x0275, 0x0001, d_unsup
}, // Iomega MDHD500-U
1379 { 0x059f, 0x0651, -1, d_unsup
}, // LaCie hard disk (FA Porsche design)
1380 { 0x059f, 0x1018, -1, d_sat
}, // LaCie hard disk (Neil Poulton design)
1382 { 0x05ab, 0x0060, 0x1101, d_cypress
}, // In-System/Cypress ISD-300A1
1384 { 0x067b, 0x3507, 0x0001, d_unsup
}, // Prolific PL3507
1386 { 0x0930, 0x0b09, -1, d_sunplus
}, // Toshiba PX1396E-3T01 (similar to Dura Micro 501)
1388 { 0x0bc2, 0x2000, -1, d_sat
}, // Seagate FreeAgent Go
1389 { 0x0bc2, 0x2100, -1, d_sat
}, // Seagate FreeAgent Go
1390 { 0x0bc2, 0x3001, -1, d_sat
}, // Seagate FreeAgent Desk
1392 { 0x0c0b, 0xb159, 0x0103, d_sunplus
}, // Dura Micro 509
1394 { 0x0d49, 0x7310, 0x0125, d_sat
}, // Maxtor OneTouch 4
1395 { 0x0d49, 0x7350, 0x0125, d_sat
}, // Maxtor OneTouch 4 Mini
1396 { 0x0d49, 0x7410, 0x0122, d_sat
}, // Maxtor Basics Desktop
1397 { 0x0d49, 0x7450, 0x0122, d_sat
}, // Maxtor Basics Portable
1399 { 0x1058, 0x0704, 0x0175, d_sat
}, // WD My Passport Essential
1400 { 0x1058, 0x0705, 0x0175, d_sat
}, // WD My Passport Elite
1401 { 0x1058, 0x0906, 0x0012, d_sat
}, // WD My Book ES
1402 { 0x1058, 0x1001, 0x0104, d_sat
}, // WD Elements Desktop
1403 { 0x1058, 0x1003, 0x0175, d_sat
}, // WD Elements Desktop WDE1UBK...
1404 { 0x1058, 0x1010, 0x0105, d_sat
}, // WD Elements
1405 { 0x1058, 0x1100, 0x0165, d_sat
}, // WD My Book Essential
1406 { 0x1058, 0x1102, 0x1028, d_sat
}, // WD My Book
1408 { 0x13fd, 0x1240, 0x0104, d_sat
}, // Initio ? (USB->SATA)
1409 { 0x13fd, 0x1340, 0x0208, d_sat
}, // Initio ? (USB+SATA->SATA)
1411 { 0x152d, 0x2329, 0x0100, d_jmicron
}, // JMicron JM20329 (USB->SATA)
1412 { 0x152d, 0x2336, 0x0100, d_jmicron_x
},// JMicron JM20336 (USB+SATA->SATA, USB->2xSATA)
1413 { 0x152d, 0x2338, 0x0100, d_jmicron
}, // JMicron JM20337/8 (USB->SATA+PATA, USB+SATA->PATA)
1414 { 0x152d, 0x2339, 0x0100, d_jmicron_x
},// JMicron JM20339 (USB->SATA)
1416 { 0x18a5, 0x0215, 0x0001, d_sat
}, // Verbatim FW/USB160 - Oxford OXUF934SSA-LQAG (USB+IEE1394->SATA)
1418 { 0x1bcf, 0x0c31, -1, d_sunplus
}, // SunplusIT
1420 { 0x55aa, 0x2b00, 0x0100, d_unsup
} // OnSpec ? (USB->PATA)
1423 const unsigned num_usb_ids
= sizeof(usb_ids
)/sizeof(usb_ids
[0]);
1426 // Format USB ID for error messages
1427 static std::string
format_usb_id(int vendor_id
, int product_id
, int version
)
1430 return strprintf("[0x%04x:0x%04x (0x%03x)]", vendor_id
, product_id
, version
);
1432 return strprintf("[0x%04x:0x%04x]", vendor_id
, product_id
);
1435 // Get type name for USB device with known VENDOR:PRODUCT ID.
1436 const char * smart_interface::get_usb_dev_type_by_id(int vendor_id
, int product_id
,
1437 int version
/*= -1*/)
1439 const usb_id_entry
* entry
= 0;
1442 for (unsigned i
= 0; i
< num_usb_ids
; i
++) {
1443 const usb_id_entry
& e
= usb_ids
[i
];
1444 if (!(vendor_id
== e
.vendor_id
&& product_id
== e
.product_id
))
1447 // If two entries with same vendor:product ID have different
1448 // types, use version (if provided by OS) to select entry.
1449 bool s
= (version
>= 0 && version
== e
.version
);
1452 if (s
== state
&& e
.type
!= entry
->type
) {
1453 set_err(EINVAL
, "USB bridge %s type is ambiguous: '%s' or '%s'",
1454 format_usb_id(vendor_id
, product_id
, version
).c_str(),
1455 e
.type
, entry
->type
);
1466 set_err(EINVAL
, "Unknown USB bridge %s",
1467 format_usb_id(vendor_id
, product_id
, version
).c_str());
1470 if (entry
->type
== d_unsup
) {
1471 set_err(ENOSYS
, "Unsupported USB bridge %s",
1472 format_usb_id(vendor_id
, product_id
, version
).c_str());