89#define SAT_ATA_PASSTHROUGH_12LEN 12
90#define SAT_ATA_PASSTHROUGH_16LEN 16
92#define DEF_SAT_ATA_PASSTHRU_SIZE 16
93#define ATA_RETURN_DESCRIPTOR 9
143 (mode == sat_always ?
"sat" : mode == sat_auto ?
"sat,auto" :
"scsi"), req_type),
145 m_passthrulen(passthrulen),
147 m_variant(variant), m_port(port)
159 (port == 0 ?
"ASM1352R_0" :
"ASM1352R_1") ));
274 unsigned char sense[32] = {};
275 const unsigned char * ardp;
276 int ard_len, have_sense;
284 bool sense_descriptor =
true;
301 return set_err(EINVAL,
"sat_device::ata_pass_through: invalid direction=%d",
308 return set_err(ENOSYS,
"NO DATA ATA commands not implemented [ASM1352R]");
309 protocol = (
m_port == 0 ? 0xd : 0xe);
323 return set_err(ENOSYS,
"48-bit ATA commands require SAT ATA PASS-THROUGH (16)");
330 cdb[1] = (protocol << 1) | extend;
331 cdb[2] = (ck_cond << 5) | (t_dir << 3) |
332 (byte_block << 2) | t_length;
386 pout(
"sat_device::ata_pass_through: scsi_pass_through() failed, "
396 if (sense_descriptor) {
402 ard_len = ardp[1] + 2;
405 else if (ard_len > 14)
413 if ( status && ck_cond && ardp && ard_len > 13
414 && (ardp[13] & 0xc1) == 0x40 ) {
416 pout(
"ATA status (0x%02x) indicates success, ignoring SCSI sense_key\n",
423 pout(
"sat_device::ata_pass_through: scsi error: %s\n",
426 pout(
"Values from ATA Return Descriptor are:\n");
427 dStrHex((
const uint8_t *)ardp, ard_len, 1);
439 pout(
"Values from ATA Return Descriptor are:\n");
440 dStrHex((
const uint8_t *)ardp, ard_len, 1);
458 }
else if ((! sense_descriptor) &&
461 (0 != io_hdr.
sensep[4] )) {
473 if (0 == (0x60 & io_hdr.
sensep[8])) {
496 if (sense_descriptor && ardp) {
497 pout(
"Values from ATA Return Descriptor are:\n");
498 dStrHex((
const uint8_t *)ardp, ard_len, 1);
499 }
else if (! sense_descriptor) {
500 pout(
"Values from ATA fixed format sense are:\n");
508 return set_err(EIO,
"SAT command failed");
529 unsigned char inqdata[36] = {0, };
538 int inqsize = inqdata[4] + 5;
539 bool sat = (inqsize >= 36 && !memcmp(inqdata + 8,
"ATA ", 8));
547 (
sat ?
"SAT" :
"SCSI"));
564 char *
data = (
char *)malloc(512);
582 if ((NULL == sensep) || (0 == sb_len) || (0x70 != (0x70 & sensep[0])))
590 sshp->
asc = sensep[2];
592 sshp->
ascq = sensep[3];
599 sb_len = (sb_len < (sensep[7] + 8)) ? sb_len :
602 sshp->
asc = sensep[12];
604 sshp->
ascq = sensep[13];
619 ata_device_with_command_set
625 const char * req_type,
unsigned char signature);
637 const char * req_type,
unsigned char signature)
638:
smart_device(intf, scsidev->get_dev_name(),
"usbcypress", req_type),
640 m_signature(signature)
651#define USBCYPRESS_PASSTHROUGH_LEN 16
656 unsigned char sense[32] = {};
665 int sector_count = 0;
734 sector_count = select;
738 sector_count = select;
751 pout(
"Unrecognized command %d in usbcypress_device::ata_command_interface()\n"
752 "Please contact " PACKAGE_BUGREPORT
"\n", command);
766 cdb[3] = 0xff - (1<<0) - (1<<6);
772 cdb[7] = sector_count;
776 cdb[12] = ata_command;
785 memset(
data, 0, copydata);
800 pout(
"usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
813 unsigned char ardp[8];
824 memset(sense, 0,
sizeof(sense));
827 memset(&io_hdr, 0,
sizeof(io_hdr));
830 io_hdr.
dxferp = (
unsigned char *)ardp;
831 memset(ardp, 0, ard_len);
842 pout(
"usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
856 pout(
"Values from ATA Return Descriptor are:\n");
857 dStrHex((
const uint8_t *)ardp, ard_len, 1);
863 if ((ardp[4] == 0x4f) && (ardp[5] == 0xc2))
865 if ((ardp[4] == 0xf4) && (ardp[5] == 0x2c))
869 syserror(
"Error SMART Status command failed");
870 pout(
"This may be due to a race in usbcypress\n");
871 pout(
"Retry without other disc access\n");
872 pout(
"Please get assistance from " PACKAGE_URL
"\n");
873 pout(
"Values from ATA Return Descriptor are:\n");
874 dStrHex((
const uint8_t *)ardp, ard_len, 1);
893 const char * req_type,
bool prolific,
894 bool ata_48bit_support,
int port);
898 virtual bool open()
override;
912 const char * req_type,
bool prolific,
913 bool ata_48bit_support,
int port)
914:
smart_device(intf, scsidev->get_dev_name(),
"usbjmicron", req_type),
916 m_prolific(prolific), m_ata_48bit_support(ata_48bit_support),
917 m_port(port >= 0 || !prolific ? port : 0)
935 unsigned char regbuf[1] = {0};
941 switch (regbuf[0] & 0x44) {
948 return set_err(EINVAL,
"Two devices connected, try '-d usbjmicron,[01]'");
951 return set_err(ENODEV,
"No device connected");
970 return set_err(EIO,
"Unknown JMicron port");
975 unsigned char smart_status = 0xff;
983 io_hdr.
dxferp = &smart_status;
1006 unsigned char cdb[14];
1008 cdb[ 1] = (rwbit ? 0x10 : 0x00);
1027 "usbjmicron_device::ata_pass_through: "))
1031 if (is_smart_status) {
1032 if (io_hdr.
resid == 1)
1034 return set_err(ENOSYS,
"Incomplete response, status byte missing [JMicron]");
1036 switch (smart_status) {
1047 return set_err(ENOSYS,
"Invalid status byte (0x%02x) [JMicron]", smart_status);
1056 unsigned char regbuf[16] = {0, };
1075 unsigned char * buf,
unsigned short size)
1077 unsigned char cdb[14];
1101 "usbjmicron_device::get_registers: "))
1120 const char * req_type);
1129 const char * req_type)
1130:
smart_device(intf, scsidev->get_dev_name(),
"usbprolific", req_type),
1152 unsigned char cmd_rw = 0x10;
1186 unsigned char cdb[16];
1188 cdb[ 1] = cmd_rw|0x5;
1207 "usbprolific_device::ata_pass_through: "))
1212 unsigned char regbuf[16] = {0, };
1213 memset(&io_hdr, 0,
sizeof(io_hdr));
1218 memset(
cdb, 0,
sizeof(
cdb));
1226 "usbprolific_device::scsi_pass_through (get registers): "))
1258 const char * req_type);
1267 const char * req_type)
1268:
smart_device(intf, scsidev->get_dev_name(),
"usbsunplus", req_type),
1289 unsigned char cdb[12];
1313 "usbsunplus_device::scsi_pass_through (presetting): "))
1318 memset(&io_hdr, 0,
sizeof(io_hdr));
1319 unsigned char protocol;
1360 "usbsunplus_device::scsi_pass_through: "))
1366 unsigned char regbuf[8] = {0, };
1367 memset(&io_hdr, 0,
sizeof(io_hdr));
1375 memset(
cdb+3, 0,
sizeof(
cdb)-3);
1380 "usbsunplus_device::scsi_pass_through (get registers): "))
1408 throw std::logic_error(
"smart_interface: get_sat_device() called with scsidev=0");
1415 const char * t = type + 3;
1421 int ptlen = 0, n = -1;
1422 if (*t && !(sscanf(t,
",%d%n", &ptlen, &n) == 1 && n == (
int)strlen(t)
1423 && (ptlen == 0 || ptlen == 12 || ptlen == 16)))
1424 return set_err_np(EINVAL,
"Option '-d sat[,auto][,N]' requires N to be 0, 12 or 16");
1425 satdev =
new sat_device(
this, scsidev, type, mode, ptlen);
1428 else if (!strcmp(type,
"scsi")) {
1433 unsigned signature = 0x24;
int n1 = -1, n2 = -1;
1434 if (!(((sscanf(type,
"usbcypress%n,0x%x%n", &n1, &signature, &n2) == 1 && n2 == (
int)strlen(type))
1435 || n1 == (
int)strlen(type)) && signature <= 0xff))
1436 return set_err_np(EINVAL,
"Option '-d usbcypress,<n>' requires <n> to be "
1437 "an hexadecimal number between 0x0 and 0xff" );
1442 const char * t = type + 10;
1443 bool prolific =
false;
1448 bool ata_48bit_support =
false;
1451 ata_48bit_support =
true;
1453 int port = -1, n = -1;
1454 if (*t && !( (sscanf(t,
",%d%n", &port, &n) == 1
1455 && n == (
int)strlen(t) && 0 <= port && port <= 1)))
1456 return set_err_np(EINVAL,
"Option '-d usbjmicron[,p][,x],<n>' requires <n> to be 0 or 1");
1457 satdev =
new usbjmicron_device(
this, scsidev, type, prolific, ata_48bit_support, port);
1460 else if (!strcmp(type,
"usbprolific")) {
1464 else if (!strcmp(type,
"usbsunplus")) {
1469 unsigned port = ~0;
int n = -1;
1470 if (!(sscanf(type,
"usbasm1352r,%u%n", &port, &n) == 1 && n == (
int)strlen(type) && port <= 1))
1471 return set_err_np(EINVAL,
"Option '-d usbasm1352r,<n>' requires <n> to be 0 or 1");
1476 return set_err_np(EINVAL,
"Unknown USB device type '%s'", type);
1487 const unsigned char * inqdata,
unsigned inqsize)
1493 if (inqdata && inqsize >= 36 && !memcmp(inqdata + 8,
"ATA ", 8)) {
1512 return strprintf(
"[0x%04x:0x%04x (0x%03x)]", vendor_id, product_id, version);
1514 return strprintf(
"[0x%04x:0x%04x]", vendor_id, product_id);
1525 set_err(EINVAL,
"Unknown USB bridge %s",
1531 set_err(EINVAL,
"USB bridge %s type is ambiguous: '%s' or '%s'",
1539 set_err(ENOSYS,
"Unsupported USB bridge %s",
1545 static std::string type;
1547 return type.c_str();
#define ATA_SMART_AUTO_OFFLINE
#define ATA_IDENTIFY_DEVICE
#define ATA_SMART_WRITE_LOG_SECTOR
#define ATA_IDENTIFY_PACKET_DEVICE
#define ATA_SMART_READ_VALUES
#define ATA_SMART_READ_THRESHOLDS
#define ATA_SMART_READ_LOG_SECTOR
#define ATA_SMART_IMMEDIATE_OFFLINE
#define ATA_SMART_AUTOSAVE
#define ATA_SMART_DISABLE
#define ATA_CHECK_POWER_MODE
Smart pointer class for device pointers.
device_type * release()
Return the pointer and release ownership.
device_type * get() const
Return the pointer.
Adapter class to implement new ATA pass through old interface.
bool ata_cmd_is_supported(const ata_cmd_in &in, unsigned flags, const char *type=0)
Check command input parameters.
void hide_ata(bool hide=true)
Hide/unhide ATA interface.
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out)=0
ATA pass through.
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out) override
ATA pass through.
sat_device(smart_interface *intf, scsi_device *scsidev, const char *req_type, sat_scsi_mode mode=sat_always, int passthrulen=0, sat_variant variant=sat_standard, int port=0)
virtual smart_device * autodetect_open() override
Open device with autodetection support.
virtual bool scsi_pass_through(scsi_cmnd_io *iop) override
SCSI pass through.
Cypress USB Bridge support.
unsigned char m_signature
virtual ~usbcypress_device()
virtual int ata_command_interface(smart_command_set command, int select, char *data) override
Old ATA interface called by ata_pass_through()
usbcypress_device(smart_interface *intf, scsi_device *scsidev, const char *req_type, unsigned char signature)
JMicron USB Bridge support.
virtual ~usbjmicron_device()
bool get_registers(unsigned short addr, unsigned char *buf, unsigned short size)
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out) override
ATA pass through.
virtual bool open() override
Open device, return false on error.
usbjmicron_device(smart_interface *intf, scsi_device *scsidev, const char *req_type, bool prolific, bool ata_48bit_support, int port)
Prolific USB Bridge support. (PL2773) (Probably works on PL2771 also...)
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out) override
ATA pass through.
usbprolific_device(smart_interface *intf, scsi_device *scsidev, const char *req_type)
virtual ~usbprolific_device()
SunplusIT USB Bridge support.
virtual ~usbsunplus_device()
usbsunplus_device(smart_interface *intf, scsi_device *scsidev, const char *req_type)
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out) override
ATA pass through.
void hide_scsi(bool hide=true)
Hide/unhide SCSI interface.
bool scsi_pass_through_and_check(scsi_cmnd_io *iop, const char *msg="")
virtual bool scsi_pass_through(scsi_cmnd_io *iop)=0
SCSI pass through.
Base class for all devices.
int get_errno() const
Get last error number.
const error_info & get_err() const
Get last error info struct.
const char * get_dev_type() const
Get device type.
const char * get_errmsg() const
Get last error message.
virtual bool close()=0
Close device, return false on error.
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
const char * get_info_name() const
Get informal name.
virtual bool is_open() const =0
Return true if device is open.
device_info & set_info()
R/W access to device info struct.
virtual bool open()=0
Open device, return false on error.
The platform interface abstraction.
virtual const char * get_usb_dev_type_by_id(int vendor_id, int product_id, int version=-1)
Get type name for USB device with known VENDOR:PRODUCT ID.
virtual ata_device * get_sat_device(const char *type, scsi_device *scsidev)
Return ATA->SCSI filter for a SAT or USB 'type'.
bool decltype(nullptr) set_err_np(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
virtual ata_device * autodetect_sat_device(scsi_device *scsidev, const unsigned char *inqdata, unsigned inqsize)
Try to detect a SAT device behind a SCSI interface.
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
virtual bool close() override
Close device, return false on error.
Implement a device by tunneling through another device.
tunnel_device_type * get_tunnel_dev()
int lookup_usb_device(int vendor_id, int product_id, int bcd_device, usb_dev_info &info, usb_dev_info &info2)
struct megasas_pd_address addr[MAX_SYS_PDS]
#define SAT_ATA_PASSTHROUGH_16LEN
#define ATA_RETURN_DESCRIPTOR
#define USBCYPRESS_PASSTHROUGH_LEN
#define SAT_ATA_PASSTHROUGH_12LEN
const char * scsiata_cpp_cvsid
#define DEF_SAT_ATA_PASSTHRU_SIZE
static bool has_sat_pass_through(ata_device *dev, bool packet_interface=false)
static int sg_scsi_normalize_sense(const unsigned char *sensep, int sb_len, struct sg_scsi_sense_hdr *sshp)
static std::string format_usb_id(int vendor_id, int product_id, int version)
int scsiSimpleSenseFilter(const struct scsi_sense_disect *sinfo)
void scsi_do_sense_disect(const struct scsi_cmnd_io *io_buf, struct scsi_sense_disect *out)
int scsiStdInquiry(scsi_device *device, uint8_t *pBuf, int bufLen)
const unsigned char * sg_scsi_sense_desc_find(const unsigned char *sensep, int sense_len, int desc_type)
void dStrHex(const uint8_t *up, int len, int no_ascii)
const char * scsiErrString(int scsiErr)
unsigned char scsi_debugmode
#define SAT_ATA_PASSTHROUGH_12
#define SCSI_ASCQ_ATA_PASS_THROUGH
#define DXFER_FROM_DEVICE
#define SCSI_TIMEOUT_DEFAULT
#define SAT_ATA_PASSTHROUGH_16
#define SCSI_STATUS_CHECK_CONDITION
#define SCSI_SK_RECOVERED_ERR
static void sg_put_unaligned_be32(uint32_t val, void *p)
static void sg_put_unaligned_be16(uint16_t val, void *p)
void pout(const char *fmt,...)
ATA pass through input parameters.
enum ata_cmd_in::@29 direction
I/O direction.
void * buffer
Pointer to data buffer.
ata_in_regs_48bit in_regs
Input registers.
unsigned size
Size of buffer.
ata_out_regs_flags out_needed
True if output register value needed.
void set_data_in(void *buf, unsigned nsectors)
Prepare for 28-bit DATA IN command.
ATA pass through output parameters.
ata_out_regs_48bit out_regs
Output registers.
bool is_48bit_cmd() const
Return true if 48-bit command.
ata_in_regs prev
"previous content"
ATA Input registers (for 28-bit commands)
ata_register sector_count
ata_out_regs prev
read with HOB=1
bool is_set() const
Return true if any flag is set.
ATA Output registers (for 28-bit commands)
ata_register sector_count
Abridged SCSI sense data.
unsigned char additional_length
unsigned char response_code
std::string info_name
Informal name.
std::string dev_type
Actual device type.
Error (number,message) pair.
std::string msg
Error message.
void syserror(const char *message)
std::string strprintf(const char *fmt,...)
bool str_starts_with(const char *str, const char *prefix)