smartmontools SVN Rev 5611
Utility to control and monitor storage systems with "S.M.A.R.T."
os_openbsd.cpp
Go to the documentation of this file.
1/*
2 * os_openbsd.cpp
3 *
4 * Home page of code is: https://www.smartmontools.org
5 *
6 * Copyright (C) 2004-10 David Snyder
7 *
8 * Derived from os_netbsd.cpp by Sergey Svishchev, Copyright (C) 2003-8
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 */
12
13#include "config.h"
14
15#include "atacmds.h"
16#include "scsicmds.h"
17#include "utility.h"
18#include "os_openbsd.h"
19
20#include <sys/utsname.h>
21#include <errno.h>
22#include <sys/stat.h>
23#include <util.h>
24
25const char * os_openbsd_cpp_cvsid = "$Id: os_openbsd.cpp 5393 2022-05-29 05:08:10Z dpgilbert $"
27
28#define ARGUSED(x) ((void)(x))
29
30/////////////////////////////////////////////////////////////////////////////
31
32namespace os_openbsd { // No need to publish anything, name provided for Doxygen
33
34static const char *net_dev_prefix = "/dev/";
35static const char *net_dev_ata_disk = "wd";
36static const char *net_dev_scsi_disk = "sd";
37static const char *net_dev_scsi_tape = "st";
38
39/////////////////////////////////////////////////////////////////////////////
40/// Implement shared open/close routines with old functions.
41
43: virtual public /*implements*/ smart_device
44{
45public:
48 m_fd(-1) { }
49
50 virtual ~openbsd_smart_device();
51
52 virtual bool is_open() const;
53
54 virtual bool open();
55
56 virtual bool close();
57
58protected:
59 /// Return filedesc for derived classes.
60 int get_fd() const
61 { return m_fd; }
62
63 void set_fd(int fd)
64 { m_fd = fd; }
65
66private:
67 int m_fd; ///< filedesc, -1 if not open.
68};
69
71{
72 if (m_fd >= 0)
74}
75
77{
78 return (m_fd >= 0);
79}
80
81
83{
84 const char *dev = get_dev_name();
85 int fd;
86
87 if (is_scsi()) {
88 fd = ::open(dev,O_RDWR|O_NONBLOCK);
89
90 if (fd < 0 && errno == EROFS)
91 fd = ::open(dev,O_RDONLY|O_NONBLOCK);
92 if (fd < 0) {
93 set_err(errno);
94 return false;
95 }
96 } else if (is_ata()) {
97 if ((fd = ::open(dev,O_RDWR|O_NONBLOCK))<0) {
98 set_err(errno);
99 return false;
100 }
101 } else
102 return false;
103
104 set_fd(fd);
105 return true;
106}
107
109{
110 int failed = 0;
111 // close device, if open
112 if (is_open())
113 failed=::close(get_fd());
114
115 set_fd(-1);
116
117 if(failed) return false;
118 else return true;
119}
120
121/////////////////////////////////////////////////////////////////////////////
122/// Implement standard ATA support
123
125: public /*implements*/ ata_device,
126 public /*extends*/ openbsd_smart_device
127{
128public:
129 openbsd_ata_device(smart_interface * intf, const char * dev_name, const char * req_type);
130 virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override;
131
132protected:
133 virtual int do_cmd(struct atareq* request, bool is_48bit_cmd);
134};
135
136openbsd_ata_device::openbsd_ata_device(smart_interface * intf, const char * dev_name, const char * req_type)
137: smart_device(intf, dev_name, "ata", req_type),
139{
140}
141
142int openbsd_ata_device::do_cmd( struct atareq* request, bool is_48bit_cmd)
143{
144 int fd = get_fd(), ret;
145 ARGUSED(is_48bit_cmd); // no support for 48 bit commands in the ATAIOCCOMMAND
146 ret = ioctl(fd, ATAIOCCOMMAND, request);
147 if (ret) set_err(errno);
148 return ret;
149}
150
152{
153 bool ata_48bit = false; // no ata_48bit_support via ATAIOCCOMMAND
154
155 if (!ata_cmd_is_ok(in,
156 true, // data_out_support
157 true, // multi_sector_support
158 ata_48bit)
159 ) {
160 set_err(ENOSYS, "48-bit ATA commands not implemented");
161 return false;
162 }
163
164 struct atareq req;
165
166 memset(&req, 0, sizeof(req));
167 req.command = in.in_regs.command;
168 req.features = in.in_regs.features;
169 req.sec_count = in.in_regs.sector_count;
170 req.sec_num = in.in_regs.lba_low;
171 req.head = in.in_regs.device;
172 req.cylinder = in.in_regs.lba_mid | (in.in_regs.lba_high << 8);
173 req.timeout = SCSI_TIMEOUT_DEFAULT * 1000;
174
175 switch (in.direction) {
177 req.flags = ATACMD_READREG;
178 break;
180 req.flags = ATACMD_READ | ATACMD_READREG;
181 req.databuf = (char *)in.buffer;
182 req.datalen = in.size;
183 break;
185 req.flags = ATACMD_WRITE | ATACMD_READREG;
186 req.databuf = (char *)in.buffer;
187 req.datalen = in.size;
188 break;
189 default:
190 return set_err(ENOSYS);
191 }
192
193 clear_err();
194 errno = 0;
195 if (do_cmd(&req, in.in_regs.is_48bit_cmd()))
196 return false;
197 if (req.retsts != ATACMD_OK)
198 return set_err(EIO, "request failed, error code 0x%02x", req.retsts);
199
200 out.out_regs.error = req.error;
201 out.out_regs.sector_count = req.sec_count;
202 out.out_regs.lba_low = req.sec_num;
203 out.out_regs.device = req.head;
204 out.out_regs.lba_mid = req.cylinder;
205 out.out_regs.lba_high = req.cylinder >> 8;
206 out.out_regs.status = req.command;
207
208 return true;
209}
210
211/////////////////////////////////////////////////////////////////////////////
212/// Standard SCSI support
213
215: public /*implements*/ scsi_device,
216 public /*extends*/ openbsd_smart_device
217{
218public:
219 openbsd_scsi_device(smart_interface * intf, const char * dev_name, const char * req_type, bool scanning = false);
220
221 virtual smart_device * autodetect_open() override;
222
223 virtual bool scsi_pass_through(scsi_cmnd_io * iop) override;
224
225private:
226 bool m_scanning; ///< true if created within scan_smart_devices
227};
228
230 const char * dev_name, const char * req_type, bool scanning /* = false */)
231: smart_device(intf, dev_name, "scsi", req_type),
233 m_scanning(scanning)
234{
235}
236
238{
239 struct scsireq sc;
240 int fd = get_fd();
241
242 if (scsi_debugmode) {
243 unsigned int k;
244 const unsigned char * ucp = iop->cmnd;
245 const char * np;
246
247 np = scsi_get_opcode_name(ucp);
248 pout(" [%s: ", np ? np : "<unknown opcode>");
249 for (k = 0; k < iop->cmnd_len; ++k)
250 pout("%02x ", ucp[k]);
251 if ((scsi_debugmode > 1) &&
252 (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) {
253 int trunc = (iop->dxfer_len > 256) ? 1 : 0;
254
255 pout("]\n Outgoing data, len=%d%s:\n", (int)iop->dxfer_len,
256 (trunc ? " [only first 256 bytes shown]" : ""));
257 dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
258 }
259 else
260 pout("]\n");
261 }
262
263 memset(&sc, 0, sizeof(sc));
264 memcpy(sc.cmd, iop->cmnd, iop->cmnd_len);
265 sc.cmdlen = iop->cmnd_len;
266 sc.databuf = (char *)iop->dxferp;
267 sc.datalen = iop->dxfer_len;
268 sc.senselen = iop->max_sense_len;
269 sc.timeout = (iop->timeout == 0 ? 60 : iop->timeout) * 1000;
270 sc.flags =
271 (iop->dxfer_dir == DXFER_NONE ? SCCMD_READ :
272 (iop->dxfer_dir == DXFER_FROM_DEVICE ? SCCMD_READ : SCCMD_WRITE));
273
274 if (ioctl(fd, SCIOCCOMMAND, &sc) < 0) {
275 if (scsi_debugmode) {
276 pout(" error sending SCSI ccb\n");
277 }
278 return set_err(EIO);
279 }
280 iop->resid = sc.datalen - sc.datalen_used;
281 iop->scsi_status = sc.status;
282 if (iop->sensep) {
283 memcpy(iop->sensep, sc.sense, sc.senselen_used);
284 iop->resp_sense_len = sc.senselen_used;
285 }
286 if (scsi_debugmode) {
287 int trunc;
288
289 pout(" status=0\n");
290 trunc = (iop->dxfer_len > 256) ? 1 : 0;
291
292 pout(" Incoming data, len=%d%s:\n", (int) iop->dxfer_len,
293 (trunc ? " [only first 256 bytes shown]" : ""));
294 dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len), 1);
295 }
296 // XXX we probably need error handling here
297 return true;
298}
299
300/////////////////////////////////////////////////////////////////////////////
301///// SCSI open with autodetection support
302
304{
305 // Open device
306 if (!open())
307 return this;
308
309 // No Autodetection if device type was specified by user
310 bool sat_only = false;
311 if (*get_req_type()) {
312 // Detect SAT if device object was created by scan_smart_devices().
313 if (!(m_scanning && !strcmp(get_req_type(), "sat")))
314 return this;
315 sat_only = true;
316 }
317
318 // The code below is based on smartd.cpp:SCSIFilterKnown()
319
320 // Get INQUIRY
321 unsigned char req_buff[64] = {0, };
322 int req_len = 36;
323 if (scsiStdInquiry(this, req_buff, req_len)) {
324 // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices
325 // watch this spot ... other devices could lock up here
326 req_len = 64;
327 if (scsiStdInquiry(this, req_buff, req_len)) {
328 // device doesn't like INQUIRY commands
329 close();
330 set_err(EIO, "INQUIRY failed");
331 return this;
332 }
333 }
334
335 int avail_len = req_buff[4] + 5;
336 int len = (avail_len < req_len ? avail_len : req_len);
337 if (len < 36) {
338 if (sat_only) {
339 close();
340 set_err(EIO, "INQUIRY too short for SAT");
341 }
342 return this;
343 }
344
345 // Use INQUIRY to detect type
346
347 // SAT or USB, skip MFI controllers because of bugs
348 {
349 smart_device * newdev = smi()->autodetect_sat_device(this, req_buff, len);
350 if (newdev) {
351 // NOTE: 'this' is now owned by '*newdev'
352 return newdev;
353 }
354 }
355
356 // Nothing special found
357
358 if (sat_only) {
359 close();
360 set_err(EIO, "Not a SAT device");
361 }
362 return this;
363}
364
365/////////////////////////////////////////////////////////////////////////////
366/// Implement platform interface with old functions.
367
369: public /*implements*/ smart_interface
370{
371public:
372 virtual std::string get_os_version_str() override;
373
374 virtual std::string get_app_examples(const char * appname) override;
375
376 virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
377 const char * pattern = 0) override;
378
379protected:
380 virtual ata_device * get_ata_device(const char * name, const char * type) override;
381
382 virtual scsi_device * get_scsi_device(const char * name, const char * type) override;
383
384 virtual smart_device * autodetect_smart_device(const char * name) override;
385
386 virtual smart_device * get_custom_smart_device(const char * name, const char * type) override;
387
388 virtual std::string get_valid_custom_dev_types_str() override;
389
390private:
391 int get_dev_names(char ***, const char *);
392};
393
394
395//////////////////////////////////////////////////////////////////////
396
398{
399 struct utsname osname;
400 uname(&osname);
401 return strprintf("%s %s %s", osname.sysname, osname.release, osname.machine);
402}
403
404std::string openbsd_smart_interface::get_app_examples(const char * appname)
405{
406 if (!strcmp(appname, "smartctl")) {
407 char p;
408
409 p = 'a' + getrawpartition();
410 return strprintf(
411 "=================================================== SMARTCTL EXAMPLES =====\n\n"
412 " smartctl -a /dev/wd0%c (Prints all SMART information)\n\n"
413 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/wd0%c\n"
414 " (Enables SMART on first disk)\n\n"
415 " smartctl -t long /dev/wd0%c (Executes extended disk self-test)\n\n"
416 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/wd0%c\n"
417 " (Prints Self-Test & Attribute errors)\n"
418 " smartctl -a /dev/wd0%c (Prints all SMART information)\n"
419 " smartctl -s on -o on -S on /dev/wd0%c (Enables SMART on first disk)\n"
420 " smartctl -t long /dev/wd0%c (Executes extended disk self-test)\n"
421 " smartctl -A -l selftest -q errorsonly /dev/wd0%c"
422 " (Prints Self-Test & Attribute errors)\n",
423 p, p, p, p, p, p, p, p);
424 }
425 return "";
426}
427ata_device * openbsd_smart_interface::get_ata_device(const char * name, const char * type)
428{
429 return new openbsd_ata_device(this, name, type);
430}
431
432scsi_device * openbsd_smart_interface::get_scsi_device(const char * name, const char * type)
433{
434 return new openbsd_scsi_device(this, name, type);
435}
436
437int openbsd_smart_interface::get_dev_names(char ***names, const char *prefix)
438{
439 char *disknames, *p, **mp;
440 int n = 0;
441 int sysctl_mib[2];
442 size_t sysctl_len;
443
444 *names = NULL;
445
446 sysctl_mib[0] = CTL_HW;
447 sysctl_mib[1] = HW_DISKNAMES;
448 if (-1 == sysctl(sysctl_mib, 2, NULL, &sysctl_len, NULL, 0)) {
449 pout("Failed to get value of sysctl `hw.disknames'\n");
450 return -1;
451 }
452 if (!(disknames = (char *)malloc(sysctl_len))) {
453 pout("Out of memory constructing scan device list\n");
454 return -1;
455 }
456 if (-1 == sysctl(sysctl_mib, 2, disknames, &sysctl_len, NULL, 0)) {
457 pout("Failed to get value of sysctl `hw.disknames'\n");
458 return -1;
459 }
460 if (!(mp = (char **) calloc(strlen(disknames) / 2, sizeof(char *)))) {
461 pout("Out of memory constructing scan device list\n");
462 return -1;
463 }
464
465 for (p = strtok(disknames, ","); p; p = strtok(NULL, ",")) {
466 if (strncmp(p, prefix, strlen(prefix))) {
467 continue;
468 }
469 char * u = strchr(p, ':');
470 if (u)
471 *u = 0;
472 mp[n] = (char *)malloc(strlen(net_dev_prefix) + strlen(p) + 2);
473 if (!mp[n]) {
474 pout("Out of memory constructing scan device list\n");
475 return -1;
476 }
477 sprintf(mp[n], "%s%s%c", net_dev_prefix, p, 'a' + getrawpartition());
478 n++;
479 }
480
481 char ** tmp = (char **)realloc(mp, n * (sizeof(char *)));
482 if (NULL == tmp) {
483 pout("Out of memory constructing scan device list\n");
484 free(mp);
485 return -1;
486 }
487 else
488 mp = tmp;
489 *names = mp;
490 return n;
491}
492
493
495 const char * type, const char * pattern /*= 0*/)
496 {
497 if (pattern) {
498 set_err(EINVAL, "DEVICESCAN with pattern not implemented yet");
499 return false;
500 }
501
502 if (type == NULL)
503 type = "";
504
505 bool scan_ata = !*type || !strcmp(type, "ata");
506 bool scan_scsi = !*type || !strcmp(type, "scsi") || !strcmp(type, "sat");
507
508 // Make namelists
509 char * * atanames = 0; int numata = 0;
510 if (scan_ata) {
511 numata = get_dev_names(&atanames, net_dev_ata_disk);
512 if (numata < 0) {
513 set_err(ENOMEM);
514 return false;
515 }
516 }
517
518 char * * scsinames = 0; int numscsi = 0;
519 char * * scsitapenames = 0; int numscsitape = 0;
520 if (scan_scsi) {
521 numscsi = get_dev_names(&scsinames, net_dev_scsi_disk);
522 if (numscsi < 0) {
523 set_err(ENOMEM);
524 return false;
525 }
526 numscsitape = get_dev_names(&scsitapenames, net_dev_scsi_tape);
527 if (numscsitape < 0) {
528 set_err(ENOMEM);
529 return false;
530 }
531 }
532
533 // Add to devlist
534 int i;
535 for (i = 0; i < numata; i++) {
536 ata_device * atadev = get_ata_device(atanames[i], type);
537 if (atadev)
538 devlist.push_back(atadev);
539 free(atanames[i]);
540 }
541 if(numata) free(atanames);
542
543 for (i = 0; i < numscsi; i++) {
544 scsi_device * scsidev = new openbsd_scsi_device(this, scsinames[i], type, true /*scanning*/);
545 if (scsidev)
546 devlist.push_back(scsidev);
547 free(scsinames[i]);
548 }
549 if(numscsi) free(scsinames);
550
551 for (i = 0; i < numscsitape; i++) {
552 scsi_device * scsidev = get_scsi_device(scsitapenames[i], type);
553 if (scsidev)
554 devlist.push_back(scsidev);
555 free(scsitapenames[i]);
556 }
557 if(numscsitape) free(scsitapenames);
558
559 return true;
560}
561
563{
564 const char * test_name = name;
565
566 // if dev_name null, or string length zero
567 if (!name || !*name)
568 return 0;
569
570 // Dereference symlinks
571 struct stat st;
572 std::string pathbuf;
573 if (!lstat(name, &st) && S_ISLNK(st.st_mode)) {
574 char * p = realpath(name, (char *)0);
575 if (p) {
576 pathbuf = p;
577 free(p);
578 test_name = pathbuf.c_str();
579 }
580 }
581
582 if (str_starts_with(test_name, net_dev_prefix)) {
583 test_name += strlen(net_dev_prefix);
584 if (!strncmp(net_dev_ata_disk, test_name, strlen(net_dev_ata_disk)))
585 return get_ata_device(name, "ata");
586 if (!strncmp(net_dev_scsi_disk, test_name, strlen(net_dev_scsi_disk))) {
587 // XXX Try to detect possible USB->(S)ATA bridge
588 // XXX get USB vendor ID, product ID and version from sd(4)/umass(4).
589 // XXX check sat device via get_usb_dev_type_by_id().
590
591 // No USB bridge found, assume regular SCSI or SAT device
592 return get_scsi_device(name, "");
593 }
594 if (!strncmp(net_dev_scsi_tape, test_name, strlen(net_dev_scsi_tape)))
595 return get_scsi_device(name, "scsi");
596 }
597 // device type unknown
598 return 0;
599}
600
601
603{
604 ARGUSED(name);
605 ARGUSED(type);
606 return 0;
607}
608
610{
611 return "";
612}
613
614} // namespace
615
616/////////////////////////////////////////////////////////////////////////////
617/// Initialize platform interface and register with smi()
618
620{
621 static os_openbsd::openbsd_smart_interface the_interface;
622 smart_interface::set(&the_interface);
623}
ATA device access.
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).
Implement standard ATA support.
Definition: os_openbsd.cpp:127
virtual int do_cmd(struct atareq *request, bool is_48bit_cmd)
Definition: os_openbsd.cpp:142
openbsd_ata_device(smart_interface *intf, const char *dev_name, const char *req_type)
Definition: os_openbsd.cpp:136
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out) override
ATA pass through.
Definition: os_openbsd.cpp:151
Standard SCSI support.
Definition: os_openbsd.cpp:217
openbsd_scsi_device(smart_interface *intf, const char *dev_name, const char *req_type, bool scanning=false)
Definition: os_openbsd.cpp:229
virtual bool scsi_pass_through(scsi_cmnd_io *iop) override
SCSI pass through.
Definition: os_openbsd.cpp:237
virtual smart_device * autodetect_open() override
Open device with autodetection support.
Definition: os_openbsd.cpp:303
bool m_scanning
true if created within scan_smart_devices
Definition: os_openbsd.cpp:226
Implement shared open/close routines with old functions.
Definition: os_openbsd.cpp:44
int m_fd
filedesc, -1 if not open.
Definition: os_openbsd.cpp:67
virtual bool close()
Close device, return false on error.
Definition: os_openbsd.cpp:108
virtual bool is_open() const
Return true if device is open.
Definition: os_openbsd.cpp:76
int get_fd() const
Return filedesc for derived classes.
Definition: os_openbsd.cpp:60
virtual bool open()
Open device, return false on error.
Definition: os_openbsd.cpp:82
Implement platform interface with old functions.
Definition: os_openbsd.cpp:370
virtual std::string get_os_version_str() override
Return info string about build host and/or OS version.
Definition: os_openbsd.cpp:397
virtual smart_device * get_custom_smart_device(const char *name, const char *type) override
Return device for platform specific 'type'.
Definition: os_openbsd.cpp:602
int get_dev_names(char ***, const char *)
Definition: os_openbsd.cpp:437
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'.
Definition: os_openbsd.cpp:494
virtual std::string get_valid_custom_dev_types_str() override
Return valid 'type' args accepted by above.
Definition: os_openbsd.cpp:609
virtual ata_device * get_ata_device(const char *name, const char *type) override
Return standard ATA device.
Definition: os_openbsd.cpp:427
virtual smart_device * autodetect_smart_device(const char *name) override
Autodetect device if no device type specified.
Definition: os_openbsd.cpp:562
virtual scsi_device * get_scsi_device(const char *name, const char *type) override
Return standard SCSI device.
Definition: os_openbsd.cpp:432
virtual std::string get_app_examples(const char *appname) override
Return example string for program 'appname'.
Definition: os_openbsd.cpp:404
SCSI device access.
List of devices for DEVICESCAN.
void push_back(smart_device *dev)
Base class for all devices.
Definition: dev_interface.h:33
bool is_scsi() const
Return true if SCSI device.
Definition: dev_interface.h:89
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.
Definition: dev_interface.h:86
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().
Definition: dev_legacy.cpp:334
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.
Definition: scsiata.cpp:1486
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
static const char * net_dev_scsi_disk
Definition: os_openbsd.cpp:36
static const char * net_dev_ata_disk
Definition: os_openbsd.cpp:35
static const char * net_dev_prefix
Definition: os_openbsd.cpp:34
static const char * net_dev_scsi_tape
Definition: os_openbsd.cpp:37
#define ARGUSED(x)
Definition: os_darwin.cpp:39
const char * os_openbsd_cpp_cvsid
Definition: os_openbsd.cpp:25
#define OS_OPENBSD_H_CVSID
Definition: os_openbsd.h:16
int scsiStdInquiry(scsi_device *device, uint8_t *pBuf, int bufLen)
Definition: scsicmds.cpp:1163
void dStrHex(const uint8_t *up, int len, int no_ascii)
Definition: scsicmds.cpp:368
unsigned char scsi_debugmode
Definition: scsicmds.cpp:45
const char * scsi_get_opcode_name(const uint8_t *cdbp)
Definition: scsicmds.cpp:511
#define DXFER_NONE
Definition: scsicmds.h:108
#define DXFER_FROM_DEVICE
Definition: scsicmds.h:109
#define SCSI_TIMEOUT_DEFAULT
Definition: scsicmds.h:379
#define DXFER_TO_DEVICE
Definition: scsicmds.h:110
void pout(const char *fmt,...)
Definition: smartd.cpp:1338
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 device
ata_register lba_high
ata_register sector_count
ata_register lba_low
ata_register features
ata_register command
ata_register lba_mid
ata_register sector_count
ata_register lba_low
ata_register lba_mid
ata_register error
ata_register lba_high
ata_register device
ata_register status
uint8_t * sensep
Definition: scsicmds.h:123
uint8_t * dxferp
Definition: scsicmds.h:121
int dxfer_dir
Definition: scsicmds.h:119
size_t cmnd_len
Definition: scsicmds.h:118
size_t resp_sense_len
Definition: scsicmds.h:127
size_t dxfer_len
Definition: scsicmds.h:122
size_t max_sense_len
Definition: scsicmds.h:125
uint8_t scsi_status
Definition: scsicmds.h:128
uint8_t * cmnd
Definition: scsicmds.h:117
unsigned timeout
Definition: scsicmds.h:126
std::string strprintf(const char *fmt,...)
Definition: utility.cpp:799
bool str_starts_with(const char *str, const char *prefix)
Definition: utility.h:52