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",
307 protocol = (
m_port == 0 ? 0xd : 0xe);
320 return set_err(ENOSYS,
"48-bit ATA commands require SAT ATA PASS-THROUGH (16)");
327 cdb[1] = (protocol << 1) | extend;
328 cdb[2] = (ck_cond << 5) | (t_dir << 3) |
329 (byte_block << 2) | t_length;
383 pout(
"sat_device::ata_pass_through: scsi_pass_through() failed, "
393 if (sense_descriptor) {
399 ard_len = ardp[1] + 2;
402 else if (ard_len > 14)
410 if ( status && ck_cond && ardp && ard_len > 13
411 && (ardp[13] & 0xc1) == 0x40 ) {
413 pout(
"ATA status (0x%02x) indicates success, ignoring SCSI sense_key\n",
420 pout(
"sat_device::ata_pass_through: scsi error: %s\n",
423 pout(
"Values from ATA Return Descriptor are:\n");
424 dStrHex((
const uint8_t *)ardp, ard_len, 1);
436 pout(
"Values from ATA Return Descriptor are:\n");
437 dStrHex((
const uint8_t *)ardp, ard_len, 1);
455 }
else if ((! sense_descriptor) &&
458 (0 != io_hdr.
sensep[4] )) {
470 if (0 == (0x60 & io_hdr.
sensep[8])) {
493 if (sense_descriptor && ardp) {
494 pout(
"Values from ATA Return Descriptor are:\n");
495 dStrHex((
const uint8_t *)ardp, ard_len, 1);
496 }
else if (! sense_descriptor) {
497 pout(
"Values from ATA fixed format sense are:\n");
505 return set_err(EIO,
"SAT command failed");
526 unsigned char inqdata[36] = {0, };
535 int inqsize = inqdata[4] + 5;
536 bool sat = (inqsize >= 36 && !memcmp(inqdata + 8,
"ATA ", 8));
544 (
sat ?
"SAT" :
"SCSI"));
561 char *
data = (
char *)malloc(512);
579 if ((NULL == sensep) || (0 == sb_len) || (0x70 != (0x70 & sensep[0])))
587 sshp->
asc = sensep[2];
589 sshp->
ascq = sensep[3];
596 sb_len = (sb_len < (sensep[7] + 8)) ? sb_len :
599 sshp->
asc = sensep[12];
601 sshp->
ascq = sensep[13];
616 ata_device_with_command_set
622 const char * req_type,
unsigned char signature);
634 const char * req_type,
unsigned char signature)
635:
smart_device(intf, scsidev->get_dev_name(),
"usbcypress", req_type),
637 m_signature(signature)
648#define USBCYPRESS_PASSTHROUGH_LEN 16
653 unsigned char sense[32] = {};
662 int sector_count = 0;
731 sector_count = select;
735 sector_count = select;
748 pout(
"Unrecognized command %d in usbcypress_device::ata_command_interface()\n"
749 "Please contact " PACKAGE_BUGREPORT
"\n", command);
763 cdb[3] = 0xff - (1<<0) - (1<<6);
769 cdb[7] = sector_count;
773 cdb[12] = ata_command;
782 memset(
data, 0, copydata);
797 pout(
"usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
810 unsigned char ardp[8];
821 memset(sense, 0,
sizeof(sense));
824 memset(&io_hdr, 0,
sizeof(io_hdr));
827 io_hdr.
dxferp = (
unsigned char *)ardp;
828 memset(ardp, 0, ard_len);
839 pout(
"usbcypress_device::ata_command_interface: scsi_pass_through() failed, "
853 pout(
"Values from ATA Return Descriptor are:\n");
854 dStrHex((
const uint8_t *)ardp, ard_len, 1);
860 if ((ardp[4] == 0x4f) && (ardp[5] == 0xc2))
862 if ((ardp[4] == 0xf4) && (ardp[5] == 0x2c))
866 syserror(
"Error SMART Status command failed");
867 pout(
"This may be due to a race in usbcypress\n");
868 pout(
"Retry without other disc access\n");
869 pout(
"Please get assistance from " PACKAGE_URL
"\n");
870 pout(
"Values from ATA Return Descriptor are:\n");
871 dStrHex((
const uint8_t *)ardp, ard_len, 1);
890 const char * req_type,
bool prolific,
891 bool ata_48bit_support,
int port);
895 virtual bool open()
override;
909 const char * req_type,
bool prolific,
910 bool ata_48bit_support,
int port)
911:
smart_device(intf, scsidev->get_dev_name(),
"usbjmicron", req_type),
913 m_prolific(prolific), m_ata_48bit_support(ata_48bit_support),
914 m_port(port >= 0 || !prolific ? port : 0)
932 unsigned char regbuf[1] = {0};
938 switch (regbuf[0] & 0x44) {
945 return set_err(EINVAL,
"Two devices connected, try '-d usbjmicron,[01]'");
948 return set_err(ENODEV,
"No device connected");
967 return set_err(EIO,
"Unknown JMicron port");
972 unsigned char smart_status = 0xff;
980 io_hdr.
dxferp = &smart_status;
1003 unsigned char cdb[14];
1005 cdb[ 1] = (rwbit ? 0x10 : 0x00);
1024 "usbjmicron_device::ata_pass_through: "))
1028 if (is_smart_status) {
1029 if (io_hdr.
resid == 1)
1031 return set_err(ENOSYS,
"Incomplete response, status byte missing [JMicron]");
1033 switch (smart_status) {
1044 return set_err(ENOSYS,
"Invalid status byte (0x%02x) [JMicron]", smart_status);
1053 unsigned char regbuf[16] = {0, };
1072 unsigned char * buf,
unsigned short size)
1074 unsigned char cdb[14];
1098 "usbjmicron_device::get_registers: "))
1117 const char * req_type);
1126 const char * req_type)
1127:
smart_device(intf, scsidev->get_dev_name(),
"usbprolific", req_type),
1149 unsigned char cmd_rw = 0x10;
1183 unsigned char cdb[16];
1185 cdb[ 1] = cmd_rw|0x5;
1204 "usbprolific_device::ata_pass_through: "))
1209 unsigned char regbuf[16] = {0, };
1210 memset(&io_hdr, 0,
sizeof(io_hdr));
1215 memset(
cdb, 0,
sizeof(
cdb));
1223 "usbprolific_device::scsi_pass_through (get registers): "))
1255 const char * req_type);
1264 const char * req_type)
1265:
smart_device(intf, scsidev->get_dev_name(),
"usbsunplus", req_type),
1286 unsigned char cdb[12];
1310 "usbsunplus_device::scsi_pass_through (presetting): "))
1315 memset(&io_hdr, 0,
sizeof(io_hdr));
1316 unsigned char protocol;
1357 "usbsunplus_device::scsi_pass_through: "))
1363 unsigned char regbuf[8] = {0, };
1364 memset(&io_hdr, 0,
sizeof(io_hdr));
1372 memset(
cdb+3, 0,
sizeof(
cdb)-3);
1377 "usbsunplus_device::scsi_pass_through (get registers): "))
1405 throw std::logic_error(
"smart_interface: get_sat_device() called with scsidev=0");
1412 const char * t = type + 3;
1418 int ptlen = 0, n = -1;
1419 if (*t && !(sscanf(t,
",%d%n", &ptlen, &n) == 1 && n == (
int)strlen(t)
1420 && (ptlen == 0 || ptlen == 12 || ptlen == 16)))
1421 return set_err_np(EINVAL,
"Option '-d sat[,auto][,N]' requires N to be 0, 12 or 16");
1422 satdev =
new sat_device(
this, scsidev, type, mode, ptlen);
1425 else if (!strcmp(type,
"scsi")) {
1430 unsigned signature = 0x24;
int n1 = -1, n2 = -1;
1431 if (!(((sscanf(type,
"usbcypress%n,0x%x%n", &n1, &signature, &n2) == 1 && n2 == (
int)strlen(type))
1432 || n1 == (
int)strlen(type)) && signature <= 0xff))
1433 return set_err_np(EINVAL,
"Option '-d usbcypress,<n>' requires <n> to be "
1434 "an hexadecimal number between 0x0 and 0xff" );
1439 const char * t = type + 10;
1440 bool prolific =
false;
1445 bool ata_48bit_support =
false;
1448 ata_48bit_support =
true;
1450 int port = -1, n = -1;
1451 if (*t && !( (sscanf(t,
",%d%n", &port, &n) == 1
1452 && n == (
int)strlen(t) && 0 <= port && port <= 1)))
1453 return set_err_np(EINVAL,
"Option '-d usbjmicron[,p][,x],<n>' requires <n> to be 0 or 1");
1454 satdev =
new usbjmicron_device(
this, scsidev, type, prolific, ata_48bit_support, port);
1457 else if (!strcmp(type,
"usbprolific")) {
1461 else if (!strcmp(type,
"usbsunplus")) {
1466 unsigned port = ~0;
int n = -1;
1467 if (!(sscanf(type,
"usbasm1352r,%u%n", &port, &n) == 1 && n == (
int)strlen(type) && port <= 1))
1468 return set_err_np(EINVAL,
"Option '-d usbasm1352r,<n>' requires <n> to be 0 or 1");
1473 return set_err_np(EINVAL,
"Unknown USB device type '%s'", type);
1484 const unsigned char * inqdata,
unsigned inqsize)
1490 if (inqdata && inqsize >= 36 && !memcmp(inqdata + 8,
"ATA ", 8)) {
1509 return strprintf(
"[0x%04x:0x%04x (0x%03x)]", vendor_id, product_id, version);
1511 return strprintf(
"[0x%04x:0x%04x]", vendor_id, product_id);
1522 set_err(EINVAL,
"Unknown USB bridge %s",
1528 set_err(EINVAL,
"USB bridge %s type is ambiguous: '%s' or '%s'",
1536 set_err(ENOSYS,
"Unsupported USB bridge %s",
1542 static std::string type;
1544 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)