21#include <sys/utsname.h>
29#define ARGUSED(x) ((void)(x))
43 memset(&pt, 0,
sizeof(pt));
46 int fd = ::open(dev, O_RDWR);
53 return status != -1 || errno != ENOTTY;
109 fd =
::open(dev,O_RDWR|O_NONBLOCK);
111 if (fd < 0 && errno == EROFS)
112 fd =
::open(dev,O_RDONLY|O_NONBLOCK);
118 if ((fd =
::open(dev,O_RDWR|O_NONBLOCK))<0) {
138 if(failed)
return false;
154 virtual int do_cmd(
struct atareq* request,
bool is_48bit_cmd);
167 ret = ioctl(fd, ATAIOCCOMMAND, request);
174 bool ata_48bit =
false;
181 set_err(ENOSYS,
"48-bit ATA commands not implemented");
187 memset(&req, 0,
sizeof(req));
198 req.flags = ATACMD_READREG;
201 req.flags = ATACMD_READ | ATACMD_READREG;
202 req.databuf = (
char *)in.
buffer;
203 req.datalen = in.
size;
206 req.flags = ATACMD_WRITE | ATACMD_READREG;
207 req.databuf = (
char *)in.
buffer;
208 req.datalen = in.
size;
218 if (req.retsts != ATACMD_OK)
219 return set_err(EIO,
"request failed, error code 0x%02x", req.retsts);
241 const char * req_type,
unsigned nsid);
243 virtual bool open()
override;
249 const char * req_type,
unsigned nsid)
261 if ((fd =
::open(dev, O_RDWR)) == -1) {
262 set_err(errno,
"can't open sd device");
276 memset(&ps, 0,
sizeof(ps));
295 return set_err(errno,
"NVME_PASSTHROUGH_CMD: %s", strerror(errno));
325 const char * dev_name,
const char * req_type,
bool scanning )
339 const unsigned char * ucp = iop->
cmnd;
343 pout(
" [%s: ", np ? np :
"<unknown opcode>");
345 pout(
"%02x ", ucp[k]);
348 int trunc = (iop->
dxfer_len > 256) ? 1 : 0;
351 (trunc ?
" [only first 256 bytes shown]" :
""));
358 memset(&sc, 0,
sizeof(sc));
361 sc.databuf = (
char *)iop->
dxferp;
369 if (ioctl(fd, SCIOCCOMMAND, &sc) < 0) {
371 pout(
" error sending SCSI ccb\n");
375 iop->
resid = sc.datalen - sc.datalen_used;
378 memcpy(iop->
sensep, sc.sense, sc.senselen_used);
388 (trunc ?
" [only first 256 bytes shown]" :
""));
405 bool sat_only =
false;
416 unsigned char req_buff[64] = {0, };
425 set_err(EIO,
"INQUIRY failed");
430 int avail_len = req_buff[4] + 5;
431 int len = (avail_len < req_len ? avail_len : req_len);
435 set_err(EIO,
"INQUIRY too short for SAT");
455 set_err(EIO,
"Not a SAT device");
472 const char * pattern = 0)
override;
480 unsigned nsid)
override;
497 struct utsname osname;
499 return strprintf(
"%s %s %s", osname.sysname, osname.release, osname.machine);
504 if (!strcmp(appname,
"smartctl")) {
507 p =
'a' + getrawpartition();
509 "=================================================== SMARTCTL EXAMPLES =====\n\n"
510 " smartctl -a /dev/wd0%c (Prints all SMART information)\n\n"
511 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/wd0%c\n"
512 " (Enables SMART on first disk)\n\n"
513 " smartctl -t long /dev/wd0%c (Executes extended disk self-test)\n\n"
514 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/wd0%c\n"
515 " (Prints Self-Test & Attribute errors)\n"
516 " smartctl -a /dev/wd0%c (Prints all SMART information)\n"
517 " smartctl -s on -o on -S on /dev/wd0%c (Enables SMART on first disk)\n"
518 " smartctl -t long /dev/wd0%c (Executes extended disk self-test)\n"
519 " smartctl -A -l selftest -q errorsonly /dev/wd0%c"
520 " (Prints Self-Test & Attribute errors)\n",
521 p, p, p, p, p, p, p, p);
542 char *disknames, *p, **mp;
549 sysctl_mib[0] = CTL_HW;
550 sysctl_mib[1] = HW_DISKNAMES;
551 if (-1 == sysctl(sysctl_mib, 2, NULL, &sysctl_len, NULL, 0)) {
552 pout(
"Failed to get value of sysctl `hw.disknames'\n");
555 if (!(disknames = (
char *)malloc(sysctl_len))) {
556 pout(
"Out of memory constructing scan device list\n");
559 if (-1 == sysctl(sysctl_mib, 2, disknames, &sysctl_len, NULL, 0)) {
560 pout(
"Failed to get value of sysctl `hw.disknames'\n");
563 if (!(mp = (
char **) calloc(strlen(disknames) / 2,
sizeof(
char *)))) {
564 pout(
"Out of memory constructing scan device list\n");
568 for (p = strtok(disknames,
","); p; p = strtok(NULL,
",")) {
569 if (strncmp(p, prefix, strlen(prefix))) {
572 char * u = strchr(p,
':');
577 pout(
"Out of memory constructing scan device list\n");
580 sprintf(mp[n],
"%s%s%c",
net_dev_prefix, p,
'a' + getrawpartition());
584 char ** tmp = (
char **)realloc(mp, n * (
sizeof(
char *)));
586 pout(
"Out of memory constructing scan device list\n");
598 const char * type,
const char * pattern )
601 set_err(EINVAL,
"DEVICESCAN with pattern not implemented yet");
608 bool scan_ata = !*type || !strcmp(type,
"ata");
609 bool scan_scsi = !*type || !strcmp(type,
"scsi") || !strcmp(type,
"sat");
610 bool scan_nvme = !*type || !strcmp(type,
"nvme");
613 char * * atanames = 0;
int numata = 0;
622 char * * scsinames = 0;
int numscsi = 0;
623 char * * scsitapenames = 0;
int numscsitape = 0;
624 if (scan_scsi || scan_nvme) {
631 if (numscsitape < 0) {
639 for (i = 0; i < numata; i++) {
645 if(numata) free(atanames);
647 for (i = 0; i < numscsi; i++) {
654 }
else if (scan_scsi) {
661 if(numscsi) free(scsinames);
663 for (i = 0; i < numscsitape; i++) {
667 free(scsitapenames[i]);
669 if(numscsitape) free(scsitapenames);
676 const char * test_name = name;
685 if (!lstat(name, &st) && S_ISLNK(st.st_mode)) {
686 char * p = realpath(name, (
char *)0);
690 test_name = pathbuf.c_str();
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).
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.
Implement standard ATA support.
virtual int do_cmd(struct atareq *request, bool is_48bit_cmd)
openbsd_ata_device(smart_interface *intf, const char *dev_name, const char *req_type)
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out) override
ATA pass through.
virtual bool nvme_pass_through(const nvme_cmd_in &in, nvme_cmd_out &out) override
NVMe pass through.
openbsd_nvme_device(smart_interface *intf, const char *dev_name, const char *req_type, unsigned nsid)
virtual bool open() override
Open device, return false on error.
openbsd_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.
virtual smart_device * autodetect_open() override
Open device with autodetection support.
bool m_scanning
true if created within scan_smart_devices
Implement shared open/close routines with old functions.
int m_fd
filedesc, -1 if not open.
virtual bool close()
Close device, return false on error.
virtual bool is_open() const
Return true if device is open.
int get_fd() const
Return filedesc for derived classes.
virtual bool open()
Open device, return false on error.
virtual ~openbsd_smart_device()
Implement platform interface with old functions.
virtual std::string get_os_version_str() override
Return info string about build host and/or OS version.
virtual smart_device * get_custom_smart_device(const char *name, const char *type) override
Return device for platform specific 'type'.
int get_dev_names(char ***, const char *)
virtual bool scan_smart_devices(smart_device_list &devlist, const char *type, const char *pattern=0) override
Fill 'devlist' with devices of some 'type' with device names specified by some optional 'pattern'.
virtual std::string get_valid_custom_dev_types_str() override
Return valid 'type' args accepted by above.
virtual ata_device * get_ata_device(const char *name, const char *type) override
Return standard ATA device.
virtual smart_device * autodetect_smart_device(const char *name) override
Autodetect device if no device type specified.
virtual scsi_device * get_scsi_device(const char *name, const char *type) override
Return standard SCSI device.
virtual nvme_device * get_nvme_device(const char *name, const char *type, unsigned nsid) override
Return standard NVMe device.
virtual std::string get_app_examples(const char *appname) override
Return example string for program 'appname'.
List of devices for DEVICESCAN.
void push_back(smart_device *dev)
Base class for all devices.
bool is_scsi() const
Return true if SCSI device.
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.
const char * get_dev_name() const
Get device (path)name.
void clear_err()
Clear last error info.
The platform interface abstraction.
static void set(smart_interface *intf)
Set interface to use, must be called from init().
static void init()
Initialize platform interface and register with smi().
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.
#define NVME_PASSTHROUGH_CMD
#define nvme_completion_is_error(cpl)
static const char * net_dev_scsi_disk
static const char * net_dev_ata_disk
bool sd_is_nvme(const char *dev)
static const char * net_dev_prefix
static const char * net_dev_scsi_tape
const char * os_openbsd_cpp_cvsid
#define OS_OPENBSD_H_CVSID
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 DXFER_FROM_DEVICE
#define SCSI_TIMEOUT_DEFAULT
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 pass through output parameters.
ata_out_regs_48bit out_regs
Output registers.
bool is_48bit_cmd() const
Return true if 48-bit command.
ata_register sector_count
ata_register sector_count
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 strprintf(const char *fmt,...)
bool str_starts_with(const char *str, const char *prefix)