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