smartmontools SVN Rev 5474
Utility to control and monitor storage systems with "S.M.A.R.T."
scsiata.cpp
Go to the documentation of this file.
1/*
2 * scsiata.cpp
3 *
4 * Home page of code is: https://www.smartmontools.org
5 *
6 * Copyright (C) 2006-15 Douglas Gilbert <dgilbert@interlog.com>
7 * Copyright (C) 2009-23 Christian Franke
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 *
11 * The code in this file is based on the SCSI to ATA Translation (SAT)
12 * draft found at http://www.t10.org . The original draft used for this
13 * code is sat-r08.pdf which is not too far away from becoming a
14 * standard. The SAT commands of interest to smartmontools are the
15 * ATA PASS THROUGH SCSI (16) and ATA PASS THROUGH SCSI (12) defined in
16 * section 12 of that document.
17 *
18 * sat-r09.pdf is the most recent, easily accessible draft prior to the
19 * original SAT standard (ANSI INCITS 431-2007). By mid-2009 the second
20 * version of the SAT standard (SAT-2) is nearing standardization. In
21 * their wisdom an incompatible change has been introduced in draft
22 * sat2r08a.pdf in the area of the ATA RETURN DESCRIPTOR. A new "fixed
23 * format" ATA RETURN buffer has been defined (sat2r08b.pdf section
24 * 12.2.7) for the case when DSENSE=0 in the Control mode page.
25 * Unfortunately this is the normal case. If the change stands our
26 * code will need to be extended for this case.
27 *
28 * With more transports "hiding" SATA disks (and other S-ATAPI devices)
29 * behind a SCSI command set, accessing special features like SMART
30 * information becomes a challenge. The SAT standard offers ATA PASS
31 * THROUGH commands for special usages. Note that the SAT layer may
32 * be inside a generic OS layer (e.g. libata in linux), in a host
33 * adapter (HA or HBA) firmware, or somewhere on the interconnect
34 * between the host computer and the SATA devices (e.g. a RAID made
35 * of SATA disks and the RAID talks "SCSI" to the host computer).
36 * Note that in the latter case, this code does not solve the
37 * addressing issue (i.e. which SATA disk to address behind the logical
38 * SCSI (RAID) interface).
39 *
40 */
41
42#include <stdio.h>
43#include <string.h>
44#include <stdlib.h>
45#include <ctype.h>
46#include <errno.h>
47
48#include "config.h"
49
50#include "scsicmds.h"
51#include "atacmds.h" // ataReadHDIdentity()
52#include "knowndrives.h" // lookup_usb_device()
53#include "utility.h"
54#include "dev_interface.h"
55#include "dev_ata_cmd_set.h" // ata_device_with_command_set
56#include "dev_tunnelled.h" // tunnelled_device<>
57#include "sg_unaligned.h"
58
59const char * scsiata_cpp_cvsid = "$Id: scsiata.cpp 5437 2023-01-23 17:48:54Z chrfranke $";
60
61/* This is a slightly stretched SCSI sense "descriptor" format header.
62 The addition is to allow the 0x70 and 0x71 response codes. The idea
63 is to place the salient data of both "fixed" and "descriptor" sense
64 format into one structure to ease application processing.
65 The original sense buffer should be kept around for those cases
66 in which more information is required (e.g. the LBA of a MEDIUM ERROR). */
67/// Abridged SCSI sense data
69 unsigned char response_code; /* permit: 0x0, 0x70, 0x71, 0x72, 0x73 */
70 unsigned char sense_key;
71 unsigned char asc;
72 unsigned char ascq;
73 unsigned char byte4;
74 unsigned char byte5;
75 unsigned char byte6;
76 unsigned char additional_length;
77};
78
79/* Maps the salient data from a sense buffer which is in either fixed or
80 descriptor format into a structure mimicking a descriptor format
81 header (i.e. the first 8 bytes of sense descriptor format).
82 If zero response code returns 0. Otherwise returns 1 and if 'sshp' is
83 non-NULL then zero all fields and then set the appropriate fields in
84 that structure. sshp::additional_length is always 0 for response
85 codes 0x70 and 0x71 (fixed format). */
86static int sg_scsi_normalize_sense(const unsigned char * sensep, int sb_len,
87 struct sg_scsi_sense_hdr * sshp);
88
89#define SAT_ATA_PASSTHROUGH_12LEN 12
90#define SAT_ATA_PASSTHROUGH_16LEN 16
91
92#define DEF_SAT_ATA_PASSTHRU_SIZE 16
93#define ATA_RETURN_DESCRIPTOR 9
94
95
96namespace sat { // no need to publish anything, name provided for Doxygen
97
98/// SAT support.
99/// Implements ATA by tunnelling through SCSI.
100
102: public tunnelled_device<
103 /*implements*/ ata_device
104 /*by tunnelling through a*/, scsi_device
105 >,
106 virtual public /*implements*/ scsi_device
107{
108public:
113 };
116 sat_asm1352r, // ASM1352R port 0 or 1
117 };
118
119 sat_device(smart_interface * intf, scsi_device * scsidev,
120 const char * req_type, sat_scsi_mode mode = sat_always, int passthrulen = 0,
121 sat_variant variant = sat_standard, int port = 0);
122
123 virtual ~sat_device();
124
125 virtual smart_device * autodetect_open() override;
126
127 virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override;
128
129 virtual bool scsi_pass_through(scsi_cmnd_io * iop) override;
130
131private:
136};
137
138
140 const char * req_type, sat_scsi_mode mode /* = sat_always */,
141 int passthrulen /* = 0 */, sat_variant variant /* = sat_standard */, int port /* = 0 */)
142: smart_device(intf, scsidev->get_dev_name(),
143 (mode == sat_always ? "sat" : mode == sat_auto ? "sat,auto" : "scsi"), req_type),
145 m_passthrulen(passthrulen),
146 m_mode(mode),
147 m_variant(variant), m_port(port)
148{
149 if (mode != sat_always)
150 hide_ata(); // Start as SCSI, switch to ATA in autodetect_open()
151 else
152 hide_scsi(); // ATA always
153 if (strcmp(scsidev->get_dev_type(), "scsi"))
154 set_info().dev_type += strprintf("+%s", scsidev->get_dev_type());
155
156 set_info().info_name = strprintf("%s [%s]", scsidev->get_info_name(),
157 (variant == sat_standard ?
158 (mode == sat_always ? "SAT" : mode == sat_auto ? "SCSI/SAT" : "SCSI") :
159 (port == 0 ? "ASM1352R_0" : "ASM1352R_1") ));
160}
161
163{
164}
165
166
167// cdb[0]: ATA PASS THROUGH (16) SCSI command opcode byte (0x85)
168// cdb[1]: multiple_count, protocol + extend
169// cdb[2]: offline, ck_cond, t_dir, byte_block + t_length
170// cdb[3]: features (15:8)
171// cdb[4]: features (7:0)
172// cdb[5]: sector_count (15:8)
173// cdb[6]: sector_count (7:0)
174// cdb[7]: lba_low (15:8)
175// cdb[8]: lba_low (7:0)
176// cdb[9]: lba_mid (15:8)
177// cdb[10]: lba_mid (7:0)
178// cdb[11]: lba_high (15:8)
179// cdb[12]: lba_high (7:0)
180// cdb[13]: device
181// cdb[14]: (ata) command
182// cdb[15]: control (SCSI, leave as zero)
183//
184// 24 bit lba (from MSB): cdb[12] cdb[10] cdb[8]
185// 48 bit lba (from MSB): cdb[11] cdb[9] cdb[7] cdb[12] cdb[10] cdb[8]
186//
187//
188// cdb[0]: ATA PASS THROUGH (12) SCSI command opcode byte (0xa1)
189// cdb[1]: multiple_count, protocol + extend
190// cdb[2]: offline, ck_cond, t_dir, byte_block + t_length
191// cdb[3]: features (7:0)
192// cdb[4]: sector_count (7:0)
193// cdb[5]: lba_low (7:0)
194// cdb[6]: lba_mid (7:0)
195// cdb[7]: lba_high (7:0)
196// cdb[8]: device
197// cdb[9]: (ata) command
198// cdb[10]: reserved
199// cdb[11]: control (SCSI, leave as zero)
200//
201//
202// ATA Return Descriptor (component of descriptor sense data)
203// des[0]: descriptor code (0x9)
204// des[1]: additional descriptor length (0xc)
205// des[2]: extend (bit 0)
206// des[3]: error
207// des[4]: sector_count (15:8)
208// des[5]: sector_count (7:0)
209// des[6]: lba_low (15:8)
210// des[7]: lba_low (7:0)
211// des[8]: lba_mid (15:8)
212// des[9]: lba_mid (7:0)
213// des[10]: lba_high (15:8)
214// des[11]: lba_high (7:0)
215// des[12]: device
216// des[13]: status
217//
218//
219// ATA registers returned via fixed format sense (allowed >= SAT-2)
220// fxs[0]: info_valid (bit 7); response_code (6:0)
221// fxs[1]: (obsolete)
222// fxs[2]: sense_key (3:0) --> recovered error (formerly 'no sense')
223// fxs[3]: information (31:24) --> ATA Error register
224// fxs[4]: information (23:16) --> ATA Status register
225// fxs[5]: information (15:8) --> ATA Device register
226// fxs[6]: information (7:0) --> ATA Count (7:0)
227// fxs[7]: additional sense length [should be >= 10]
228// fxs[8]: command specific info (31:24) --> Extend (7), count_upper_nonzero
229// (6), lba_upper_nonzero(5), log_index (3:0)
230// fxs[9]: command specific info (23:16) --> ATA LBA (7:0)
231// fxs[10]: command specific info (15:8) --> ATA LBA (15:8)
232// fxs[11]: command specific info (7:0) --> ATA LBA (23:16)
233// fxs[12]: additional sense code (asc) --> 0x0
234// fxs[13]: additional sense code qualifier (ascq) --> 0x1d
235// asc,ascq = 0x0,0x1d --> 'ATA pass through information available'
236
237
238
239// PURPOSE
240// This interface routine takes ATA SMART commands and packages
241// them in the SAT-defined ATA PASS THROUGH SCSI commands. There are
242// two available SCSI commands: a 12 byte and 16 byte variant; the
243// one used is chosen via this->m_passthrulen .
244// DETAILED DESCRIPTION OF ARGUMENTS
245// device: is the file descriptor provided by (a SCSI dvice type) open()
246// command: defines the different ATA operations.
247// select: additional input data if needed (which log, which type of
248// self-test).
249// data: location to write output data, if needed (512 bytes).
250// Note: not all commands use all arguments.
251// RETURN VALUES
252// -1 if the command failed
253// 0 if the command succeeded,
254// STATUS_CHECK routine:
255// -1 if the command failed
256// 0 if the command succeeded and disk SMART status is "OK"
257// 1 if the command succeeded and disk SMART status is "FAILING"
258
260{
261 if (!ata_cmd_is_supported(in,
266 "SAT")
267 )
268 return false;
269
270 struct scsi_cmnd_io io_hdr = {};
271 struct scsi_sense_disect sinfo;
272 struct sg_scsi_sense_hdr ssh;
273 unsigned char cdb[SAT_ATA_PASSTHROUGH_16LEN] = {};
274 unsigned char sense[32] = {};
275 const unsigned char * ardp;
276 int ard_len, have_sense;
277 int extend = 0;
278 int ck_cond = 0; /* set to 1 to read register(s) back */
279 int protocol = 3; /* non-data */
280 int t_dir = 1; /* 0 -> to device, 1 -> from device */
281 int byte_block = 1; /* 0 -> bytes, 1 -> 512 byte blocks */
282 int t_length = 0; /* 0 -> no data transferred */
283 int passthru_size = DEF_SAT_ATA_PASSTHRU_SIZE;
284 bool sense_descriptor = true;
285
286 // Set data direction
287 // TODO: This works only for commands where sector_count holds count!
288 switch (in.direction) {
290 break;
292 protocol = 4; // PIO data-in
293 t_length = 2; // sector_count holds count
294 break;
296 protocol = 5; // PIO data-out
297 t_length = 2; // sector_count holds count
298 t_dir = 0; // to device
299 break;
300 default:
301 return set_err(EINVAL, "sat_device::ata_pass_through: invalid direction=%d",
302 (int)in.direction);
303 }
304
305 // The ASM1352R uses reserved values for 'protocol' field to select drive
306 if (m_variant == sat_asm1352r)
307 protocol = (m_port == 0 ? 0xd : 0xe);
308
309 // Check condition if any output register needed
310 if (in.out_needed.is_set())
311 ck_cond = 1;
312
315 passthru_size = m_passthrulen;
316
317 // Set extend bit on 48-bit ATA command
318 if (in.in_regs.is_48bit_cmd()) {
319 if (passthru_size != SAT_ATA_PASSTHROUGH_16LEN)
320 return set_err(ENOSYS, "48-bit ATA commands require SAT ATA PASS-THROUGH (16)");
321 extend = 1;
322 }
323
324 cdb[0] = (SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ?
326
327 cdb[1] = (protocol << 1) | extend;
328 cdb[2] = (ck_cond << 5) | (t_dir << 3) |
329 (byte_block << 2) | t_length;
330
331 if (passthru_size == SAT_ATA_PASSTHROUGH_12LEN) {
332 // ATA PASS-THROUGH (12)
333 const ata_in_regs & lo = in.in_regs;
334 cdb[3] = lo.features;
335 cdb[4] = lo.sector_count;
336 cdb[5] = lo.lba_low;
337 cdb[6] = lo.lba_mid;
338 cdb[7] = lo.lba_high;
339 cdb[8] = lo.device;
340 cdb[9] = lo.command;
341 }
342 else {
343 // ATA PASS-THROUGH (16)
344 const ata_in_regs & lo = in.in_regs;
345 const ata_in_regs & hi = in.in_regs.prev;
346 // Note: all 'in.in_regs.prev.*' are always zero for 28-bit commands
347 cdb[ 3] = hi.features;
348 cdb[ 4] = lo.features;
349 cdb[ 5] = hi.sector_count;
350 cdb[ 6] = lo.sector_count;
351 cdb[ 7] = hi.lba_low;
352 cdb[ 8] = lo.lba_low;
353 cdb[ 9] = hi.lba_mid;
354 cdb[10] = lo.lba_mid;
355 cdb[11] = hi.lba_high;
356 cdb[12] = lo.lba_high;
357 cdb[13] = lo.device;
358 cdb[14] = lo.command;
359 }
360
361 if (0 == t_length) {
362 io_hdr.dxfer_dir = DXFER_NONE;
363 io_hdr.dxfer_len = 0;
364 } else if (t_dir) { /* from device */
366 io_hdr.dxfer_len = in.size;
367 io_hdr.dxferp = (unsigned char *)in.buffer;
368 memset(in.buffer, 0, in.size); // prefill with zeroes
369 } else { /* to device */
370 io_hdr.dxfer_dir = DXFER_TO_DEVICE;
371 io_hdr.dxfer_len = in.size;
372 io_hdr.dxferp = (unsigned char *)in.buffer;
373 }
374 io_hdr.cmnd = cdb;
375 io_hdr.cmnd_len = passthru_size;
376 io_hdr.sensep = sense;
377 io_hdr.max_sense_len = sizeof(sense);
379
380 scsi_device * scsidev = get_tunnel_dev();
381 if (!scsidev->scsi_pass_through(&io_hdr)) {
382 if (scsi_debugmode > 0)
383 pout("sat_device::ata_pass_through: scsi_pass_through() failed, "
384 "errno=%d [%s]\n", scsidev->get_errno(), scsidev->get_errmsg());
385 return set_err(scsidev->get_err());
386 }
387 ardp = NULL;
388 ard_len = 0;
389 have_sense = sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len,
390 &ssh);
391 if (have_sense) {
392 sense_descriptor = ssh.response_code >= 0x72;
393 if (sense_descriptor) {
394 /* look for SAT ATA Return Descriptor */
395 ardp = sg_scsi_sense_desc_find(io_hdr.sensep,
396 io_hdr.resp_sense_len,
398 if (ardp) {
399 ard_len = ardp[1] + 2;
400 if (ard_len < 12)
401 ard_len = 12;
402 else if (ard_len > 14)
403 ard_len = 14;
404 }
405 }
406 scsi_do_sense_disect(&io_hdr, &sinfo);
407 int status = scsiSimpleSenseFilter(&sinfo);
408
409 // Workaround for bogus sense_key in sense data with SAT ATA Return Descriptor
410 if ( status && ck_cond && ardp && ard_len > 13
411 && (ardp[13] & 0xc1) == 0x40 /* !BSY && DRDY && !ERR */) {
412 if (scsi_debugmode > 0)
413 pout("ATA status (0x%02x) indicates success, ignoring SCSI sense_key\n",
414 ardp[13]);
415 status = 0;
416 }
417
418 if (0 != status) { /* other than no_sense and recovered_error */
419 if (scsi_debugmode > 0) {
420 pout("sat_device::ata_pass_through: scsi error: %s\n",
421 scsiErrString(status));
422 if (ardp && (scsi_debugmode > 1)) {
423 pout("Values from ATA Return Descriptor are:\n");
424 dStrHex((const uint8_t *)ardp, ard_len, 1);
425 }
426 }
427 if (t_dir && (t_length > 0) && (in.direction == ata_cmd_in::data_in))
428 memset(in.buffer, 0, in.size);
429 return set_err(EIO, "scsi error %s", scsiErrString(status));
430 }
431 }
432 if (ck_cond) { /* expecting SAT specific sense data */
433 if (have_sense) {
434 if (ardp) {
435 if (scsi_debugmode > 1) {
436 pout("Values from ATA Return Descriptor are:\n");
437 dStrHex((const uint8_t *)ardp, ard_len, 1);
438 }
439 // Set output registers
440 ata_out_regs & lo = out.out_regs;
441 lo.error = ardp[ 3];
442 lo.sector_count = ardp[ 5];
443 lo.lba_low = ardp[ 7];
444 lo.lba_mid = ardp[ 9];
445 lo.lba_high = ardp[11];
446 lo.device = ardp[12];
447 lo.status = ardp[13];
448 if (in.in_regs.is_48bit_cmd()) {
449 ata_out_regs & hi = out.out_regs.prev;
450 hi.sector_count = ardp[ 4];
451 hi.lba_low = ardp[ 6];
452 hi.lba_mid = ardp[ 8];
453 hi.lba_high = ardp[10];
454 }
455 } else if ((! sense_descriptor) &&
456 (0 == ssh.asc) &&
458 (0 != io_hdr.sensep[4] /* Some ATA STATUS bit must be set */)) {
459 /* in SAT-2 and later, ATA registers may be passed back via
460 * fixed format sense data [ref: sat3r07 section 12.2.2.7] */
461 ata_out_regs & lo = out.out_regs;
462 lo.error = io_hdr.sensep[ 3];
463 lo.status = io_hdr.sensep[ 4];
464 lo.device = io_hdr.sensep[ 5];
465 lo.sector_count = io_hdr.sensep[ 6];
466 lo.lba_low = io_hdr.sensep[ 9];
467 lo.lba_mid = io_hdr.sensep[10];
468 lo.lba_high = io_hdr.sensep[11];
469 if (in.in_regs.is_48bit_cmd()) {
470 if (0 == (0x60 & io_hdr.sensep[8])) {
471 ata_out_regs & hi = out.out_regs.prev;
472 hi.sector_count = 0;
473 hi.lba_low = 0;
474 hi.lba_mid = 0;
475 hi.lba_high = 0;
476 } else {
477 /* getting the "hi." values when either
478 * count_upper_nonzero or lba_upper_nonzero are set
479 * involves fetching the SCSI ATA PASS-THROUGH
480 * Results log page and decoding the descriptor with
481 * the matching log_index field. Painful. */
482 }
483 }
484 }
485 }
486 } else { /* ck_cond == 0 */
487 if (have_sense) {
488 if (((SCSI_SK_NO_SENSE == ssh.sense_key) ||
490 (0 == ssh.asc) &&
492 if (scsi_debugmode > 0) {
493 if (sense_descriptor && ardp) {
494 pout("Values from ATA Return Descriptor are:\n");
495 dStrHex((const uint8_t *)ardp, ard_len, 1);
496 } else if (! sense_descriptor) {
497 pout("Values from ATA fixed format sense are:\n");
498 pout(" Error: 0x%x\n", io_hdr.sensep[3]);
499 pout(" Status: 0x%x\n", io_hdr.sensep[4]);
500 pout(" Device: 0x%x\n", io_hdr.sensep[5]);
501 pout(" Count: 0x%x\n", io_hdr.sensep[6]);
502 }
503 }
504 }
505 return set_err(EIO, "SAT command failed");
506 }
507 }
508 return true;
509}
510
512{
513 scsi_device * scsidev = get_tunnel_dev();
514 if (!scsidev->scsi_pass_through(iop))
515 return set_err(scsidev->get_err());
516 return true;
517}
518
520{
521 if (!open() || m_mode != sat_auto)
522 return this;
523
524 scsi_device * scsidev = get_tunnel_dev();
525
526 unsigned char inqdata[36] = {0, };
527 if (scsiStdInquiry(scsidev, inqdata, sizeof(inqdata))) {
528 smart_device::error_info err = scsidev->get_err();
529 close();
530 set_err(err.no, "INQUIRY [SAT]: %s", err.msg.c_str());
531 return this;
532 }
533
534 // Check for SAT "VENDOR"
535 int inqsize = inqdata[4] + 5;
536 bool sat = (inqsize >= 36 && !memcmp(inqdata + 8, "ATA ", 8));
537
538 // Change interface
539 hide_ata(!sat);
540 hide_scsi(sat);
541
542 set_info().dev_type = (sat ? "sat" : scsidev->get_dev_type());
543 set_info().info_name = strprintf("%s [%s]", scsidev->get_info_name(),
544 (sat ? "SAT" : "SCSI"));
545 return this;
546}
547
548} // namespace
549
550/////////////////////////////////////////////////////////////////////////////
551
552/* Attempt an IDENTIFY DEVICE ATA command via SATL when packet_interface
553 is false otherwise attempt IDENTIFY PACKET DEVICE. If successful
554 return true, else false */
555
556static bool has_sat_pass_through(ata_device * dev, bool packet_interface = false)
557{
558 /* Note: malloc() ensures the read buffer lands on a single
559 page. This avoids some bugs seen on LSI controllers under
560 FreeBSD */
561 char *data = (char *)malloc(512);
562 ata_cmd_in in;
564 in.set_data_in(data, 1);
565 bool ret = dev->ata_pass_through(in);
566 free(data);
567 return ret;
568}
569
570/////////////////////////////////////////////////////////////////////////////
571
572/* Next two functions are borrowed from sg_lib.c in the sg3_utils
573 package. Same copyrght owner, same license as this file. */
574static int sg_scsi_normalize_sense(const unsigned char * sensep, int sb_len,
575 struct sg_scsi_sense_hdr * sshp)
576{
577 if (sshp)
578 memset(sshp, 0, sizeof(struct sg_scsi_sense_hdr));
579 if ((NULL == sensep) || (0 == sb_len) || (0x70 != (0x70 & sensep[0])))
580 return 0;
581 if (sshp) {
582 sshp->response_code = (0x7f & sensep[0]);
583 if (sshp->response_code >= 0x72) { /* descriptor format */
584 if (sb_len > 1)
585 sshp->sense_key = (0xf & sensep[1]);
586 if (sb_len > 2)
587 sshp->asc = sensep[2];
588 if (sb_len > 3)
589 sshp->ascq = sensep[3];
590 if (sb_len > 7)
591 sshp->additional_length = sensep[7];
592 } else { /* fixed format */
593 if (sb_len > 2)
594 sshp->sense_key = (0xf & sensep[2]);
595 if (sb_len > 7) {
596 sb_len = (sb_len < (sensep[7] + 8)) ? sb_len :
597 (sensep[7] + 8);
598 if (sb_len > 12)
599 sshp->asc = sensep[12];
600 if (sb_len > 13)
601 sshp->ascq = sensep[13];
602 }
603 }
604 }
605 return 1;
606}
607
608/////////////////////////////////////////////////////////////////////////////
609
610namespace sat {
611
612/// Cypress USB Bridge support.
613
615: public tunnelled_device<
616 /*implements*/ ata_device_with_command_set
617 /*by tunnelling through a*/, scsi_device
618 >
619{
620public:
622 const char * req_type, unsigned char signature);
623
624 virtual ~usbcypress_device();
625
626protected:
627 virtual int ata_command_interface(smart_command_set command, int select, char * data) override;
628
629 unsigned char m_signature;
630};
631
632
634 const char * req_type, unsigned char signature)
635: smart_device(intf, scsidev->get_dev_name(), "usbcypress", req_type),
637 m_signature(signature)
638{
639 set_info().info_name = strprintf("%s [USB Cypress]", scsidev->get_info_name());
640}
641
643{
644}
645
646
647/* see cy7c68300c_8.pdf for more information */
648#define USBCYPRESS_PASSTHROUGH_LEN 16
650{
651 struct scsi_cmnd_io io_hdr = {};
652 unsigned char cdb[USBCYPRESS_PASSTHROUGH_LEN] = {};
653 unsigned char sense[32] = {};
654 int copydata = 0;
655 int outlen = 0;
656 int ck_cond = 0; /* set to 1 to read register(s) back */
657 int t_dir = 1; /* 0 -> to device, 1 -> from device */
658 int byte_block = 1; /* 0 -> bytes, 1 -> 512 byte blocks */
659 int t_length = 0; /* 0 -> no data transferred */
660 int feature = 0;
661 int ata_command = 0;
662 int sector_count = 0;
663 int lba_low = 0;
664 int lba_mid = 0;
665 int lba_high = 0;
666 int passthru_size = USBCYPRESS_PASSTHROUGH_LEN;
667
668 ata_command = ATA_SMART_CMD;
669 switch (command) {
670 case CHECK_POWER_MODE:
671 ata_command = ATA_CHECK_POWER_MODE;
672 ck_cond = 1;
673 copydata = 1;
674 break;
675 case READ_VALUES: /* READ DATA */
676 feature = ATA_SMART_READ_VALUES;
677 sector_count = 1; /* one (512 byte) block */
678 t_length = 2; /* sector count holds count */
679 copydata = 512;
680 break;
681 case READ_THRESHOLDS: /* obsolete */
683 sector_count = 1; /* one (512 byte) block */
684 lba_low = 1;
685 t_length = 2; /* sector count holds count */
686 copydata=512;
687 break;
688 case READ_LOG:
690 sector_count = 1; /* one (512 byte) block */
691 lba_low = select;
692 t_length = 2; /* sector count holds count */
693 copydata = 512;
694 break;
695 case WRITE_LOG:
697 sector_count = 1; /* one (512 byte) block */
698 lba_low = select;
699 t_length = 2; /* sector count holds count */
700 t_dir = 0; /* to device */
701 outlen = 512;
702 break;
703 case IDENTIFY:
704 ata_command = ATA_IDENTIFY_DEVICE;
705 sector_count = 1; /* one (512 byte) block */
706 t_length = 2; /* sector count holds count */
707 copydata = 512;
708 break;
709 case PIDENTIFY:
710 ata_command = ATA_IDENTIFY_PACKET_DEVICE;
711 sector_count = 1; /* one (512 byte) block */
712 t_length = 2; /* sector count (7:0) holds count */
713 copydata = 512;
714 break;
715 case ENABLE:
716 feature = ATA_SMART_ENABLE;
717 lba_low = 1;
718 break;
719 case DISABLE:
720 feature = ATA_SMART_DISABLE;
721 lba_low = 1;
722 break;
723 case STATUS:
724 // this command only says if SMART is working. It could be
725 // replaced with STATUS_CHECK below.
726 feature = ATA_SMART_STATUS;
727 ck_cond = 1;
728 break;
729 case AUTO_OFFLINE:
730 feature = ATA_SMART_AUTO_OFFLINE;
731 sector_count = select; // YET NOTE - THIS IS A NON-DATA COMMAND!!
732 break;
733 case AUTOSAVE:
734 feature = ATA_SMART_AUTOSAVE;
735 sector_count = select; // YET NOTE - THIS IS A NON-DATA COMMAND!!
736 break;
739 lba_low = select;
740 break;
741 case STATUS_CHECK:
742 // This command uses HDIO_DRIVE_TASK and has different syntax than
743 // the other commands.
744 feature = ATA_SMART_STATUS; /* SMART RETURN STATUS */
745 ck_cond = 1;
746 break;
747 default:
748 pout("Unrecognized command %d in usbcypress_device::ata_command_interface()\n"
749 "Please contact " PACKAGE_BUGREPORT "\n", command);
750 errno=ENOSYS;
751 return -1;
752 }
753 if (ATA_SMART_CMD == ata_command) {
754 lba_mid = 0x4f;
755 lba_high = 0xc2;
756 }
757
758 cdb[0] = m_signature; // bVSCBSignature : vendor-specific command
759 cdb[1] = 0x24; // bVSCBSubCommand : 0x24 for ATACB
760 cdb[2] = 0x0;
761 if (ata_command == ATA_IDENTIFY_DEVICE || ata_command == ATA_IDENTIFY_PACKET_DEVICE)
762 cdb[2] |= (1<<7); //set IdentifyPacketDevice for these cmds
763 cdb[3] = 0xff - (1<<0) - (1<<6); //features, sector count, lba low, lba med
764 // lba high, command are valid
765 cdb[4] = byte_block; //TransferBlockCount : 512
766
767
768 cdb[6] = feature;
769 cdb[7] = sector_count;
770 cdb[8] = lba_low;
771 cdb[9] = lba_mid;
772 cdb[10] = lba_high;
773 cdb[12] = ata_command;
774
775 if (0 == t_length) {
776 io_hdr.dxfer_dir = DXFER_NONE;
777 io_hdr.dxfer_len = 0;
778 } else if (t_dir) { /* from device */
780 io_hdr.dxfer_len = copydata;
781 io_hdr.dxferp = (unsigned char *)data;
782 memset(data, 0, copydata); /* prefill with zeroes */
783 } else { /* to device */
784 io_hdr.dxfer_dir = DXFER_TO_DEVICE;
785 io_hdr.dxfer_len = outlen;
786 io_hdr.dxferp = (unsigned char *)data;
787 }
788 io_hdr.cmnd = cdb;
789 io_hdr.cmnd_len = passthru_size;
790 io_hdr.sensep = sense;
791 io_hdr.max_sense_len = sizeof(sense);
793
794 scsi_device * scsidev = get_tunnel_dev();
795 if (!scsidev->scsi_pass_through(&io_hdr)) {
796 if (scsi_debugmode > 0)
797 pout("usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
798 "errno=%d [%s]\n", scsidev->get_errno(), scsidev->get_errmsg());
799 set_err(scsidev->get_err());
800 return -1;
801 }
802
803 // if there is a sense the command failed or the
804 // device doesn't support usbcypress
806 sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len, NULL)) {
807 return -1;
808 }
809 if (ck_cond) {
810 unsigned char ardp[8];
811 int ard_len = 8;
812 /* XXX this is racy if there other scsi command between
813 * the first usbcypress command and this one
814 */
815 //pout("If you got strange result, please retry without traffic on the disc\n");
816 /* we use the same command as before, but we set
817 * * the read taskfile bit, for not executing usbcypress command,
818 * * but reading register selected in srb->cmnd[4]
819 */
820 cdb[2] = (1<<0); /* ask read taskfile */
821 memset(sense, 0, sizeof(sense));
822
823 /* transfer 8 bytes */
824 memset(&io_hdr, 0, sizeof(io_hdr));
826 io_hdr.dxfer_len = ard_len;
827 io_hdr.dxferp = (unsigned char *)ardp;
828 memset(ardp, 0, ard_len); /* prefill with zeroes */
829
830 io_hdr.cmnd = cdb;
831 io_hdr.cmnd_len = passthru_size;
832 io_hdr.sensep = sense;
833 io_hdr.max_sense_len = sizeof(sense);
835
836
837 if (!scsidev->scsi_pass_through(&io_hdr)) {
838 if (scsi_debugmode > 0)
839 pout("usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
840 "errno=%d [%s]\n", scsidev->get_errno(), scsidev->get_errmsg());
841 set_err(scsidev->get_err());
842 return -1;
843 }
844 // if there is a sense the command failed or the
845 // device doesn't support usbcypress
847 sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len, NULL)) {
848 return -1;
849 }
850
851
852 if (scsi_debugmode > 1) {
853 pout("Values from ATA Return Descriptor are:\n");
854 dStrHex((const uint8_t *)ardp, ard_len, 1);
855 }
856
857 if (ATA_CHECK_POWER_MODE == ata_command)
858 data[0] = ardp[2]; /* sector count (0:7) */
859 else if (STATUS_CHECK == command) {
860 if ((ardp[4] == 0x4f) && (ardp[5] == 0xc2))
861 return 0; /* GOOD smart status */
862 if ((ardp[4] == 0xf4) && (ardp[5] == 0x2c))
863 return 1; // smart predicting failure, "bad" status
864 // We haven't gotten output that makes sense so
865 // print out some debugging info
866 syserror("Error SMART Status command failed");
867 pout("This may be due to a race in usbcypress\n");
868 pout("Retry without other disc access\n");
869 pout("Please get assistance from " PACKAGE_URL "\n");
870 pout("Values from ATA Return Descriptor are:\n");
871 dStrHex((const uint8_t *)ardp, ard_len, 1);
872 return -1;
873 }
874 }
875 return 0;
876}
877
878/////////////////////////////////////////////////////////////////////////////
879
880/// JMicron USB Bridge support.
881
883: public tunnelled_device<
884 /*implements*/ ata_device,
885 /*by tunnelling through a*/ scsi_device
886 >
887{
888public:
890 const char * req_type, bool prolific,
891 bool ata_48bit_support, int port);
892
893 virtual ~usbjmicron_device();
894
895 virtual bool open() override;
896
897 virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override;
898
899private:
900 bool get_registers(unsigned short addr, unsigned char * buf, unsigned short size);
901
905};
906
907
909 const char * req_type, bool prolific,
910 bool ata_48bit_support, int port)
911: smart_device(intf, scsidev->get_dev_name(), "usbjmicron", req_type),
913 m_prolific(prolific), m_ata_48bit_support(ata_48bit_support),
914 m_port(port >= 0 || !prolific ? port : 0)
915{
916 set_info().info_name = strprintf("%s [USB JMicron]", scsidev->get_info_name());
917}
918
920{
921}
922
923
925{
926 // Open USB first
928 return false;
929
930 // Detect port if not specified
931 if (m_port < 0) {
932 unsigned char regbuf[1] = {0};
933 if (!get_registers(0x720f, regbuf, sizeof(regbuf))) {
934 close();
935 return false;
936 }
937
938 switch (regbuf[0] & 0x44) {
939 case 0x04:
940 m_port = 0; break;
941 case 0x40:
942 m_port = 1; break;
943 case 0x44:
944 close();
945 return set_err(EINVAL, "Two devices connected, try '-d usbjmicron,[01]'");
946 default:
947 close();
948 return set_err(ENODEV, "No device connected");
949 }
950 }
951
952 return true;
953}
954
955
957{
958 if (!ata_cmd_is_supported(in,
962 "JMicron")
963 )
964 return false;
965
966 if (m_port < 0)
967 return set_err(EIO, "Unknown JMicron port");
968
969 scsi_cmnd_io io_hdr = {};
970
971 bool rwbit = true;
972 unsigned char smart_status = 0xff;
973
974 bool is_smart_status = ( in.in_regs.command == ATA_SMART_CMD
976
977 if (is_smart_status && in.out_needed.is_set()) {
979 io_hdr.dxfer_len = 1;
980 io_hdr.dxferp = &smart_status;
981 }
982 else switch (in.direction) {
984 io_hdr.dxfer_dir = DXFER_NONE;
985 break;
988 io_hdr.dxfer_len = in.size;
989 io_hdr.dxferp = (unsigned char *)in.buffer;
990 memset(in.buffer, 0, in.size);
991 break;
993 io_hdr.dxfer_dir = DXFER_TO_DEVICE;
994 io_hdr.dxfer_len = in.size;
995 io_hdr.dxferp = (unsigned char *)in.buffer;
996 rwbit = false;
997 break;
998 default:
999 return set_err(EINVAL);
1000 }
1001
1002 // Build pass through command
1003 unsigned char cdb[14];
1004 cdb[ 0] = 0xdf;
1005 cdb[ 1] = (rwbit ? 0x10 : 0x00);
1006 cdb[ 2] = 0x00;
1007 sg_put_unaligned_be16(io_hdr.dxfer_len, cdb + 3);
1008 cdb[ 5] = in.in_regs.features;
1009 cdb[ 6] = in.in_regs.sector_count;
1010 cdb[ 7] = in.in_regs.lba_low;
1011 cdb[ 8] = in.in_regs.lba_mid;
1012 cdb[ 9] = in.in_regs.lba_high;
1013 cdb[10] = in.in_regs.device | (m_port == 0 ? 0xa0 : 0xb0);
1014 cdb[11] = in.in_regs.command;
1015 // Prolific PL3507
1016 cdb[12] = 0x06;
1017 cdb[13] = 0x7b;
1018
1019 io_hdr.cmnd = cdb;
1020 io_hdr.cmnd_len = (!m_prolific ? 12 : 14);
1021
1022 scsi_device * scsidev = get_tunnel_dev();
1023 if (!scsidev->scsi_pass_through_and_check(&io_hdr,
1024 "usbjmicron_device::ata_pass_through: "))
1025 return set_err(scsidev->get_err());
1026
1027 if (in.out_needed.is_set()) {
1028 if (is_smart_status) {
1029 if (io_hdr.resid == 1)
1030 // Some (Prolific) USB bridges do not transfer a status byte
1031 return set_err(ENOSYS, "Incomplete response, status byte missing [JMicron]");
1032
1033 switch (smart_status) {
1034 case 0xc2:
1035 out.out_regs.lba_high = 0xc2;
1036 out.out_regs.lba_mid = 0x4f;
1037 break;
1038 case 0x2c:
1039 out.out_regs.lba_high = 0x2c;
1040 out.out_regs.lba_mid = 0xf4;
1041 break;
1042 default:
1043 // Some (JM20336) USB bridges always return 0x01, regardless of SMART Status
1044 return set_err(ENOSYS, "Invalid status byte (0x%02x) [JMicron]", smart_status);
1045 }
1046 }
1047
1048#if 0 // Not needed for SMART STATUS, see also notes below
1049 else {
1050 // Read ATA output registers
1051 // NOTE: The register addresses are not valid for some older chip revisions
1052 // NOTE: There is a small race condition here!
1053 unsigned char regbuf[16] = {0, };
1054 if (!get_registers((m_port == 0 ? 0x8000 : 0x9000), regbuf, sizeof(regbuf)))
1055 return false;
1056
1057 out.out_regs.sector_count = regbuf[ 0];
1058 out.out_regs.lba_mid = regbuf[ 4];
1059 out.out_regs.lba_low = regbuf[ 6];
1060 out.out_regs.device = regbuf[ 9];
1061 out.out_regs.lba_high = regbuf[10];
1062 out.out_regs.error = regbuf[13];
1063 out.out_regs.status = regbuf[14];
1064 }
1065#endif
1066 }
1067
1068 return true;
1069}
1070
1072 unsigned char * buf, unsigned short size)
1073{
1074 unsigned char cdb[14];
1075 cdb[ 0] = 0xdf;
1076 cdb[ 1] = 0x10;
1077 cdb[ 2] = 0x00;
1079 cdb[ 5] = 0x00;
1081 cdb[ 8] = 0x00;
1082 cdb[ 9] = 0x00;
1083 cdb[10] = 0x00;
1084 cdb[11] = 0xfd;
1085 // Prolific PL3507
1086 cdb[12] = 0x06;
1087 cdb[13] = 0x7b;
1088
1089 scsi_cmnd_io io_hdr = {};
1091 io_hdr.dxfer_len = size;
1092 io_hdr.dxferp = buf;
1093 io_hdr.cmnd = cdb;
1094 io_hdr.cmnd_len = (!m_prolific ? 12 : 14);
1095
1096 scsi_device * scsidev = get_tunnel_dev();
1097 if (!scsidev->scsi_pass_through_and_check(&io_hdr,
1098 "usbjmicron_device::get_registers: "))
1099 return set_err(scsidev->get_err());
1100
1101 return true;
1102}
1103
1104
1105/////////////////////////////////////////////////////////////////////////////
1106
1107/// Prolific USB Bridge support. (PL2773) (Probably works on PL2771 also...)
1108
1110: public tunnelled_device<
1111 /*implements*/ ata_device,
1112 /*by tunnelling through a*/ scsi_device
1113 >
1114{
1115public:
1117 const char * req_type);
1118
1119 virtual ~usbprolific_device();
1120
1121 virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override;
1122};
1123
1124
1126 const char * req_type)
1127: smart_device(intf, scsidev->get_dev_name(), "usbprolific", req_type),
1129{
1130 set_info().info_name = strprintf("%s [USB Prolific]", scsidev->get_info_name());
1131}
1132
1134{
1135}
1136
1138{
1139 if (!ata_cmd_is_supported(in,
1144 "Prolific" )
1145 )
1146 return false;
1147
1148 scsi_cmnd_io io_hdr = {};
1149 unsigned char cmd_rw = 0x10; // Read
1150
1151 switch (in.direction) {
1153 io_hdr.dxfer_dir = DXFER_NONE;
1154 break;
1157 io_hdr.dxfer_len = in.size;
1158 io_hdr.dxferp = (unsigned char *)in.buffer;
1159 memset(in.buffer, 0, in.size);
1160 break;
1162 io_hdr.dxfer_dir = DXFER_TO_DEVICE;
1163 io_hdr.dxfer_len = in.size;
1164 io_hdr.dxferp = (unsigned char *)in.buffer;
1165 cmd_rw = 0x0; // Write
1166 break;
1167 default:
1168 return set_err(EINVAL);
1169 }
1170
1171 // Based on reverse engineering of iSmart.exe with API Monitor.
1172 // Seen commands:
1173 // D0 0 0 0 06 7B 0 0 0 0 0 0 // Read Firmware info?, reads 16 bytes
1174 // F4 0 0 0 06 7B // ??
1175 // D8 15 0 D8 06 7B 0 0 0 0 1 1 4F C2 A0 B0 // SMART Enable
1176 // D8 15 0 D0 06 7B 0 0 2 0 1 1 4F C2 A0 B0 // SMART Read values
1177 // D8 15 0 D1 06 7B 0 0 2 0 1 1 4F C2 A0 B0 // SMART Read thresholds
1178 // D8 15 0 D4 06 7B 0 0 0 0 0 1 4F C2 A0 B0 // SMART Execute self test
1179 // D7 0 0 0 06 7B 0 0 0 0 0 0 0 0 0 0 // Read status registers, Reads 16 bytes of data
1180 // Additional DATA OUT support based on document from Prolific
1181
1182 // Build pass through command
1183 unsigned char cdb[16];
1184 cdb[ 0] = 0xD8; // Operation Code (D8 = Prolific ATA pass through)
1185 cdb[ 1] = cmd_rw|0x5; // Read(0x10)/Write(0x0) | NORMAL(0x5)/PREFIX(0x0)(?)
1186 cdb[ 2] = 0x0; // Reserved
1187 cdb[ 3] = in.in_regs.features; // Feature register (SMART command)
1188 cdb[ 4] = 0x06; // Check Word (VendorID magic, Prolific: 0x067B)
1189 cdb[ 5] = 0x7B; // Check Word (VendorID magic, Prolific: 0x067B)
1190 sg_put_unaligned_be32(io_hdr.dxfer_len, cdb + 6);
1191 cdb[10] = in.in_regs.sector_count; // Sector Count
1192 cdb[11] = in.in_regs.lba_low; // LBA Low (7:0)
1193 cdb[12] = in.in_regs.lba_mid; // LBA Mid (15:8)
1194 cdb[13] = in.in_regs.lba_high; // LBA High (23:16)
1195 cdb[14] = in.in_regs.device | 0xA0; // Device/Head
1196 cdb[15] = in.in_regs.command; // ATA Command Register (only PIO supported)
1197 // Use '-r scsiioctl,1' to print CDB for debug purposes
1198
1199 io_hdr.cmnd = cdb;
1200 io_hdr.cmnd_len = 16;
1201
1202 scsi_device * scsidev = get_tunnel_dev();
1203 if (!scsidev->scsi_pass_through_and_check(&io_hdr,
1204 "usbprolific_device::ata_pass_through: "))
1205 return set_err(scsidev->get_err());
1206
1207 if (in.out_needed.is_set()) {
1208 // Read ATA output registers
1209 unsigned char regbuf[16] = {0, };
1210 memset(&io_hdr, 0, sizeof(io_hdr));
1212 io_hdr.dxfer_len = sizeof(regbuf);
1213 io_hdr.dxferp = regbuf;
1214
1215 memset(cdb, 0, sizeof(cdb));
1216 cdb[ 0] = 0xD7; // Prolific read registers
1217 cdb[ 4] = 0x06; // Check Word (VendorID magic, Prolific: 0x067B)
1218 cdb[ 5] = 0x7B; // Check Word (VendorID magic, Prolific: 0x067B)
1219 io_hdr.cmnd = cdb;
1220 io_hdr.cmnd_len = sizeof(cdb);
1221
1222 if (!scsidev->scsi_pass_through_and_check(&io_hdr,
1223 "usbprolific_device::scsi_pass_through (get registers): "))
1224 return set_err(scsidev->get_err());
1225
1226 // Use '-r scsiioctl,2' to print input registers for debug purposes
1227 // Example: 50 00 00 00 00 01 4f 00 c2 00 a0 da 00 b0 00 50
1228 out.out_regs.status = regbuf[0]; // Status
1229 out.out_regs.error = regbuf[1]; // Error
1230 out.out_regs.sector_count = regbuf[2]; // Sector Count (7:0)
1231 out.out_regs.lba_low = regbuf[4]; // LBA Low (7:0)
1232 out.out_regs.lba_mid = regbuf[6]; // LBA Mid (7:0)
1233 out.out_regs.lba_high = regbuf[8]; // LBA High (7:0)
1234 out.out_regs.device = regbuf[10]; // Device/Head
1235 // = regbuf[11]; // ATA Feature (7:0)
1236 // = regbuf[13]; // ATA Command
1237 }
1238
1239 return true;
1240}
1241
1242
1243/////////////////////////////////////////////////////////////////////////////
1244
1245/// SunplusIT USB Bridge support.
1246
1248: public tunnelled_device<
1249 /*implements*/ ata_device,
1250 /*by tunnelling through a*/ scsi_device
1251 >
1252{
1253public:
1255 const char * req_type);
1256
1257 virtual ~usbsunplus_device();
1258
1259 virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override;
1260};
1261
1262
1264 const char * req_type)
1265: smart_device(intf, scsidev->get_dev_name(), "usbsunplus", req_type),
1267{
1268 set_info().info_name = strprintf("%s [USB Sunplus]", scsidev->get_info_name());
1269}
1270
1272{
1273}
1274
1276{
1277 if (!ata_cmd_is_supported(in,
1281 "Sunplus")
1282 )
1283 return false;
1284
1285 scsi_cmnd_io io_hdr = {};
1286 unsigned char cdb[12];
1287
1288 if (in.in_regs.is_48bit_cmd()) {
1289 // Set "previous" registers
1290 io_hdr.dxfer_dir = DXFER_NONE;
1291
1292 cdb[ 0] = 0xf8;
1293 cdb[ 1] = 0x00;
1294 cdb[ 2] = 0x23; // Subcommand: Pass through presetting
1295 cdb[ 3] = 0x00;
1296 cdb[ 4] = 0x00;
1297 cdb[ 5] = in.in_regs.prev.features;
1298 cdb[ 6] = in.in_regs.prev.sector_count;
1299 cdb[ 7] = in.in_regs.prev.lba_low;
1300 cdb[ 8] = in.in_regs.prev.lba_mid;
1301 cdb[ 9] = in.in_regs.prev.lba_high;
1302 cdb[10] = 0x00;
1303 cdb[11] = 0x00;
1304
1305 io_hdr.cmnd = cdb;
1306 io_hdr.cmnd_len = sizeof(cdb);
1307
1308 scsi_device * scsidev = get_tunnel_dev();
1309 if (!scsidev->scsi_pass_through_and_check(&io_hdr,
1310 "usbsunplus_device::scsi_pass_through (presetting): "))
1311 return set_err(scsidev->get_err());
1312 }
1313
1314 // Run Pass through command
1315 memset(&io_hdr, 0, sizeof(io_hdr));
1316 unsigned char protocol;
1317 switch (in.direction) {
1319 io_hdr.dxfer_dir = DXFER_NONE;
1320 protocol = 0x00;
1321 break;
1324 io_hdr.dxfer_len = in.size;
1325 io_hdr.dxferp = (unsigned char *)in.buffer;
1326 memset(in.buffer, 0, in.size);
1327 protocol = 0x10;
1328 break;
1330 io_hdr.dxfer_dir = DXFER_TO_DEVICE;
1331 io_hdr.dxfer_len = in.size;
1332 io_hdr.dxferp = (unsigned char *)in.buffer;
1333 protocol = 0x11;
1334 break;
1335 default:
1336 return set_err(EINVAL);
1337 }
1338
1339 cdb[ 0] = 0xf8;
1340 cdb[ 1] = 0x00;
1341 cdb[ 2] = 0x22; // Subcommand: Pass through
1342 cdb[ 3] = protocol;
1343 cdb[ 4] = (unsigned char)(io_hdr.dxfer_len >> 9);
1344 cdb[ 5] = in.in_regs.features;
1345 cdb[ 6] = in.in_regs.sector_count;
1346 cdb[ 7] = in.in_regs.lba_low;
1347 cdb[ 8] = in.in_regs.lba_mid;
1348 cdb[ 9] = in.in_regs.lba_high;
1349 cdb[10] = in.in_regs.device | 0xa0;
1350 cdb[11] = in.in_regs.command;
1351
1352 io_hdr.cmnd = cdb;
1353 io_hdr.cmnd_len = sizeof(cdb);
1354
1355 scsi_device * scsidev = get_tunnel_dev();
1356 if (!scsidev->scsi_pass_through_and_check(&io_hdr,
1357 "usbsunplus_device::scsi_pass_through: "))
1358 // Returns sense key 0x03 (medium error) on ATA command error
1359 return set_err(scsidev->get_err());
1360
1361 if (in.out_needed.is_set()) {
1362 // Read ATA output registers
1363 unsigned char regbuf[8] = {0, };
1364 memset(&io_hdr, 0, sizeof(io_hdr));
1366 io_hdr.dxfer_len = sizeof(regbuf);
1367 io_hdr.dxferp = regbuf;
1368
1369 cdb[ 0] = 0xf8;
1370 cdb[ 1] = 0x00;
1371 cdb[ 2] = 0x21; // Subcommand: Get status
1372 memset(cdb+3, 0, sizeof(cdb)-3);
1373 io_hdr.cmnd = cdb;
1374 io_hdr.cmnd_len = sizeof(cdb);
1375
1376 if (!scsidev->scsi_pass_through_and_check(&io_hdr,
1377 "usbsunplus_device::scsi_pass_through (get registers): "))
1378 return set_err(scsidev->get_err());
1379
1380 out.out_regs.error = regbuf[1];
1381 out.out_regs.sector_count = regbuf[2];
1382 out.out_regs.lba_low = regbuf[3];
1383 out.out_regs.lba_mid = regbuf[4];
1384 out.out_regs.lba_high = regbuf[5];
1385 out.out_regs.device = regbuf[6];
1386 out.out_regs.status = regbuf[7];
1387 }
1388
1389 return true;
1390}
1391
1392
1393} // namespace
1394
1395using namespace sat;
1396
1397
1398/////////////////////////////////////////////////////////////////////////////
1399
1400// Return ATA->SCSI filter for SAT or USB.
1401
1403{
1404 if (!scsidev)
1405 throw std::logic_error("smart_interface: get_sat_device() called with scsidev=0");
1406
1407 // Take temporary ownership of 'scsidev' to delete it on error
1408 scsi_device_auto_ptr scsidev_holder(scsidev);
1409 ata_device * satdev = nullptr;
1410
1411 if (str_starts_with(type, "sat")) {
1412 const char * t = type + 3;
1414 if (str_starts_with(t, ",auto")) {
1415 t += 5;
1416 mode = sat_device::sat_auto;
1417 }
1418 int ptlen = 0, n = -1;
1419 if (*t && !(sscanf(t, ",%d%n", &ptlen, &n) == 1 && n == (int)strlen(t)
1420 && (ptlen == 0 || ptlen == 12 || ptlen == 16)))
1421 return set_err_np(EINVAL, "Option '-d sat[,auto][,N]' requires N to be 0, 12 or 16");
1422 satdev = new sat_device(this, scsidev, type, mode, ptlen);
1423 }
1424
1425 else if (!strcmp(type, "scsi")) {
1426 satdev = new sat_device(this, scsidev, type, sat_device::scsi_always);
1427 }
1428
1429 else if (str_starts_with(type, "usbcypress")) {
1430 unsigned signature = 0x24; int n1 = -1, n2 = -1;
1431 if (!(((sscanf(type, "usbcypress%n,0x%x%n", &n1, &signature, &n2) == 1 && n2 == (int)strlen(type))
1432 || n1 == (int)strlen(type)) && signature <= 0xff))
1433 return set_err_np(EINVAL, "Option '-d usbcypress,<n>' requires <n> to be "
1434 "an hexadecimal number between 0x0 and 0xff" );
1435 satdev = new usbcypress_device(this, scsidev, type, signature);
1436 }
1437
1438 else if (str_starts_with(type, "usbjmicron")) {
1439 const char * t = type + 10;
1440 bool prolific = false;
1441 if (str_starts_with(t, ",p")) {
1442 t += 2;
1443 prolific = true;
1444 }
1445 bool ata_48bit_support = false;
1446 if (str_starts_with(t, ",x")) {
1447 t += 2;
1448 ata_48bit_support = true;
1449 }
1450 int port = -1, n = -1;
1451 if (*t && !( (sscanf(t, ",%d%n", &port, &n) == 1
1452 && n == (int)strlen(t) && 0 <= port && port <= 1)))
1453 return set_err_np(EINVAL, "Option '-d usbjmicron[,p][,x],<n>' requires <n> to be 0 or 1");
1454 satdev = new usbjmicron_device(this, scsidev, type, prolific, ata_48bit_support, port);
1455 }
1456
1457 else if (!strcmp(type, "usbprolific")) {
1458 satdev = new usbprolific_device(this, scsidev, type);
1459 }
1460
1461 else if (!strcmp(type, "usbsunplus")) {
1462 satdev = new usbsunplus_device(this, scsidev, type);
1463 }
1464
1465 else if (str_starts_with(type, "usbasm1352r")) {
1466 unsigned port = ~0; int n = -1;
1467 if (!(sscanf(type, "usbasm1352r,%u%n", &port, &n) == 1 && n == (int)strlen(type) && port <= 1))
1468 return set_err_np(EINVAL, "Option '-d usbasm1352r,<n>' requires <n> to be 0 or 1");
1469 satdev = new sat_device(this, scsidev, type, sat_device::sat_always, 0, sat_device::sat_asm1352r, port);
1470 }
1471
1472 else {
1473 return set_err_np(EINVAL, "Unknown USB device type '%s'", type);
1474 }
1475
1476 // 'scsidev' is now owned by 'satdev'
1477 scsidev_holder.release();
1478 return satdev;
1479}
1480
1481// Try to detect a SAT device behind a SCSI interface.
1482
1484 const unsigned char * inqdata, unsigned inqsize)
1485{
1486 if (!scsidev->is_open())
1487 return 0;
1488
1489 // SAT ?
1490 if (inqdata && inqsize >= 36 && !memcmp(inqdata + 8, "ATA ", 8)) {
1491 // TODO: Linux-specific? No, all SAT standards say the 'T10 Vendor
1492 // Identification' field shall be 'ATA '.
1493 ata_device_auto_ptr atadev( new sat_device(this, scsidev, "") , scsidev);
1494 if (has_sat_pass_through(atadev.get()))
1495 return atadev.release(); // Detected SAT
1496 }
1497
1498 return 0;
1499}
1500
1501
1502/////////////////////////////////////////////////////////////////////////////
1503// USB device type detection
1504
1505// Format USB ID for error messages
1506static std::string format_usb_id(int vendor_id, int product_id, int version)
1507{
1508 if (version >= 0)
1509 return strprintf("[0x%04x:0x%04x (0x%03x)]", vendor_id, product_id, version);
1510 else
1511 return strprintf("[0x%04x:0x%04x]", vendor_id, product_id);
1512}
1513
1514// Get type name for USB device with known VENDOR:PRODUCT ID.
1515const char * smart_interface::get_usb_dev_type_by_id(int vendor_id, int product_id,
1516 int version /*= -1*/)
1517{
1518 usb_dev_info info, info2;
1519 int n = lookup_usb_device(vendor_id, product_id, version, info, info2);
1520
1521 if (n <= 0) {
1522 set_err(EINVAL, "Unknown USB bridge %s",
1523 format_usb_id(vendor_id, product_id, version).c_str());
1524 return 0;
1525 }
1526
1527 if (n > 1) {
1528 set_err(EINVAL, "USB bridge %s type is ambiguous: '%s' or '%s'",
1529 format_usb_id(vendor_id, product_id, version).c_str(),
1530 (!info.usb_type.empty() ? info.usb_type.c_str() : "[unsupported]"),
1531 (!info2.usb_type.empty() ? info2.usb_type.c_str() : "[unsupported]"));
1532 return 0;
1533 }
1534
1535 if (info.usb_type.empty()) {
1536 set_err(ENOSYS, "Unsupported USB bridge %s",
1537 format_usb_id(vendor_id, product_id, version).c_str());
1538 return 0;
1539 }
1540
1541 // TODO: change return type to std::string
1542 static std::string type;
1543 type = info.usb_type;
1544 return type.c_str();
1545}
#define ATA_SMART_AUTO_OFFLINE
Definition: atacmds.h:94
#define ATA_IDENTIFY_DEVICE
Definition: atacmds.h:53
#define ATA_SMART_WRITE_LOG_SECTOR
Definition: atacmds.h:87
#define ATA_IDENTIFY_PACKET_DEVICE
Definition: atacmds.h:54
#define ATA_SMART_STATUS
Definition: atacmds.h:91
#define ATA_SMART_READ_VALUES
Definition: atacmds.h:81
#define ATA_SMART_READ_THRESHOLDS
Definition: atacmds.h:82
#define ATA_SMART_READ_LOG_SECTOR
Definition: atacmds.h:86
#define ATA_SMART_CMD
Definition: atacmds.h:56
#define ATA_SMART_IMMEDIATE_OFFLINE
Definition: atacmds.h:85
smart_command_set
Definition: atacmds.h:29
@ PIDENTIFY
Definition: atacmds.h:43
@ CHECK_POWER_MODE
Definition: atacmds.h:45
@ IDENTIFY
Definition: atacmds.h:42
@ STATUS_CHECK
Definition: atacmds.h:37
@ IMMEDIATE_OFFLINE
Definition: atacmds.h:34
@ AUTO_OFFLINE
Definition: atacmds.h:35
@ ENABLE
Definition: atacmds.h:31
@ WRITE_LOG
Definition: atacmds.h:47
@ READ_VALUES
Definition: atacmds.h:39
@ AUTOSAVE
Definition: atacmds.h:33
@ STATUS
Definition: atacmds.h:36
@ READ_THRESHOLDS
Definition: atacmds.h:40
@ DISABLE
Definition: atacmds.h:32
@ READ_LOG
Definition: atacmds.h:41
#define ATA_SMART_ENABLE
Definition: atacmds.h:89
#define ATA_SMART_AUTOSAVE
Definition: atacmds.h:83
#define ATA_SMART_DISABLE
Definition: atacmds.h:90
#define ATA_CHECK_POWER_MODE
Definition: atacmds.h:52
Smart pointer class for device pointers.
device_type * release()
Return the pointer and release ownership.
device_type * get() const
Return the pointer.
Adapter class to implement new ATA pass through old interface.
ATA device access.
@ supports_output_regs
@ supports_48bit_hi_null
@ supports_multi_sector
@ supports_smart_status
bool ata_cmd_is_supported(const ata_cmd_in &in, unsigned flags, const char *type=0)
Check command input parameters.
void hide_ata(bool hide=true)
Hide/unhide ATA interface.
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out)=0
ATA pass through.
SAT support.
Definition: scsiata.cpp:107
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out) override
ATA pass through.
Definition: scsiata.cpp:259
sat_device(smart_interface *intf, scsi_device *scsidev, const char *req_type, sat_scsi_mode mode=sat_always, int passthrulen=0, sat_variant variant=sat_standard, int port=0)
Definition: scsiata.cpp:139
sat_variant m_variant
Definition: scsiata.cpp:134
virtual ~sat_device()
Definition: scsiata.cpp:162
virtual smart_device * autodetect_open() override
Open device with autodetection support.
Definition: scsiata.cpp:519
virtual bool scsi_pass_through(scsi_cmnd_io *iop) override
SCSI pass through.
Definition: scsiata.cpp:511
sat_scsi_mode m_mode
Definition: scsiata.cpp:133
Cypress USB Bridge support.
Definition: scsiata.cpp:619
unsigned char m_signature
Definition: scsiata.cpp:629
virtual ~usbcypress_device()
Definition: scsiata.cpp:642
virtual int ata_command_interface(smart_command_set command, int select, char *data) override
Old ATA interface called by ata_pass_through()
Definition: scsiata.cpp:649
usbcypress_device(smart_interface *intf, scsi_device *scsidev, const char *req_type, unsigned char signature)
Definition: scsiata.cpp:633
JMicron USB Bridge support.
Definition: scsiata.cpp:887
virtual ~usbjmicron_device()
Definition: scsiata.cpp:919
bool get_registers(unsigned short addr, unsigned char *buf, unsigned short size)
Definition: scsiata.cpp:1071
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out) override
ATA pass through.
Definition: scsiata.cpp:956
virtual bool open() override
Open device, return false on error.
Definition: scsiata.cpp:924
usbjmicron_device(smart_interface *intf, scsi_device *scsidev, const char *req_type, bool prolific, bool ata_48bit_support, int port)
Definition: scsiata.cpp:908
Prolific USB Bridge support. (PL2773) (Probably works on PL2771 also...)
Definition: scsiata.cpp:1114
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out) override
ATA pass through.
Definition: scsiata.cpp:1137
usbprolific_device(smart_interface *intf, scsi_device *scsidev, const char *req_type)
Definition: scsiata.cpp:1125
virtual ~usbprolific_device()
Definition: scsiata.cpp:1133
SunplusIT USB Bridge support.
Definition: scsiata.cpp:1252
virtual ~usbsunplus_device()
Definition: scsiata.cpp:1271
usbsunplus_device(smart_interface *intf, scsi_device *scsidev, const char *req_type)
Definition: scsiata.cpp:1263
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out) override
ATA pass through.
Definition: scsiata.cpp:1275
SCSI device access.
void hide_scsi(bool hide=true)
Hide/unhide SCSI interface.
bool scsi_pass_through_and_check(scsi_cmnd_io *iop, const char *msg="")
virtual bool scsi_pass_through(scsi_cmnd_io *iop)=0
SCSI pass through.
Base class for all devices.
Definition: dev_interface.h:33
int get_errno() const
Get last error number.
const error_info & get_err() const
Get last error info struct.
const char * get_dev_type() const
Get device type.
const char * get_errmsg() const
Get last error message.
virtual bool close()=0
Close device, return false on error.
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
const char * get_info_name() const
Get informal name.
virtual bool is_open() const =0
Return true if device is open.
device_info & set_info()
R/W access to device info struct.
virtual bool open()=0
Open device, return false on error.
The platform interface abstraction.
virtual const char * get_usb_dev_type_by_id(int vendor_id, int product_id, int version=-1)
Get type name for USB device with known VENDOR:PRODUCT ID.
Definition: scsiata.cpp:1515
virtual ata_device * get_sat_device(const char *type, scsi_device *scsidev)
Return ATA->SCSI filter for a SAT or USB 'type'.
Definition: scsiata.cpp:1402
bool decltype(nullptr) set_err_np(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
virtual ata_device * autodetect_sat_device(scsi_device *scsidev, const unsigned char *inqdata, unsigned inqsize)
Try to detect a SAT device behind a SCSI interface.
Definition: scsiata.cpp:1483
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
virtual bool close() override
Close device, return false on error.
Implement a device by tunneling through another device.
Definition: dev_tunnelled.h:56
int lookup_usb_device(int vendor_id, int product_id, int bcd_device, usb_dev_info &info, usb_dev_info &info2)
u8 cdb[16]
Definition: megaraid.h:21
struct megasas_pd_address addr[MAX_SYS_PDS]
Definition: megaraid.h:2
ptr_t data
Definition: megaraid.h:15
u32 size
Definition: megaraid.h:0
uint32_t outlen
Definition: megaraid.h:1
Definition: scsiata.cpp:96
#define SAT_ATA_PASSTHROUGH_16LEN
Definition: scsiata.cpp:90
#define ATA_RETURN_DESCRIPTOR
Definition: scsiata.cpp:93
#define USBCYPRESS_PASSTHROUGH_LEN
Definition: scsiata.cpp:648
#define SAT_ATA_PASSTHROUGH_12LEN
Definition: scsiata.cpp:89
const char * scsiata_cpp_cvsid
Definition: scsiata.cpp:59
#define DEF_SAT_ATA_PASSTHRU_SIZE
Definition: scsiata.cpp:92
static bool has_sat_pass_through(ata_device *dev, bool packet_interface=false)
Definition: scsiata.cpp:556
static int sg_scsi_normalize_sense(const unsigned char *sensep, int sb_len, struct sg_scsi_sense_hdr *sshp)
Definition: scsiata.cpp:574
static std::string format_usb_id(int vendor_id, int product_id, int version)
Definition: scsiata.cpp:1506
int scsiSimpleSenseFilter(const struct scsi_sense_disect *sinfo)
Definition: scsicmds.cpp:587
void scsi_do_sense_disect(const struct scsi_cmnd_io *io_buf, struct scsi_sense_disect *out)
Definition: scsicmds.cpp:565
int scsiStdInquiry(scsi_device *device, uint8_t *pBuf, int bufLen)
Definition: scsicmds.cpp:1163
const unsigned char * sg_scsi_sense_desc_find(const unsigned char *sensep, int sense_len, int desc_type)
Definition: scsicmds.cpp:3088
void dStrHex(const uint8_t *up, int len, int no_ascii)
Definition: scsicmds.cpp:368
const char * scsiErrString(int scsiErr)
Definition: scsicmds.cpp:630
unsigned char scsi_debugmode
Definition: scsicmds.cpp:45
#define SAT_ATA_PASSTHROUGH_12
Definition: scsicmds.h:101
#define DXFER_NONE
Definition: scsicmds.h:108
#define SCSI_ASCQ_ATA_PASS_THROUGH
Definition: scsicmds.h:344
#define DXFER_FROM_DEVICE
Definition: scsicmds.h:109
#define SCSI_TIMEOUT_DEFAULT
Definition: scsicmds.h:379
#define SAT_ATA_PASSTHROUGH_16
Definition: scsicmds.h:104
#define DXFER_TO_DEVICE
Definition: scsicmds.h:110
#define SCSI_STATUS_CHECK_CONDITION
Definition: scsicmds.h:320
#define SCSI_SK_NO_SENSE
Definition: scsicmds.h:323
#define SCSI_SK_RECOVERED_ERR
Definition: scsicmds.h:324
static void sg_put_unaligned_be32(uint32_t val, void *p)
Definition: sg_unaligned.h:279
static void sg_put_unaligned_be16(uint16_t val, void *p)
Definition: sg_unaligned.h:273
void pout(const char *fmt,...)
Definition: smartd.cpp:1336
ATA pass through input parameters.
enum ata_cmd_in::@29 direction
I/O direction.
void * buffer
Pointer to data buffer.
ata_in_regs_48bit in_regs
Input registers.
unsigned size
Size of buffer.
ata_out_regs_flags out_needed
True if output register value needed.
void set_data_in(void *buf, unsigned nsectors)
Prepare for 28-bit DATA IN command.
ATA pass through output parameters.
ata_out_regs_48bit out_regs
Output registers.
bool is_48bit_cmd() const
Return true if 48-bit command.
ata_in_regs prev
"previous content"
ATA Input registers (for 28-bit commands)
ata_register device
ata_register lba_high
ata_register sector_count
ata_register lba_low
ata_register features
ata_register command
ata_register lba_mid
ata_out_regs prev
read with HOB=1
bool is_set() const
Return true if any flag is set.
ATA Output registers (for 28-bit commands)
ata_register sector_count
ata_register lba_low
ata_register lba_mid
ata_register error
ata_register lba_high
ata_register device
ata_register status
uint8_t * sensep
Definition: scsicmds.h:123
uint8_t * dxferp
Definition: scsicmds.h:121
int dxfer_dir
Definition: scsicmds.h:119
size_t cmnd_len
Definition: scsicmds.h:118
size_t resp_sense_len
Definition: scsicmds.h:127
size_t dxfer_len
Definition: scsicmds.h:122
size_t max_sense_len
Definition: scsicmds.h:125
uint8_t scsi_status
Definition: scsicmds.h:128
uint8_t * cmnd
Definition: scsicmds.h:117
unsigned timeout
Definition: scsicmds.h:126
Abridged SCSI sense data.
Definition: scsiata.cpp:68
unsigned char byte4
Definition: scsiata.cpp:73
unsigned char byte6
Definition: scsiata.cpp:75
unsigned char asc
Definition: scsiata.cpp:71
unsigned char ascq
Definition: scsiata.cpp:72
unsigned char additional_length
Definition: scsiata.cpp:76
unsigned char sense_key
Definition: scsiata.cpp:70
unsigned char response_code
Definition: scsiata.cpp:69
unsigned char byte5
Definition: scsiata.cpp:74
std::string info_name
Informal name.
Definition: dev_interface.h:46
std::string dev_type
Actual device type.
Definition: dev_interface.h:47
Error (number,message) pair.
Definition: dev_interface.h:52
std::string msg
Error message.
Definition: dev_interface.h:61
int no
Error number.
Definition: dev_interface.h:60
std::string usb_type
Definition: knowndrives.h:31
void syserror(const char *message)
Definition: utility.cpp:385
std::string strprintf(const char *fmt,...)
Definition: utility.cpp:775
bool str_starts_with(const char *str, const char *prefix)
Definition: utility.h:51