34 snprintf(msg,
sizeof(msg),
"dev_jmb39x_raid.cpp(%d): Assertion failed: %s", line, expr);
35 throw std::logic_error(msg);
38#define jmbassert(expr) (!(expr) ? jmbassert_failed(__LINE__, #expr) : (void)0)
42 static const uint8_t xor_table[] = {
43 0x08, 0xc1, 0x67, 0x44, 0x04, 0x91, 0x0d, 0x3d, 0x9c, 0x44, 0xdb, 0x61, 0xba, 0x63, 0x00, 0x5c,
44 0x48, 0x78, 0xc4, 0x19, 0x9f, 0xc8, 0x8a, 0x1f, 0x8f, 0xa3, 0x7f, 0x83, 0x08, 0xcf, 0x7a, 0x71,
45 0x89, 0xa4, 0x1d, 0xcd, 0xe7, 0xd2, 0x32, 0xe1, 0x27, 0xad, 0xd4, 0xfa, 0x0e, 0x03, 0x99, 0xeb,
46 0xf7, 0x83, 0x50, 0x50, 0x11, 0x2d, 0x79, 0xbe, 0x3c, 0xb4, 0xf1, 0xe3, 0x8f, 0xd9, 0x3b, 0x9f,
47 0xd9, 0xb0, 0xf3, 0x67, 0x87, 0x90, 0xe0, 0x5d, 0xff, 0xf9, 0xf0, 0x60, 0x61, 0x55, 0x1a, 0x2e,
48 0x81, 0x52, 0xaf, 0x73, 0xee, 0x25, 0xad, 0xc7, 0x01, 0x6e, 0xce, 0x6b, 0x01, 0x8d, 0x49, 0x74,
49 0x9c, 0x9e, 0xed, 0x7e, 0xe9, 0x3b, 0xf3, 0xa2, 0x8e, 0x45, 0xa0, 0x39, 0x0f, 0xcd, 0x96, 0x6b,
50 0x90, 0x3c, 0xa7, 0xb4, 0x5a, 0x6f, 0x72, 0xba, 0x08, 0x6b, 0x58, 0x1f, 0x35, 0x42, 0x2a, 0xc6,
51 0x4f, 0xf4, 0x51, 0xa2, 0xa1, 0x48, 0x6e, 0x89, 0xe9, 0x36, 0x6d, 0xc8, 0x3b, 0x12, 0xec, 0x3a,
52 0xad, 0x89, 0x2f, 0x37, 0xab, 0x1a, 0xde, 0x63, 0x2f, 0xef, 0x74, 0xee, 0xc7, 0xa9, 0x51, 0xd1,
53 0xae, 0x63, 0xad, 0x92, 0x1b, 0x78, 0x98, 0xf1, 0xb6, 0x40, 0xbb, 0xfa, 0x22, 0x07, 0xf3, 0x22,
54 0x95, 0xb7, 0x46, 0xa3, 0xca, 0x2b, 0x16, 0x85, 0x40, 0x41, 0x0a, 0xc5, 0xf3, 0x61, 0xc7, 0xad,
55 0x53, 0xfb, 0x1b, 0x65, 0xac, 0xc9, 0x55, 0xee, 0x73, 0xc1, 0x02, 0xa0, 0x29, 0xfe, 0x53, 0x15,
56 0x8f, 0x1f, 0xad, 0x8d, 0x77, 0xde, 0x15, 0xef, 0x6b, 0xf3, 0x1b, 0xd8, 0x44, 0x96, 0xe3, 0xaa,
57 0x5a, 0x2a, 0xdc, 0x10, 0x7b, 0x96, 0xda, 0x3c, 0x8b, 0xf2, 0x3d, 0x38, 0xa4, 0x81, 0xf3, 0x2c,
58 0x58, 0x41, 0xf5, 0x54, 0x73, 0x45, 0x9d, 0x73, 0xc5, 0xfd, 0xe8, 0x2a, 0xbe, 0xc6, 0x30, 0x50,
59 0x9e, 0x4f, 0x8f, 0xa0, 0x29, 0xed, 0x4a, 0xe9, 0x2f, 0x32, 0x03, 0xca, 0x13, 0xd8, 0x5b, 0x7a,
60 0xae, 0x9d, 0x58, 0xe6, 0x88, 0x73, 0x22, 0x90, 0x0a, 0x43, 0x6c, 0x41, 0x5b, 0x17, 0xc4, 0x1a,
61 0x27, 0x5e, 0xf9, 0xef, 0x63, 0x9f, 0x57, 0x23, 0x6c, 0x27, 0x97, 0x70, 0xf5, 0xa8, 0x5b, 0x7b,
62 0x5d, 0xa9, 0x0f, 0x37, 0xae, 0xff, 0x8b, 0xb2, 0xc8, 0xca, 0xd9, 0x28, 0x8e, 0x5b, 0xb2, 0x46,
63 0xbe, 0x80, 0x40, 0x38, 0xe4, 0xee, 0xbb, 0x2c, 0xd2, 0x82, 0xc1, 0x72, 0x5a, 0x11, 0x4f, 0x4b,
64 0x54, 0xe2, 0xb9, 0xf1, 0x24, 0x96, 0x53, 0x3d, 0x33, 0x81, 0xf1, 0x50, 0x2e, 0x1a, 0x04, 0x71,
65 0x80, 0xf9, 0xbf, 0x66, 0x69, 0x9c, 0x6f, 0x22, 0x44, 0xd0, 0x69, 0xbb, 0xad, 0x93, 0x84, 0x98,
66 0x74, 0xaf, 0x67, 0x32, 0xb9, 0x8f, 0x65, 0xf3, 0x4b, 0x0f, 0xf4, 0x85, 0xef, 0xb5, 0xba, 0xff,
67 0xe1, 0xda, 0x9e, 0x9e, 0x32, 0x96, 0xa9, 0x19, 0xb8, 0x4f, 0x43, 0xf7, 0xf6, 0x4c, 0x1c, 0x0f,
68 0xce, 0xd2, 0x67, 0xb6, 0xe3, 0xe3, 0x8d, 0x27, 0x1e, 0x27, 0x98, 0x4c, 0x73, 0x37, 0x5c, 0xff,
69 0xab, 0x16, 0xca, 0x64, 0x7d, 0x91, 0xc0, 0x6d, 0xae, 0x60, 0xf0, 0x1a, 0x43, 0x12, 0xe6, 0xf4,
70 0xd6, 0xe8, 0xba, 0xc2, 0x9b, 0x2f, 0xe6, 0xce, 0x07, 0x08, 0x6a, 0x8d, 0x28, 0x62, 0xa7, 0x31,
71 0xe9, 0x3d, 0x4b, 0x9b, 0x5b, 0x19, 0x18, 0x13, 0xd2, 0xa9, 0xc1, 0x08, 0xce, 0x62, 0x12, 0x8c,
72 0x12, 0x64, 0xe3, 0x43, 0xbb, 0xe3, 0x59, 0x1c, 0x57, 0x7f, 0xcd, 0xb9, 0x72, 0x65, 0x47, 0xab,
73 0xb8, 0xfe, 0x61, 0xc1, 0x08, 0xc2, 0xec, 0x25, 0x8e, 0xb9, 0x1c, 0x89, 0xdf, 0x6d, 0xd2, 0xa7,
74 0x36, 0xa7, 0x10, 0x52, 0x2a, 0x21, 0x2d, 0xaa, 0x98, 0x31, 0xd1, 0x77, 0x35, 0xa8, 0x3b, 0x40,
78 for (
unsigned i = 0; i <
sizeof(
data); i++) {
79 data[i] ^= xor_table[i];
85 static const uint32_t crc_table[] = {
86 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
87 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
88 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
89 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
90 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
91 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
92 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
93 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
94 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
95 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
96 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
97 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
98 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
99 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
100 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
101 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
102 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
103 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
104 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
105 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
106 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
107 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
108 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
109 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
110 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
111 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
112 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
113 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
114 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
115 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
116 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
117 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
121 uint32_t crc = 0x52325032;
122 for (
unsigned i = 0; i <
sizeof(
data)/
sizeof(uint32_t) - 1; i++) {
124 crc = crc_table[( dw & 0xff) ^ (crc >> 24)] ^ (crc << 8);
125 crc = crc_table[((dw>> 8) & 0xff) ^ (crc >> 24)] ^ (crc << 8);
126 crc = crc_table[((dw>>16) & 0xff) ^ (crc >> 24)] ^ (crc << 8);
127 crc = crc_table[( dw>>24 ) ^ (crc >> 24)] ^ (crc << 8);
155 uint32_t code = 0, crc = 0;
157 case 0: code = 0x3c75a80b; crc = 0x706d10d9;
break;
158 case 1: code = 0x0388e337; crc = 0x6958511e;
break;
159 case 2: code = 0x689705f3; crc = 0xfe234b07;
break;
160 case 3: code = 0xe00c523a; crc = 0x5be57adb;
break;
165 memset(
data + 8, 0, 8);
166 for (
unsigned i = 16; i <
sizeof(
data) - 8; i++)
167 data[i] = (uint8_t)i;
173 const uint8_t *
cmd,
unsigned cmdsize)
175 jmbassert(4 <= cmdsize && cmdsize <= 24);
178 uint32_t scrambled_cmd_code;
181 case 0: scrambled_cmd_code = 0x197b0322;
break;
184 scrambled_cmd_code = 0x197b0393;
break;
185 case 2: scrambled_cmd_code = 0x197b0562;
break;
190 memcpy(
data + 8,
cmd, cmdsize);
199 memcpy(data2,
data,
sizeof(data2));
222 uint8_t
cmd[] = {1, 2, 3, 4, 5, 6, 7};
281 uint8_t
cdb[] = {0x28 , 0x00, 0x00, 0x00, 0x00, lba8, 0x00, 0x00, 0x01, 0x00};
299 uint8_t
cdb[] = {0x2a , 0x00, 0x00, 0x00, 0x00, lba8, 0x00, 0x00, 0x01, 0x00};
322 uint8_t version, uint8_t port, uint8_t lba,
bool force);
326 virtual bool open()
override;
328 virtual bool close()
override;
345 bool run_jmb_command(
const uint8_t *
cmd,
unsigned cmdsize, uint8_t (& response)[512]);
351 uint8_t version, uint8_t port, uint8_t lba,
bool force)
352:
smart_device(intf, smartdev->get_dev_name(), req_type, req_type),
354 m_version(version), m_port(port), m_lba(lba), m_force(force),
355 m_blocked(false), m_orig_write_back(false), m_cmd_id(0)
406 uint8_t request[512];
412 dStrHex(request,
sizeof(request), 0);
424 memset(response, 0,
sizeof(response));
434 dStrHex(response,
sizeof(response), 0);
438 if (!memcmp(request, response,
sizeof(request))) {
440 return set_err(EIO,
"No JMB39x response detected");
446 ?
"CRC error in JMB39x response"
447 :
"JMB39x response contains a wakeup sector"));
449 if (memcmp(request, response, 8)) {
451 return set_err(EIO,
"Invalid header in JMB39x response");
461 pout(
"JMB39x: WARNING: Data (%szero filled) at LBA %d lost\n", (zf ?
"" :
"not "),
m_lba);
469 pout(
"JMB39x: Restore original sector (%szero filled)\n",
483 return set_err(EIO,
"Device blocked due to previous errors");
494 return set_err(err.
no,
"SCSI READ CAPACITY failed: %s", err.
msg.c_str());
496 if (lba_size != 512) {
498 return set_err(EINVAL,
"LBA size is %d but must be 512", lba_size);
504 pout(
"JMB39x: Read original data at LBA %d\n",
m_lba);
519 return set_err(EINVAL,
"Original sector at LBA %d %s",
m_lba,
520 (st == 0 ?
"is not zero filled" :
521 st == 1 ?
"contains JMB39x wakeup data"
522 :
"contains JMB39x protocol data"));
527 pout(
"JMB39x: Zero filling original data\n");
535 uint8_t dataout[512];
536 for (
int id = 0;
id < 4;
id++) {
539 pout(
"JMB39x: Write wakeup sector #%d\n",
id+1);
541 dStrHex(dataout,
sizeof(dataout), 0);
549 return set_err(err.
no,
"Write of JMB39x wakeup sector #%d: %s",
id + 1, err.
msg.c_str());
567 0x00, 0x00, 0x00, 0x00,
568 0x00, 0x00, 0x00, 0x00,
569 0x00, 0x00, 0x00, 0x00
571 uint8_t (& response)[512] = dataout;
579 if (response[16] <
' ') {
581 return set_err(ENOENT,
"No device connected to JMB39x port %d",
m_port);
627 return set_err(EIO,
"Device blocked due to previous errors");
629 return set_err(ENOSYS,
"NO DATA ATA commands not implemented [JMB39x]");
635 return set_err(ENOSYS,
"ATA command not implemented due to truncated response [JMB39x]");
640 0x00, 0x02, 0x03, 0xff,
642 0x02, 0x00, 0xe0, 0x00, 0x00,
659 uint8_t response[512];
664 uint8_t status = response[31];
665 if (status == 0x00) {
667 return set_err(EIO,
"No device connected to JMB39x port %d",
m_port);
669 if ((status & 0xc1) != 0x40 )
670 return set_err(EIO,
"ATA command failed (status=0x%02x)", status);
675 memcpy(in.
buffer, response + 32, in.
size - 32 - 16);
695 set_err(EINVAL,
"Type '%s+...': Device type '%s' is not ATA or SCSI", type, smartdev->
get_req_type());
700 char prefix[15+1] =
"";
701 sscanf(type,
"%15[^,],%n", prefix, &n1);
703 if (!strcmp(prefix,
"jmb39x"))
705 else if (!strcmp(prefix,
"jmb39x-q"))
707 else if (!strcmp(prefix,
"jms56x"))
709 else if (!strcmp(prefix,
"jmb39x-q2"))
714 set_err(EINVAL,
"Unknown JMicron type '%s'", type);
725 const char * args = type + n1;
727 sscanf(args,
"%u%n", &port, &n1);
728 int n2 = -1, len = strlen(args);
729 if (0 < n1 && n1 < len && sscanf(args + n1,
",s%u%n", &lba, &n2) == 1 && n2 > 0)
732 if (0 < n1 && n1 < len && (sscanf(args + n1,
",force%n", &n2), n2) > 0) {
736 if (!(n1 == len && port <= 4 && 1 <= lba && lba <= 255)) {
737 set_err(EINVAL,
"Option -d %s,N[,sLBA][,force] must have 0 <= N <= 4 [, 1 <= LBA <= 255]", prefix);
unsigned char checksum(const void *data)
unsigned char ata_debugmode
#define ATA_IDENTIFY_DEVICE
#define ATA_SMART_READ_VALUES
#define ATA_SMART_READ_THRESHOLDS
#define ATA_SMART_READ_LOG_SECTOR
Smart pointer class for device pointers.
device_type * release()
Return the pointer and release ownership.
bool ata_cmd_is_supported(const ata_cmd_in &in, unsigned flags, const char *type=0)
Check command input parameters.
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out)=0
ATA pass through.
bool run_jmb_command(const uint8_t *cmd, unsigned cmdsize, uint8_t(&response)[512])
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out) override
ATA pass through.
void report_orig_data_lost() const
virtual bool close() override
Close device, return false on error.
jmb39x_device(smart_interface *intf, smart_device *smartdev, const char *req_type, uint8_t version, uint8_t port, uint8_t lba, bool force)
virtual bool open() override
Open device, return false on error.
bool raw_read(uint8_t(&data)[512])
bool raw_write(const uint8_t(&data)[512])
bool scsi_pass_through_and_check(scsi_cmnd_io *iop, const char *msg="")
Base class for all devices.
bool is_scsi() const
Return true if SCSI device.
const error_info & get_err() const
Get last error info struct.
const char * get_req_type() const
Get type requested by user, empty if none.
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.
ata_device * to_ata()
Downcast to ATA device.
const char * get_info_name() const
Get informal name.
scsi_device * to_scsi()
Downcast to SCSI device.
bool is_ata() const
Return true if ATA device.
device_info & set_info()
R/W access to device info struct.
The platform interface abstraction.
virtual ata_device * get_jmb39x_device(const char *type, smart_device *smartdev)
Return JMB93x->ATA filter.
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
virtual bool is_open() const override
Return true if device is open.
Implement a device by tunneling through another device.
tunnel_device_type * get_tunnel_dev()
static bool scsi_read_lba8(scsi_device *scsidev, uint8_t lba8, uint8_t(&data)[512])
static void jmb_put_crc(uint8_t(&data)[512], uint32_t crc)
static bool ata_write_lba8(ata_device *atadev, uint8_t lba8, const uint8_t(&data)[512])
const char * dev_jmb39x_raid_cpp_svnid
static uint32_t jmb_get_crc(const uint8_t(&data)[512])
static int scsi_get_lba_size(scsi_device *scsidev)
static bool jmb_check_crc(const uint8_t(&data)[512])
static bool scsi_write_lba8(scsi_device *scsidev, uint8_t lba8, const uint8_t(&data)[512])
static void jmb_put_le32(uint8_t(&data)[512], unsigned index, uint32_t val)
static uint32_t jmb_crc(const uint8_t(&data)[512])
static void jmbassert_failed(int line, const char *expr)
static bool ata_read_lba8(ata_device *atadev, uint8_t lba8, uint8_t(&data)[512])
static void jmb_set_request_sector(uint8_t(&data)[512], uint8_t version, uint32_t cmd_id, const uint8_t *cmd, unsigned cmdsize)
static void jmb_check_funcs()
static void jmb_set_wakeup_sector(uint8_t(&data)[512], int id)
static int jmb_get_sector_type(const uint8_t(&data)[512])
static void jmb_xor(uint8_t(&data)[512])
static int is_supported_by_jmb(const ata_in_regs &r)
uint64_t scsiGetSize(scsi_device *device, bool avoid_rcap16, struct scsi_readcap_resp *srrp)
void dStrHex(const uint8_t *up, int len, int no_ascii)
#define DXFER_FROM_DEVICE
#define SCSI_TIMEOUT_DEFAULT
static void sg_put_unaligned_le32(uint32_t val, void *p)
static uint32_t sg_get_unaligned_le32(const void *p)
static uint32_t sg_get_unaligned_be32(const void *p)
void pout(const char *fmt,...)
ATA pass through input parameters.
enum ata_cmd_in::@29 direction
I/O direction.
void set_data_out(const void *buf, unsigned nsectors)
Prepare for 28-bit DATA OUT command.
void * buffer
Pointer to data buffer.
ata_in_regs_48bit in_regs
Input registers.
unsigned size
Size of buffer.
void set_data_in(void *buf, unsigned nsectors)
Prepare for 28-bit DATA IN command.
ATA pass through output parameters.
ATA Input registers (for 28-bit commands)
ata_register sector_count
std::string info_name
Informal name.
Error (number,message) pair.
std::string msg
Error message.
std::string strprintf(const char *fmt,...)
bool nonempty(const void *data, int size)