1: /*
2: * scsiata.cpp
3: *
4: * Home page of code is: http://smartmontools.sourceforge.net
5: *
6: * Copyright (C) 2006-12 Douglas Gilbert <dgilbert@interlog.com>
7: * Copyright (C) 2009-12 Christian Franke <smartmontools-support@lists.sourceforge.net>
8: *
9: * This program is free software; you can redistribute it and/or modify
10: * it under the terms of the GNU General Public License as published by
11: * the Free Software Foundation; either version 2, or (at your option)
12: * any later version.
13: *
14: * You should have received a copy of the GNU General Public License
15: * (for example COPYING); if not, write to the Free
16: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17: *
18: * The code in this file is based on the SCSI to ATA Translation (SAT)
19: * draft found at http://www.t10.org . The original draft used for this
20: * code is sat-r08.pdf which is not too far away from becoming a
21: * standard. The SAT commands of interest to smartmontools are the
22: * ATA PASS THROUGH SCSI (16) and ATA PASS THROUGH SCSI (12) defined in
23: * section 12 of that document.
24: *
25: * sat-r09.pdf is the most recent, easily accessible draft prior to the
26: * original SAT standard (ANSI INCITS 431-2007). By mid-2009 the second
27: * version of the SAT standard (SAT-2) is nearing standardization. In
28: * their wisdom an incompatible change has been introduced in draft
29: * sat2r08a.pdf in the area of the ATA RETURN DESCRIPTOR. A new "fixed
30: * format" ATA RETURN buffer has been defined (sat2r08b.pdf section
31: * 12.2.7) for the case when DSENSE=0 in the Control mode page.
32: * Unfortunately this is the normal case. If the change stands our
33: * code will need to be extended for this case.
34: *
35: * With more transports "hiding" SATA disks (and other S-ATAPI devices)
36: * behind a SCSI command set, accessing special features like SMART
37: * information becomes a challenge. The SAT standard offers ATA PASS
38: * THROUGH commands for special usages. Note that the SAT layer may
39: * be inside a generic OS layer (e.g. libata in linux), in a host
40: * adapter (HA or HBA) firmware, or somewhere on the interconnect
41: * between the host computer and the SATA devices (e.g. a RAID made
42: * of SATA disks and the RAID talks "SCSI" to the host computer).
43: * Note that in the latter case, this code does not solve the
44: * addressing issue (i.e. which SATA disk to address behind the logical
45: * SCSI (RAID) interface).
46: *
47: */
48:
49: #include <stdio.h>
50: #include <string.h>
51: #include <stdlib.h>
52: #include <ctype.h>
53: #include <errno.h>
54:
55: #include "config.h"
56: #include "int64.h"
57: #include "scsicmds.h"
58: #include "atacmds.h" // ataReadHDIdentity()
59: #include "knowndrives.h" // lookup_usb_device()
60: #include "utility.h"
61: #include "dev_interface.h"
62: #include "dev_ata_cmd_set.h" // ata_device_with_command_set
63: #include "dev_tunnelled.h" // tunnelled_device<>
64:
65: const char * scsiata_cpp_cvsid = "$Id: scsiata.cpp,v 1.1.1.2 2012/10/09 09:36:45 misho Exp $";
66:
67: /* This is a slightly stretched SCSI sense "descriptor" format header.
68: The addition is to allow the 0x70 and 0x71 response codes. The idea
69: is to place the salient data of both "fixed" and "descriptor" sense
70: format into one structure to ease application processing.
71: The original sense buffer should be kept around for those cases
72: in which more information is required (e.g. the LBA of a MEDIUM ERROR). */
73: /// Abridged SCSI sense data
74: struct sg_scsi_sense_hdr {
75: unsigned char response_code; /* permit: 0x0, 0x70, 0x71, 0x72, 0x73 */
76: unsigned char sense_key;
77: unsigned char asc;
78: unsigned char ascq;
79: unsigned char byte4;
80: unsigned char byte5;
81: unsigned char byte6;
82: unsigned char additional_length;
83: };
84:
85: /* Maps the salient data from a sense buffer which is in either fixed or
86: descriptor format into a structure mimicking a descriptor format
87: header (i.e. the first 8 bytes of sense descriptor format).
88: If zero response code returns 0. Otherwise returns 1 and if 'sshp' is
89: non-NULL then zero all fields and then set the appropriate fields in
90: that structure. sshp::additional_length is always 0 for response
91: codes 0x70 and 0x71 (fixed format). */
92: static int sg_scsi_normalize_sense(const unsigned char * sensep, int sb_len,
93: struct sg_scsi_sense_hdr * sshp);
94:
95: /* Attempt to find the first SCSI sense data descriptor that matches the
96: given 'desc_type'. If found return pointer to start of sense data
97: descriptor; otherwise (including fixed format sense data) returns NULL. */
98: static const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep,
99: int sense_len, int desc_type);
100:
101: #define SAT_ATA_PASSTHROUGH_12LEN 12
102: #define SAT_ATA_PASSTHROUGH_16LEN 16
103:
104: #define DEF_SAT_ATA_PASSTHRU_SIZE 16
105: #define ATA_RETURN_DESCRIPTOR 9
106:
107:
108: namespace sat { // no need to publish anything, name provided for Doxygen
109:
110: /// SAT support.
111: /// Implements ATA by tunnelling through SCSI.
112:
113: class sat_device
114: : public tunnelled_device<
115: /*implements*/ ata_device
116: /*by tunnelling through a*/, scsi_device
117: >,
118: virtual public /*implements*/ scsi_device
119: {
120: public:
121: sat_device(smart_interface * intf, scsi_device * scsidev,
122: const char * req_type, int passthrulen = 0, bool enable_auto = false);
123:
124: virtual ~sat_device() throw();
125:
126: virtual smart_device * autodetect_open();
127:
128: virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
129:
130: virtual bool scsi_pass_through(scsi_cmnd_io * iop);
131:
132: private:
133: int m_passthrulen;
134: bool m_enable_auto;
135: };
136:
137:
138: sat_device::sat_device(smart_interface * intf, scsi_device * scsidev,
139: const char * req_type, int passthrulen /* = 0 */, bool enable_auto /* = false */)
140: : smart_device(intf, scsidev->get_dev_name(),
141: (enable_auto ? "sat,auto" : "sat"), req_type),
142: tunnelled_device<ata_device, scsi_device>(scsidev),
143: m_passthrulen(passthrulen),
144: m_enable_auto(enable_auto)
145: {
146: if (enable_auto)
147: hide_ata(); // Start as SCSI, switch to ATA in autodetect_open()
148: else
149: hide_scsi(); // ATA always
150:
151: set_info().info_name = strprintf("%s [%sSAT]", scsidev->get_info_name(),
152: (enable_auto ? "SCSI/" : ""));
153: }
154:
155: sat_device::~sat_device() throw()
156: {
157: }
158:
159:
160: // cdb[0]: ATA PASS THROUGH (16) SCSI command opcode byte (0x85)
161: // cdb[1]: multiple_count, protocol + extend
162: // cdb[2]: offline, ck_cond, t_dir, byte_block + t_length
163: // cdb[3]: features (15:8)
164: // cdb[4]: features (7:0)
165: // cdb[5]: sector_count (15:8)
166: // cdb[6]: sector_count (7:0)
167: // cdb[7]: lba_low (15:8)
168: // cdb[8]: lba_low (7:0)
169: // cdb[9]: lba_mid (15:8)
170: // cdb[10]: lba_mid (7:0)
171: // cdb[11]: lba_high (15:8)
172: // cdb[12]: lba_high (7:0)
173: // cdb[13]: device
174: // cdb[14]: (ata) command
175: // cdb[15]: control (SCSI, leave as zero)
176: //
177: // 24 bit lba (from MSB): cdb[12] cdb[10] cdb[8]
178: // 48 bit lba (from MSB): cdb[11] cdb[9] cdb[7] cdb[12] cdb[10] cdb[8]
179: //
180: //
181: // cdb[0]: ATA PASS THROUGH (12) SCSI command opcode byte (0xa1)
182: // cdb[1]: multiple_count, protocol + extend
183: // cdb[2]: offline, ck_cond, t_dir, byte_block + t_length
184: // cdb[3]: features (7:0)
185: // cdb[4]: sector_count (7:0)
186: // cdb[5]: lba_low (7:0)
187: // cdb[6]: lba_mid (7:0)
188: // cdb[7]: lba_high (7:0)
189: // cdb[8]: device
190: // cdb[9]: (ata) command
191: // cdb[10]: reserved
192: // cdb[11]: control (SCSI, leave as zero)
193: //
194: //
195: // ATA Return Descriptor (component of descriptor sense data)
196: // des[0]: descriptor code (0x9)
197: // des[1]: additional descriptor length (0xc)
198: // des[2]: extend (bit 0)
199: // des[3]: error
200: // des[4]: sector_count (15:8)
201: // des[5]: sector_count (7:0)
202: // des[6]: lba_low (15:8)
203: // des[7]: lba_low (7:0)
204: // des[8]: lba_mid (15:8)
205: // des[9]: lba_mid (7:0)
206: // des[10]: lba_high (15:8)
207: // des[11]: lba_high (7:0)
208: // des[12]: device
209: // des[13]: status
210:
211:
212:
213: // PURPOSE
214: // This interface routine takes ATA SMART commands and packages
215: // them in the SAT-defined ATA PASS THROUGH SCSI commands. There are
216: // two available SCSI commands: a 12 byte and 16 byte variant; the
217: // one used is chosen via this->m_passthrulen .
218: // DETAILED DESCRIPTION OF ARGUMENTS
219: // device: is the file descriptor provided by (a SCSI dvice type) open()
220: // command: defines the different ATA operations.
221: // select: additional input data if needed (which log, which type of
222: // self-test).
223: // data: location to write output data, if needed (512 bytes).
224: // Note: not all commands use all arguments.
225: // RETURN VALUES
226: // -1 if the command failed
227: // 0 if the command succeeded,
228: // STATUS_CHECK routine:
229: // -1 if the command failed
230: // 0 if the command succeeded and disk SMART status is "OK"
231: // 1 if the command succeeded and disk SMART status is "FAILING"
232:
233: bool sat_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
234: {
235: if (!ata_cmd_is_ok(in,
236: true, // data_out_support
237: true, // multi_sector_support
238: true) // ata_48bit_support
239: )
240: return false;
241:
242: struct scsi_cmnd_io io_hdr;
243: struct scsi_sense_disect sinfo;
244: struct sg_scsi_sense_hdr ssh;
245: unsigned char cdb[SAT_ATA_PASSTHROUGH_16LEN];
246: unsigned char sense[32];
247: const unsigned char * ardp;
248: int status, ard_len, have_sense;
249: int extend = 0;
250: int ck_cond = 0; /* set to 1 to read register(s) back */
251: int protocol = 3; /* non-data */
252: int t_dir = 1; /* 0 -> to device, 1 -> from device */
253: int byte_block = 1; /* 0 -> bytes, 1 -> 512 byte blocks */
254: int t_length = 0; /* 0 -> no data transferred */
255: int passthru_size = DEF_SAT_ATA_PASSTHRU_SIZE;
256:
257: memset(cdb, 0, sizeof(cdb));
258: memset(sense, 0, sizeof(sense));
259:
260: // Set data direction
261: // TODO: This works only for commands where sector_count holds count!
262: switch (in.direction) {
263: case ata_cmd_in::no_data:
264: break;
265: case ata_cmd_in::data_in:
266: protocol = 4; // PIO data-in
267: t_length = 2; // sector_count holds count
268: break;
269: case ata_cmd_in::data_out:
270: protocol = 5; // PIO data-out
271: t_length = 2; // sector_count holds count
272: t_dir = 0; // to device
273: break;
274: default:
275: return set_err(EINVAL, "sat_device::ata_pass_through: invalid direction=%d",
276: (int)in.direction);
277: }
278:
279: // Check condition if any output register needed
280: if (in.out_needed.is_set())
281: ck_cond = 1;
282:
283: if ((SAT_ATA_PASSTHROUGH_12LEN == m_passthrulen) ||
284: (SAT_ATA_PASSTHROUGH_16LEN == m_passthrulen))
285: passthru_size = m_passthrulen;
286:
287: // Set extend bit on 48-bit ATA command
288: if (in.in_regs.is_48bit_cmd()) {
289: if (passthru_size != SAT_ATA_PASSTHROUGH_16LEN)
290: return set_err(ENOSYS, "48-bit ATA commands require SAT ATA PASS-THROUGH (16)");
291: extend = 1;
292: }
293:
294: cdb[0] = (SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ?
295: SAT_ATA_PASSTHROUGH_12 : SAT_ATA_PASSTHROUGH_16;
296:
297: cdb[1] = (protocol << 1) | extend;
298: cdb[2] = (ck_cond << 5) | (t_dir << 3) |
299: (byte_block << 2) | t_length;
300:
301: if (passthru_size == SAT_ATA_PASSTHROUGH_12LEN) {
302: // ATA PASS-THROUGH (12)
303: const ata_in_regs & lo = in.in_regs;
304: cdb[3] = lo.features;
305: cdb[4] = lo.sector_count;
306: cdb[5] = lo.lba_low;
307: cdb[6] = lo.lba_mid;
308: cdb[7] = lo.lba_high;
309: cdb[8] = lo.device;
310: cdb[9] = lo.command;
311: }
312: else {
313: // ATA PASS-THROUGH (16)
314: const ata_in_regs & lo = in.in_regs;
315: const ata_in_regs & hi = in.in_regs.prev;
316: // Note: all 'in.in_regs.prev.*' are always zero for 28-bit commands
317: cdb[ 3] = hi.features;
318: cdb[ 4] = lo.features;
319: cdb[ 5] = hi.sector_count;
320: cdb[ 6] = lo.sector_count;
321: cdb[ 7] = hi.lba_low;
322: cdb[ 8] = lo.lba_low;
323: cdb[ 9] = hi.lba_mid;
324: cdb[10] = lo.lba_mid;
325: cdb[11] = hi.lba_high;
326: cdb[12] = lo.lba_high;
327: cdb[13] = lo.device;
328: cdb[14] = lo.command;
329: }
330:
331: memset(&io_hdr, 0, sizeof(io_hdr));
332: if (0 == t_length) {
333: io_hdr.dxfer_dir = DXFER_NONE;
334: io_hdr.dxfer_len = 0;
335: } else if (t_dir) { /* from device */
336: io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
337: io_hdr.dxfer_len = in.size;
338: io_hdr.dxferp = (unsigned char *)in.buffer;
339: memset(in.buffer, 0, in.size); // prefill with zeroes
340: } else { /* to device */
341: io_hdr.dxfer_dir = DXFER_TO_DEVICE;
342: io_hdr.dxfer_len = in.size;
343: io_hdr.dxferp = (unsigned char *)in.buffer;
344: }
345: io_hdr.cmnd = cdb;
346: io_hdr.cmnd_len = passthru_size;
347: io_hdr.sensep = sense;
348: io_hdr.max_sense_len = sizeof(sense);
349: io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
350:
351: scsi_device * scsidev = get_tunnel_dev();
352: if (!scsidev->scsi_pass_through(&io_hdr)) {
353: if (scsi_debugmode > 0)
354: pout("sat_device::ata_pass_through: scsi_pass_through() failed, "
355: "errno=%d [%s]\n", scsidev->get_errno(), scsidev->get_errmsg());
356: return set_err(scsidev->get_err());
357: }
358: ardp = NULL;
359: ard_len = 0;
360: have_sense = sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len,
361: &ssh);
362: if (have_sense) {
363: /* look for SAT ATA Return Descriptor */
364: ardp = sg_scsi_sense_desc_find(io_hdr.sensep,
365: io_hdr.resp_sense_len,
366: ATA_RETURN_DESCRIPTOR);
367: if (ardp) {
368: ard_len = ardp[1] + 2;
369: if (ard_len < 12)
370: ard_len = 12;
371: else if (ard_len > 14)
372: ard_len = 14;
373: }
374: scsi_do_sense_disect(&io_hdr, &sinfo);
375: status = scsiSimpleSenseFilter(&sinfo);
376: if (0 != status) {
377: if (scsi_debugmode > 0) {
378: pout("sat_device::ata_pass_through: scsi error: %s\n",
379: scsiErrString(status));
380: if (ardp && (scsi_debugmode > 1)) {
381: pout("Values from ATA Return Descriptor are:\n");
382: dStrHex((const char *)ardp, ard_len, 1);
383: }
384: }
385: if (t_dir && (t_length > 0) && (in.direction == ata_cmd_in::data_in))
386: memset(in.buffer, 0, in.size);
387: return set_err(EIO, "scsi error %s", scsiErrString(status));
388: }
389: }
390: if (ck_cond) { /* expecting SAT specific sense data */
391: if (have_sense) {
392: if (ardp) {
393: if (scsi_debugmode > 1) {
394: pout("Values from ATA Return Descriptor are:\n");
395: dStrHex((const char *)ardp, ard_len, 1);
396: }
397: // Set output registers
398: ata_out_regs & lo = out.out_regs;
399: lo.error = ardp[ 3];
400: lo.sector_count = ardp[ 5];
401: lo.lba_low = ardp[ 7];
402: lo.lba_mid = ardp[ 9];
403: lo.lba_high = ardp[11];
404: lo.device = ardp[12];
405: lo.status = ardp[13];
406: if (in.in_regs.is_48bit_cmd()) {
407: ata_out_regs & hi = out.out_regs.prev;
408: hi.sector_count = ardp[ 4];
409: hi.lba_low = ardp[ 6];
410: hi.lba_mid = ardp[ 8];
411: hi.lba_high = ardp[10];
412: }
413: }
414: }
415: if (ardp == NULL)
416: ck_cond = 0; /* not the type of sense data expected */
417: }
418: if (0 == ck_cond) {
419: if (have_sense) {
420: if ((ssh.response_code >= 0x72) &&
421: ((SCSI_SK_NO_SENSE == ssh.sense_key) ||
422: (SCSI_SK_RECOVERED_ERR == ssh.sense_key)) &&
423: (0 == ssh.asc) &&
424: (SCSI_ASCQ_ATA_PASS_THROUGH == ssh.ascq)) {
425: if (ardp) {
426: if (scsi_debugmode > 0) {
427: pout("Values from ATA Return Descriptor are:\n");
428: dStrHex((const char *)ardp, ard_len, 1);
429: }
430: return set_err(EIO, "SAT command failed");
431: }
432: }
433: }
434: }
435: return true;
436: }
437:
438: bool sat_device::scsi_pass_through(scsi_cmnd_io * iop)
439: {
440: scsi_device * scsidev = get_tunnel_dev();
441: if (!scsidev->scsi_pass_through(iop)) {
442: set_err(scsidev->get_err());
443: return false;
444: }
445: return true;
446: }
447:
448: smart_device * sat_device::autodetect_open()
449: {
450: if (!open() || !m_enable_auto)
451: return this;
452:
453: scsi_device * scsidev = get_tunnel_dev();
454:
455: unsigned char inqdata[36] = {0, };
456: if (scsiStdInquiry(scsidev, inqdata, sizeof(inqdata))) {
457: smart_device::error_info err = scsidev->get_err();
458: close();
459: set_err(err.no, "INQUIRY [SAT]: %s", err.msg.c_str());
460: return this;
461: }
462:
463: // Check for SAT "VENDOR"
464: int inqsize = inqdata[4] + 5;
465: bool sat = (inqsize >= 36 && !memcmp(inqdata + 8, "ATA ", 8));
466:
467: // Change interface
468: hide_ata(!sat);
469: hide_scsi(sat);
470:
471: set_info().dev_type = (sat ? "sat" : scsidev->get_dev_type());
472: set_info().info_name = strprintf("%s [%s]", scsidev->get_info_name(),
473: (sat ? "SAT" : "SCSI"));
474: return this;
475: }
476:
477: } // namespace
478:
479: /////////////////////////////////////////////////////////////////////////////
480:
481: /* Attempt an IDENTIFY DEVICE ATA command via SATL when packet_interface
482: is false otherwise attempt IDENTIFY PACKET DEVICE. If successful
483: return true, else false */
484:
485: static bool has_sat_pass_through(ata_device * dev, bool packet_interface = false)
486: {
487: /* Note: malloc() ensures the read buffer lands on a single
488: page. This avoids some bugs seen on LSI controlers under
489: FreeBSD */
490: char *data = (char *)malloc(512);
491: ata_cmd_in in;
492: in.in_regs.command = (packet_interface ? ATA_IDENTIFY_PACKET_DEVICE : ATA_IDENTIFY_DEVICE);
493: in.set_data_in(data, 1);
494: bool ret = dev->ata_pass_through(in);
495: free(data);
496: return ret;
497: }
498:
499: /////////////////////////////////////////////////////////////////////////////
500:
501: /* Next two functions are borrowed from sg_lib.c in the sg3_utils
502: package. Same copyrght owner, same license as this file. */
503: static int sg_scsi_normalize_sense(const unsigned char * sensep, int sb_len,
504: struct sg_scsi_sense_hdr * sshp)
505: {
506: if (sshp)
507: memset(sshp, 0, sizeof(struct sg_scsi_sense_hdr));
508: if ((NULL == sensep) || (0 == sb_len) || (0x70 != (0x70 & sensep[0])))
509: return 0;
510: if (sshp) {
511: sshp->response_code = (0x7f & sensep[0]);
512: if (sshp->response_code >= 0x72) { /* descriptor format */
513: if (sb_len > 1)
514: sshp->sense_key = (0xf & sensep[1]);
515: if (sb_len > 2)
516: sshp->asc = sensep[2];
517: if (sb_len > 3)
518: sshp->ascq = sensep[3];
519: if (sb_len > 7)
520: sshp->additional_length = sensep[7];
521: } else { /* fixed format */
522: if (sb_len > 2)
523: sshp->sense_key = (0xf & sensep[2]);
524: if (sb_len > 7) {
525: sb_len = (sb_len < (sensep[7] + 8)) ? sb_len :
526: (sensep[7] + 8);
527: if (sb_len > 12)
528: sshp->asc = sensep[12];
529: if (sb_len > 13)
530: sshp->ascq = sensep[13];
531: }
532: }
533: }
534: return 1;
535: }
536:
537:
538: static const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep,
539: int sense_len, int desc_type)
540: {
541: int add_sen_len, add_len, desc_len, k;
542: const unsigned char * descp;
543:
544: if ((sense_len < 8) || (0 == (add_sen_len = sensep[7])))
545: return NULL;
546: if ((sensep[0] < 0x72) || (sensep[0] > 0x73))
547: return NULL;
548: add_sen_len = (add_sen_len < (sense_len - 8)) ?
549: add_sen_len : (sense_len - 8);
550: descp = &sensep[8];
551: for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) {
552: descp += desc_len;
553: add_len = (k < (add_sen_len - 1)) ? descp[1]: -1;
554: desc_len = add_len + 2;
555: if (descp[0] == desc_type)
556: return descp;
557: if (add_len < 0) /* short descriptor ?? */
558: break;
559: }
560: return NULL;
561: }
562:
563:
564: // Call scsi_pass_through and check sense.
565: // TODO: Provide as member function of class scsi_device (?)
566: static bool scsi_pass_through_and_check(scsi_device * scsidev, scsi_cmnd_io * iop,
567: const char * msg = "")
568: {
569: // Provide sense buffer
570: unsigned char sense[32] = {0, };
571: iop->sensep = sense;
572: iop->max_sense_len = sizeof(sense);
573: iop->timeout = SCSI_TIMEOUT_DEFAULT;
574:
575: // Run cmd
576: if (!scsidev->scsi_pass_through(iop)) {
577: if (scsi_debugmode > 0)
578: pout("%sscsi_pass_through() failed, errno=%d [%s]\n",
579: msg, scsidev->get_errno(), scsidev->get_errmsg());
580: return false;
581: }
582:
583: // Check sense
584: scsi_sense_disect sinfo;
585: scsi_do_sense_disect(iop, &sinfo);
586: int err = scsiSimpleSenseFilter(&sinfo);
587: if (err) {
588: if (scsi_debugmode > 0)
589: pout("%sscsi error: %s\n", msg, scsiErrString(err));
590: return scsidev->set_err(EIO, "scsi error %s", scsiErrString(err));
591: }
592:
593: return true;
594: }
595:
596:
597: /////////////////////////////////////////////////////////////////////////////
598:
599: namespace sat {
600:
601: /// Cypress USB Brigde support.
602:
603: class usbcypress_device
604: : public tunnelled_device<
605: /*implements*/ ata_device_with_command_set
606: /*by tunnelling through a*/, scsi_device
607: >
608: {
609: public:
610: usbcypress_device(smart_interface * intf, scsi_device * scsidev,
611: const char * req_type, unsigned char signature);
612:
613: virtual ~usbcypress_device() throw();
614:
615: protected:
616: virtual int ata_command_interface(smart_command_set command, int select, char * data);
617:
618: unsigned char m_signature;
619: };
620:
621:
622: usbcypress_device::usbcypress_device(smart_interface * intf, scsi_device * scsidev,
623: const char * req_type, unsigned char signature)
624: : smart_device(intf, scsidev->get_dev_name(), "sat", req_type),
625: tunnelled_device<ata_device_with_command_set, scsi_device>(scsidev),
626: m_signature(signature)
627: {
628: set_info().info_name = strprintf("%s [USB Cypress]", scsidev->get_info_name());
629: }
630:
631: usbcypress_device::~usbcypress_device() throw()
632: {
633: }
634:
635:
636: /* see cy7c68300c_8.pdf for more information */
637: #define USBCYPRESS_PASSTHROUGH_LEN 16
638: int usbcypress_device::ata_command_interface(smart_command_set command, int select, char *data)
639: {
640: struct scsi_cmnd_io io_hdr;
641: unsigned char cdb[USBCYPRESS_PASSTHROUGH_LEN];
642: unsigned char sense[32];
643: int copydata = 0;
644: int outlen = 0;
645: int ck_cond = 0; /* set to 1 to read register(s) back */
646: int t_dir = 1; /* 0 -> to device, 1 -> from device */
647: int byte_block = 1; /* 0 -> bytes, 1 -> 512 byte blocks */
648: int t_length = 0; /* 0 -> no data transferred */
649: int feature = 0;
650: int ata_command = 0;
651: int sector_count = 0;
652: int lba_low = 0;
653: int lba_mid = 0;
654: int lba_high = 0;
655: int passthru_size = USBCYPRESS_PASSTHROUGH_LEN;
656:
657: memset(cdb, 0, sizeof(cdb));
658: memset(sense, 0, sizeof(sense));
659:
660: ata_command = ATA_SMART_CMD;
661: switch (command) {
662: case CHECK_POWER_MODE:
663: ata_command = ATA_CHECK_POWER_MODE;
664: ck_cond = 1;
665: copydata = 1;
666: break;
667: case READ_VALUES: /* READ DATA */
668: feature = ATA_SMART_READ_VALUES;
669: sector_count = 1; /* one (512 byte) block */
670: t_length = 2; /* sector count holds count */
671: copydata = 512;
672: break;
673: case READ_THRESHOLDS: /* obsolete */
674: feature = ATA_SMART_READ_THRESHOLDS;
675: sector_count = 1; /* one (512 byte) block */
676: lba_low = 1;
677: t_length = 2; /* sector count holds count */
678: copydata=512;
679: break;
680: case READ_LOG:
681: feature = ATA_SMART_READ_LOG_SECTOR;
682: sector_count = 1; /* one (512 byte) block */
683: lba_low = select;
684: t_length = 2; /* sector count holds count */
685: copydata = 512;
686: break;
687: case WRITE_LOG:
688: feature = ATA_SMART_WRITE_LOG_SECTOR;
689: sector_count = 1; /* one (512 byte) block */
690: lba_low = select;
691: t_length = 2; /* sector count holds count */
692: t_dir = 0; /* to device */
693: outlen = 512;
694: break;
695: case IDENTIFY:
696: ata_command = ATA_IDENTIFY_DEVICE;
697: sector_count = 1; /* one (512 byte) block */
698: t_length = 2; /* sector count holds count */
699: copydata = 512;
700: break;
701: case PIDENTIFY:
702: ata_command = ATA_IDENTIFY_PACKET_DEVICE;
703: sector_count = 1; /* one (512 byte) block */
704: t_length = 2; /* sector count (7:0) holds count */
705: copydata = 512;
706: break;
707: case ENABLE:
708: feature = ATA_SMART_ENABLE;
709: lba_low = 1;
710: break;
711: case DISABLE:
712: feature = ATA_SMART_DISABLE;
713: lba_low = 1;
714: break;
715: case STATUS:
716: // this command only says if SMART is working. It could be
717: // replaced with STATUS_CHECK below.
718: feature = ATA_SMART_STATUS;
719: ck_cond = 1;
720: break;
721: case AUTO_OFFLINE:
722: feature = ATA_SMART_AUTO_OFFLINE;
723: sector_count = select; // YET NOTE - THIS IS A NON-DATA COMMAND!!
724: break;
725: case AUTOSAVE:
726: feature = ATA_SMART_AUTOSAVE;
727: sector_count = select; // YET NOTE - THIS IS A NON-DATA COMMAND!!
728: break;
729: case IMMEDIATE_OFFLINE:
730: feature = ATA_SMART_IMMEDIATE_OFFLINE;
731: lba_low = select;
732: break;
733: case STATUS_CHECK:
734: // This command uses HDIO_DRIVE_TASK and has different syntax than
735: // the other commands.
736: feature = ATA_SMART_STATUS; /* SMART RETURN STATUS */
737: ck_cond = 1;
738: break;
739: default:
740: pout("Unrecognized command %d in usbcypress_device::ata_command_interface()\n"
741: "Please contact " PACKAGE_BUGREPORT "\n", command);
742: errno=ENOSYS;
743: return -1;
744: }
745: if (ATA_SMART_CMD == ata_command) {
746: lba_mid = 0x4f;
747: lba_high = 0xc2;
748: }
749:
750: cdb[0] = m_signature; // bVSCBSignature : vendor-specific command
751: cdb[1] = 0x24; // bVSCBSubCommand : 0x24 for ATACB
752: cdb[2] = 0x0;
753: if (ata_command == ATA_IDENTIFY_DEVICE || ata_command == ATA_IDENTIFY_PACKET_DEVICE)
754: cdb[2] |= (1<<7); //set IdentifyPacketDevice for these cmds
755: cdb[3] = 0xff - (1<<0) - (1<<6); //features, sector count, lba low, lba med
756: // lba high, command are valid
757: cdb[4] = byte_block; //TransferBlockCount : 512
758:
759:
760: cdb[6] = feature;
761: cdb[7] = sector_count;
762: cdb[8] = lba_low;
763: cdb[9] = lba_mid;
764: cdb[10] = lba_high;
765: cdb[12] = ata_command;
766:
767: memset(&io_hdr, 0, sizeof(io_hdr));
768: if (0 == t_length) {
769: io_hdr.dxfer_dir = DXFER_NONE;
770: io_hdr.dxfer_len = 0;
771: } else if (t_dir) { /* from device */
772: io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
773: io_hdr.dxfer_len = copydata;
774: io_hdr.dxferp = (unsigned char *)data;
775: memset(data, 0, copydata); /* prefill with zeroes */
776: } else { /* to device */
777: io_hdr.dxfer_dir = DXFER_TO_DEVICE;
778: io_hdr.dxfer_len = outlen;
779: io_hdr.dxferp = (unsigned char *)data;
780: }
781: io_hdr.cmnd = cdb;
782: io_hdr.cmnd_len = passthru_size;
783: io_hdr.sensep = sense;
784: io_hdr.max_sense_len = sizeof(sense);
785: io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
786:
787: scsi_device * scsidev = get_tunnel_dev();
788: if (!scsidev->scsi_pass_through(&io_hdr)) {
789: if (scsi_debugmode > 0)
790: pout("usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
791: "errno=%d [%s]\n", scsidev->get_errno(), scsidev->get_errmsg());
792: set_err(scsidev->get_err());
793: return -1;
794: }
795:
796: // if there is a sense the command failed or the
797: // device doesn't support usbcypress
798: if (io_hdr.scsi_status == SCSI_STATUS_CHECK_CONDITION &&
799: sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len, NULL)) {
800: return -1;
801: }
802: if (ck_cond) {
803: unsigned char ardp[8];
804: int ard_len = 8;
805: /* XXX this is racy if there other scsi command between
806: * the first usbcypress command and this one
807: */
808: //pout("If you got strange result, please retry without traffic on the disc\n");
809: /* we use the same command as before, but we set
810: * * the read taskfile bit, for not executing usbcypress command,
811: * * but reading register selected in srb->cmnd[4]
812: */
813: cdb[2] = (1<<0); /* ask read taskfile */
814: memset(sense, 0, sizeof(sense));
815:
816: /* transfert 8 bytes */
817: memset(&io_hdr, 0, sizeof(io_hdr));
818: io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
819: io_hdr.dxfer_len = ard_len;
820: io_hdr.dxferp = (unsigned char *)ardp;
821: memset(ardp, 0, ard_len); /* prefill with zeroes */
822:
823: io_hdr.cmnd = cdb;
824: io_hdr.cmnd_len = passthru_size;
825: io_hdr.sensep = sense;
826: io_hdr.max_sense_len = sizeof(sense);
827: io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
828:
829:
830: if (!scsidev->scsi_pass_through(&io_hdr)) {
831: if (scsi_debugmode > 0)
832: pout("usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
833: "errno=%d [%s]\n", scsidev->get_errno(), scsidev->get_errmsg());
834: set_err(scsidev->get_err());
835: return -1;
836: }
837: // if there is a sense the command failed or the
838: // device doesn't support usbcypress
839: if (io_hdr.scsi_status == SCSI_STATUS_CHECK_CONDITION &&
840: sg_scsi_normalize_sense(io_hdr.sensep, io_hdr.resp_sense_len, NULL)) {
841: return -1;
842: }
843:
844:
845: if (scsi_debugmode > 1) {
846: pout("Values from ATA Return Descriptor are:\n");
847: dStrHex((const char *)ardp, ard_len, 1);
848: }
849:
850: if (ATA_CHECK_POWER_MODE == ata_command)
851: data[0] = ardp[2]; /* sector count (0:7) */
852: else if (STATUS_CHECK == command) {
853: if ((ardp[4] == 0x4f) && (ardp[5] == 0xc2))
854: return 0; /* GOOD smart status */
855: if ((ardp[4] == 0xf4) && (ardp[5] == 0x2c))
856: return 1; // smart predicting failure, "bad" status
857: // We haven't gotten output that makes sense so
858: // print out some debugging info
859: syserror("Error SMART Status command failed");
860: pout("This may be due to a race in usbcypress\n");
861: pout("Retry without other disc access\n");
862: pout("Please get assistance from " PACKAGE_HOMEPAGE "\n");
863: pout("Values from ATA Return Descriptor are:\n");
864: dStrHex((const char *)ardp, ard_len, 1);
865: return -1;
866: }
867: }
868: return 0;
869: }
870:
871: #if 0 // Not used, see autodetect_sat_device() below.
872: static int isprint_string(const char *s)
873: {
874: while (*s) {
875: if (isprint(*s) == 0)
876: return 0;
877: s++;
878: }
879: return 1;
880: }
881:
882: /* Attempt an IDENTIFY DEVICE ATA or IDENTIFY PACKET DEVICE command
883: If successful return 1, else 0 */
884: // TODO: Combine with has_sat_pass_through above
885: static int has_usbcypress_pass_through(ata_device * atadev, const char *manufacturer, const char *product)
886: {
887: struct ata_identify_device drive;
888: char model[40], serial[20], firm[8];
889:
890: /* issue the command and do a checksum if possible */
891: if (ataReadHDIdentity(atadev, &drive) < 0)
892: return 0;
893:
894: /* check if model string match, revision doesn't work for me */
895: format_ata_string(model, drive.model, 40);
896: if (*model == 0 || isprint_string(model) == 0)
897: return 0;
898:
899: if (manufacturer && strncmp(manufacturer, model, 8))
900: pout("manufacturer doesn't match in pass_through test\n");
901: if (product &&
902: strlen(model) > 8 && strncmp(product, model+8, strlen(model)-8))
903: pout("product doesn't match in pass_through test\n");
904:
905: /* check serial */
906: format_ata_string(serial, drive.serial_no, 20);
907: if (isprint_string(serial) == 0)
908: return 0;
909: format_ata_string(firm, drive.fw_rev, 8);
910: if (isprint_string(firm) == 0)
911: return 0;
912: return 1;
913: }
914: #endif
915:
916: /////////////////////////////////////////////////////////////////////////////
917:
918: /// JMicron USB Bridge support.
919:
920: class usbjmicron_device
921: : public tunnelled_device<
922: /*implements*/ ata_device,
923: /*by tunnelling through a*/ scsi_device
924: >
925: {
926: public:
927: usbjmicron_device(smart_interface * intf, scsi_device * scsidev,
928: const char * req_type, bool ata_48bit_support, int port);
929:
930: virtual ~usbjmicron_device() throw();
931:
932: virtual bool open();
933:
934: virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
935:
936: private:
937: bool get_registers(unsigned short addr, unsigned char * buf, unsigned short size);
938:
939: bool m_ata_48bit_support;
940: int m_port;
941: };
942:
943:
944: usbjmicron_device::usbjmicron_device(smart_interface * intf, scsi_device * scsidev,
945: const char * req_type, bool ata_48bit_support, int port)
946: : smart_device(intf, scsidev->get_dev_name(), "usbjmicron", req_type),
947: tunnelled_device<ata_device, scsi_device>(scsidev),
948: m_ata_48bit_support(ata_48bit_support), m_port(port)
949: {
950: set_info().info_name = strprintf("%s [USB JMicron]", scsidev->get_info_name());
951: }
952:
953: usbjmicron_device::~usbjmicron_device() throw()
954: {
955: }
956:
957:
958: bool usbjmicron_device::open()
959: {
960: // Open USB first
961: if (!tunnelled_device<ata_device, scsi_device>::open())
962: return false;
963:
964: // Detect port if not specified
965: if (m_port < 0) {
966: unsigned char regbuf[1] = {0};
967: if (!get_registers(0x720f, regbuf, sizeof(regbuf))) {
968: close();
969: return false;
970: }
971:
972: switch (regbuf[0] & 0x44) {
973: case 0x04:
974: m_port = 0; break;
975: case 0x40:
976: m_port = 1; break;
977: case 0x44:
978: close();
979: return set_err(EINVAL, "Two devices connected, try '-d usbjmicron,[01]'");
980: default:
981: close();
982: return set_err(ENODEV, "No device connected");
983: }
984: }
985:
986: return true;
987: }
988:
989:
990: bool usbjmicron_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
991: {
992: if (!ata_cmd_is_ok(in,
993: true, // data_out_support
994: false, // !multi_sector_support
995: m_ata_48bit_support) // limited, see below
996: )
997: return false;
998:
999: bool is_smart_status = ( in.in_regs.command == ATA_SMART_CMD
1000: && in.in_regs.features == ATA_SMART_STATUS);
1001:
1002: // Support output registers for SMART STATUS
1003: if (in.out_needed.is_set() && !is_smart_status)
1004: return set_err(ENOSYS, "ATA output registers not supported");
1005:
1006: // Support 48-bit commands with zero high bytes
1007: if (in.in_regs.is_real_48bit_cmd())
1008: return set_err(ENOSYS, "48-bit ATA commands not fully supported");
1009:
1010: if (m_port < 0)
1011: return set_err(EIO, "Unknown JMicron port");
1012:
1013: scsi_cmnd_io io_hdr;
1014: memset(&io_hdr, 0, sizeof(io_hdr));
1015:
1016: bool rwbit = true;
1017: unsigned char smart_status = 0;
1018:
1019: if (is_smart_status && in.out_needed.is_set()) {
1020: io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
1021: io_hdr.dxfer_len = 1;
1022: io_hdr.dxferp = &smart_status;
1023: }
1024: else switch (in.direction) {
1025: case ata_cmd_in::no_data:
1026: io_hdr.dxfer_dir = DXFER_NONE;
1027: break;
1028: case ata_cmd_in::data_in:
1029: io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
1030: io_hdr.dxfer_len = in.size;
1031: io_hdr.dxferp = (unsigned char *)in.buffer;
1032: memset(in.buffer, 0, in.size);
1033: break;
1034: case ata_cmd_in::data_out:
1035: io_hdr.dxfer_dir = DXFER_TO_DEVICE;
1036: io_hdr.dxfer_len = in.size;
1037: io_hdr.dxferp = (unsigned char *)in.buffer;
1038: rwbit = false;
1039: break;
1040: default:
1041: return set_err(EINVAL);
1042: }
1043:
1044: // Build pass through command
1045: unsigned char cdb[12];
1046: cdb[ 0] = 0xdf;
1047: cdb[ 1] = (rwbit ? 0x10 : 0x00);
1048: cdb[ 2] = 0x00;
1049: cdb[ 3] = (unsigned char)(io_hdr.dxfer_len >> 8);
1050: cdb[ 4] = (unsigned char)(io_hdr.dxfer_len );
1051: cdb[ 5] = in.in_regs.features;
1052: cdb[ 6] = in.in_regs.sector_count;
1053: cdb[ 7] = in.in_regs.lba_low;
1054: cdb[ 8] = in.in_regs.lba_mid;
1055: cdb[ 9] = in.in_regs.lba_high;
1056: cdb[10] = in.in_regs.device | (m_port == 0 ? 0xa0 : 0xb0);
1057: cdb[11] = in.in_regs.command;
1058:
1059: io_hdr.cmnd = cdb;
1060: io_hdr.cmnd_len = sizeof(cdb);
1061:
1062: scsi_device * scsidev = get_tunnel_dev();
1063: if (!scsi_pass_through_and_check(scsidev, &io_hdr,
1064: "usbjmicron_device::ata_pass_through: "))
1065: return set_err(scsidev->get_err());
1066:
1067: if (in.out_needed.is_set()) {
1068: if (is_smart_status) {
1069: switch (smart_status) {
1070: case 0x01: case 0xc2:
1071: out.out_regs.lba_high = 0xc2;
1072: out.out_regs.lba_mid = 0x4f;
1073: break;
1074: case 0x00: case 0x2c:
1075: out.out_regs.lba_high = 0x2c;
1076: out.out_regs.lba_mid = 0xf4;
1077: break;
1078: }
1079: }
1080:
1081: #if 0 // Not needed for SMART STATUS, see also notes below
1082: else {
1083: // Read ATA output registers
1084: // NOTE: The register addresses are not valid for some older chip revisions
1085: // NOTE: There is a small race condition here!
1086: unsigned char regbuf[16] = {0, };
1087: if (!get_registers((m_port == 0 ? 0x8000 : 0x9000), regbuf, sizeof(regbuf)))
1088: return false;
1089:
1090: out.out_regs.sector_count = regbuf[ 0];
1091: out.out_regs.lba_mid = regbuf[ 4];
1092: out.out_regs.lba_low = regbuf[ 6];
1093: out.out_regs.device = regbuf[ 9];
1094: out.out_regs.lba_high = regbuf[10];
1095: out.out_regs.error = regbuf[13];
1096: out.out_regs.status = regbuf[14];
1097: }
1098: #endif
1099: }
1100:
1101: return true;
1102: }
1103:
1104: bool usbjmicron_device::get_registers(unsigned short addr,
1105: unsigned char * buf, unsigned short size)
1106: {
1107: unsigned char cdb[12];
1108: cdb[ 0] = 0xdf;
1109: cdb[ 1] = 0x10;
1110: cdb[ 2] = 0x00;
1111: cdb[ 3] = (unsigned char)(size >> 8);
1112: cdb[ 4] = (unsigned char)(size );
1113: cdb[ 5] = 0x00;
1114: cdb[ 6] = (unsigned char)(addr >> 8);
1115: cdb[ 7] = (unsigned char)(addr );
1116: cdb[ 8] = 0x00;
1117: cdb[ 9] = 0x00;
1118: cdb[10] = 0x00;
1119: cdb[11] = 0xfd;
1120:
1121: scsi_cmnd_io io_hdr;
1122: memset(&io_hdr, 0, sizeof(io_hdr));
1123: io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
1124: io_hdr.dxfer_len = size;
1125: io_hdr.dxferp = buf;
1126: io_hdr.cmnd = cdb;
1127: io_hdr.cmnd_len = sizeof(cdb);
1128:
1129: scsi_device * scsidev = get_tunnel_dev();
1130: if (!scsi_pass_through_and_check(scsidev, &io_hdr,
1131: "usbjmicron_device::get_registers: "))
1132: return set_err(scsidev->get_err());
1133:
1134: return true;
1135: }
1136:
1137:
1138: /////////////////////////////////////////////////////////////////////////////
1139:
1140: /// SunplusIT USB Bridge support.
1141:
1142: class usbsunplus_device
1143: : public tunnelled_device<
1144: /*implements*/ ata_device,
1145: /*by tunnelling through a*/ scsi_device
1146: >
1147: {
1148: public:
1149: usbsunplus_device(smart_interface * intf, scsi_device * scsidev,
1150: const char * req_type);
1151:
1152: virtual ~usbsunplus_device() throw();
1153:
1154: virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
1155: };
1156:
1157:
1158: usbsunplus_device::usbsunplus_device(smart_interface * intf, scsi_device * scsidev,
1159: const char * req_type)
1160: : smart_device(intf, scsidev->get_dev_name(), "usbsunplus", req_type),
1161: tunnelled_device<ata_device, scsi_device>(scsidev)
1162: {
1163: set_info().info_name = strprintf("%s [USB Sunplus]", scsidev->get_info_name());
1164: }
1165:
1166: usbsunplus_device::~usbsunplus_device() throw()
1167: {
1168: }
1169:
1170: bool usbsunplus_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
1171: {
1172: if (!ata_cmd_is_ok(in,
1173: true, // data_out_support
1174: false, // !multi_sector_support
1175: true) // ata_48bit_support
1176: )
1177: return false;
1178:
1179: scsi_cmnd_io io_hdr;
1180: unsigned char cdb[12];
1181:
1182: if (in.in_regs.is_48bit_cmd()) {
1183: // Set "previous" registers
1184: memset(&io_hdr, 0, sizeof(io_hdr));
1185: io_hdr.dxfer_dir = DXFER_NONE;
1186:
1187: cdb[ 0] = 0xf8;
1188: cdb[ 1] = 0x00;
1189: cdb[ 2] = 0x23; // Subcommand: Pass through presetting
1190: cdb[ 3] = 0x00;
1191: cdb[ 4] = 0x00;
1192: cdb[ 5] = in.in_regs.prev.features;
1193: cdb[ 6] = in.in_regs.prev.sector_count;
1194: cdb[ 7] = in.in_regs.prev.lba_low;
1195: cdb[ 8] = in.in_regs.prev.lba_mid;
1196: cdb[ 9] = in.in_regs.prev.lba_high;
1197: cdb[10] = 0x00;
1198: cdb[11] = 0x00;
1199:
1200: io_hdr.cmnd = cdb;
1201: io_hdr.cmnd_len = sizeof(cdb);
1202:
1203: scsi_device * scsidev = get_tunnel_dev();
1204: if (!scsi_pass_through_and_check(scsidev, &io_hdr,
1205: "usbsunplus_device::scsi_pass_through (presetting): "))
1206: return set_err(scsidev->get_err());
1207: }
1208:
1209: // Run Pass through command
1210: memset(&io_hdr, 0, sizeof(io_hdr));
1211: unsigned char protocol;
1212: switch (in.direction) {
1213: case ata_cmd_in::no_data:
1214: io_hdr.dxfer_dir = DXFER_NONE;
1215: protocol = 0x00;
1216: break;
1217: case ata_cmd_in::data_in:
1218: io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
1219: io_hdr.dxfer_len = in.size;
1220: io_hdr.dxferp = (unsigned char *)in.buffer;
1221: memset(in.buffer, 0, in.size);
1222: protocol = 0x10;
1223: break;
1224: case ata_cmd_in::data_out:
1225: io_hdr.dxfer_dir = DXFER_TO_DEVICE;
1226: io_hdr.dxfer_len = in.size;
1227: io_hdr.dxferp = (unsigned char *)in.buffer;
1228: protocol = 0x11;
1229: break;
1230: default:
1231: return set_err(EINVAL);
1232: }
1233:
1234: cdb[ 0] = 0xf8;
1235: cdb[ 1] = 0x00;
1236: cdb[ 2] = 0x22; // Subcommand: Pass through
1237: cdb[ 3] = protocol;
1238: cdb[ 4] = (unsigned char)(io_hdr.dxfer_len >> 9);
1239: cdb[ 5] = in.in_regs.features;
1240: cdb[ 6] = in.in_regs.sector_count;
1241: cdb[ 7] = in.in_regs.lba_low;
1242: cdb[ 8] = in.in_regs.lba_mid;
1243: cdb[ 9] = in.in_regs.lba_high;
1244: cdb[10] = in.in_regs.device | 0xa0;
1245: cdb[11] = in.in_regs.command;
1246:
1247: io_hdr.cmnd = cdb;
1248: io_hdr.cmnd_len = sizeof(cdb);
1249:
1250: scsi_device * scsidev = get_tunnel_dev();
1251: if (!scsi_pass_through_and_check(scsidev, &io_hdr,
1252: "usbsunplus_device::scsi_pass_through: "))
1253: // Returns sense key 0x03 (medium error) on ATA command error
1254: return set_err(scsidev->get_err());
1255:
1256: if (in.out_needed.is_set()) {
1257: // Read ATA output registers
1258: unsigned char regbuf[8] = {0, };
1259: memset(&io_hdr, 0, sizeof(io_hdr));
1260: io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
1261: io_hdr.dxfer_len = sizeof(regbuf);
1262: io_hdr.dxferp = regbuf;
1263:
1264: cdb[ 0] = 0xf8;
1265: cdb[ 1] = 0x00;
1266: cdb[ 2] = 0x21; // Subcommand: Get status
1267: memset(cdb+3, 0, sizeof(cdb)-3);
1268: io_hdr.cmnd = cdb;
1269: io_hdr.cmnd_len = sizeof(cdb);
1270:
1271: if (!scsi_pass_through_and_check(scsidev, &io_hdr,
1272: "usbsunplus_device::scsi_pass_through (get registers): "))
1273: return set_err(scsidev->get_err());
1274:
1275: out.out_regs.error = regbuf[1];
1276: out.out_regs.sector_count = regbuf[2];
1277: out.out_regs.lba_low = regbuf[3];
1278: out.out_regs.lba_mid = regbuf[4];
1279: out.out_regs.lba_high = regbuf[5];
1280: out.out_regs.device = regbuf[6];
1281: out.out_regs.status = regbuf[7];
1282: }
1283:
1284: return true;
1285: }
1286:
1287:
1288: } // namespace
1289:
1290: using namespace sat;
1291:
1292:
1293: /////////////////////////////////////////////////////////////////////////////
1294:
1295: // Return ATA->SCSI filter for SAT or USB.
1296:
1297: ata_device * smart_interface::get_sat_device(const char * type, scsi_device * scsidev)
1298: {
1299: if (!strncmp(type, "sat", 3)) {
1300: const char * t = type + 3;
1301: bool enable_auto = false;
1302: if (!strncmp(t, ",auto", 5)) {
1303: t += 5;
1304: enable_auto = true;
1305: }
1306: int ptlen = 0, n = -1;
1307: if (*t && !(sscanf(t, ",%d%n", &ptlen, &n) == 1 && n == (int)strlen(t)
1308: && (ptlen == 0 || ptlen == 12 || ptlen == 16))) {
1309: set_err(EINVAL, "Option '-d sat[,auto][,N]' requires N to be 0, 12 or 16");
1310: return 0;
1311: }
1312: return new sat_device(this, scsidev, type, ptlen, enable_auto);
1313: }
1314:
1315: else if (!strncmp(type, "usbcypress", 10)) {
1316: unsigned signature = 0x24; int n1 = -1, n2 = -1;
1317: if (!(((sscanf(type, "usbcypress%n,0x%x%n", &n1, &signature, &n2) == 1 && n2 == (int)strlen(type)) || n1 == (int)strlen(type))
1318: && signature <= 0xff)) {
1319: set_err(EINVAL, "Option '-d usbcypress,<n>' requires <n> to be "
1320: "an hexadecimal number between 0x0 and 0xff");
1321: return 0;
1322: }
1323: return new usbcypress_device(this, scsidev, type, signature);
1324: }
1325:
1326: else if (!strncmp(type, "usbjmicron", 10)) {
1327: const char * t = type + 10;
1328: bool ata_48bit_support = false;
1329: if (!strncmp(t, ",x", 2)) {
1330: t += 2;
1331: ata_48bit_support = true;
1332: }
1333: int port = -1, n = -1;
1334: if (*t && !( (sscanf(t, ",%d%n", &port, &n) == 1
1335: && n == (int)strlen(t) && 0 <= port && port <= 1))) {
1336: set_err(EINVAL, "Option '-d usbmicron[,x],<n>' requires <n> to be 0 or 1");
1337: return 0;
1338: }
1339: return new usbjmicron_device(this, scsidev, type, ata_48bit_support, port);
1340: }
1341:
1342: else if (!strcmp(type, "usbsunplus")) {
1343: return new usbsunplus_device(this, scsidev, type);
1344: }
1345:
1346: else {
1347: set_err(EINVAL, "Unknown USB device type '%s'", type);
1348: return 0;
1349: }
1350: }
1351:
1352: // Try to detect a SAT device behind a SCSI interface.
1353:
1354: ata_device * smart_interface::autodetect_sat_device(scsi_device * scsidev,
1355: const unsigned char * inqdata, unsigned inqsize)
1356: {
1357: if (!scsidev->is_open())
1358: return 0;
1359:
1360: // SAT ?
1361: if (inqdata && inqsize >= 36 && !memcmp(inqdata + 8, "ATA ", 8)) { // TODO: Linux-specific?
1362: ata_device_auto_ptr atadev( new sat_device(this, scsidev, "") , scsidev);
1363: if (has_sat_pass_through(atadev.get()))
1364: return atadev.release(); // Detected SAT
1365: }
1366:
1367: return 0;
1368: }
1369:
1370:
1371: /////////////////////////////////////////////////////////////////////////////
1372: // USB device type detection
1373:
1374: // Format USB ID for error messages
1375: static std::string format_usb_id(int vendor_id, int product_id, int version)
1376: {
1377: if (version >= 0)
1378: return strprintf("[0x%04x:0x%04x (0x%03x)]", vendor_id, product_id, version);
1379: else
1380: return strprintf("[0x%04x:0x%04x]", vendor_id, product_id);
1381: }
1382:
1383: // Get type name for USB device with known VENDOR:PRODUCT ID.
1384: const char * smart_interface::get_usb_dev_type_by_id(int vendor_id, int product_id,
1385: int version /*= -1*/)
1386: {
1387: usb_dev_info info, info2;
1388: int n = lookup_usb_device(vendor_id, product_id, version, info, info2);
1389:
1390: if (n <= 0) {
1391: set_err(EINVAL, "Unknown USB bridge %s",
1392: format_usb_id(vendor_id, product_id, version).c_str());
1393: return 0;
1394: }
1395:
1396: if (n > 1) {
1397: set_err(EINVAL, "USB bridge %s type is ambiguous: '%s' or '%s'",
1398: format_usb_id(vendor_id, product_id, version).c_str(),
1399: (!info.usb_type.empty() ? info.usb_type.c_str() : "[unsupported]"),
1400: (!info2.usb_type.empty() ? info2.usb_type.c_str() : "[unsupported]"));
1401: return 0;
1402: }
1403:
1404: if (info.usb_type.empty()) {
1405: set_err(ENOSYS, "Unsupported USB bridge %s",
1406: format_usb_id(vendor_id, product_id, version).c_str());
1407: return 0;
1408: }
1409:
1410: // TODO: change return type to std::string
1411: static std::string type;
1412: type = info.usb_type;
1413: return type.c_str();
1414: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>