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