smartmontools SVN Rev 5640
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 5482 2023-06-25 16:46:49Z 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) {
308 return set_err(ENOSYS, "NO DATA ATA commands not implemented [ASM1352R]");
309 protocol = (m_port == 0 ? 0xd : 0xe);
310 }
311
312 // Check condition if any output register needed
313 if (in.out_needed.is_set())
314 ck_cond = 1;
315
318 passthru_size = m_passthrulen;
319
320 // Set extend bit on 48-bit ATA command
321 if (in.in_regs.is_48bit_cmd()) {
322 if (passthru_size != SAT_ATA_PASSTHROUGH_16LEN)
323 return set_err(ENOSYS, "48-bit ATA commands require SAT ATA PASS-THROUGH (16)");
324 extend = 1;
325 }
326
327 cdb[0] = (SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ?
329
330 cdb[1] = (protocol << 1) | extend;
331 cdb[2] = (ck_cond << 5) | (t_dir << 3) |
332 (byte_block << 2) | t_length;
333
334 if (passthru_size == SAT_ATA_PASSTHROUGH_12LEN) {
335 // ATA PASS-THROUGH (12)
336 const ata_in_regs & lo = in.in_regs;
337 cdb[3] = lo.features;
338 cdb[4] = lo.sector_count;
339 cdb[5] = lo.lba_low;
340 cdb[6] = lo.lba_mid;
341 cdb[7] = lo.lba_high;
342 cdb[8] = lo.device;
343 cdb[9] = lo.command;
344 }
345 else {
346 // ATA PASS-THROUGH (16)
347 const ata_in_regs & lo = in.in_regs;
348 const ata_in_regs & hi = in.in_regs.prev;
349 // Note: all 'in.in_regs.prev.*' are always zero for 28-bit commands
350 cdb[ 3] = hi.features;
351 cdb[ 4] = lo.features;
352 cdb[ 5] = hi.sector_count;
353 cdb[ 6] = lo.sector_count;
354 cdb[ 7] = hi.lba_low;
355 cdb[ 8] = lo.lba_low;
356 cdb[ 9] = hi.lba_mid;
357 cdb[10] = lo.lba_mid;
358 cdb[11] = hi.lba_high;
359 cdb[12] = lo.lba_high;
360 cdb[13] = lo.device;
361 cdb[14] = lo.command;
362 }
363
364 if (0 == t_length) {
365 io_hdr.dxfer_dir = DXFER_NONE;
366 io_hdr.dxfer_len = 0;
367 } else if (t_dir) { /* from device */
369 io_hdr.dxfer_len = in.size;
370 io_hdr.dxferp = (unsigned char *)in.buffer;
371 memset(in.buffer, 0, in.size); // prefill with zeroes
372 } else { /* to device */
373 io_hdr.dxfer_dir = DXFER_TO_DEVICE;
374 io_hdr.dxfer_len = in.size;
375 io_hdr.dxferp = (unsigned char *)in.buffer;
376 }
377 io_hdr.cmnd = cdb;
378 io_hdr.cmnd_len = passthru_size;
379 io_hdr.sensep = sense;
380 io_hdr.max_sense_len = sizeof(sense);
382
383 scsi_device * scsidev = get_tunnel_dev();
384 if (!scsidev->scsi_pass_through(&io_hdr)) {
385 if (scsi_debugmode > 0)
386 pout("sat_device::ata_pass_through: scsi_pass_through() failed, "
387 "errno=%d [%s]\n", scsidev->get_errno(), scsidev->get_errmsg());
388 return set_err(scsidev->get_err());
389 }
390 ardp = NULL;
391 ard_len = 0;
392 have_sense = sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len,
393 &ssh);
394 if (have_sense) {
395 sense_descriptor = ssh.response_code >= 0x72;
396 if (sense_descriptor) {
397 /* look for SAT ATA Return Descriptor */
398 ardp = sg_scsi_sense_desc_find(io_hdr.sensep,
399 io_hdr.resp_sense_len,
401 if (ardp) {
402 ard_len = ardp[1] + 2;
403 if (ard_len < 12)
404 ard_len = 12;
405 else if (ard_len > 14)
406 ard_len = 14;
407 }
408 }
409 scsi_do_sense_disect(&io_hdr, &sinfo);
410 int status = scsiSimpleSenseFilter(&sinfo);
411
412 // Workaround for bogus sense_key in sense data with SAT ATA Return Descriptor
413 if ( status && ck_cond && ardp && ard_len > 13
414 && (ardp[13] & 0xc1) == 0x40 /* !BSY && DRDY && !ERR */) {
415 if (scsi_debugmode > 0)
416 pout("ATA status (0x%02x) indicates success, ignoring SCSI sense_key\n",
417 ardp[13]);
418 status = 0;
419 }
420
421 if (0 != status) { /* other than no_sense and recovered_error */
422 if (scsi_debugmode > 0) {
423 pout("sat_device::ata_pass_through: scsi error: %s\n",
424 scsiErrString(status));
425 if (ardp && (scsi_debugmode > 1)) {
426 pout("Values from ATA Return Descriptor are:\n");
427 dStrHex((const uint8_t *)ardp, ard_len, 1);
428 }
429 }
430 if (t_dir && (t_length > 0) && (in.direction == ata_cmd_in::data_in))
431 memset(in.buffer, 0, in.size);
432 return set_err(EIO, "scsi error %s", scsiErrString(status));
433 }
434 }
435 if (ck_cond) { /* expecting SAT specific sense data */
436 if (have_sense) {
437 if (ardp) {
438 if (scsi_debugmode > 1) {
439 pout("Values from ATA Return Descriptor are:\n");
440 dStrHex((const uint8_t *)ardp, ard_len, 1);
441 }
442 // Set output registers
443 ata_out_regs & lo = out.out_regs;
444 lo.error = ardp[ 3];
445 lo.sector_count = ardp[ 5];
446 lo.lba_low = ardp[ 7];
447 lo.lba_mid = ardp[ 9];
448 lo.lba_high = ardp[11];
449 lo.device = ardp[12];
450 lo.status = ardp[13];
451 if (in.in_regs.is_48bit_cmd()) {
452 ata_out_regs & hi = out.out_regs.prev;
453 hi.sector_count = ardp[ 4];
454 hi.lba_low = ardp[ 6];
455 hi.lba_mid = ardp[ 8];
456 hi.lba_high = ardp[10];
457 }
458 } else if ((! sense_descriptor) &&
459 (0 == ssh.asc) &&
461 (0 != io_hdr.sensep[4] /* Some ATA STATUS bit must be set */)) {
462 /* in SAT-2 and later, ATA registers may be passed back via
463 * fixed format sense data [ref: sat3r07 section 12.2.2.7] */
464 ata_out_regs & lo = out.out_regs;
465 lo.error = io_hdr.sensep[ 3];
466 lo.status = io_hdr.sensep[ 4];
467 lo.device = io_hdr.sensep[ 5];
468 lo.sector_count = io_hdr.sensep[ 6];
469 lo.lba_low = io_hdr.sensep[ 9];
470 lo.lba_mid = io_hdr.sensep[10];
471 lo.lba_high = io_hdr.sensep[11];
472 if (in.in_regs.is_48bit_cmd()) {
473 if (0 == (0x60 & io_hdr.sensep[8])) {
474 ata_out_regs & hi = out.out_regs.prev;
475 hi.sector_count = 0;
476 hi.lba_low = 0;
477 hi.lba_mid = 0;
478 hi.lba_high = 0;
479 } else {
480 /* getting the "hi." values when either
481 * count_upper_nonzero or lba_upper_nonzero are set
482 * involves fetching the SCSI ATA PASS-THROUGH
483 * Results log page and decoding the descriptor with
484 * the matching log_index field. Painful. */
485 }
486 }
487 }
488 }
489 } else { /* ck_cond == 0 */
490 if (have_sense) {
491 if (((SCSI_SK_NO_SENSE == ssh.sense_key) ||
493 (0 == ssh.asc) &&
495 if (scsi_debugmode > 0) {
496 if (sense_descriptor && ardp) {
497 pout("Values from ATA Return Descriptor are:\n");
498 dStrHex((const uint8_t *)ardp, ard_len, 1);
499 } else if (! sense_descriptor) {
500 pout("Values from ATA fixed format sense are:\n");
501 pout(" Error: 0x%x\n", io_hdr.sensep[3]);
502 pout(" Status: 0x%x\n", io_hdr.sensep[4]);
503 pout(" Device: 0x%x\n", io_hdr.sensep[5]);
504 pout(" Count: 0x%x\n", io_hdr.sensep[6]);
505 }
506 }
507 }
508 return set_err(EIO, "SAT command failed");
509 }
510 }
511 return true;
512}
513
515{
516 scsi_device * scsidev = get_tunnel_dev();
517 if (!scsidev->scsi_pass_through(iop))
518 return set_err(scsidev->get_err());
519 return true;
520}
521
523{
524 if (!open() || m_mode != sat_auto)
525 return this;
526
527 scsi_device * scsidev = get_tunnel_dev();
528
529 unsigned char inqdata[36] = {0, };
530 if (scsiStdInquiry(scsidev, inqdata, sizeof(inqdata))) {
531 smart_device::error_info err = scsidev->get_err();
532 close();
533 set_err(err.no, "INQUIRY [SAT]: %s", err.msg.c_str());
534 return this;
535 }
536
537 // Check for SAT "VENDOR"
538 int inqsize = inqdata[4] + 5;
539 bool sat = (inqsize >= 36 && !memcmp(inqdata + 8, "ATA ", 8));
540
541 // Change interface
542 hide_ata(!sat);
543 hide_scsi(sat);
544
545 set_info().dev_type = (sat ? "sat" : scsidev->get_dev_type());
546 set_info().info_name = strprintf("%s [%s]", scsidev->get_info_name(),
547 (sat ? "SAT" : "SCSI"));
548 return this;
549}
550
551} // namespace
552
553/////////////////////////////////////////////////////////////////////////////
554
555/* Attempt an IDENTIFY DEVICE ATA command via SATL when packet_interface
556 is false otherwise attempt IDENTIFY PACKET DEVICE. If successful
557 return true, else false */
558
559static bool has_sat_pass_through(ata_device * dev, bool packet_interface = false)
560{
561 /* Note: malloc() ensures the read buffer lands on a single
562 page. This avoids some bugs seen on LSI controllers under
563 FreeBSD */
564 char *data = (char *)malloc(512);
565 ata_cmd_in in;
567 in.set_data_in(data, 1);
568 bool ret = dev->ata_pass_through(in);
569 free(data);
570 return ret;
571}
572
573/////////////////////////////////////////////////////////////////////////////
574
575/* Next two functions are borrowed from sg_lib.c in the sg3_utils
576 package. Same copyrght owner, same license as this file. */
577static int sg_scsi_normalize_sense(const unsigned char * sensep, int sb_len,
578 struct sg_scsi_sense_hdr * sshp)
579{
580 if (sshp)
581 memset(sshp, 0, sizeof(struct sg_scsi_sense_hdr));
582 if ((NULL == sensep) || (0 == sb_len) || (0x70 != (0x70 & sensep[0])))
583 return 0;
584 if (sshp) {
585 sshp->response_code = (0x7f & sensep[0]);
586 if (sshp->response_code >= 0x72) { /* descriptor format */
587 if (sb_len > 1)
588 sshp->sense_key = (0xf & sensep[1]);
589 if (sb_len > 2)
590 sshp->asc = sensep[2];
591 if (sb_len > 3)
592 sshp->ascq = sensep[3];
593 if (sb_len > 7)
594 sshp->additional_length = sensep[7];
595 } else { /* fixed format */
596 if (sb_len > 2)
597 sshp->sense_key = (0xf & sensep[2]);
598 if (sb_len > 7) {
599 sb_len = (sb_len < (sensep[7] + 8)) ? sb_len :
600 (sensep[7] + 8);
601 if (sb_len > 12)
602 sshp->asc = sensep[12];
603 if (sb_len > 13)
604 sshp->ascq = sensep[13];
605 }
606 }
607 }
608 return 1;
609}
610
611/////////////////////////////////////////////////////////////////////////////
612
613namespace sat {
614
615/// Cypress USB Bridge support.
616
618: public tunnelled_device<
619 /*implements*/ ata_device_with_command_set
620 /*by tunnelling through a*/, scsi_device
621 >
622{
623public:
625 const char * req_type, unsigned char signature);
626
627 virtual ~usbcypress_device();
628
629protected:
630 virtual int ata_command_interface(smart_command_set command, int select, char * data) override;
631
632 unsigned char m_signature;
633};
634
635
637 const char * req_type, unsigned char signature)
638: smart_device(intf, scsidev->get_dev_name(), "usbcypress", req_type),
640 m_signature(signature)
641{
642 set_info().info_name = strprintf("%s [USB Cypress]", scsidev->get_info_name());
643}
644
646{
647}
648
649
650/* see cy7c68300c_8.pdf for more information */
651#define USBCYPRESS_PASSTHROUGH_LEN 16
653{
654 struct scsi_cmnd_io io_hdr = {};
655 unsigned char cdb[USBCYPRESS_PASSTHROUGH_LEN] = {};
656 unsigned char sense[32] = {};
657 int copydata = 0;
658 int outlen = 0;
659 int ck_cond = 0; /* set to 1 to read register(s) back */
660 int t_dir = 1; /* 0 -> to device, 1 -> from device */
661 int byte_block = 1; /* 0 -> bytes, 1 -> 512 byte blocks */
662 int t_length = 0; /* 0 -> no data transferred */
663 int feature = 0;
664 int ata_command = 0;
665 int sector_count = 0;
666 int lba_low = 0;
667 int lba_mid = 0;
668 int lba_high = 0;
669 int passthru_size = USBCYPRESS_PASSTHROUGH_LEN;
670
671 ata_command = ATA_SMART_CMD;
672 switch (command) {
673 case CHECK_POWER_MODE:
674 ata_command = ATA_CHECK_POWER_MODE;
675 ck_cond = 1;
676 copydata = 1;
677 break;
678 case READ_VALUES: /* READ DATA */
679 feature = ATA_SMART_READ_VALUES;
680 sector_count = 1; /* one (512 byte) block */
681 t_length = 2; /* sector count holds count */
682 copydata = 512;
683 break;
684 case READ_THRESHOLDS: /* obsolete */
686 sector_count = 1; /* one (512 byte) block */
687 lba_low = 1;
688 t_length = 2; /* sector count holds count */
689 copydata=512;
690 break;
691 case READ_LOG:
693 sector_count = 1; /* one (512 byte) block */
694 lba_low = select;
695 t_length = 2; /* sector count holds count */
696 copydata = 512;
697 break;
698 case WRITE_LOG:
700 sector_count = 1; /* one (512 byte) block */
701 lba_low = select;
702 t_length = 2; /* sector count holds count */
703 t_dir = 0; /* to device */
704 outlen = 512;
705 break;
706 case IDENTIFY:
707 ata_command = ATA_IDENTIFY_DEVICE;
708 sector_count = 1; /* one (512 byte) block */
709 t_length = 2; /* sector count holds count */
710 copydata = 512;
711 break;
712 case PIDENTIFY:
713 ata_command = ATA_IDENTIFY_PACKET_DEVICE;
714 sector_count = 1; /* one (512 byte) block */
715 t_length = 2; /* sector count (7:0) holds count */
716 copydata = 512;
717 break;
718 case ENABLE:
719 feature = ATA_SMART_ENABLE;
720 lba_low = 1;
721 break;
722 case DISABLE:
723 feature = ATA_SMART_DISABLE;
724 lba_low = 1;
725 break;
726 case STATUS:
727 // this command only says if SMART is working. It could be
728 // replaced with STATUS_CHECK below.
729 feature = ATA_SMART_STATUS;
730 ck_cond = 1;
731 break;
732 case AUTO_OFFLINE:
733 feature = ATA_SMART_AUTO_OFFLINE;
734 sector_count = select; // YET NOTE - THIS IS A NON-DATA COMMAND!!
735 break;
736 case AUTOSAVE:
737 feature = ATA_SMART_AUTOSAVE;
738 sector_count = select; // YET NOTE - THIS IS A NON-DATA COMMAND!!
739 break;
742 lba_low = select;
743 break;
744 case STATUS_CHECK:
745 // This command uses HDIO_DRIVE_TASK and has different syntax than
746 // the other commands.
747 feature = ATA_SMART_STATUS; /* SMART RETURN STATUS */
748 ck_cond = 1;
749 break;
750 default:
751 pout("Unrecognized command %d in usbcypress_device::ata_command_interface()\n"
752 "Please contact " PACKAGE_BUGREPORT "\n", command);
753 errno=ENOSYS;
754 return -1;
755 }
756 if (ATA_SMART_CMD == ata_command) {
757 lba_mid = 0x4f;
758 lba_high = 0xc2;
759 }
760
761 cdb[0] = m_signature; // bVSCBSignature : vendor-specific command
762 cdb[1] = 0x24; // bVSCBSubCommand : 0x24 for ATACB
763 cdb[2] = 0x0;
764 if (ata_command == ATA_IDENTIFY_DEVICE || ata_command == ATA_IDENTIFY_PACKET_DEVICE)
765 cdb[2] |= (1<<7); //set IdentifyPacketDevice for these cmds
766 cdb[3] = 0xff - (1<<0) - (1<<6); //features, sector count, lba low, lba med
767 // lba high, command are valid
768 cdb[4] = byte_block; //TransferBlockCount : 512
769
770
771 cdb[6] = feature;
772 cdb[7] = sector_count;
773 cdb[8] = lba_low;
774 cdb[9] = lba_mid;
775 cdb[10] = lba_high;
776 cdb[12] = ata_command;
777
778 if (0 == t_length) {
779 io_hdr.dxfer_dir = DXFER_NONE;
780 io_hdr.dxfer_len = 0;
781 } else if (t_dir) { /* from device */
783 io_hdr.dxfer_len = copydata;
784 io_hdr.dxferp = (unsigned char *)data;
785 memset(data, 0, copydata); /* prefill with zeroes */
786 } else { /* to device */
787 io_hdr.dxfer_dir = DXFER_TO_DEVICE;
788 io_hdr.dxfer_len = outlen;
789 io_hdr.dxferp = (unsigned char *)data;
790 }
791 io_hdr.cmnd = cdb;
792 io_hdr.cmnd_len = passthru_size;
793 io_hdr.sensep = sense;
794 io_hdr.max_sense_len = sizeof(sense);
796
797 scsi_device * scsidev = get_tunnel_dev();
798 if (!scsidev->scsi_pass_through(&io_hdr)) {
799 if (scsi_debugmode > 0)
800 pout("usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
801 "errno=%d [%s]\n", scsidev->get_errno(), scsidev->get_errmsg());
802 set_err(scsidev->get_err());
803 return -1;
804 }
805
806 // if there is a sense the command failed or the
807 // device doesn't support usbcypress
809 sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len, NULL)) {
810 return -1;
811 }
812 if (ck_cond) {
813 unsigned char ardp[8];
814 int ard_len = 8;
815 /* XXX this is racy if there other scsi command between
816 * the first usbcypress command and this one
817 */
818 //pout("If you got strange result, please retry without traffic on the disc\n");
819 /* we use the same command as before, but we set
820 * * the read taskfile bit, for not executing usbcypress command,
821 * * but reading register selected in srb->cmnd[4]
822 */
823 cdb[2] = (1<<0); /* ask read taskfile */
824 memset(sense, 0, sizeof(sense));
825
826 /* transfer 8 bytes */
827 memset(&io_hdr, 0, sizeof(io_hdr));
829 io_hdr.dxfer_len = ard_len;
830 io_hdr.dxferp = (unsigned char *)ardp;
831 memset(ardp, 0, ard_len); /* prefill with zeroes */
832
833 io_hdr.cmnd = cdb;
834 io_hdr.cmnd_len = passthru_size;
835 io_hdr.sensep = sense;
836 io_hdr.max_sense_len = sizeof(sense);
838
839
840 if (!scsidev->scsi_pass_through(&io_hdr)) {
841 if (scsi_debugmode > 0)
842 pout("usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
843 "errno=%d [%s]\n", scsidev->get_errno(), scsidev->get_errmsg());
844 set_err(scsidev->get_err());
845 return -1;
846 }
847 // if there is a sense the command failed or the
848 // device doesn't support usbcypress
850 sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len, NULL)) {
851 return -1;
852 }
853
854
855 if (scsi_debugmode > 1) {
856 pout("Values from ATA Return Descriptor are:\n");
857 dStrHex((const uint8_t *)ardp, ard_len, 1);
858 }
859
860 if (ATA_CHECK_POWER_MODE == ata_command)
861 data[0] = ardp[2]; /* sector count (0:7) */
862 else if (STATUS_CHECK == command) {
863 if ((ardp[4] == 0x4f) && (ardp[5] == 0xc2))
864 return 0; /* GOOD smart status */
865 if ((ardp[4] == 0xf4) && (ardp[5] == 0x2c))
866 return 1; // smart predicting failure, "bad" status
867 // We haven't gotten output that makes sense so
868 // print out some debugging info
869 syserror("Error SMART Status command failed");
870 pout("This may be due to a race in usbcypress\n");
871 pout("Retry without other disc access\n");
872 pout("Please get assistance from " PACKAGE_URL "\n");
873 pout("Values from ATA Return Descriptor are:\n");
874 dStrHex((const uint8_t *)ardp, ard_len, 1);
875 return -1;
876 }
877 }
878 return 0;
879}
880
881/////////////////////////////////////////////////////////////////////////////
882
883/// JMicron USB Bridge support.
884
886: public tunnelled_device<
887 /*implements*/ ata_device,
888 /*by tunnelling through a*/ scsi_device
889 >
890{
891public:
893 const char * req_type, bool prolific,
894 bool ata_48bit_support, int port);
895
896 virtual ~usbjmicron_device();
897
898 virtual bool open() override;
899
900 virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override;
901
902private:
903 bool get_registers(unsigned short addr, unsigned char * buf, unsigned short size);
904
908};
909
910
912 const char * req_type, bool prolific,
913 bool ata_48bit_support, int port)
914: smart_device(intf, scsidev->get_dev_name(), "usbjmicron", req_type),
916 m_prolific(prolific), m_ata_48bit_support(ata_48bit_support),
917 m_port(port >= 0 || !prolific ? port : 0)
918{
919 set_info().info_name = strprintf("%s [USB JMicron]", scsidev->get_info_name());
920}
921
923{
924}
925
926
928{
929 // Open USB first
931 return false;
932
933 // Detect port if not specified
934 if (m_port < 0) {
935 unsigned char regbuf[1] = {0};
936 if (!get_registers(0x720f, regbuf, sizeof(regbuf))) {
937 close();
938 return false;
939 }
940
941 switch (regbuf[0] & 0x44) {
942 case 0x04:
943 m_port = 0; break;
944 case 0x40:
945 m_port = 1; break;
946 case 0x44:
947 close();
948 return set_err(EINVAL, "Two devices connected, try '-d usbjmicron,[01]'");
949 default:
950 close();
951 return set_err(ENODEV, "No device connected");
952 }
953 }
954
955 return true;
956}
957
958
960{
961 if (!ata_cmd_is_supported(in,
965 "JMicron")
966 )
967 return false;
968
969 if (m_port < 0)
970 return set_err(EIO, "Unknown JMicron port");
971
972 scsi_cmnd_io io_hdr = {};
973
974 bool rwbit = true;
975 unsigned char smart_status = 0xff;
976
977 bool is_smart_status = ( in.in_regs.command == ATA_SMART_CMD
979
980 if (is_smart_status && in.out_needed.is_set()) {
982 io_hdr.dxfer_len = 1;
983 io_hdr.dxferp = &smart_status;
984 }
985 else switch (in.direction) {
987 io_hdr.dxfer_dir = DXFER_NONE;
988 break;
991 io_hdr.dxfer_len = in.size;
992 io_hdr.dxferp = (unsigned char *)in.buffer;
993 memset(in.buffer, 0, in.size);
994 break;
996 io_hdr.dxfer_dir = DXFER_TO_DEVICE;
997 io_hdr.dxfer_len = in.size;
998 io_hdr.dxferp = (unsigned char *)in.buffer;
999 rwbit = false;
1000 break;
1001 default:
1002 return set_err(EINVAL);
1003 }
1004
1005 // Build pass through command
1006 unsigned char cdb[14];
1007 cdb[ 0] = 0xdf;
1008 cdb[ 1] = (rwbit ? 0x10 : 0x00);
1009 cdb[ 2] = 0x00;
1010 sg_put_unaligned_be16(io_hdr.dxfer_len, cdb + 3);
1011 cdb[ 5] = in.in_regs.features;
1012 cdb[ 6] = in.in_regs.sector_count;
1013 cdb[ 7] = in.in_regs.lba_low;
1014 cdb[ 8] = in.in_regs.lba_mid;
1015 cdb[ 9] = in.in_regs.lba_high;
1016 cdb[10] = in.in_regs.device | (m_port == 0 ? 0xa0 : 0xb0);
1017 cdb[11] = in.in_regs.command;
1018 // Prolific PL3507
1019 cdb[12] = 0x06;
1020 cdb[13] = 0x7b;
1021
1022 io_hdr.cmnd = cdb;
1023 io_hdr.cmnd_len = (!m_prolific ? 12 : 14);
1024
1025 scsi_device * scsidev = get_tunnel_dev();
1026 if (!scsidev->scsi_pass_through_and_check(&io_hdr,
1027 "usbjmicron_device::ata_pass_through: "))
1028 return set_err(scsidev->get_err());
1029
1030 if (in.out_needed.is_set()) {
1031 if (is_smart_status) {
1032 if (io_hdr.resid == 1)
1033 // Some (Prolific) USB bridges do not transfer a status byte
1034 return set_err(ENOSYS, "Incomplete response, status byte missing [JMicron]");
1035
1036 switch (smart_status) {
1037 case 0xc2:
1038 out.out_regs.lba_high = 0xc2;
1039 out.out_regs.lba_mid = 0x4f;
1040 break;
1041 case 0x2c:
1042 out.out_regs.lba_high = 0x2c;
1043 out.out_regs.lba_mid = 0xf4;
1044 break;
1045 default:
1046 // Some (JM20336) USB bridges always return 0x01, regardless of SMART Status
1047 return set_err(ENOSYS, "Invalid status byte (0x%02x) [JMicron]", smart_status);
1048 }
1049 }
1050
1051#if 0 // Not needed for SMART STATUS, see also notes below
1052 else {
1053 // Read ATA output registers
1054 // NOTE: The register addresses are not valid for some older chip revisions
1055 // NOTE: There is a small race condition here!
1056 unsigned char regbuf[16] = {0, };
1057 if (!get_registers((m_port == 0 ? 0x8000 : 0x9000), regbuf, sizeof(regbuf)))
1058 return false;
1059
1060 out.out_regs.sector_count = regbuf[ 0];
1061 out.out_regs.lba_mid = regbuf[ 4];
1062 out.out_regs.lba_low = regbuf[ 6];
1063 out.out_regs.device = regbuf[ 9];
1064 out.out_regs.lba_high = regbuf[10];
1065 out.out_regs.error = regbuf[13];
1066 out.out_regs.status = regbuf[14];
1067 }
1068#endif
1069 }
1070
1071 return true;
1072}
1073
1075 unsigned char * buf, unsigned short size)
1076{
1077 unsigned char cdb[14];
1078 cdb[ 0] = 0xdf;
1079 cdb[ 1] = 0x10;
1080 cdb[ 2] = 0x00;
1082 cdb[ 5] = 0x00;
1084 cdb[ 8] = 0x00;
1085 cdb[ 9] = 0x00;
1086 cdb[10] = 0x00;
1087 cdb[11] = 0xfd;
1088 // Prolific PL3507
1089 cdb[12] = 0x06;
1090 cdb[13] = 0x7b;
1091
1092 scsi_cmnd_io io_hdr = {};
1094 io_hdr.dxfer_len = size;
1095 io_hdr.dxferp = buf;
1096 io_hdr.cmnd = cdb;
1097 io_hdr.cmnd_len = (!m_prolific ? 12 : 14);
1098
1099 scsi_device * scsidev = get_tunnel_dev();
1100 if (!scsidev->scsi_pass_through_and_check(&io_hdr,
1101 "usbjmicron_device::get_registers: "))
1102 return set_err(scsidev->get_err());
1103
1104 return true;
1105}
1106
1107
1108/////////////////////////////////////////////////////////////////////////////
1109
1110/// Prolific USB Bridge support. (PL2773) (Probably works on PL2771 also...)
1111
1113: public tunnelled_device<
1114 /*implements*/ ata_device,
1115 /*by tunnelling through a*/ scsi_device
1116 >
1117{
1118public:
1120 const char * req_type);
1121
1122 virtual ~usbprolific_device();
1123
1124 virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override;
1125};
1126
1127
1129 const char * req_type)
1130: smart_device(intf, scsidev->get_dev_name(), "usbprolific", req_type),
1132{
1133 set_info().info_name = strprintf("%s [USB Prolific]", scsidev->get_info_name());
1134}
1135
1137{
1138}
1139
1141{
1142 if (!ata_cmd_is_supported(in,
1147 "Prolific" )
1148 )
1149 return false;
1150
1151 scsi_cmnd_io io_hdr = {};
1152 unsigned char cmd_rw = 0x10; // Read
1153
1154 switch (in.direction) {
1156 io_hdr.dxfer_dir = DXFER_NONE;
1157 break;
1160 io_hdr.dxfer_len = in.size;
1161 io_hdr.dxferp = (unsigned char *)in.buffer;
1162 memset(in.buffer, 0, in.size);
1163 break;
1165 io_hdr.dxfer_dir = DXFER_TO_DEVICE;
1166 io_hdr.dxfer_len = in.size;
1167 io_hdr.dxferp = (unsigned char *)in.buffer;
1168 cmd_rw = 0x0; // Write
1169 break;
1170 default:
1171 return set_err(EINVAL);
1172 }
1173
1174 // Based on reverse engineering of iSmart.exe with API Monitor.
1175 // Seen commands:
1176 // D0 0 0 0 06 7B 0 0 0 0 0 0 // Read Firmware info?, reads 16 bytes
1177 // F4 0 0 0 06 7B // ??
1178 // D8 15 0 D8 06 7B 0 0 0 0 1 1 4F C2 A0 B0 // SMART Enable
1179 // D8 15 0 D0 06 7B 0 0 2 0 1 1 4F C2 A0 B0 // SMART Read values
1180 // D8 15 0 D1 06 7B 0 0 2 0 1 1 4F C2 A0 B0 // SMART Read thresholds
1181 // D8 15 0 D4 06 7B 0 0 0 0 0 1 4F C2 A0 B0 // SMART Execute self test
1182 // D7 0 0 0 06 7B 0 0 0 0 0 0 0 0 0 0 // Read status registers, Reads 16 bytes of data
1183 // Additional DATA OUT support based on document from Prolific
1184
1185 // Build pass through command
1186 unsigned char cdb[16];
1187 cdb[ 0] = 0xD8; // Operation Code (D8 = Prolific ATA pass through)
1188 cdb[ 1] = cmd_rw|0x5; // Read(0x10)/Write(0x0) | NORMAL(0x5)/PREFIX(0x0)(?)
1189 cdb[ 2] = 0x0; // Reserved
1190 cdb[ 3] = in.in_regs.features; // Feature register (SMART command)
1191 cdb[ 4] = 0x06; // Check Word (VendorID magic, Prolific: 0x067B)
1192 cdb[ 5] = 0x7B; // Check Word (VendorID magic, Prolific: 0x067B)
1193 sg_put_unaligned_be32(io_hdr.dxfer_len, cdb + 6);
1194 cdb[10] = in.in_regs.sector_count; // Sector Count
1195 cdb[11] = in.in_regs.lba_low; // LBA Low (7:0)
1196 cdb[12] = in.in_regs.lba_mid; // LBA Mid (15:8)
1197 cdb[13] = in.in_regs.lba_high; // LBA High (23:16)
1198 cdb[14] = in.in_regs.device | 0xA0; // Device/Head
1199 cdb[15] = in.in_regs.command; // ATA Command Register (only PIO supported)
1200 // Use '-r scsiioctl,1' to print CDB for debug purposes
1201
1202 io_hdr.cmnd = cdb;
1203 io_hdr.cmnd_len = 16;
1204
1205 scsi_device * scsidev = get_tunnel_dev();
1206 if (!scsidev->scsi_pass_through_and_check(&io_hdr,
1207 "usbprolific_device::ata_pass_through: "))
1208 return set_err(scsidev->get_err());
1209
1210 if (in.out_needed.is_set()) {
1211 // Read ATA output registers
1212 unsigned char regbuf[16] = {0, };
1213 memset(&io_hdr, 0, sizeof(io_hdr));
1215 io_hdr.dxfer_len = sizeof(regbuf);
1216 io_hdr.dxferp = regbuf;
1217
1218 memset(cdb, 0, sizeof(cdb));
1219 cdb[ 0] = 0xD7; // Prolific read registers
1220 cdb[ 4] = 0x06; // Check Word (VendorID magic, Prolific: 0x067B)
1221 cdb[ 5] = 0x7B; // Check Word (VendorID magic, Prolific: 0x067B)
1222 io_hdr.cmnd = cdb;
1223 io_hdr.cmnd_len = sizeof(cdb);
1224
1225 if (!scsidev->scsi_pass_through_and_check(&io_hdr,
1226 "usbprolific_device::scsi_pass_through (get registers): "))
1227 return set_err(scsidev->get_err());
1228
1229 // Use '-r scsiioctl,2' to print input registers for debug purposes
1230 // Example: 50 00 00 00 00 01 4f 00 c2 00 a0 da 00 b0 00 50
1231 out.out_regs.status = regbuf[0]; // Status
1232 out.out_regs.error = regbuf[1]; // Error
1233 out.out_regs.sector_count = regbuf[2]; // Sector Count (7:0)
1234 out.out_regs.lba_low = regbuf[4]; // LBA Low (7:0)
1235 out.out_regs.lba_mid = regbuf[6]; // LBA Mid (7:0)
1236 out.out_regs.lba_high = regbuf[8]; // LBA High (7:0)
1237 out.out_regs.device = regbuf[10]; // Device/Head
1238 // = regbuf[11]; // ATA Feature (7:0)
1239 // = regbuf[13]; // ATA Command
1240 }
1241
1242 return true;
1243}
1244
1245
1246/////////////////////////////////////////////////////////////////////////////
1247
1248/// SunplusIT USB Bridge support.
1249
1251: public tunnelled_device<
1252 /*implements*/ ata_device,
1253 /*by tunnelling through a*/ scsi_device
1254 >
1255{
1256public:
1258 const char * req_type);
1259
1260 virtual ~usbsunplus_device();
1261
1262 virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override;
1263};
1264
1265
1267 const char * req_type)
1268: smart_device(intf, scsidev->get_dev_name(), "usbsunplus", req_type),
1270{
1271 set_info().info_name = strprintf("%s [USB Sunplus]", scsidev->get_info_name());
1272}
1273
1275{
1276}
1277
1279{
1280 if (!ata_cmd_is_supported(in,
1284 "Sunplus")
1285 )
1286 return false;
1287
1288 scsi_cmnd_io io_hdr = {};
1289 unsigned char cdb[12];
1290
1291 if (in.in_regs.is_48bit_cmd()) {
1292 // Set "previous" registers
1293 io_hdr.dxfer_dir = DXFER_NONE;
1294
1295 cdb[ 0] = 0xf8;
1296 cdb[ 1] = 0x00;
1297 cdb[ 2] = 0x23; // Subcommand: Pass through presetting
1298 cdb[ 3] = 0x00;
1299 cdb[ 4] = 0x00;
1300 cdb[ 5] = in.in_regs.prev.features;
1301 cdb[ 6] = in.in_regs.prev.sector_count;
1302 cdb[ 7] = in.in_regs.prev.lba_low;
1303 cdb[ 8] = in.in_regs.prev.lba_mid;
1304 cdb[ 9] = in.in_regs.prev.lba_high;
1305 cdb[10] = 0x00;
1306 cdb[11] = 0x00;
1307
1308 io_hdr.cmnd = cdb;
1309 io_hdr.cmnd_len = sizeof(cdb);
1310
1311 scsi_device * scsidev = get_tunnel_dev();
1312 if (!scsidev->scsi_pass_through_and_check(&io_hdr,
1313 "usbsunplus_device::scsi_pass_through (presetting): "))
1314 return set_err(scsidev->get_err());
1315 }
1316
1317 // Run Pass through command
1318 memset(&io_hdr, 0, sizeof(io_hdr));
1319 unsigned char protocol;
1320 switch (in.direction) {
1322 io_hdr.dxfer_dir = DXFER_NONE;
1323 protocol = 0x00;
1324 break;
1327 io_hdr.dxfer_len = in.size;
1328 io_hdr.dxferp = (unsigned char *)in.buffer;
1329 memset(in.buffer, 0, in.size);
1330 protocol = 0x10;
1331 break;
1333 io_hdr.dxfer_dir = DXFER_TO_DEVICE;
1334 io_hdr.dxfer_len = in.size;
1335 io_hdr.dxferp = (unsigned char *)in.buffer;
1336 protocol = 0x11;
1337 break;
1338 default:
1339 return set_err(EINVAL);
1340 }
1341
1342 cdb[ 0] = 0xf8;
1343 cdb[ 1] = 0x00;
1344 cdb[ 2] = 0x22; // Subcommand: Pass through
1345 cdb[ 3] = protocol;
1346 cdb[ 4] = (unsigned char)(io_hdr.dxfer_len >> 9);
1347 cdb[ 5] = in.in_regs.features;
1348 cdb[ 6] = in.in_regs.sector_count;
1349 cdb[ 7] = in.in_regs.lba_low;
1350 cdb[ 8] = in.in_regs.lba_mid;
1351 cdb[ 9] = in.in_regs.lba_high;
1352 cdb[10] = in.in_regs.device | 0xa0;
1353 cdb[11] = in.in_regs.command;
1354
1355 io_hdr.cmnd = cdb;
1356 io_hdr.cmnd_len = sizeof(cdb);
1357
1358 scsi_device * scsidev = get_tunnel_dev();
1359 if (!scsidev->scsi_pass_through_and_check(&io_hdr,
1360 "usbsunplus_device::scsi_pass_through: "))
1361 // Returns sense key 0x03 (medium error) on ATA command error
1362 return set_err(scsidev->get_err());
1363
1364 if (in.out_needed.is_set()) {
1365 // Read ATA output registers
1366 unsigned char regbuf[8] = {0, };
1367 memset(&io_hdr, 0, sizeof(io_hdr));
1369 io_hdr.dxfer_len = sizeof(regbuf);
1370 io_hdr.dxferp = regbuf;
1371
1372 cdb[ 0] = 0xf8;
1373 cdb[ 1] = 0x00;
1374 cdb[ 2] = 0x21; // Subcommand: Get status
1375 memset(cdb+3, 0, sizeof(cdb)-3);
1376 io_hdr.cmnd = cdb;
1377 io_hdr.cmnd_len = sizeof(cdb);
1378
1379 if (!scsidev->scsi_pass_through_and_check(&io_hdr,
1380 "usbsunplus_device::scsi_pass_through (get registers): "))
1381 return set_err(scsidev->get_err());
1382
1383 out.out_regs.error = regbuf[1];
1384 out.out_regs.sector_count = regbuf[2];
1385 out.out_regs.lba_low = regbuf[3];
1386 out.out_regs.lba_mid = regbuf[4];
1387 out.out_regs.lba_high = regbuf[5];
1388 out.out_regs.device = regbuf[6];
1389 out.out_regs.status = regbuf[7];
1390 }
1391
1392 return true;
1393}
1394
1395
1396} // namespace
1397
1398using namespace sat;
1399
1400
1401/////////////////////////////////////////////////////////////////////////////
1402
1403// Return ATA->SCSI filter for SAT or USB.
1404
1406{
1407 if (!scsidev)
1408 throw std::logic_error("smart_interface: get_sat_device() called with scsidev=0");
1409
1410 // Take temporary ownership of 'scsidev' to delete it on error
1411 scsi_device_auto_ptr scsidev_holder(scsidev);
1412 ata_device * satdev = nullptr;
1413
1414 if (str_starts_with(type, "sat")) {
1415 const char * t = type + 3;
1417 if (str_starts_with(t, ",auto")) {
1418 t += 5;
1419 mode = sat_device::sat_auto;
1420 }
1421 int ptlen = 0, n = -1;
1422 if (*t && !(sscanf(t, ",%d%n", &ptlen, &n) == 1 && n == (int)strlen(t)
1423 && (ptlen == 0 || ptlen == 12 || ptlen == 16)))
1424 return set_err_np(EINVAL, "Option '-d sat[,auto][,N]' requires N to be 0, 12 or 16");
1425 satdev = new sat_device(this, scsidev, type, mode, ptlen);
1426 }
1427
1428 else if (!strcmp(type, "scsi")) {
1429 satdev = new sat_device(this, scsidev, type, sat_device::scsi_always);
1430 }
1431
1432 else if (str_starts_with(type, "usbcypress")) {
1433 unsigned signature = 0x24; int n1 = -1, n2 = -1;
1434 if (!(((sscanf(type, "usbcypress%n,0x%x%n", &n1, &signature, &n2) == 1 && n2 == (int)strlen(type))
1435 || n1 == (int)strlen(type)) && signature <= 0xff))
1436 return set_err_np(EINVAL, "Option '-d usbcypress,<n>' requires <n> to be "
1437 "an hexadecimal number between 0x0 and 0xff" );
1438 satdev = new usbcypress_device(this, scsidev, type, signature);
1439 }
1440
1441 else if (str_starts_with(type, "usbjmicron")) {
1442 const char * t = type + 10;
1443 bool prolific = false;
1444 if (str_starts_with(t, ",p")) {
1445 t += 2;
1446 prolific = true;
1447 }
1448 bool ata_48bit_support = false;
1449 if (str_starts_with(t, ",x")) {
1450 t += 2;
1451 ata_48bit_support = true;
1452 }
1453 int port = -1, n = -1;
1454 if (*t && !( (sscanf(t, ",%d%n", &port, &n) == 1
1455 && n == (int)strlen(t) && 0 <= port && port <= 1)))
1456 return set_err_np(EINVAL, "Option '-d usbjmicron[,p][,x],<n>' requires <n> to be 0 or 1");
1457 satdev = new usbjmicron_device(this, scsidev, type, prolific, ata_48bit_support, port);
1458 }
1459
1460 else if (!strcmp(type, "usbprolific")) {
1461 satdev = new usbprolific_device(this, scsidev, type);
1462 }
1463
1464 else if (!strcmp(type, "usbsunplus")) {
1465 satdev = new usbsunplus_device(this, scsidev, type);
1466 }
1467
1468 else if (str_starts_with(type, "usbasm1352r")) {
1469 unsigned port = ~0; int n = -1;
1470 if (!(sscanf(type, "usbasm1352r,%u%n", &port, &n) == 1 && n == (int)strlen(type) && port <= 1))
1471 return set_err_np(EINVAL, "Option '-d usbasm1352r,<n>' requires <n> to be 0 or 1");
1472 satdev = new sat_device(this, scsidev, type, sat_device::sat_always, 0, sat_device::sat_asm1352r, port);
1473 }
1474
1475 else {
1476 return set_err_np(EINVAL, "Unknown USB device type '%s'", type);
1477 }
1478
1479 // 'scsidev' is now owned by 'satdev'
1480 scsidev_holder.release();
1481 return satdev;
1482}
1483
1484// Try to detect a SAT device behind a SCSI interface.
1485
1487 const unsigned char * inqdata, unsigned inqsize)
1488{
1489 if (!scsidev->is_open())
1490 return 0;
1491
1492 // SAT ?
1493 if (inqdata && inqsize >= 36 && !memcmp(inqdata + 8, "ATA ", 8)) {
1494 // TODO: Linux-specific? No, all SAT standards say the 'T10 Vendor
1495 // Identification' field shall be 'ATA '.
1496 ata_device_auto_ptr atadev( new sat_device(this, scsidev, "") , scsidev);
1497 if (has_sat_pass_through(atadev.get()))
1498 return atadev.release(); // Detected SAT
1499 }
1500
1501 return 0;
1502}
1503
1504
1505/////////////////////////////////////////////////////////////////////////////
1506// USB device type detection
1507
1508// Format USB ID for error messages
1509static std::string format_usb_id(int vendor_id, int product_id, int version)
1510{
1511 if (version >= 0)
1512 return strprintf("[0x%04x:0x%04x (0x%03x)]", vendor_id, product_id, version);
1513 else
1514 return strprintf("[0x%04x:0x%04x]", vendor_id, product_id);
1515}
1516
1517// Get type name for USB device with known VENDOR:PRODUCT ID.
1518const char * smart_interface::get_usb_dev_type_by_id(int vendor_id, int product_id,
1519 int version /*= -1*/)
1520{
1521 usb_dev_info info, info2;
1522 int n = lookup_usb_device(vendor_id, product_id, version, info, info2);
1523
1524 if (n <= 0) {
1525 set_err(EINVAL, "Unknown USB bridge %s",
1526 format_usb_id(vendor_id, product_id, version).c_str());
1527 return 0;
1528 }
1529
1530 if (n > 1) {
1531 set_err(EINVAL, "USB bridge %s type is ambiguous: '%s' or '%s'",
1532 format_usb_id(vendor_id, product_id, version).c_str(),
1533 (!info.usb_type.empty() ? info.usb_type.c_str() : "[unsupported]"),
1534 (!info2.usb_type.empty() ? info2.usb_type.c_str() : "[unsupported]"));
1535 return 0;
1536 }
1537
1538 if (info.usb_type.empty()) {
1539 set_err(ENOSYS, "Unsupported USB bridge %s",
1540 format_usb_id(vendor_id, product_id, version).c_str());
1541 return 0;
1542 }
1543
1544 // TODO: change return type to std::string
1545 static std::string type;
1546 type = info.usb_type;
1547 return type.c_str();
1548}
#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:522
virtual bool scsi_pass_through(scsi_cmnd_io *iop) override
SCSI pass through.
Definition: scsiata.cpp:514
sat_scsi_mode m_mode
Definition: scsiata.cpp:133
Cypress USB Bridge support.
Definition: scsiata.cpp:622
unsigned char m_signature
Definition: scsiata.cpp:632
virtual ~usbcypress_device()
Definition: scsiata.cpp:645
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:652
usbcypress_device(smart_interface *intf, scsi_device *scsidev, const char *req_type, unsigned char signature)
Definition: scsiata.cpp:636
JMicron USB Bridge support.
Definition: scsiata.cpp:890
virtual ~usbjmicron_device()
Definition: scsiata.cpp:922
bool get_registers(unsigned short addr, unsigned char *buf, unsigned short size)
Definition: scsiata.cpp:1074
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out) override
ATA pass through.
Definition: scsiata.cpp:959
virtual bool open() override
Open device, return false on error.
Definition: scsiata.cpp:927
usbjmicron_device(smart_interface *intf, scsi_device *scsidev, const char *req_type, bool prolific, bool ata_48bit_support, int port)
Definition: scsiata.cpp:911
Prolific USB Bridge support. (PL2773) (Probably works on PL2771 also...)
Definition: scsiata.cpp:1117
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out) override
ATA pass through.
Definition: scsiata.cpp:1140
usbprolific_device(smart_interface *intf, scsi_device *scsidev, const char *req_type)
Definition: scsiata.cpp:1128
virtual ~usbprolific_device()
Definition: scsiata.cpp:1136
SunplusIT USB Bridge support.
Definition: scsiata.cpp:1255
virtual ~usbsunplus_device()
Definition: scsiata.cpp:1274
usbsunplus_device(smart_interface *intf, scsi_device *scsidev, const char *req_type)
Definition: scsiata.cpp:1266
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out) override
ATA pass through.
Definition: scsiata.cpp:1278
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:1518
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:1405
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:1486
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:651
#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:559
static int sg_scsi_normalize_sense(const unsigned char *sensep, int sb_len, struct sg_scsi_sense_hdr *sshp)
Definition: scsiata.cpp:577
static std::string format_usb_id(int vendor_id, int product_id, int version)
Definition: scsiata.cpp:1509
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:3090
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:1347
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:409
std::string strprintf(const char *fmt,...)
Definition: utility.cpp:799
bool str_starts_with(const char *str, const char *prefix)
Definition: utility.h:52