47#include <scsi/scsi_ioctl.h>
54#include <sys/utsname.h>
60#ifdef HAVE_SYS_SYSMACROS_H
64#include <sys/sysmacros.h>
67#include <selinux/selinux.h>
91#define ARGUSED(x) ((void)(x))
114 virtual bool is_open()
const override;
116 virtual bool open()
override;
118 virtual bool close()
override;
154 if (errno == EBUSY && (
m_flags & O_EXCL))
157 "The requested controller is used exclusively by another process!\n"
158 "(e.g. smartctl or smartd)\n"
159 "Please quit the impeding process or try again later...");
160 return set_err((errno==ENOENT || errno==ENOTDIR) ? ENODEV : errno);
168 if (-1 == fcntl(
m_fd, F_SETFD, FD_CLOEXEC))
170 pout(
"fcntl(set FD_CLOEXEC) failed, errno=%d [%s]\n", errno, strerror(errno));
187 "=================================================== SMARTCTL EXAMPLES =====\n\n"
188 " smartctl --all /dev/sda (Prints all SMART information)\n\n"
189 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/sda\n"
190 " (Enables SMART on first disk)\n\n"
191 " smartctl --test=long /dev/sda (Executes extended disk self-test)\n\n"
192 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/sda\n"
193 " (Prints Self-Test & Attribute errors)\n"
194 " smartctl --all --device=3ware,2 /dev/sda\n"
195 " smartctl --all --device=3ware,2 /dev/twe0\n"
196 " smartctl --all --device=3ware,2 /dev/twa0\n"
197 " smartctl --all --device=3ware,2 /dev/twl0\n"
198 " (Prints all SMART info for 3rd ATA disk on 3ware RAID controller)\n"
199 " smartctl --all --device=hpt,1/1/3 /dev/sda\n"
200 " (Prints all SMART info for the SATA disk attached to the 3rd PMPort\n"
201 " of the 1st channel on the 1st HighPoint RAID controller)\n"
202 " smartctl --all --device=areca,3/1 /dev/sg2\n"
203 " (Prints all SMART info for 3rd ATA disk of the 1st enclosure\n"
204 " on Areca RAID controller)\n"
247#define BUFFER_LENGTH (4+512)
256 const int HDIO_DRIVE_CMD_OFFSET = 4;
338 pout(
"Unrecognized command %d in linux_ata_command_interface()\n"
339 "Please contact " PACKAGE_BUGREPORT
"\n", command);
351 memset(task, 0,
sizeof(task));
364 reqtask->out_size = 512;
365 reqtask->in_size = 0;
372 pout(
"Kernel lacks HDIO_DRIVE_TASKFILE support; compile kernel with CONFIG_IDE_TASK_IOCTL set\n");
391 unsigned const char normal_lo=0x4f, normal_hi=0xc2;
392 unsigned const char failed_lo=0xf4, failed_hi=0x2c;
398 pout(
"Error SMART Status command via HDIO_DRIVE_TASK failed");
399 pout(
"Rebuild older linux 2.2 kernels with HDIO_DRIVE_TASK support added\n");
402 syserror(
"Error SMART Status command failed");
407 if (buff[4]==normal_lo && buff[5]==normal_hi)
411 if (buff[4]==failed_lo && buff[5]==failed_hi)
415 syserror(
"Error SMART Status command failed");
416 pout(
"Please get assistance from " PACKAGE_URL
"\n");
417 pout(
"Register values returned from SMART Status command are:\n");
418 pout(
"ST =0x%02x\n",(
int)buff[0]);
419 pout(
"ERR=0x%02x\n",(
int)buff[1]);
420 pout(
"NS =0x%02x\n",(
int)buff[2]);
421 pout(
"SC =0x%02x\n",(
int)buff[3]);
422 pout(
"CL =0x%02x\n",(
int)buff[4]);
423 pout(
"CH =0x%02x\n",(
int)buff[5]);
424 pout(
"SEL=0x%02x\n",(
int)buff[6]);
445 unsigned short deviceid[256];
462 buff[HDIO_DRIVE_CMD_OFFSET]=buff[2];
466 memcpy(
data, buff+HDIO_DRIVE_CMD_OFFSET, copydata);
489#define MAX_DXFER_LEN 1024
490#define SEND_IOCTL_RESP_SENSE_LEN 16
491#define SG_IO_RESP_SENSE_LEN 64
492#define LSCSI_DRIVER_MASK 0xf
493#define LSCSI_DRIVER_SENSE 0x8
494#define LSCSI_DID_ERROR 0x7
495#define LSCSI_DRIVER_TIMEOUT 0x6
496#define LSCSI_DID_TIME_OUT 0x3
497#define LSCSI_DID_BUS_BUSY 0x2
498#define LSCSI_DID_NO_CONNECT 0x1
519 struct sg_io_hdr io_hdr_v3;
520 struct sg_io_v4 io_hdr_v4;
526 const unsigned char * ucp = iop->
cmnd;
528 pout(
">>>>>>>> %s: cdb seems invalid, opcode=0x%x, len=%d, cdb:\n",
529 __func__, ((n > 0) ? ucp[0] : 0), n);
532 pout(
" <<truncating to first 16 bytes>>\n");
533 dStrHex((
const uint8_t *)ucp, ((n > 16) ? 16 : n), 1);
541 const unsigned char * ucp = iop->
cmnd;
544 const int sz = (int)
sizeof(buff);
546 pout(
">>>> %s: sg_io_ifc=%d\n", __func__, (
int)sg_io_ifc);
548 j = snprintf(buff, sz,
" [%s: ", np ? np :
"<unknown opcode>");
549 for (k = 0; k < (int)iop->
cmnd_len; ++k)
550 j += snprintf(&buff[j], (sz > j ? (sz - j) : 0),
"%02x ", ucp[k]);
553 int trunc = (iop->
dxfer_len > 256) ? 1 : 0;
555 snprintf(&buff[j], (sz > j ? (sz - j) : 0),
"]\n Outgoing "
556 "data, len=%d%s:\n", (
int)iop->
dxfer_len,
557 (trunc ?
" [only first 256 bytes shown]" :
""));
561 snprintf(&buff[j], (sz > j ? (sz - j) : 0),
"]\n");
567 memset(&io_hdr_v3, 0,
sizeof(
struct sg_io_hdr));
568 memset(&io_hdr_v4, 0,
sizeof(
struct sg_io_v4));
570 io_hdr_v3.interface_id =
'S';
574 io_hdr_v3.dxferp = iop->
dxferp;
575 io_hdr_v3.cmdp = iop->
cmnd;
576 io_hdr_v3.sbp = iop->
sensep;
579 io_hdr_v3.timeout = ((0 == iop->
timeout) ? 60 : iop->
timeout) * 1000;
581 io_hdr_v4.guard =
'Q';
582 io_hdr_v4.request_len = iop->
cmnd_len;
583 io_hdr_v4.request = __u64(iop->
cmnd);
585 io_hdr_v4.response = __u64(iop->
sensep);
586 io_hdr_v4.timeout = ((0 == iop->
timeout) ? 60 : iop->
timeout) * 1000;
590 io_hdr_v3.dxfer_direction = SG_DXFER_NONE;
593 io_hdr_v3.dxfer_direction = SG_DXFER_FROM_DEV;
595 io_hdr_v4.din_xferp = __u64(iop->
dxferp);
598 io_hdr_v3.dxfer_direction = SG_DXFER_TO_DEV;
599 io_hdr_v4.dout_xfer_len = iop->
dxfer_len;
600 io_hdr_v4.dout_xferp = __u64(iop->
dxferp);
603 pout(
"do_scsi_cmnd_io: bad dxfer_dir\n");
611 void * io_hdr = NULL;
626 if (ioctl(dev_fd, SG_IO, io_hdr) < 0) {
628 pout(
" SG_IO ioctl failed, errno=%d [%s], SG_IO_V%d\n", errno,
629 strerror(errno), (
int)sg_io_ifc);
633 unsigned int sg_driver_status = 0, sg_transport_status = 0, sg_info = 0,
637 iop->
resid = io_hdr_v3.resid;
639 sg_driver_status = io_hdr_v3.driver_status;
640 sg_transport_status = io_hdr_v3.host_status;
641 sg_info = io_hdr_v3.info;
643 sg_duration = io_hdr_v3.duration;
652 iop->
resid = io_hdr_v4.din_resid;
655 iop->
resid = io_hdr_v4.dout_resid;
659 sg_driver_status = io_hdr_v4.driver_status;
660 sg_transport_status = io_hdr_v4.transport_status;
661 sg_info = io_hdr_v4.info;
663 sg_duration = io_hdr_v4.duration;
669 pout(
" scsi_status=0x%x, sg_transport_status=0x%x, sg_driver_status=0x%x\n"
670 " sg_info=0x%x sg_duration=%d milliseconds resid=%d\n", iop->
scsi_status,
671 sg_transport_status, sg_driver_status, sg_info,
672 sg_duration, iop->
resid);
679 trunc = (len > 256) ? 1 : 0;
681 pout(
" Incoming data, len=%d%s:\n", len,
682 (trunc ?
" [only first 256 bytes shown]" :
""));
685 pout(
" Incoming data trimmed to nothing by resid\n");
691 if (sg_info & SG_INFO_CHECK) {
694 if (0 != sg_transport_status) {
705 if (0 != masked_driver_status) {
716 pout(
" >>> Sense buffer, len=%d:\n",
723 if ((iop->
sensep[0] & 0x7f) > 0x71)
724 pout(
" status=%x: [desc] sense_key=%x asc=%x ascq=%x\n",
728 pout(
" status=%x: sense_key=%x asc=%x ascq=%x\n",
763 }
else if ((-ENODEV == res) || (-EACCES == res) || (-EPERM == res))
769 }
else if ((-ENODEV == res) || (-EACCES == res) || (-EPERM == res))
784 pout(
">>>> do_scsi_cmnd_io: bad sg_io_interface=%d\n",
802 const char * req_type,
bool scanning =
false);
813 const char * dev_name,
const char * req_type,
bool scanning )
839 unsigned int host,
unsigned int channel,
unsigned int device);
843 virtual bool open()
override;
860 const char *dev_name,
unsigned int host,
unsigned int channel,
unsigned int device)
863 aHost(host), aLun(channel), aId(device)
878 snprintf(dev_name,
sizeof(dev_name),
"/dev/aac%d",
aHost);
881 int afd =
::open(dev_name,O_RDWR);
883 if(afd < 0 && errno == ENOENT) {
885 FILE *fp = fopen(
"/proc/devices",
"r");
887 return set_err(errno,
"cannot open /proc/devices:%s",
893 while(fgets(line,
sizeof(line),fp) !=NULL) {
895 if(sscanf(line,
"%d aac%n",&mjr,&nc) == 1
896 && nc > 0 &&
'\n' == line[nc])
905 return set_err(ENOENT,
"aac entry not found in /proc/devices");
908 if(mknod(dev_name, S_IFCHR|0600, makedev(mjr,
aHost)))
909 return set_err(errno,
"cannot create %s:%s",dev_name,strerror(errno));
911 afd =
::open(dev_name,O_RDWR);
915 return set_err(errno,
"cannot open %s:%s",dev_name,strerror(errno));
927 const unsigned char * ucp = iop->
cmnd;
930 const int sz = (int)
sizeof(buff);
933 j = snprintf(buff, sz,
" [%s: ", np ? np :
"<unknown opcode>");
934 for (k = 0; k < (int)iop->
cmnd_len; ++k)
935 j += snprintf(&buff[j], (sz > j ? (sz - j) : 0),
"%02x ", ucp[k]);
938 int trunc = (iop->
dxfer_len > 256) ? 1 : 0;
940 snprintf(&buff[j], (sz > j ? (sz - j) : 0),
"]\n Outgoing "
941 "data, len=%d%s:\n", (
int)iop->
dxfer_len,
942 (trunc ?
" [only first 256 bytes shown]" :
""));
946 snprintf(&buff[j], (sz > j ? (sz - j) : 0),
"]\n");
953 if (iop->
cmnd[0] == 0x00)
966 #elif defined(ENVIRONMENT32)
996 pout(
"aacraid: bad dxfer_dir\n");
997 return set_err(EINVAL,
"aacraid: bad dxfer_dir\n");
1002 #ifdef ENVIRONMENT64
1010 #elif defined(ENVIRONMENT32)
1011 pSrb->sg32.
count = 1;
1012 pSrb->sg32.sg32[0].addr32 = (intptr_t)iop->
dxferp;
1014 pSrb->sg32.sg32[0].length = (uint32_t)iop->
dxfer_len;
1029 return set_err(errno,
"aacraid send_raw_srb: %d.%d = %s",
1033#define SRB_STATUS_SUCCESS 0x1
1034#define SRB_STATUS_ERROR 0x4
1035#define SRB_STATUS_NO_DEVICE 0x08
1036#define SRB_STATUS_SELECTION_TIMEOUT 0x0a
1037#define SRB_STATUS_AUTOSENSE_VALID 0x80
1054 return set_err(EIO,
"aacraid: Device %d %d does not exist",
aLun,
aId);
1057 return set_err(EIO,
"aacraid: Device %d %d not responding",
aLun,
aId);
1060 return set_err(EIO,
"aacraid result: %d.%d = 0x%x",
1081 virtual bool open()
override;
1082 virtual bool close()
override;
1092 int senseLen,
void *sense,
int report,
int direction);
1094 int senseLen,
void *sense,
int report,
int direction);
1096 int senseLen,
void *sense,
int report,
int direction);
1100 const char *dev_name,
unsigned int tgt)
1101 :
smart_device(intf, dev_name,
"megaraid",
"megaraid"),
1103 m_disknum(tgt), m_hba(0),
1129 unsigned char req_buff[64] = {0, };
1133 set_err(EIO,
"INQUIRY failed");
1137 int avail_len = req_buff[4] + 5;
1138 int len = (avail_len < req_len ? avail_len : req_len);
1143 pout(
"Got MegaRAID inquiry.. %s\n", req_buff+8);
1166 struct sg_scsi_id sgid;
1167 if (ioctl(
get_fd(), SG_GET_SCSI_ID, &sgid) == 0) {
1168 m_hba = sgid.host_no;
1170 else if (ioctl(
get_fd(), SCSI_IOCTL_GET_BUS_NUMBER, &
m_hba) != 0) {
1173 return set_err(err,
"can't get bus number");
1178 FILE * fp = fopen(
"/proc/devices",
"r");
1181 while (fgets(line,
sizeof(line), fp) != NULL) {
1183 if (sscanf(line,
"%d megaraid_sas_ioctl%n", &mjr, &n1) == 1 && n1 == 22) {
1184 n1=mknod(
"/dev/megaraid_sas_ioctl_node", S_IFCHR|0600, makedev(mjr, 0));
1186 pout(
"Creating /dev/megaraid_sas_ioctl_node = %d\n", n1 >= 0 ? 0 : errno);
1187 if (n1 >= 0 || errno == EEXIST)
1190 else if (sscanf(line,
"%d megadev%n", &mjr, &n1) == 1 && n1 == 11) {
1191 n1=mknod(
"/dev/megadev0", S_IFCHR|0600, makedev(mjr, 0));
1193 pout(
"Creating /dev/megadev0 = %d\n", n1 >= 0 ? 0 : errno);
1194 if (n1 >= 0 || errno == EEXIST)
1202 if ((
m_fd =
::open(
"/dev/megaraid_sas_ioctl_node", O_RDWR)) >= 0) {
1205 else if ((
m_fd =
::open(
"/dev/megadev0", O_RDWR)) >= 0) {
1211 return set_err(err,
"cannot open /dev/megaraid_sas_ioctl_node or /dev/megadev0");
1232 const unsigned char * ucp = iop->
cmnd;
1235 const int sz = (int)
sizeof(buff);
1238 j = snprintf(buff, sz,
" [%s: ", np ? np :
"<unknown opcode>");
1239 for (k = 0; k < (int)iop->
cmnd_len; ++k)
1240 j += snprintf(&buff[j], (sz > j ? (sz - j) : 0),
"%02x ", ucp[k]);
1243 int trunc = (iop->
dxfer_len > 256) ? 1 : 0;
1245 snprintf(&buff[j], (sz > j ? (sz - j) : 0),
"]\n Outgoing "
1246 "data, len=%d%s:\n", (
int)iop->
dxfer_len,
1247 (trunc ?
" [only first 256 bytes shown]" :
""));
1251 snprintf(&buff[j], (sz > j ? (sz - j) : 0),
"]\n");
1256 if (iop->
cmnd[0] == 0x00)
1261 if (iop->
cmnd[2] & (1 << 5))
1262 return set_err(ENOSYS,
"ATA return descriptor not supported by controller firmware");
1271 return set_err(ENOSYS,
"SMART WRITE LOG SECTOR may cause problems, try with -T permissive to force");
1282 int dataLen,
void *
data,
1283 int ,
void * ,
int ,
int dxfer_dir)
1288 memset(&uio, 0,
sizeof(uio));
1291 pthru->cmd_status = 0xFF;
1292 pthru->scsi_status = 0x0;
1295 pthru->cdb_len = cdbLen;
1297 switch (dxfer_dir) {
1308 pout(
"megasas_cmd: bad dxfer_dir\n");
1309 return set_err(EINVAL,
"megasas_cmd: bad dxfer_dir\n");
1313 pthru->sge_count = 1;
1314 pthru->data_xfer_len = dataLen;
1315 pthru->sgl.sge32[0].phys_addr = (intptr_t)
data;
1316 pthru->sgl.sge32[0].length = (uint32_t)dataLen;
1325 uio.
sgl[0].iov_len = dataLen;
1330 if (
pthru->cmd_status || rc != 0) {
1331 if (
pthru->cmd_status == 12) {
1334 return set_err((errno ? errno : EIO),
"megasas_cmd result: %d.%d = %d/%d",
1343 int dataLen,
void *
data,
1344 int ,
void * ,
int ,
int )
1353 memset(&uio, 0,
sizeof(uio));
1354 uio.
inlen = dataLen;
1357 memset(
data, 0, dataLen);
1358 uio.ui.fcs.
opcode = 0x80;
1364 uio.
mbox.xferaddr = (intptr_t)&uio.
pthru;
1367 uio.
pthru.timeout = 2;
1368 uio.
pthru.channel = 0;
1370 uio.
pthru.cdblen = cdbLen;
1372 uio.
pthru.dataxferaddr = (intptr_t)
data;
1373 uio.
pthru.dataxferlen = dataLen;
1374 memcpy(uio.
pthru.cdb,
cdb, cdbLen);
1377 if (uio.
pthru.scsistatus || rc != 0) {
1378 return set_err((errno ? errno : EIO),
"megadev_cmd result: %d.%d = %d/%d",
1380 uio.
pthru.scsistatus);
1394 unsigned int eid,
unsigned int sid);
1406 const char *dev_name,
unsigned int eid,
unsigned int sid)
1409 m_eid(eid), m_sid(sid)
1420 const unsigned char * ucp = iop->
cmnd;
1423 const int sz = (int)
sizeof(buff);
1426 j = snprintf(buff, sz,
" [%s: ", np ? np :
"<unknown opcode>");
1427 for (k = 0; k < (int)iop->
cmnd_len; ++k)
1428 j += snprintf(&buff[j], (sz > j ? (sz - j) : 0),
"%02x ", ucp[k]);
1430 int trunc = (iop->
dxfer_len > 256) ? 1 : 0;
1432 snprintf(&buff[j], (sz > j ? (sz - j) : 0),
"]\n Outgoing "
1433 "data, len=%d%s:\n", (
int)iop->
dxfer_len,
1434 (trunc ?
" [only first 256 bytes shown]" :
""));
1438 snprintf(&buff[j], (sz > j ? (sz - j) : 0),
"]\n");
1449 struct sg_io_v4 io_hdr_v4{};
1451 unsigned char sense_buff[96] = { 0 };
1460 io_hdr_v4.guard =
'Q';
1461 io_hdr_v4.protocol = BSG_PROTOCOL_SCSI;
1462 io_hdr_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_TRANSPORT;
1463 io_hdr_v4.response = (uintptr_t)sense_buff;
1466 io_hdr_v4.request = (uintptr_t)(&bsg_param);
1474 io_hdr_v4.din_xferp = (uintptr_t)iop->
dxferp;
1475 io_hdr_v4.din_xfer_len = iop->
dxfer_len;
1479 io_hdr_v4.dout_xferp = (uintptr_t)iop->
dxferp;
1480 io_hdr_v4.dout_xfer_len = iop->
dxfer_len;
1484 pout(
"scsi_cmd: bad dxfer_dir\n");
1485 return set_err(EINVAL,
"scsi_cmd: bad dxfer_dir\n");
1497 io_hdr_v4.response = (uintptr_t)scsi_param.
sense_buffer;
1506 int r = ioctl(
get_fd(), SG_IO, &io_hdr_v4);
1508 return set_err((errno ? errno : EIO),
"scsi_cmd ioctl failed: %d %d,%d",
1514 int len = ( iop->
max_sense_len < io_hdr_v4.max_response_len ) ?
1517 if (iop->
sensep && len > 0) {
1518 memcpy(iop->
sensep,
reinterpret_cast<void *
>(io_hdr_v4.response), len);
1528#ifdef HAVE_LINUX_CCISS_IOCTL_H
1530class linux_cciss_device
1535 linux_cciss_device(
smart_interface * intf,
const char * name,
unsigned char disknum);
1537 virtual bool scsi_pass_through(
scsi_cmnd_io * iop)
override;
1540 unsigned char m_disknum;
1544 const char * dev_name,
unsigned char disknum)
1546 linux_smart_device(O_RDWR | O_NONBLOCK),
1552bool linux_cciss_device::scsi_pass_through(
scsi_cmnd_io * iop)
1556 return set_err(-status);
1580 virtual bool open()
override;
1593 m_escalade_type(escalade_type), m_disknum(disknum)
1599#define MAJOR_STRING_LENGTH 3
1600#define DEVICE_STRING_LENGTH 32
1601#define NODE_STRING_LENGTH 16
1609 struct stat stat_buf;
1612#ifdef HAVE_LIBSELINUX
1613 security_context_t orig_context = NULL;
1614 security_context_t node_context = NULL;
1615 int selinux_enabled = is_selinux_enabled();
1616 int selinux_enforced = security_getenforce();
1620 if (!(file = fopen(
"/proc/devices",
"r"))) {
1621 pout(
"Error opening /proc/devices to check/create 3ware device nodes\n");
1627 while (EOF != fscanf(file,
"%3s %32s", majorstring, device_name)) {
1631 tw_major = atoi(majorstring);
1639 pout(
"No major number for /dev/%s listed in /proc/devices. Is the %s driver loaded?\n", nodename, driver_name);
1642#ifdef HAVE_LIBSELINUX
1645 if (selinux_enabled) {
1646 if (matchpathcon_init_prefix(NULL,
"/dev") < 0)
1647 pout(
"Error initializing contexts database for /dev");
1648 if (getfscreatecon(&orig_context) < 0) {
1649 pout(
"Error retrieving original SELinux fscreate context");
1650 if (selinux_enforced) {
1651 matchpathcon_fini();
1658 for (index=0; index<16; index++) {
1659 snprintf(nodestring,
sizeof(nodestring),
"/dev/%s%d", nodename, index);
1660#ifdef HAVE_LIBSELINUX
1662 if (selinux_enabled) {
1663 if (matchpathcon(nodestring, S_IRUSR | S_IWUSR, &node_context) < 0) {
1664 pout(
"Could not retrieve context for %s", nodestring);
1665 if (selinux_enforced) {
1670 if (setfscreatecon(node_context) < 0) {
1671 pout (
"Error setting default fscreate context");
1672 if (selinux_enforced) {
1680 if ((stat(nodestring, &stat_buf))) {
1681 pout(
"Node %s does not exist and must be created. Check the udev rules.\n", nodestring);
1683 if (mknod(nodestring, S_IFCHR|0600, makedev(tw_major, index))) {
1684 pout(
"problem creating 3ware device nodes %s", nodestring);
1689#ifdef HAVE_LIBSELINUX
1690 if (selinux_enabled && node_context) {
1691 freecon(node_context);
1692 node_context = NULL;
1700 if ((tw_major != (
int)(major(stat_buf.st_rdev))) ||
1701 (index != (
int)(minor(stat_buf.st_rdev))) ||
1702 (!S_ISCHR(stat_buf.st_mode))) {
1703 pout(
"Node %s has wrong major/minor number and must be created anew."
1704 " Check the udev rules.\n", nodestring);
1706 if (unlink(nodestring)) {
1707 pout(
"problem unlinking stale 3ware device node %s", nodestring);
1714 if (mknod(nodestring, S_IFCHR|0600, makedev(tw_major, index))) {
1715 pout(
"problem creating 3ware device nodes %s", nodestring);
1721#ifdef HAVE_LIBSELINUX
1722 if (selinux_enabled && node_context) {
1723 freecon(node_context);
1724 node_context = NULL;
1729#ifdef HAVE_LIBSELINUX
1730 if (selinux_enabled) {
1731 if(setfscreatecon(orig_context) < 0) {
1732 pout(
"Error re-setting original fscreate context");
1733 if (selinux_enforced)
1737 freecon(orig_context);
1739 freecon(node_context);
1740 matchpathcon_fini();
1760 return set_err((errno ? errno : ENXIO),
"setup_3ware_nodes(\"%s\", \"%s\") failed", node, driver);
1769#ifndef SCSI_IOCTL_SEND_COMMAND
1770#define SCSI_IOCTL_SEND_COMMAND 1
1797#define BUFFER_LEN_678K ( sizeof(TW_Ioctl) )
1798#define BUFFER_LEN_678K_CHAR ( sizeof(TW_New_Ioctl)+512-1 )
1799#define BUFFER_LEN_9000 ( sizeof(TW_Ioctl_Buf_Apache)+512-1 )
1800#define TW_IOCTL_BUFFER_SIZE ( MAX(MAX(BUFFER_LEN_678K, BUFFER_LEN_9000), BUFFER_LEN_678K_CHAR) )
1840 tw_ioctl = (
TW_Ioctl *)ioctl_buffer;
1850 "Unrecognized escalade_type %d in linux_3ware_command_interface(disk %d)\n"
1859 passthru->
flags = 0x1;
1880 bool readdata =
false;
1884 passthru->
size = 0x7;
1885 passthru->
param = 0xD;
1891 &&
sizeof(
long) == 8)
1898 passthru->
size = 0x5;
1899 passthru->
param = 0x8;
1911 return set_err(
ENOTSUP,
"DATA OUT not supported for this 3ware controller type");
1914 passthru->
size = 0x7;
1915 passthru->
param = 0xF;
1917 &&
sizeof(
long) == 8)
1970 if (passthru && (passthru->
status || (passthru->
command & 0x21))) {
2039 const char* proc_format_string=
"host\tchan\tid\tlun\ttype\topens\tqdepth\tbusy\tonline\n";
2042 FILE *fp=fopen(
"/proc/scsi/sg/device_hdr",
"r");
2044 pout(
"Unable to open /proc/scsi/sg/device_hdr for reading\n");
2051 char *out = fgets(linebuf, 256, fp);
2054 pout(
"Unable to read contents of /proc/scsi/sg/device_hdr\n");
2058 if (strcmp(linebuf, proc_format_string)) {
2061 pout(
"Unexpected format %s in /proc/scsi/sg/device_hdr\n", proc_format_string);
2066 fp=fopen(
"/proc/scsi/sg/devices",
"r");
2068 int host, chan,
id,
lun, type, opens, qdepth, busy, online;
2071 while (9 == fscanf(fp,
"%d %d %d %d %d %d %d %d %d", &host, &chan, &
id, &
lun, &type, &opens, &qdepth, &busy, &online)) {
2073 if (
id == 16 && type == 3) {
2075 pout(
"Device /dev/sg%d appears to be an Areca controller.\n", dev);
2119 int ioctlreturn = 0;
2164 int ioctlreturn = 0;
2207 const char * dev_name,
const char * req_type)
2222 mvsata_scsi_cmd smart_command;
2223 unsigned char *buff = (
unsigned char *)&smart_command.cmd[6];
2231 memset(&smart_command, 0,
sizeof(smart_command));
2232 smart_command.inlen = 540;
2233 smart_command.outlen = 540;
2234 smart_command.cmd[0] = 0xC;
2235 smart_command.cmd[4] = 6;
2248 copydata=buff[1]=buff[3]=1;
2290 pout(
"Unrecognized command %d in mvsata_os_specific_handler()\n", command);
2315 if (buff[4] == 0x4F && buff[5] == 0xC2)
2318 if (buff[4] == 0xF4 && buff[5] == 0x2C)
2321 syserror(
"Error SMART Status command failed");
2322 pout(
"Please get assistance from %s\n",PACKAGE_BUGREPORT);
2323 pout(
"Register values returned from SMART Status command are:\n");
2324 pout(
"CMD =0x%02x\n",(
int)buff[0]);
2325 pout(
"FR =0x%02x\n",(
int)buff[1]);
2326 pout(
"NS =0x%02x\n",(
int)buff[2]);
2327 pout(
"SC =0x%02x\n",(
int)buff[3]);
2328 pout(
"CL =0x%02x\n",(
int)buff[4]);
2329 pout(
"CH =0x%02x\n",(
int)buff[5]);
2330 pout(
"SEL=0x%02x\n",(
int)buff[6]);
2335 memcpy(
data, buff, 512);
2348 unsigned char controller,
unsigned char channel,
unsigned char port);
2358 unsigned char controller,
unsigned char channel,
unsigned char port)
2385#define STRANGE_BUFFER_LENGTH (4+512*0xf8)
2390 unsigned int *hpt = (
unsigned int *)hpt_buff;
2391 unsigned char *buff = &hpt_buff[4*
sizeof(int)];
2393 const int HDIO_DRIVE_CMD_OFFSET = 4;
2461 pout(
"Unrecognized command %d in linux_highpoint_command_interface()\n"
2462 "Please contact " PACKAGE_BUGREPORT
"\n", command);
2469 unsigned int *hpt_tf = (
unsigned int *)task;
2473 memset(task, 0,
sizeof(task));
2503 unsigned const char normal_lo=0x4f, normal_hi=0xc2;
2504 unsigned const char failed_lo=0xf4, failed_hi=0x2c;
2513 if (buff[4]==normal_lo && buff[5]==normal_hi)
2516 if (buff[4]==failed_lo && buff[5]==failed_hi)
2519 syserror(
"Error SMART Status command failed");
2520 pout(
"Please get assistance from " PACKAGE_URL
"\n");
2521 pout(
"Register values returned from SMART Status command are:\n");
2522 pout(
"CMD=0x%02x\n",(
int)buff[0]);
2523 pout(
"FR =0x%02x\n",(
int)buff[1]);
2524 pout(
"NS =0x%02x\n",(
int)buff[2]);
2525 pout(
"SC =0x%02x\n",(
int)buff[3]);
2526 pout(
"CL =0x%02x\n",(
int)buff[4]);
2527 pout(
"CH =0x%02x\n",(
int)buff[5]);
2528 pout(
"SEL=0x%02x\n",(
int)buff[6]);
2534 unsigned char deviceid[4*
sizeof(int)+512*
sizeof(
char)];
2535 unsigned int *hpt_id = (
unsigned int *)deviceid;
2542 if (!ioctl(
get_fd(),
HPTIO_CTL, deviceid) && (deviceid[4*
sizeof(
int)] & 0x8000))
2552 buff[HDIO_DRIVE_CMD_OFFSET]=buff[2];
2555 memcpy(
data, buff+HDIO_DRIVE_CMD_OFFSET, copydata);
2563 static int printed[4]={0,0,0,0};
2564 const char* message=
2565 "can not be passed through the 3ware 3w-xxxx driver. This can be fixed by\n"
2566 "applying a simple 3w-xxxx driver patch that can be found here:\n"
2568 "Alternatively, upgrade your 3w-xxxx driver to version 1.02.00.037 or greater.\n\n";
2572 pout(
"The SMART AUTO-OFFLINE ENABLE command (smartmontools -o on option/Directive)\n%s", message);
2574 else if (command==
AUTOSAVE && !printed[1]) {
2576 pout(
"The SMART AUTOSAVE ENABLE command (smartmontools -S on option/Directive)\n%s", message);
2580 pout(
"The SMART RETURN STATUS return value (smartmontools -H option/Directive)\n%s", message);
2582 else if (command==
WRITE_LOG && !printed[3]) {
2584 pout(
"The SMART WRITE LOG command (smartmontools -t selective) only supported via char /dev/tw[ae] interface\n");
2601 bool sat_only =
false;
2612 unsigned char req_buff[64] = {0, };
2621 set_err(EIO,
"INQUIRY failed");
2626 int avail_len = req_buff[4] + 5;
2627 int len = (avail_len < req_len ? avail_len : req_len);
2631 set_err(EIO,
"INQUIRY too short for SAT");
2640 if (!memcmp(req_buff + 8,
"3ware", 5) || !memcmp(req_buff + 8,
"AMCC", 4)) {
2642 set_err(EINVAL,
"AMCC/3ware controller, please try adding '-d 3ware,N',\n"
2643 "you may need to replace %s with /dev/twlN, /dev/twaN or /dev/tweN",
get_dev_name());
2648 if (!memcmp(req_buff + 8,
"DELL PERC", 12) || !memcmp(req_buff + 8,
"MegaRAID", 8)
2649 || !memcmp(req_buff + 16,
"PERC ", 5) || !memcmp(req_buff + 8,
"LSI\0",4)
2652 set_err(EINVAL,
"DELL or MegaRaid controller, please try adding '-d megaraid,N'");
2657 if (len >= 42 && !memcmp(req_buff + 36,
"MVSATA", 6)) {
2681 set_err(EIO,
"Not a SAT device");
2695 const char * req_type,
unsigned nsid);
2697 virtual bool open()
override;
2703 const char * req_type,
unsigned nsid)
2728 memset(&pt, 0,
sizeof(pt));
2746 return set_err(errno,
"NVME_IOCTL_ADMIN_CMD: %s", strerror(errno));
2760static bool read_id(
const std::string & path,
unsigned short &
id)
2762 FILE * f = fopen(path.c_str(),
"r");
2766 bool ok = (fscanf(f,
"%hx%n", &
id, &n) == 1 && n == 4);
2772static bool get_usb_id(
const char * name,
unsigned short & vendor_id,
2773 unsigned short & product_id,
unsigned short & version)
2776 if (!(name[0] ==
's' && (name[1] ==
'd' || name[1] ==
'g') && !strchr(name,
'/')))
2783 std::string dir =
strprintf(
"/sys/%s/%s%s",
2784 (name[1] ==
'd' ?
"block" :
"class/scsi_generic"), name,
2785 (name[1] ==
'd' ?
"/device" :
""));
2789 if (stat(
"/sys/devices", &st))
2791 ino_t stop_ino = st.st_ino;
2798 if (!(++cnt < 10 && !stat(dir.c_str(), &st) && st.st_ino != stop_ino))
2800 }
while (access((dir +
"/idVendor").c_str(), 0));
2803 pout(
"Found idVendor in: %s\n", dir.c_str());
2804 char * p = realpath(dir.c_str(), (
char *)0);
2806 pout(
" realpath: %s\n", p);
2812 if (!(
read_id(dir +
"/idVendor", vendor_id)
2813 &&
read_id(dir +
"/idProduct", product_id)
2814 &&
read_id(dir +
"/bcdDevice", version) ))
2818 pout(
"USB ID = 0x%04x:0x%04x (0x%03x)\n", vendor_id, product_id, version);
2842 unsigned nsid)
override;
2852 static int devxy_to_n(
const char * name,
bool debug);
2856 bool scan_nvme,
const char * req_type,
bool autodetect);
2861 size_t bufsize, uint8_t *
mbox,
size_t mboxlen, uint8_t *statusp);
2865 int sssraid_pdlist_cmd(
int bus_no, uint16_t start_idx,
void *buf,
size_t bufsize, uint8_t *statusp);
2872 return strprintf(
"%s-linux-%s", u.machine, u.release);
2874 return SMARTMONTOOLS_BUILD_HOST;
2879 if (!strcmp(appname,
"smartctl"))
2893 xy = name +
sizeof(
"/dev/sd") - 1;
2897 int sz = readlink(name, dest,
sizeof(dest)-1);
2898 if (!(0 < sz && sz < (
int)
sizeof(dest)))
2904 pout(
"%s -> %s\n", name, dest);
2905 xy = dest +
sizeof(
"../../sd") - 1;
2909 if (!(
'a' <= x && x <=
'z'))
2916 if (!(
'a' <= y && y <=
'z' && !xy[2]))
2920 return (x -
'a' + 1) * (
'z' -
'a' + 1) + (y -
'a');
2924 const char * pattern,
bool scan_scsi,
bool (* p_dev_sdxy_seen)[devxy_to_n_max+1],
2925 bool scan_nvme,
const char * req_type,
bool autodetect)
2931 memset(&globbuf, 0,
sizeof(globbuf));
2932 int retglob = glob(pattern, GLOB_ERR, NULL, &globbuf);
2938 pout(
"glob(3) error %d for pattern %s\n", retglob, pattern);
2940 if (retglob == GLOB_NOSPACE)
2941 throw std::bad_alloc();
2946 const int max_pathc = 1024;
2947 int n = (int)globbuf.gl_pathc;
2948 if (n > max_pathc) {
2949 pout(
"glob(3) found %d > MAX=%d devices matching pattern %s: ignoring %d paths\n",
2950 n, max_pathc, pattern, n - max_pathc);
2955 for (
int i = 0; i < n; i++) {
2956 const char * name = globbuf.gl_pathv[i];
2958 if (p_dev_sdxy_seen) {
2963 if ((*p_dev_sdxy_seen)[dev_n]) {
2965 pout(
"%s: duplicate, ignored\n", name);
2968 (*p_dev_sdxy_seen)[dev_n] =
true;
2997 bool scan_megasas =
false;
2998 FILE * fp = fopen(
"/proc/devices",
"r");
3001 while (fgets(line,
sizeof(line), fp) != NULL) {
3003 if (sscanf(line,
"%d megaraid_sas_ioctl%n", &mjr, &n1) == 1 && n1 == 22) {
3004 scan_megasas =
true;
3005 n1=mknod(
"/dev/megaraid_sas_ioctl_node", S_IFCHR|0600, makedev(mjr, 0));
3007 pout(
"Creating /dev/megaraid_sas_ioctl_node = %d\n", n1 >= 0 ? 0 : errno);
3008 if (n1 >= 0 || errno == EEXIST)
3019 DIR * dp = opendir (
"/sys/class/scsi_host/");
3023 while ((ep = readdir (dp)) != NULL) {
3025 if (!sscanf(ep->d_name,
"host%u", &
host_no))
3029 snprintf(sysfsdir,
sizeof(sysfsdir) - 1,
3030 "/sys/class/scsi_host/host%u/proc_name",
host_no);
3031 if((fp = fopen(sysfsdir,
"r")) == NULL)
3033 if(fgets(line,
sizeof(line), fp) != NULL && !strncmp(line,
"megaraid_sas",12)) {
3038 (void) closedir (dp);
3040 for(
unsigned i = 0; i <=16; i++)
3055 DIR * dp = opendir (
"/sys/class/scsi_host/");
3059 while ((ep = readdir (dp)) != NULL) {
3061 if (!sscanf(ep->d_name,
"host%u", &
host_no))
3065 snprintf(sysfsdir,
sizeof(sysfsdir) - 1,
3066 "/sys/class/scsi_host/host%u/proc_name",
host_no);
3067 if((fp = fopen(sysfsdir,
"r")) == NULL)
3069 if(fgets(line,
sizeof(line), fp) != NULL && !strncmp(line,
"sssraid",7)) {
3074 (void) closedir (dp);
3076 for(
unsigned i = 0; i <=16; i++)
3086 return set_err(EINVAL,
"DEVICESCAN with pattern not implemented yet");
3090 const char * type_ata = 0, * type_scsi = 0, * type_sat = 0, * type_nvme = 0;
3091 for (
unsigned i = 0; i < types.size(); i++) {
3092 const char * type = types[i].c_str();
3093 if (!strcmp(type,
"by-id"))
3095 else if (!strcmp(type,
"ata"))
3097 else if (!strcmp(type,
"scsi"))
3099 else if (!strcmp(type,
"sat"))
3101 else if (!strcmp(type,
"nvme"))
3104 return set_err(EINVAL,
"Invalid type '%s', valid arguments are: by-id, ata, scsi, sat, nvme",
3108 if (!(type_ata || type_scsi || type_sat || type_nvme)) {
3109 type_ata = type_scsi = type_sat =
"";
3110#ifdef WITH_NVME_DEVICESCAN
3116 get_dev_list(devlist,
"/dev/hd[a-t]",
false, 0,
false, type_ata,
false);
3118 if (type_scsi || type_sat) {
3120 const char * type_scsi_sat = ((type_scsi && type_sat) ?
""
3121 : (type_scsi ? type_scsi : type_sat));
3122 bool autodetect = !*type_scsi_sat;
3128 get_dev_list(devlist,
"/dev/disk/by-id/*",
true, &dev_sdxy_seen,
false,
3129 type_scsi_sat, autodetect);
3130 p_dev_sdxy_seen = &dev_sdxy_seen;
3133 get_dev_list(devlist,
"/dev/sd[a-z]",
true, p_dev_sdxy_seen,
false, type_scsi_sat, autodetect);
3134 get_dev_list(devlist,
"/dev/sd[a-z][a-z]",
true, p_dev_sdxy_seen,
false, type_scsi_sat, autodetect);
3143 get_dev_list(devlist,
"/dev/nvme[0-9]",
false, 0,
true, type_nvme,
false);
3144 get_dev_list(devlist,
"/dev/nvme[1-9][0-9]",
false, 0,
true, type_nvme,
false);
3168 return set_err_np(EINVAL,
"requires option '%s'", opt);
3173 size_t bufsize, uint8_t *
mbox,
size_t mboxlen, uint8_t *statusp)
3178 (
mbox == NULL && mboxlen != 0))
3184 memset(&ioc, 0,
sizeof(ioc));
3202 ioc.
sgl[0].iov_base = buf;
3203 ioc.
sgl[0].iov_len = bufsize;
3207 if ((fd = ::open(
"/dev/megaraid_sas_ioctl_node", O_RDWR)) < 0) {
3217 if (statusp != NULL)
3220 fprintf(stderr,
"command %x returned error status %x\n",
3236 for (
unsigned list_size = 1024; ; ) {
3239 throw std::bad_alloc();
3240 memset(list, 0, list_size);
3247 if (list->
size <= list_size)
3249 list_size = list->
size;
3253 for (
unsigned i = 0; i < list->
count; i++) {
3257 snprintf(line,
sizeof(line) - 1,
"/dev/bus/%d", bus_no);
3268 struct sg_io_v4 io_hdr_v4{};
3271 u8 cmd_param[24] = { 0 };
3273 io_hdr_v4.guard =
'Q';
3274 io_hdr_v4.protocol = BSG_PROTOCOL_SCSI;
3275 io_hdr_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_TRANSPORT;
3276 io_hdr_v4.response = (uintptr_t)sense_buff;
3279 io_hdr_v4.request = (uintptr_t)(&bsg_param);
3283 io_hdr_v4.din_xferp = (uintptr_t)buf;
3284 io_hdr_v4.din_xfer_len = bufsize;
3297 p_cmd_param->
start_idx = start_idx_param;
3303 snprintf(line,
sizeof(line) - 1,
"/dev/bsg/sssraid%d", bus_no);
3304 if ((fd = ::open(line, O_RDONLY)) < 0) {
3305 pout(
"open %s error %d\n", line, fd);
3309 int r = ioctl(fd, SG_IO, &io_hdr_v4);
3315 if (statusp != NULL) {
3316 *statusp = (io_hdr_v4.transport_status << 0x8) | io_hdr_v4.device_status;
3317 pout(
"statusp = 0x%x\n", *statusp);
3319 pout(
"controller returns an error - 0x%x", *statusp);
3329 unsigned disk_num = 0;
3340 disk_num += list.
num;
3346 for (
unsigned i = 0; i < disk_num; i++) {
3351 snprintf(line,
sizeof(line) - 1,
"/dev/bsg/sssraid%d", bus_no);
3364 unsigned x = 0, y = 0, z = 0;
3365 if (!(sscanf(u.release,
"%u.%u.%u", &x, &y, &z) == 3
3366 && x < 100 && y < 100 && z < 1000 ))
3368 return x * 100000 + y * 1000 + z;
3375 snprintf(path,
sizeof(path),
"/sys/block/%s/device", name);
3376 char * syshostpath = realpath(path, (
char *)0);
3380 char * syshost = strrchr(syshostpath,
'/');
3386 char * hostsep = strchr(++syshost,
':');
3390 snprintf(path,
sizeof(path),
"/sys/class/scsi_host/host%s/proc_name", syshost);
3392 int fd = open(path, O_RDONLY);
3397 ssize_t n = read(fd, proc_name,
sizeof(proc_name) - 1);
3403 if (proc_name[n - 1] ==
'\n')
3404 proc_name[n - 1] = 0;
3407 pout(
"%s -> %s: \"%s\"\n", name, path, proc_name);
3409 if (strcmp(proc_name,
"hpsa"))
3413 snprintf(path,
sizeof(path),
"/sys/block/%s/device/raid_level", name);
3414 fd = open(path, O_RDONLY);
3419 n = read(fd, raid_level,
sizeof(raid_level) - 1);
3425 if (strcmp(raid_level,
"N/A"))
3436 const char * test_name = name;
3440 std::string pathbuf;
3441 if (!lstat(name, &st) && S_ISLNK(st.st_mode)) {
3442 char * p = realpath(name, (
char *)0);
3446 test_name = pathbuf.c_str();
3451 static const char dev_prefix[] =
"/dev/";
3453 test_name += strlen(dev_prefix);
3467 unsigned short vendor_id = 0, product_id = 0, version = 0;
3468 if (
get_usb_id(test_name, vendor_id, product_id, version)) {
3531 if (!strcmp(type,
"marvell"))
3533 "The device type 'marvell' is deprecated and will be removed in a\n"
3534 "future version of smartmontools. If you still need this device type, please\n"
3535 "use '-d marvell,force' and inform " PACKAGE_BUGREPORT );
3536 if (!strcmp(type,
"marvell,force"))
3540 int disknum = -1, n1 = -1, n2 = -1;
3541 if (sscanf(type,
"3ware,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
3542 if (n2 != (
int)strlen(type))
3543 return set_err_np(EINVAL,
"Option -d 3ware,N requires N to be a non-negative integer");
3544 if (!(0 <= disknum && disknum <= 127))
3545 return set_err_np(EINVAL,
"Option -d 3ware,N (N=%d) must have 0 <= N <= 127", disknum);
3547 if (!strncmp(name,
"/dev/twl", 8))
3549 else if (!strncmp(name,
"/dev/twa", 8))
3551 else if (!strncmp(name,
"/dev/twe", 8))
3558 disknum = n1 = n2 = -1;
3560 if (sscanf(type,
"areca,%n%d/%d%n", &n1, &disknum, &encnum, &n2) >= 1 || n1 == 6) {
3561 if (!(1 <= disknum && disknum <= 128))
3562 return set_err_np(EINVAL,
"Option -d areca,N/E (N=%d) must have 1 <= N <= 128", disknum);
3563 if (!(1 <= encnum && encnum <= 8))
3564 return set_err_np(EINVAL,
"Option -d areca,N/E (E=%d) must have 1 <= E <= 8", encnum);
3569 int controller = -1, channel = -1; disknum = 1;
3570 n1 = n2 = -1;
int n3 = -1;
3571 if (sscanf(type,
"hpt,%n%d/%d%n/%d%n", &n1, &controller, &channel, &n2, &disknum, &n3) >= 2 || n1 == 4) {
3572 int len = strlen(type);
3573 if (!(n2 == len || n3 == len))
3574 return set_err_np(EINVAL,
"Option '-d hpt,L/M/N' supports 2-3 items");
3575 if (!(1 <= controller && controller <= 8))
3576 return set_err_np(EINVAL,
"Option '-d hpt,L/M/N' invalid controller id L supplied");
3577 if (!(1 <= channel && channel <= 128))
3578 return set_err_np(EINVAL,
"Option '-d hpt,L/M/N' invalid channel number M supplied");
3579 if (!(1 <= disknum && disknum <= 15))
3580 return set_err_np(EINVAL,
"Option '-d hpt,L/M/N' invalid pmport number N supplied");
3584#ifdef HAVE_LINUX_CCISS_IOCTL_H
3586 disknum = n1 = n2 = -1;
3587 if (sscanf(type,
"cciss,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
3588 if (n2 != (
int)strlen(type))
3589 return set_err_np(EINVAL,
"Option -d cciss,N requires N to be a non-negative integer");
3590 if (!(0 <= disknum && disknum <= 127))
3591 return set_err_np(EINVAL,
"Option -d cciss,N (N=%d) must have 0 <= N <= 127", disknum);
3592 return get_sat_device(
"sat,auto",
new linux_cciss_device(
this, name, disknum));
3597 if (sscanf(type,
"megaraid,%d", &disknum) == 1) {
3602 unsigned eid = -1, sid = -1;
3603 if (sscanf(type,
"sssraid,%u,%u", &eid, &sid) == 2) {
3608 unsigned host, chan, device;
3609 if (sscanf(type,
"aacraid,%u,%u,%u", &host, &chan, &device) == 3) {
3621 return "areca,N/E, 3ware,N, hpt,L/M/N, megaraid,N, aacraid,H,L,ID, sssraid,E,S"
3622#ifdef HAVE_LINUX_CCISS_IOCTL_H
#define SRB_FUNCTION_EXECUTE_SCSI
#define FSACTL_SEND_RAW_SRB
unsigned char ata_debugmode
#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
int cciss_io_interface(int device, int target, struct scsi_cmnd_io *iop, int report)
Smart pointer class for device pointers.
device_type * release()
Return the pointer and release ownership.
Adapter class to implement new ATA pass through old interface.
bool ata_cmd_is_ok(const ata_cmd_in &in, bool data_out_support=false, bool multi_sector_support=false, bool ata_48bit_support=false)
Check command input parameters (old version).
virtual int arcmsr_get_dev_type()
void set_disknum(int disknum)
void set_encnum(int encnum)
unsigned get_nsid() const
Get namespace id.
bool set_nvme_err(nvme_cmd_out &out, unsigned status, const char *msg=0)
Set last error number and message if pass-through returns NVMe error status.
void set_nsid(unsigned nsid)
Set namespace id.
virtual bool scsi_pass_through(scsi_cmnd_io *iop) override
SCSI pass through.
virtual ~linux_aacraid_device()
linux_aacraid_device(smart_interface *intf, const char *dev_name, unsigned int host, unsigned int channel, unsigned int device)
virtual bool open() override
Open device, return false on error.
linux_areca_ata_device(smart_interface *intf, const char *dev_name, int disknum, int encnum=1)
virtual smart_device * autodetect_open() override
Open device with autodetection support.
virtual bool arcmsr_lock() override
virtual bool arcmsr_unlock() override
virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io *iop) override
virtual smart_device * autodetect_open() override
Open device with autodetection support.
virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io *iop) override
virtual bool arcmsr_lock() override
virtual bool arcmsr_unlock() override
linux_areca_scsi_device(smart_interface *intf, const char *dev_name, int disknum, int encnum=1)
linux_ata_device(smart_interface *intf, const char *dev_name, const char *req_type)
virtual int ata_command_interface(smart_command_set command, int select, char *data) override
Old ATA interface called by ata_pass_through()
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.
linux_escalade_device(smart_interface *intf, const char *dev_name, escalade_type_t escalade_type, int disknum)
int m_disknum
Disk number.
escalade_type_t m_escalade_type
Controller type.
unsigned char m_hpt_data[3]
controller/channel/port
linux_highpoint_device(smart_interface *intf, const char *dev_name, unsigned char controller, unsigned char channel, unsigned char port)
virtual int ata_command_interface(smart_command_set command, int select, char *data)
Old ATA interface called by ata_pass_through()
virtual int ata_command_interface(smart_command_set command, int select, char *data)
Old ATA interface called by ata_pass_through()
linux_marvell_device(smart_interface *intf, const char *dev_name, const char *req_type)
bool megasas_cmd(int cdbLen, void *cdb, int dataLen, void *data, int senseLen, void *sense, int report, int direction)
bool(linux_megaraid_device::* pt_cmd)(int cdblen, void *cdb, int dataLen, void *data, int senseLen, void *sense, int report, int direction)
virtual ~linux_megaraid_device()
virtual bool close() override
Close device, return false on error.
virtual bool open() override
Open device, return false on error.
linux_megaraid_device(smart_interface *intf, const char *name, unsigned int tgt)
virtual smart_device * autodetect_open() override
Open device with autodetection support.
virtual bool scsi_pass_through(scsi_cmnd_io *iop) override
SCSI pass through.
bool megadev_cmd(int cdbLen, void *cdb, int dataLen, void *data, int senseLen, void *sense, int report, int direction)
linux_nvme_device(smart_interface *intf, const char *dev_name, const char *req_type, unsigned nsid)
virtual bool nvme_pass_through(const nvme_cmd_in &in, nvme_cmd_out &out) override
NVMe pass through.
virtual bool open() override
Open device, return false on error.
bool m_scanning
true if created within scan_smart_devices
virtual smart_device * autodetect_open() override
SCSI open with autodetection support.
linux_scsi_device(smart_interface *intf, const char *dev_name, const char *req_type, bool scanning=false)
virtual bool scsi_pass_through(scsi_cmnd_io *iop) override
SCSI pass through.
Shared open/close routines.
virtual bool open() override
Open device, return false on error.
int m_flags
Flags for open()
virtual bool is_open() const override
Return true if device is open.
int m_retry_flags
Flags to retry open(), -1 if no retry.
virtual bool close() override
Close device, return false on error.
virtual ~linux_smart_device()
linux_smart_device(int flags, int retry_flags=-1)
int m_fd
filedesc, -1 if not open.
int get_fd() const
Return filedesc for derived classes.
virtual nvme_device * get_nvme_device(const char *name, const char *type, unsigned nsid) override
Return standard NVMe device.
virtual ata_device * get_ata_device(const char *name, const char *type) override
Return standard ATA device.
static int devxy_to_n(const char *name, bool debug)
int sssraid_pdlist_cmd(int bus_no, uint16_t start_idx, void *buf, size_t bufsize, uint8_t *statusp)
virtual std::string get_valid_custom_dev_types_str() override
Return valid 'type' args accepted by above.
int megasas_pd_add_list(int bus_no, smart_device_list &devlist)
virtual bool scan_smart_devices(smart_device_list &devlist, const smart_devtype_list &types, const char *pattern=0) override
Fill 'devlist' with devices of all 'types' with device names specified by some optional 'pattern'.
virtual scsi_device * get_scsi_device(const char *name, const char *type) override
Return standard SCSI device.
virtual std::string get_app_examples(const char *appname) override
Return example string for program 'appname'.
int sssraid_pd_add_list(int bus_no, smart_device_list &devlist)
virtual smart_device * autodetect_smart_device(const char *name) override
Autodetect device if no device type specified.
virtual std::string get_os_version_str() override
Return info string about build host and/or OS version.
bool get_dev_megasas(smart_device_list &devlist)
virtual smart_device * get_custom_smart_device(const char *name, const char *type) override
Return device for platform specific 'type'.
int megasas_dcmd_cmd(int bus_no, uint32_t opcode, void *buf, size_t bufsize, uint8_t *mbox, size_t mboxlen, uint8_t *statusp)
void get_dev_list(smart_device_list &devlist, const char *pattern, bool scan_scsi, bool(*p_dev_sdxy_seen)[devxy_to_n_max+1], bool scan_nvme, const char *req_type, bool autodetect)
smart_device * missing_option(const char *opt)
bool get_dev_sssraid(smart_device_list &devlist)
static constexpr int devxy_to_n_max
bool scsi_cmd(scsi_cmnd_io *iop)
virtual bool scsi_pass_through(scsi_cmnd_io *iop) override
SCSI pass through.
linux_sssraid_device(smart_interface *intf, const char *name, unsigned int eid, unsigned int sid)
List of devices for DEVICESCAN.
void push_back(smart_device *dev)
Base class for all devices.
smart_interface * smi()
Get interface which produced this object.
const char * get_req_type() const
Get type requested by user, empty if none.
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
bool is_ata() const
Return true if ATA device.
device_info & set_info()
R/W access to device info struct.
const char * get_dev_name() const
Get device (path)name.
The platform interface abstraction.
static void set(smart_interface *intf)
Set interface to use, must be called from init().
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'.
static void init()
Initialize platform interface and register with smi().
bool decltype(nullptr) set_err_np(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
virtual smart_device * get_scsi_passthrough_device(const char *type, scsi_device *scsidev)
Return ATA->SCSI of NVMe->SCSI filter for a SAT, SNT or USB 'type'.
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.
std::vector< std::string > smart_devtype_list
List of types for DEVICESCAN.
#define NVME_IOCTL_ADMIN_CMD
#define MEGA_MBOXCMD_PASSTHRU
#define MFI_FRAME_DIR_WRITE
#define MEGASAS_IOC_FIRMWARE
#define MFI_FRAME_DIR_NONE
#define MFI_DCMD_PD_GET_LIST
#define MAX_REQ_SENSE_LEN
struct megasas_dcmd_frame dcmd
#define MFI_FRAME_DIR_READ
#define MFI_CMD_PD_SCSI_IO
static int sg_io_cmnd_io(int dev_fd, struct scsi_cmnd_io *iop, int report, enum lk_sg_io_ifc_t sg_io_ifc)
static int do_normal_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io *iop, int report)
static bool get_usb_id(const char *name, unsigned short &vendor_id, unsigned short &product_id, unsigned short &version)
static unsigned get_kernel_release()
static bool read_id(const std::string &path, unsigned short &id)
static int setup_3ware_nodes(const char *nodename, const char *driver_name)
static const char smartctl_examples[]
static int find_areca_in_proc()
static bool is_hpsa_in_raid_mode(const char *name)
static enum lk_sg_io_ifc_t sg_io_interface
unsigned char nvme_debugmode
unsigned char failuretest_permissive
void printwarning(int msgNo, const char *extra)
#define TW_IOCTL_BUFFER_SIZE
const char * os_linux_cpp_cvsid
unsigned char failuretest_permissive
#define LSCSI_DRIVER_TIMEOUT
#define LSCSI_DID_BUS_BUSY
#define LSCSI_DRIVER_MASK
#define LSCSI_DID_TIME_OUT
#define MAJOR_STRING_LENGTH
#define LSCSI_DRIVER_SENSE
#define LSCSI_DID_NO_CONNECT
#define SRB_STATUS_AUTOSENSE_VALID
#define DEVICE_STRING_LENGTH
#define SRB_STATUS_SELECTION_TIMEOUT
#define STRANGE_BUFFER_LENGTH
#define SRB_STATUS_NO_DEVICE
#define SRB_STATUS_SUCCESS
#define SCSI_IOCTL_SEND_COMMAND
#define NODE_STRING_LENGTH
#define TW_OP_ATA_PASSTHRU
struct ide_task_request_s ide_task_request_t
#define HDIO_DRIVE_TASKFILE
#define HDIO_GET_IDENTITY
#define TW_IOCTL_FIRMWARE_PASS_THROUGH
#define TW_CMD_PACKET_WITH_DATA
#define IDE_DRIVE_TASK_OUT
bool is_scsi_cdb(const uint8_t *cdbp, int clen)
int scsiStdInquiry(scsi_device *device, uint8_t *pBuf, int bufLen)
void dStrHex(const uint8_t *up, int len, int no_ascii)
unsigned char scsi_debugmode
const char * scsi_get_opcode_name(const uint8_t *cdbp)
#define SAT_ATA_PASSTHROUGH_12
#define DXFER_FROM_DEVICE
#define SAT_ATA_PASSTHROUGH_16
#define SCSI_STATUS_CHECK_CONDITION
void pout(const char *fmt,...)
#define DEFAULT_CONMMAND_TIMEOUT_MS
#define BSG_APPEND_TIMEOUT_MS
#define ADM_BSG_MSGCODE_SCSI_PTHRU
#define ADM_CMD_SHOW_PDLIST
#define ADM_SCSI_CDB_SENSE_MAX_LEN
#define CMD_PDLIST_ONCE_NUM
#define ADM_CMD_SCSI_PASSTHROUGH
union TAG_TW_Command_Full_9000::@63 command
TW_Command_9000 oldcommand
TW_Command_Full_9000 firmware_command
TW_Ioctl_Driver_Command_9000 driver_command
unsigned int buffer_length
unsigned int control_code
unsigned char input_data[499]
unsigned int data_buffer_length
TW_Command firmware_command
struct TAG_TW_Passthru::@51 byte0
unsigned short cylinder_hi
unsigned short cylinder_lo
unsigned short sector_num
unsigned short sector_count
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 pass through output parameters.
ata_out_regs_48bit out_regs
Output registers.
ATA Input registers for 48-bit commands.
ata_reg_alias_16 lba_high_16
ata_reg_alias_16 sector_count_16
ata_reg_alias_16 features_16
ata_reg_alias_16 lba_low_16
ata_reg_alias_16 lba_mid_16
ATA Output registers for 48-bit commands.
ata_reg_alias_16 lba_mid_16
ata_reg_alias_16 sector_count_16
ata_reg_alias_16 lba_low_16
ata_reg_alias_16 lba_high_16
struct sssraid_passthru_common_cmd ioctl_r64
struct sssraid_ioq_passthru_cmd ioctl_pthru
struct multi_disk_location loc
struct cmd_pdlist_entry disks[CMD_PDLIST_ONCE_NUM]
task_ioreg_t sector_number
task_ioreg_t low_cylinder
task_ioreg_t high_cylinder
task_ioreg_t sector_count
union megasas_dcmd_frame::@38 mbox
struct megasas_pthru_frame pthru
struct iovec sgl[MAX_IOCTL_SGE]
struct megasas_dcmd_frame dcmd
union megasas_iocpacket::@40 frame
struct megasas_pd_address addr[MAX_SYS_PDS]
NVMe pass through input parameters.
unsigned char opcode
Opcode (CDW0 07:00)
unsigned size
Size of buffer.
unsigned cdw15
Cmd specific.
unsigned nsid
Namespace ID.
void * buffer
Pointer to data buffer.
NVMe pass through output parameters.
unsigned result
Command specific result (DW0)
std::string info_name
Informal name.
std::string dev_type
Actual device type.
struct sssraid_ioq_passthru_cmd::@129::@138 info_1
struct sssraid_ioq_passthru_cmd::@127::@137 info_0
struct sssraid_ioq_passthru_cmd::@133::@140 info_3
struct sssraid_ioq_passthru_cmd::@135::@141 info_4
struct sssraid_passthru_common_cmd::@123::@126 info_1
struct sssraid_passthru_common_cmd::@121::@125 info_0
struct megasas_sge32 sge32[1]
void syserror(const char *message)
std::string strprintf(const char *fmt,...)
bool nonempty(const void *data, int size)
bool str_starts_with(const char *str, const char *prefix)