smartmontools  SVN Rev 5304
Utility to control and monitor storage systems with "S.M.A.R.T."
os_freebsd.cpp
Go to the documentation of this file.
1 /*
2  * os_freebsd.cpp
3  *
4  * Home page of code is: https://www.smartmontools.org
5  *
6  * Copyright (C) 2003-10 Eduard Martinescu
7  *
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10 
11 #include <sys/param.h>
12 #include <sys/endian.h>
13 #include <stdio.h>
14 #include <sys/types.h>
15 #include <dirent.h>
16 #include <fcntl.h>
17 #include <err.h>
18 #include <errno.h>
19 #include <camlib.h>
20 #include <cam/scsi/scsi_message.h>
21 #include <cam/scsi/scsi_pass.h>
22 #if defined(__DragonFly__)
23 #include <sys/nata.h>
24 #else
25 #include <sys/ata.h>
26 #endif
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <sys/uio.h>
30 #include <glob.h>
31 #include <stddef.h>
32 #include <paths.h>
33 #include <sys/utsname.h>
34 
35 #include "config.h"
36 
37 // set by /usr/include/sys/ata.h, suppress warning
38 #undef ATA_READ_LOG_EXT
39 #include "atacmds.h"
40 #include "scsicmds.h"
41 #include "cciss.h"
42 #include "utility.h"
43 #include "os_freebsd.h"
44 
45 #include "dev_interface.h"
46 #include "dev_ata_cmd_set.h"
47 #include "dev_areca.h"
48 
49 #define USBDEV "/dev/usb"
50 #if defined(__FreeBSD_version)
51 
52 // This way we define one variable for the GNU/kFreeBSD and FreeBSD
53 #define FREEBSDVER __FreeBSD_version
54 #else
55 #define FREEBSDVER __FreeBSD_kernel_version
56 #endif
57 
58 #if (FREEBSDVER >= 800000)
59 #include <libusb20_desc.h>
60 #include <libusb20.h>
61 #elif defined(__DragonFly__)
62 #include <bus/usb/usb.h>
63 #include <bus/usb/usbhid.h>
64 #else
65 #include <dev/usb/usb.h>
66 #include <dev/usb/usbhid.h>
67 #endif
68 
69 // based on "/sys/dev/nvme/nvme.h" from FreeBSD kernel sources
70 #include "freebsd_nvme_ioctl.h" // NVME_PASSTHROUGH_CMD, nvme_completion_is_error
71 
72 #define CONTROLLER_3WARE_9000_CHAR 0x01
73 #define CONTROLLER_3WARE_678K_CHAR 0x02
74 
75 #ifndef PATHINQ_SETTINGS_SIZE
76 #define PATHINQ_SETTINGS_SIZE 128
77 #endif
78 
79 const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 5253 2021-11-24 08:31:31Z samm2 $" \
81 
82 #define NO_RETURN 0
83 #define BAD_SMART 1
84 #define NO_DISK_3WARE 2
85 #define BAD_KERNEL 3
86 #define MAX_MSG 3
87 
88 // Utility function for printing warnings
89 void printwarning(int msgNo, const char* extra) {
90 
91  if (msgNo >= 0 && msgNo <= MAX_MSG) {
92  static int printed[] = {0,0,0,0};
93  if (!printed[msgNo]) {
94 
95  static const char* message[]={
96  "The SMART RETURN STATUS return value (smartmontools -H option/Directive)\n can not be retrieved with this version of ATAng, please do not rely on this value\nYou should update to at least 5.2\n",
97 
98  "Error SMART Status command failed\nPlease get assistance from \n" PACKAGE_HOMEPAGE "\nRegister values returned from SMART Status command are:\n",
99 
100  "You must specify a DISK # for 3ware drives with -d 3ware,<n> where <n> begins with 1 for first disk drive\n",
101 
102  "ATA support is not provided for this kernel version. Please ugrade to a recent 5-CURRENT kernel (post 09/01/2003 or so)\n"
103  };
104 
105  printed[msgNo] = 1;
106  pout("%s", message[msgNo]);
107  if (extra)
108  pout("%s",extra);
109  }
110  }
111  return;
112 }
113 
114 // Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c
115 
116 #define BUFFER_LEN_678K_CHAR ( sizeof(struct twe_usercommand) ) // 520
117 #define BUFFER_LEN_9000_CHAR ( sizeof(TW_OSLI_IOCTL_NO_DATA_BUF) + sizeof(TWE_Command) ) // 2048
118 #define TW_IOCTL_BUFFER_SIZE ( MAX(BUFFER_LEN_678K_CHAR, BUFFER_LEN_9000_CHAR) )
119 
120 #ifndef ATA_DEVICE
121 #define ATA_DEVICE "/dev/ata"
122 #endif
123 
124 #define ARGUSED(x) ((void)(x))
125 
126 extern unsigned char failuretest_permissive;
127 
128 /////////////////////////////////////////////////////////////////////////////
129 
130 namespace os_freebsd { // No need to publish anything, name provided for Doxygen
131 
132 /////////////////////////////////////////////////////////////////////////////
133 /// Implement shared open/close routines with old functions.
134 
136 : virtual public /*implements*/ smart_device
137 {
138 public:
141  m_fd(-1) { }
142 
143  virtual ~freebsd_smart_device();
144 
145  virtual bool is_open() const;
146 
147  virtual bool open();
148 
149  virtual bool close();
150 
151 protected:
152  /// Return filedesc for derived classes.
153  int get_fd() const
154  { return m_fd; }
155 
156  void set_fd(int fd)
157  { m_fd = fd; }
158 
159 private:
160  int m_fd; ///< filedesc, -1 if not open.
161 };
162 
163 #ifdef __GLIBC__
164 static inline void * reallocf(void *ptr, size_t size) {
165  void *rv = realloc(ptr, size);
166  if((rv == NULL) && (size != 0))
167  free(ptr);
168  return rv;
169  }
170 #endif
171 
173 {
174  if (m_fd >= 0)
176 }
177 
178 // migration from the old_style
179 unsigned char m_controller_type;
180 unsigned char m_controller_port;
181 
182 // examples for smartctl
183 static const char smartctl_examples[] =
184  "=================================================== SMARTCTL EXAMPLES =====\n\n"
185  " smartctl -a /dev/ad0 (Prints all SMART information)\n\n"
186  " smartctl --smart=on --offlineauto=on --saveauto=on /dev/ad0\n"
187  " (Enables SMART on first disk)\n\n"
188  " smartctl -t long /dev/ad0 (Executes extended disk self-test)\n\n"
189  " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/ad0\n"
190  " (Prints Self-Test & Attribute errors)\n"
191  " (Prints Self-Test & Attribute errors)\n\n"
192  " smartctl -a --device=3ware,2 /dev/twa0\n"
193  " smartctl -a --device=3ware,2 /dev/twe0\n"
194  " smartctl -a --device=3ware,2 /dev/tws0\n"
195  " (Prints all SMART information for ATA disk on\n"
196  " third port of first 3ware RAID controller)\n"
197  " smartctl -a --device=cciss,0 /dev/ciss0\n"
198  " (Prints all SMART information for first disk \n"
199  " on Common Interface for SCSI-3 Support driver)\n"
200  " smartctl -a --device=areca,3/1 /dev/arcmsr0\n"
201  " (Prints all SMART information for 3rd disk in the 1st enclosure \n"
202  " on first ARECA RAID controller)\n"
203  " smartctl -a --device=megaraid,3 /dev/mrsas0\n"
204  " (Prints all SMART information for 3rd disk\n"
205  " on first LSI RAID controller)\n"
206 
207  ;
208 
210 {
211  return (m_fd >= 0);
212 }
213 
214 
216 {
217  const char *dev = get_dev_name();
218  if ((m_fd = ::open(dev,O_RDONLY))<0) {
219  set_err(errno);
220  return false;
221  }
222  return true;
223 }
224 
226 {
227  int failed = 0;
228  // close device, if open
229  if (is_open())
230  failed=::close(get_fd());
231 
232  set_fd(-1);
233 
234  if(failed) return false;
235  else return true;
236 }
237 
238 /////////////////////////////////////////////////////////////////////////////
239 /// Implement standard ATA support
240 
242 : public /*implements*/ ata_device,
243  public /*extends*/ freebsd_smart_device
244 {
245 public:
246  freebsd_ata_device(smart_interface * intf, const char * dev_name, const char * req_type);
247  virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override;
248 
249 protected:
250  virtual int do_cmd(struct ata_ioc_request* request, bool is_48bit_cmd);
251 };
252 
253 freebsd_ata_device::freebsd_ata_device(smart_interface * intf, const char * dev_name, const char * req_type)
254 : smart_device(intf, dev_name, "ata", req_type),
256 {
257 }
258 
259 int freebsd_ata_device::do_cmd( struct ata_ioc_request* request, bool is_48bit_cmd)
260 {
261  int fd = get_fd(), ret;
262  ARGUSED(is_48bit_cmd); // no support for 48 bit commands in the IOCATAREQUEST
263  ret = ioctl(fd, IOCATAREQUEST, request);
264  if (ret) set_err(errno);
265  return ret;
266 }
267 
268 
269 
271 {
272  bool ata_48bit = false; // no ata_48bit_support via IOCATAREQUEST
273  if(!strcmp("atacam",get_dev_type())) // enable for atacam interface
274  ata_48bit = true;
275 
276  if (!ata_cmd_is_ok(in,
277  true, // data_out_support
278  true, // multi_sector_support
279  ata_48bit)
280  ) {
281  set_err(ENOSYS, "48-bit ATA commands not implemented for legacy controllers");
282  return false;
283  }
284 
285  struct ata_ioc_request request;
286  memset(&request, 0, sizeof(struct ata_ioc_request));
287 
288  request.timeout=SCSI_TIMEOUT_DEFAULT;
289  request.u.ata.command=in.in_regs.command;
290  request.u.ata.feature=in.in_regs.features;
291 
292  request.u.ata.count = in.in_regs.sector_count_16;
293  request.u.ata.lba = in.in_regs.lba_48;
294 
295  switch (in.direction) {
296  case ata_cmd_in::no_data:
297  request.flags=ATA_CMD_CONTROL;
298  break;
299  case ata_cmd_in::data_in:
300  request.flags=ATA_CMD_READ | ATA_CMD_CONTROL;
301  request.data=(char *)in.buffer;
302  request.count=in.size;
303  break;
304  case ata_cmd_in::data_out:
305  request.flags=ATA_CMD_WRITE | ATA_CMD_CONTROL;
306  request.data=(char *)in.buffer;
307  request.count=in.size;
308  break;
309  default:
310  return set_err(ENOSYS);
311  }
312 
313  clear_err();
314  errno = 0;
315  if (do_cmd(&request, in.in_regs.is_48bit_cmd()))
316  return false;
317  if (request.error)
318  return set_err(EIO, "request failed, error code 0x%02x", request.error);
319 
320  out.out_regs.error = request.error;
321  out.out_regs.sector_count_16 = request.u.ata.count;
322  out.out_regs.lba_48 = request.u.ata.lba;
323 
324  return true;
325 }
326 
327 #if FREEBSDVER > 800100
328 class freebsd_atacam_device : public freebsd_ata_device
329 {
330 public:
331  freebsd_atacam_device(smart_interface * intf, const char * dev_name, const char * req_type)
332  : smart_device(intf, dev_name, "atacam", req_type), freebsd_ata_device(intf, dev_name, req_type)
333  {}
334 
335  virtual bool open();
336  virtual bool close();
337 
338 protected:
339  int m_fd;
340  struct cam_device *m_camdev;
341 
342  virtual int do_cmd( struct ata_ioc_request* request , bool is_48bit_cmd);
343 };
344 
345 bool freebsd_atacam_device::open(){
346  const char *dev = get_dev_name();
347 
348  if ((m_camdev = cam_open_device(dev, O_RDWR)) == NULL) {
349  set_err(errno);
350  return false;
351  }
352  set_fd(m_camdev->fd);
353  return true;
354 }
355 
356 bool freebsd_atacam_device::close(){
357  cam_close_device(m_camdev);
358  set_fd(-1);
359  return true;
360 }
361 
362 int freebsd_atacam_device::do_cmd( struct ata_ioc_request* request, bool is_48bit_cmd)
363 {
364  union ccb ccb;
365  int camflags;
366 
367  // 48bit commands are broken in ATACAM before r242422/HEAD
368  // and may cause system hang
369  // First version with working support should be FreeBSD 9.2.0/RELEASE
370 
371 #if (FREEBSDVER < 902001)
372  if(!strcmp("ata",m_camdev->sim_name) && is_48bit_cmd) {
373  set_err(ENOSYS, "48-bit ATA commands not implemented for legacy controllers");
374  return -1;
375  }
376 #endif
377 
378  memset(&ccb, 0, sizeof(ccb));
379 
380  if (request->count == 0)
381  camflags = CAM_DIR_NONE;
382  else if (request->flags & ATA_CMD_READ)
383  camflags = CAM_DIR_IN;
384  else
385  camflags = CAM_DIR_OUT;
386 
387  cam_fill_ataio(&ccb.ataio,
388  0,
389  NULL,
390  camflags,
391  MSG_SIMPLE_Q_TAG,
392  (u_int8_t*)request->data,
393  request->count,
394  request->timeout * 1000); // timeout in seconds
395 
396  ccb.ataio.cmd.flags = CAM_ATAIO_NEEDRESULT |
397  (is_48bit_cmd ? CAM_ATAIO_48BIT : 0);
398  // ata_28bit_cmd
399  ccb.ataio.cmd.command = request->u.ata.command;
400  ccb.ataio.cmd.features = request->u.ata.feature;
401  ccb.ataio.cmd.lba_low = request->u.ata.lba;
402  ccb.ataio.cmd.lba_mid = request->u.ata.lba >> 8;
403  ccb.ataio.cmd.lba_high = request->u.ata.lba >> 16;
404  // ata_48bit cmd
405  ccb.ataio.cmd.lba_low_exp = request->u.ata.lba >> 24;
406  ccb.ataio.cmd.lba_mid_exp = request->u.ata.lba >> 32;
407  ccb.ataio.cmd.lba_high_exp = request->u.ata.lba >> 40;
408  ccb.ataio.cmd.device = 0x40 | ((request->u.ata.lba >> 24) & 0x0f);
409  ccb.ataio.cmd.sector_count = request->u.ata.count;
410  ccb.ataio.cmd.sector_count_exp = request->u.ata.count >> 8;;
411 
412  ccb.ccb_h.flags |= CAM_DEV_QFRZDIS;
413 
414  if (cam_send_ccb(m_camdev, &ccb) < 0) {
415  set_err(EIO, "cam_send_ccb failed");
416  return -1;
417  }
418 
419  if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
420  if(scsi_debugmode > 0)
421  cam_error_print(m_camdev, &ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
422  set_err(EIO);
423  return -1;
424  }
425 
426  request->u.ata.lba =
427  ((u_int64_t)(ccb.ataio.res.lba_low)) |
428  ((u_int64_t)(ccb.ataio.res.lba_mid) << 8) |
429  ((u_int64_t)(ccb.ataio.res.lba_high) << 16) |
430  ((u_int64_t)(ccb.ataio.res.lba_low_exp) << 24) |
431  ((u_int64_t)(ccb.ataio.res.lba_mid_exp) << 32) |
432  ((u_int64_t)(ccb.ataio.res.lba_high_exp) << 40);
433 
434  request->u.ata.count = ccb.ataio.res.sector_count | (ccb.ataio.res.sector_count_exp << 8);
435  request->error = ccb.ataio.res.error;
436 
437  return 0;
438 }
439 
440 #endif
441 
442 /////////////////////////////////////////////////////////////////////////////
443 /// NVMe support
444 
446 : public /*implements*/ nvme_device,
447  public /*extends*/ freebsd_smart_device
448 {
449 public:
450  freebsd_nvme_device(smart_interface * intf, const char * dev_name,
451  const char * req_type, unsigned nsid);
452 
453  virtual bool open() override;
454 
455  virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out) override;
456 };
457 
459  const char * req_type, unsigned nsid)
460 : smart_device(intf, dev_name, "nvme", req_type),
461  nvme_device(nsid),
463 {
464 }
465 
467 {
468  const char *dev = get_dev_name();
469  if (!strnstr(dev, NVME_CTRLR_PREFIX, strlen(NVME_CTRLR_PREFIX))) {
470  set_err(EINVAL, "NVMe controller controller/namespace ids must begin with '%s'",
472  return false;
473  }
474 
475  int nsid = -1, ctrlid = -1;
476  char tmp;
477 
478  if(sscanf(dev, NVME_CTRLR_PREFIX"%d%c", &ctrlid, &tmp) == 1)
479  {
480  if(ctrlid < 0) {
481  set_err(EINVAL, "Invalid NVMe controller number");
482  return false;
483  }
484  nsid = 0xFFFFFFFF; // broadcast id
485  }
486  else if (sscanf(dev, NVME_CTRLR_PREFIX"%d" NVME_NS_PREFIX "%d%c",
487  &ctrlid, &nsid, &tmp) == 2)
488  {
489  if(ctrlid < 0 || nsid < 0) {
490  set_err(EINVAL, "Invalid NVMe controller/namespace number");
491  return false;
492  }
493  }
494  else {
495  set_err(EINVAL, "Invalid NVMe controller/namespace syntax");
496  return false;
497  }
498 
499  // we should always open controller, not namespace device
500  char full_path[64];
501  snprintf(full_path, sizeof(full_path), NVME_CTRLR_PREFIX"%d", ctrlid);
502 
503  int fd;
504  if ((fd = ::open(full_path, O_RDWR))<0) {
505  set_err(errno);
506  return false;
507  }
508  set_fd(fd);
509 
510  if (!get_nsid()) {
511  set_nsid(nsid);
512  }
513 
514  return true;
515 }
516 
518 {
519  // nvme_passthru_cmd pt;
520  struct nvme_pt_command pt;
521  struct nvme_completion *cp_p;
522  memset(&pt, 0, sizeof(pt));
523 
524 #if __FreeBSD_version >= 1200058 && __FreeBSD_version < 1200081
525  pt.cmd.opc_fuse = NVME_CMD_SET_OPC(in.opcode);
526 #else
527  pt.cmd.opc = in.opcode;
528 #endif
529  pt.cmd.nsid = htole32(in.nsid);
530  pt.buf = in.buffer;
531  pt.len = in.size;
532  pt.cmd.cdw10 = htole32(in.cdw10);
533  pt.cmd.cdw11 = htole32(in.cdw11);
534  pt.cmd.cdw12 = htole32(in.cdw12);
535  pt.cmd.cdw13 = htole32(in.cdw13);
536  pt.cmd.cdw14 = htole32(in.cdw14);
537  pt.cmd.cdw15 = htole32(in.cdw15);
538  pt.is_read = 1; // should we use in.direction()?
539 
540  int status = ioctl(get_fd(), NVME_PASSTHROUGH_CMD, &pt);
541 
542  if (status < 0)
543  return set_err(errno, "NVME_PASSTHROUGH_CMD: %s", strerror(errno));
544 #if __FreeBSD_version >= 1200058
545  nvme_completion_swapbytes(&pt.cpl);
546 #endif
547  cp_p = &pt.cpl;
548  out.result=cp_p->cdw0; // Command specific result (DW0)
549 
550  if (nvme_completion_is_error(cp_p)) { /* ignore DNR and More bits */
551  return set_nvme_err(out, nvme_completion_is_error(&pt.cpl));
552  }
553 
554  return true;
555 }
556 
557 /////////////////////////////////////////////////////////////////////////////
558 /// Implement AMCC/3ware RAID support
559 
561 : public /*implements*/ ata_device,
562  public /*extends*/ freebsd_smart_device
563 {
564 public:
565  freebsd_escalade_device(smart_interface * intf, const char * dev_name,
566  int escalade_type, int disknum);
567 
568 protected:
569  virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) override;
570  virtual bool open() override;
571 
572 private:
573  int m_escalade_type; ///< Type string for escalade_command_interface().
574  int m_disknum; ///< Disk number.
575 };
576 
578  int escalade_type, int disknum)
579 : smart_device(intf, dev_name, "3ware", "3ware"),
581  m_escalade_type(escalade_type), m_disknum(disknum)
582 {
583  set_info().info_name = strprintf("%s [3ware_disk_%02d]", dev_name, disknum);
584 }
585 
587 {
588  const char *dev = get_dev_name();
589  int fd;
590 
591  if ((fd = ::open(dev,O_RDWR))<0) {
592  set_err(errno);
593  return false;
594  }
595  set_fd(fd);
596  return true;
597 }
598 
600 {
601  // to hold true file descriptor
602  int fd = get_fd();
603 
604  if (!ata_cmd_is_ok(in,
605  true, // data_out_support
606  false, // TODO: multi_sector_support
607  true) // ata_48bit_support
608  )
609  return false;
610 
611  struct twe_usercommand* cmd_twe = NULL;
612  TW_OSLI_IOCTL_NO_DATA_BUF* cmd_twa = NULL;
613  TWE_Command_ATA* ata = NULL;
614 
615  // Used by both the SCSI and char interfaces
616  char ioctl_buffer[TW_IOCTL_BUFFER_SIZE];
617 
618  if (m_disknum < 0) {
620  return false;
621  }
622 
623  memset(ioctl_buffer, 0, TW_IOCTL_BUFFER_SIZE);
624 
626  cmd_twa = (TW_OSLI_IOCTL_NO_DATA_BUF*)ioctl_buffer;
627  cmd_twa->pdata = ((TW_OSLI_IOCTL_WITH_PAYLOAD*)cmd_twa)->payload.data_buf;
628  cmd_twa->driver_pkt.buffer_length = in.size;
629  // using "old" packet format to speak with SATA devices
630  ata = (TWE_Command_ATA*)&cmd_twa->cmd_pkt.command.cmd_pkt_7k;
632  cmd_twe = (struct twe_usercommand*)ioctl_buffer;
633  ata = &cmd_twe->tu_command.ata;
634  } else {
635  return set_err(ENOSYS,
636  "Unrecognized escalade_type %d in linux_3ware_command_interface(disk %d)\n"
637  "Please contact " PACKAGE_BUGREPORT "\n", (int)m_escalade_type, m_disknum);
638  }
639 
640  ata->opcode = TWE_OP_ATA_PASSTHROUGH;
641 
642  // Same for (almost) all commands - but some reset below
643  ata->request_id = 0xFF;
644  ata->unit = m_disknum;
645  ata->status = 0;
646  ata->flags = 0x1;
647  ata->size = 0x5; // TODO: multisector support
648  // Set registers
649  {
650  const ata_in_regs_48bit & r = in.in_regs;
651  ata->features = r.features_16;
652  ata->sector_count = r.sector_count_16;
653  ata->sector_num = r.lba_low_16;
654  ata->cylinder_lo = r.lba_mid_16;
655  ata->cylinder_hi = r.lba_high_16;
656  ata->drive_head = r.device;
657  ata->command = r.command;
658  }
659 
660  // Is this a command that reads or returns 512 bytes?
661  // passthru->param values are:
662  // 0x0 - non data command without TFR write check,
663  // 0x8 - non data command with TFR write check,
664  // 0xD - data command that returns data to host from device
665  // 0xF - data command that writes data from host to device
666  // passthru->size values are 0x5 for non-data and 0x07 for data
667  bool readdata = false;
668  if (in.direction == ata_cmd_in::data_in) {
670  cmd_twe->tu_data = in.buffer;
671  cmd_twe->tu_size = 512;
672  }
673 
674  readdata=true;
675  ata->sgl_offset = 0x5;
676  ata->param = 0xD;
677  // For 64-bit to work correctly, up the size of the command packet
678  // in dwords by 1 to account for the 64-bit single sgl 'address'
679  // field. Note that this doesn't agree with the typedefs but it's
680  // right (agree with kernel driver behavior/typedefs).
681  // if (sizeof(long)==8)
682  // ata->size++;
683  }
684  else if (in.direction == ata_cmd_in::no_data) {
685  // Non data command -- but doesn't use large sector
686  // count register values.
687  ata->sgl_offset = 0x0;
688  ata->param = 0x8;
689  ata->sector_count = 0x0;
690  }
691  else if (in.direction == ata_cmd_in::data_out) {
692  ata->sgl_offset = 0x5;
693  ata->param = 0xF; // PIO data write
695  cmd_twe->tu_data = in.buffer;
696  cmd_twe->tu_size = 512;
697  }
699  memcpy(cmd_twa->pdata, in.buffer, in.size);
700  }
701  }
702  else
703  return set_err(EINVAL);
704 
705  // 3WARE controller can NOT have packet device internally
707  return set_err(ENODEV, "No drive on port %d", m_disknum);
708  }
709 
710  // Now send the command down through an ioctl()
711  int ioctlreturn;
713  ioctlreturn=ioctl(fd,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa);
714  } else {
715  ioctlreturn=ioctl(fd,TWEIO_COMMAND,cmd_twe);
716  }
717 
718  // Deal with the different error cases
719  if (ioctlreturn) {
720  return set_err(EIO);
721  }
722 
723  // See if the ATA command failed. Now that we have returned from
724  // the ioctl() call, if passthru is valid, then:
725  // - ata->status contains the 3ware controller STATUS
726  // - ata->command contains the ATA STATUS register
727  // - ata->features contains the ATA ERROR register
728  //
729  // Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS
730  // If bit 0 (error bit) is set, then ATA ERROR register is valid.
731  // While we *might* decode the ATA ERROR register, at the moment it
732  // doesn't make much sense: we don't care in detail why the error
733  // happened.
734 
735  if (ata->status || (ata->command & 0x21)) {
736  if (scsi_debugmode)
737  pout("Command failed, ata.status=(0x%2.2x), ata.command=(0x%2.2x), ata.flags=(0x%2.2x)\n",ata->status,ata->command,ata->flags);
738  return set_err(EIO);
739  }
740 
741  // If this is a read data command, copy data to output buffer
742  if (readdata) {
744  memcpy(in.buffer, cmd_twa->pdata, in.size);
746  memcpy(in.buffer, cmd_twe->tu_data, in.size); // untested
747  }
748  }
749  // Return register values
750  if (ata) {
751  ata_out_regs_48bit & r = out.out_regs;
752  r.error = ata->features;
753  r.sector_count_16 = ata->sector_count;
754  r.lba_low_16 = ata->sector_num;
755  r.lba_mid_16 = ata->cylinder_lo;
756  r.lba_high_16 = ata->cylinder_hi;
757  r.device = ata->drive_head;
758  r.status = ata->command;
759  }
760  // look for nonexistent devices/ports
762  && !nonempty((unsigned char *)in.buffer, in.size)) {
763  return set_err(ENODEV, "No drive on port %d", m_disknum);
764  }
765  return true;
766 }
767 
768 /////////////////////////////////////////////////////////////////////////////
769 /// LSI MegaRAID support
770 
772 : public /* implements */ scsi_device,
773  public /* extends */ freebsd_smart_device
774 {
775 public:
776  freebsd_megaraid_device(smart_interface *intf, const char *name,
777  unsigned int tgt);
778 
779  virtual ~freebsd_megaraid_device();
780 
781  virtual smart_device * autodetect_open() override;
782 
783  virtual bool open() override;
784  virtual bool close() override;
785 
786  virtual bool scsi_pass_through(scsi_cmnd_io *iop) override;
787 
788 private:
789  unsigned int m_disknum;
790  unsigned int m_hba;
791  int m_fd;
792 
793  bool (freebsd_megaraid_device::*pt_cmd)(int cdblen, void *cdb, int dataLen, void *data,
794  int senseLen, void *sense, int report, int direction, int timeout);
795  bool megasas_cmd(int cdbLen, void *cdb, int dataLen, void *data,
796  int senseLen, void *sense, int report, int direction, int timeout);
797 };
798 
800  const char *dev_name, unsigned int tgt)
801  : smart_device(intf, dev_name, "megaraid", "megaraid"),
803  m_disknum(tgt), m_hba(0),
804  m_fd(-1), pt_cmd(0)
805 {
806  set_info().info_name = strprintf("%s [megaraid_disk_%02d]", dev_name, m_disknum);
807  set_info().dev_type = strprintf("megaraid,%d", tgt);
808 }
809 
811 {
812  if (m_fd >= 0)
813  ::close(m_fd);
814 }
815 
817 {
818  int report = scsi_debugmode;
819 
820  // Open device
821  if (!open())
822  return this;
823 
824  // The code below is based on smartd.cpp:SCSIFilterKnown()
825  if (strcmp(get_req_type(), "megaraid"))
826  return this;
827 
828  // Get INQUIRY
829  unsigned char req_buff[64] = {0, };
830  int req_len = 36;
831  if (scsiStdInquiry(this, req_buff, req_len)) {
832  close();
833  set_err(EIO, "INQUIRY failed");
834  return this;
835  }
836 
837  int avail_len = req_buff[4] + 5;
838  int len = (avail_len < req_len ? avail_len : req_len);
839  if (len < 36)
840  return this;
841 
842  if (report)
843  pout("Got MegaRAID inquiry.. %s\n", req_buff+8);
844 
845  // Use INQUIRY to detect type
846  {
847  // SAT?
848  ata_device * newdev = smi()->autodetect_sat_device(this, req_buff, len);
849  if (newdev) // NOTE: 'this' is now owned by '*newdev'
850  return newdev;
851  }
852 
853  // Nothing special found
854  return this;
855 }
856 
858 {
859  /* Open Device IOCTL node */
860  if ((m_fd = ::open(get_dev_name(), O_RDWR)) >= 0) {
862  }
863  else {
864  int err = errno;
866  return set_err(err, "cannot open %s",get_dev_name());
867  }
868  set_fd(m_fd);
869  return true;
870 }
871 
873 {
874  if (m_fd >= 0)
875  ::close(m_fd);
876  m_fd = -1; m_hba = 0; pt_cmd = 0;
877  set_fd(m_fd);
878  return true;
879 }
880 
882 {
883  int report = scsi_debugmode;
884 
885  if (report > 0) {
886  int k, j;
887  const unsigned char * ucp = iop->cmnd;
888  const char * np;
889  char buff[256];
890  const int sz = (int)sizeof(buff);
891 
892  np = scsi_get_opcode_name(ucp[0]);
893  j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>");
894  for (k = 0; k < (int)iop->cmnd_len; ++k)
895  j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]);
896  if ((report > 1) &&
897  (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) {
898  int trunc = (iop->dxfer_len > 256) ? 1 : 0;
899 
900  snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n Outgoing "
901  "data, len=%d%s:\n", (int)iop->dxfer_len,
902  (trunc ? " [only first 256 bytes shown]" : ""));
903  dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
904  }
905  else
906  snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n");
907  pout("%s", buff);
908  }
909 
910  // Controller rejects Test Unit Ready
911  if (iop->cmnd[0] == 0x00)
912  return true;
913 
914  if (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 || iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16) {
915  // Controller does not return ATA output registers in SAT sense data
916  if (iop->cmnd[2] & (1 << 5)) // chk_cond
917  return set_err(ENOSYS, "ATA return descriptor not supported by controller firmware");
918  }
919  // SMART WRITE LOG SECTOR causing media errors
920  if ((iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16 // SAT16 WRITE LOG
921  && iop->cmnd[14] == ATA_SMART_CMD && iop->cmnd[3]==0 && iop->cmnd[4] == ATA_SMART_WRITE_LOG_SECTOR) ||
922  (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 // SAT12 WRITE LOG
923  && iop->cmnd[9] == ATA_SMART_CMD && iop->cmnd[3] == ATA_SMART_WRITE_LOG_SECTOR))
924  {
926  return set_err(ENOSYS, "SMART WRITE LOG SECTOR may cause problems, try with -T permissive to force");
927  }
928  if (pt_cmd == NULL)
929  return false;
930  return (this->*pt_cmd)(iop->cmnd_len, iop->cmnd,
931  iop->dxfer_len, iop->dxferp,
932  iop->max_sense_len, iop->sensep, report, iop->dxfer_dir, iop->timeout);
933 }
934 
936  int dataLen, void *data,
937  int senseLen, void * sense, int /*report*/, int dxfer_dir, int timeout)
938 {
939  struct mfi_pass_frame * pthru;
940  struct mfi_ioc_packet uio;
941 
942  pthru = (struct mfi_pass_frame *)&uio.mfi_frame.raw;
943  memset(&uio, 0, sizeof(uio));
944 
945  pthru->header.cmd = MFI_CMD_PD_SCSI_IO;
946  pthru->header.cmd_status = 0;
947  pthru->header.scsi_status = 0x0;
948  pthru->header.target_id = m_disknum;
949  pthru->header.lun_id = 0; // FIXME, should be bus number?
950 
951  pthru->header.sense_len = senseLen;
952  pthru->sense_addr_lo = (uintptr_t)sense ;
953  pthru->sense_addr_hi = (uintptr_t)((uint64_t)sense >> 32);
954 
955  pthru->header.cdb_len = cdbLen;
956  pthru->header.timeout = timeout;
957  switch (dxfer_dir) {
958  case DXFER_FROM_DEVICE:
959  pthru->header.flags = MFI_FRAME_DIR_READ;
960  break;
961  case DXFER_TO_DEVICE:
962  pthru->header.flags = MFI_FRAME_DIR_WRITE;
963  break;
964  case DXFER_NONE:
965  pthru->header.flags = MFI_FRAME_DIR_NONE;
966  break;
967  }
968 
969  if (dataLen > 0) {
970  uio.mfi_sge_count = 1;
971  uio.mfi_sgl_off = offsetof(struct mfi_pass_frame,sgl);
972  uio.mfi_sgl[0].iov_base = data;
973  uio.mfi_sgl[0].iov_len = dataLen;
974 
975  pthru->header.sg_count = 1;
976  pthru->header.data_len = dataLen;
977  // tested on amd64 kernel in native and 32bit mode
978  pthru->sgl.sg64[0].addr = (intptr_t)data;
979  pthru->sgl.sg64[0].len = (uint32_t)dataLen;
980  }
981  memcpy(pthru->cdb, cdb, cdbLen);
982 
983  uio.mfi_adapter_no = m_hba;
984  uio.mfi_sense_len = senseLen;
985  uio.mfi_sense_off = offsetof(struct mfi_pass_frame, sense_addr_lo);
986 
987  errno = 0;
988  int rc = ioctl(m_fd, MFI_CMD, &uio);
989 
990  if (pthru->header.cmd_status || rc != 0) {
991  if (pthru->header.cmd_status == 12) {
992  return set_err(EIO, "megasas_cmd: Device %d does not exist\n", m_disknum);
993  }
994  return set_err((errno ? errno : EIO), "megasas_cmd result: %d.%d = %d/%d",
995  m_hba, m_disknum, errno,
996  pthru->header.cmd_status);
997  }
998  return true;
999 }
1000 
1001 
1002 /////////////////////////////////////////////////////////////////////////////
1003 /// Implement Highpoint RAID support with old functions
1004 
1006 : public /*implements*/ ata_device_with_command_set,
1007  public /*extends*/ freebsd_smart_device
1008 {
1009 public:
1010  freebsd_highpoint_device(smart_interface * intf, const char * dev_name,
1011  unsigned char controller, unsigned char channel, unsigned char port);
1012 
1013 protected:
1014  virtual int ata_command_interface(smart_command_set command, int select, char * data) override;
1015  virtual bool open() override;
1016 
1017 private:
1018  unsigned char m_hpt_data[3]; ///< controller/channel/port
1019 };
1020 
1021 
1023  unsigned char controller, unsigned char channel, unsigned char port)
1024 : smart_device(intf, dev_name, "hpt", "hpt"),
1026 {
1027  m_hpt_data[0] = controller; m_hpt_data[1] = channel; m_hpt_data[2] = port;
1028  set_info().info_name = strprintf("%s [hpt_disk_%u/%u/%u]", dev_name, m_hpt_data[0], m_hpt_data[1], m_hpt_data[2]);
1029 }
1030 
1032 {
1033  const char *dev = get_dev_name();
1034  int fd;
1035 
1036  if ((fd = ::open(dev,O_RDWR))<0) {
1037  set_err(errno);
1038  return false;
1039  }
1040  set_fd(fd);
1041  return true;
1042 }
1043 
1045 {
1046  int fd=get_fd();
1047  int ids[2];
1048  HPT_IOCTL_PARAM param;
1049  HPT_CHANNEL_INFO_V2 info;
1050  unsigned char* buff[512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER)];
1051  PHPT_PASS_THROUGH_HEADER pide_pt_hdr, pide_pt_hdr_out;
1052 
1053  // get internal deviceid
1054  ids[0] = m_hpt_data[0] - 1;
1055  ids[1] = m_hpt_data[1] - 1;
1056 
1057  memset(&param, 0, sizeof(HPT_IOCTL_PARAM));
1058 
1059  param.magic = HPT_IOCTL_MAGIC;
1061  param.in = (unsigned char *)ids;
1062  param.in_size = sizeof(unsigned int) * 2;
1063  param.out = (unsigned char *)&info;
1064  param.out_size = sizeof(HPT_CHANNEL_INFO_V2);
1065 
1066  if (m_hpt_data[2]==1) {
1068  param.out_size = sizeof(HPT_CHANNEL_INFO);
1069  }
1070  if (ioctl(fd, HPT_DO_IOCONTROL, &param)!=0 ||
1071  info.devices[m_hpt_data[2]-1]==0) {
1072  return -1;
1073  }
1074 
1075  // perform smart action
1076  memset(buff, 0, sizeof(buff));
1077  pide_pt_hdr = (PHPT_PASS_THROUGH_HEADER)buff;
1078 
1079  pide_pt_hdr->lbamid = 0x4f;
1080  pide_pt_hdr->lbahigh = 0xc2;
1081  pide_pt_hdr->command = ATA_SMART_CMD;
1082  pide_pt_hdr->id = info.devices[m_hpt_data[2] - 1];
1083 
1084  switch (command){
1085  case READ_VALUES:
1086  pide_pt_hdr->feature=ATA_SMART_READ_VALUES;
1087  pide_pt_hdr->protocol=HPT_READ;
1088  break;
1089  case READ_THRESHOLDS:
1090  pide_pt_hdr->feature=ATA_SMART_READ_THRESHOLDS;
1091  pide_pt_hdr->protocol=HPT_READ;
1092  break;
1093  case READ_LOG:
1094  pide_pt_hdr->feature=ATA_SMART_READ_LOG_SECTOR;
1095  pide_pt_hdr->lbalow=select;
1096  pide_pt_hdr->protocol=HPT_READ;
1097  break;
1098  case IDENTIFY:
1099  pide_pt_hdr->command=ATA_IDENTIFY_DEVICE;
1100  pide_pt_hdr->protocol=HPT_READ;
1101  break;
1102  case ENABLE:
1103  pide_pt_hdr->feature=ATA_SMART_ENABLE;
1104  break;
1105  case DISABLE:
1106  pide_pt_hdr->feature=ATA_SMART_DISABLE;
1107  break;
1108  case AUTO_OFFLINE:
1109  pide_pt_hdr->feature=ATA_SMART_AUTO_OFFLINE;
1110  pide_pt_hdr->sectorcount=select;
1111  break;
1112  case AUTOSAVE:
1113  pide_pt_hdr->feature=ATA_SMART_AUTOSAVE;
1114  pide_pt_hdr->sectorcount=select;
1115  break;
1116  case IMMEDIATE_OFFLINE:
1117  pide_pt_hdr->feature=ATA_SMART_IMMEDIATE_OFFLINE;
1118  pide_pt_hdr->lbalow=select;
1119  break;
1120  case STATUS_CHECK:
1121  case STATUS:
1122  pide_pt_hdr->feature=ATA_SMART_STATUS;
1123  break;
1124  case CHECK_POWER_MODE:
1125  pide_pt_hdr->command=ATA_CHECK_POWER_MODE;
1126  break;
1127  case WRITE_LOG:
1128  memcpy(buff+sizeof(HPT_PASS_THROUGH_HEADER), data, 512);
1129  pide_pt_hdr->feature=ATA_SMART_WRITE_LOG_SECTOR;
1130  pide_pt_hdr->lbalow=select;
1131  pide_pt_hdr->protocol=HPT_WRITE;
1132  break;
1133  default:
1134  pout("Unrecognized command %d in highpoint_command_interface()\n"
1135  "Please contact " PACKAGE_BUGREPORT "\n", command);
1136  errno=ENOSYS;
1137  return -1;
1138  }
1139  if (pide_pt_hdr->protocol!=0) {
1140  pide_pt_hdr->sectors = 1;
1141  pide_pt_hdr->sectorcount = 1;
1142  }
1143 
1144  memset(&param, 0, sizeof(HPT_IOCTL_PARAM));
1145 
1146  param.magic = HPT_IOCTL_MAGIC;
1148  param.in = (unsigned char *)buff;
1149  param.in_size = sizeof(HPT_PASS_THROUGH_HEADER) + (pide_pt_hdr->protocol==HPT_READ ? 0 : pide_pt_hdr->sectors * 512);
1150  param.out = (unsigned char *)buff+param.in_size;
1151  param.out_size = sizeof(HPT_PASS_THROUGH_HEADER) + (pide_pt_hdr->protocol==HPT_READ ? pide_pt_hdr->sectors * 512 : 0);
1152 
1153  pide_pt_hdr_out = (PHPT_PASS_THROUGH_HEADER)param.out;
1154 
1155  if ((ioctl(fd, HPT_DO_IOCONTROL, &param)!=0) ||
1156  (pide_pt_hdr_out->command & 1)) {
1157  return -1;
1158  }
1159 
1160  if (command==STATUS_CHECK)
1161  {
1162  unsigned const char normal_lo=0x4f, normal_hi=0xc2;
1163  unsigned const char failed_lo=0xf4, failed_hi=0x2c;
1164  unsigned char low,high;
1165 
1166  high = pide_pt_hdr_out->lbahigh;
1167  low = pide_pt_hdr_out->lbamid;
1168 
1169  // Cyl low and Cyl high unchanged means "Good SMART status"
1170  if (low==normal_lo && high==normal_hi)
1171  return 0;
1172 
1173  // These values mean "Bad SMART status"
1174  if (low==failed_lo && high==failed_hi)
1175  return 1;
1176 
1177  // We haven't gotten output that makes sense; print out some debugging info
1178  char buf[512];
1179  snprintf(buf, sizeof(buf),
1180  "CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
1181  (int)pide_pt_hdr_out->command,
1182  (int)pide_pt_hdr_out->feature,
1183  (int)pide_pt_hdr_out->sectorcount,
1184  (int)pide_pt_hdr_out->lbalow,
1185  (int)pide_pt_hdr_out->lbamid,
1186  (int)pide_pt_hdr_out->lbahigh,
1187  (int)pide_pt_hdr_out->sectors);
1188  printwarning(BAD_SMART,buf);
1189  }
1190  else if (command==CHECK_POWER_MODE)
1191  data[0] = pide_pt_hdr_out->sectorcount & 0xff;
1192  else if (pide_pt_hdr->protocol==HPT_READ)
1193  memcpy(data, (unsigned char *)buff + 2 * sizeof(HPT_PASS_THROUGH_HEADER),
1194  pide_pt_hdr->sectors * 512);
1195  return 0;
1196 }
1197 
1198 
1199 /////////////////////////////////////////////////////////////////////////////
1200 /// Standard SCSI support
1201 
1203 : public /*implements*/ scsi_device,
1204  public /*extends*/ freebsd_smart_device
1205 {
1206 public:
1207  freebsd_scsi_device(smart_interface * intf, const char * dev_name, const char * req_type);
1208 
1209  virtual smart_device * autodetect_open() override;
1210 
1211  virtual bool scsi_pass_through(scsi_cmnd_io * iop) override;
1212 
1213  virtual bool open() override;
1214 
1215  virtual bool close() override;
1216 
1217 private:
1218  struct cam_device *m_camdev;
1219 };
1220 
1222  const char *dev = get_dev_name();
1223 
1224  if ((m_camdev = cam_open_device(dev, O_RDWR)) == NULL) {
1225  set_err(errno);
1226  return false;
1227  }
1228  set_fd(m_camdev->fd);
1229  return true;
1230 }
1231 
1233  cam_close_device(m_camdev);
1234  set_fd(-1);
1235  return true;
1236 }
1237 
1239  const char * dev_name, const char * req_type)
1240 : smart_device(intf, dev_name, "scsi", req_type),
1242  m_camdev(0)
1243 {
1244 }
1245 
1246 
1248 {
1249  union ccb *ccb;
1250 
1251  if (scsi_debugmode) {
1252  unsigned int k;
1253  const unsigned char * ucp = iop->cmnd;
1254  const char * np;
1255 
1256  np = scsi_get_opcode_name(ucp[0]);
1257  pout(" [%s: ", np ? np : "<unknown opcode>");
1258  for (k = 0; k < iop->cmnd_len; ++k)
1259  pout("%02x ", ucp[k]);
1260  if ((scsi_debugmode > 1) &&
1261  (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) {
1262  int trunc = (iop->dxfer_len > 256) ? 1 : 0;
1263 
1264  pout("]\n Outgoing data, len=%d%s:\n", (int)iop->dxfer_len,
1265  (trunc ? " [only first 256 bytes shown]" : ""));
1266  dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
1267  }
1268  else
1269  pout("]\n");
1270  }
1271 
1272  if(m_camdev==NULL) {
1273  if (scsi_debugmode)
1274  pout(" error: camdev=0!\n");
1275  return set_err(ENOTTY);
1276  }
1277 
1278  if (!(ccb = cam_getccb(m_camdev))) {
1279  if (scsi_debugmode)
1280  pout(" error allocating ccb\n");
1281  return set_err(ENOMEM);
1282  }
1283 
1284  // mfi SAT layer is known to be buggy
1285  if(!strcmp("mfi",m_camdev->sim_name)) {
1286  if (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 || iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16) {
1287  // Controller does not return ATA output registers in SAT sense data
1288  if (iop->cmnd[2] & (1 << 5)) // chk_cond
1289  return set_err(ENOSYS, "ATA return descriptor not supported by controller firmware");
1290  }
1291  // SMART WRITE LOG SECTOR causing media errors
1292  if ((iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16
1293  && iop->cmnd[14] == ATA_SMART_CMD && iop->cmnd[3]==0 &&
1294  iop->cmnd[4] == ATA_SMART_WRITE_LOG_SECTOR) ||
1295  (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12
1296  && iop->cmnd[9] == ATA_SMART_CMD && iop->cmnd[3] == ATA_SMART_WRITE_LOG_SECTOR))
1297  {
1299  return set_err(ENOSYS, "SMART WRITE LOG SECTOR may cause problems, try with -T permissive to force");
1300  }
1301  }
1302  // clear out structure, except for header that was filled in for us
1303  memset(&(&ccb->ccb_h)[1], 0, sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1304 
1305  cam_fill_csio(&ccb->csio,
1306  /* retries */ 1,
1307  /* cbfcnp */ NULL,
1308  /* flags */ (iop->dxfer_dir == DXFER_NONE ? CAM_DIR_NONE :(iop->dxfer_dir == DXFER_FROM_DEVICE ? CAM_DIR_IN : CAM_DIR_OUT)),
1309  /* tagaction */ MSG_SIMPLE_Q_TAG,
1310  /* dataptr */ iop->dxferp,
1311  /* datalen */ iop->dxfer_len,
1312  /* senselen */ iop->max_sense_len,
1313  /* cdblen */ iop->cmnd_len,
1314  /* timeout (converted to seconds) */ iop->timeout*1000);
1315  memcpy(ccb->csio.cdb_io.cdb_bytes,iop->cmnd,iop->cmnd_len);
1316 
1317  if (cam_send_ccb(m_camdev,ccb) < 0) {
1318  if (scsi_debugmode) {
1319  pout(" error sending SCSI ccb\n");
1320  cam_error_print(m_camdev,ccb,CAM_ESF_ALL,CAM_EPF_ALL,stderr);
1321  }
1322  cam_freeccb(ccb);
1323  return set_err(EIO);
1324  }
1325 
1326  if (scsi_debugmode) {
1327  pout(" CAM status=0x%x, SCSI status=0x%x, resid=0x%x\n",
1328  ccb->ccb_h.status, ccb->csio.scsi_status, ccb->csio.resid);
1329  if ((scsi_debugmode > 1) && (DXFER_FROM_DEVICE == iop->dxfer_dir)) {
1330  int trunc, len;
1331 
1332  len = iop->dxfer_len - ccb->csio.resid;
1333  trunc = (len > 256) ? 1 : 0;
1334  if (len > 0) {
1335  pout(" Incoming data, len=%d%s:\n", len,
1336  (trunc ? " [only first 256 bytes shown]" : ""));
1337  dStrHex(iop->dxferp, (trunc ? 256 : len), 1);
1338  }
1339  else
1340  pout(" Incoming data trimmed to nothing by resid\n");
1341  }
1342  }
1343 
1344  if (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_SCSI_STATUS_ERROR)) {
1345  if (scsi_debugmode)
1346  cam_error_print(m_camdev,ccb,CAM_ESF_ALL,CAM_EPF_ALL,stderr);
1347  cam_freeccb(ccb);
1348  return set_err(EIO);
1349  }
1350 
1351  iop->resid = ccb->csio.resid;
1352  iop->scsi_status = ccb->csio.scsi_status;
1353  if (iop->sensep && (ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0) {
1354  if (scsi_debugmode)
1355  pout(" sense_len=0x%x, sense_resid=0x%x\n",
1356  ccb->csio.sense_len, ccb->csio.sense_resid);
1357  iop->resp_sense_len = ccb->csio.sense_len - ccb->csio.sense_resid;
1358  /* Some SCSI controller device drivers miscalculate the sense_resid
1359  field so cap resp_sense_len on max_sense_len. */
1360  if (iop->resp_sense_len > iop->max_sense_len)
1361  iop->resp_sense_len = iop->max_sense_len;
1362  if (iop->resp_sense_len > 0) {
1363  memcpy(iop->sensep, &(ccb->csio.sense_data), iop->resp_sense_len);
1364  if (scsi_debugmode) {
1365  if (scsi_debugmode > 1) {
1366  pout(" >>> Sense buffer, len=%zu:\n", iop->resp_sense_len);
1367  dStrHex(iop->sensep, iop->resp_sense_len, 1);
1368  }
1369  if ((iop->sensep[0] & 0x7f) > 0x71)
1370  pout(" status=0x%x: [desc] sense_key=0x%x asc=0x%x ascq=0x%x\n",
1371  iop->scsi_status, iop->sensep[1] & 0xf,
1372  iop->sensep[2], iop->sensep[3]);
1373  else
1374  pout(" status=0x%x: sense_key=0x%x asc=0x%x ascq=0x%x\n",
1375  iop->scsi_status, iop->sensep[2] & 0xf,
1376  iop->sensep[12], iop->sensep[13]);
1377  }
1378  }
1379  else if (scsi_debugmode)
1380  pout(" status=0x%x\n", iop->scsi_status);
1381  }
1382  else if (scsi_debugmode)
1383  pout(" status=0x%x\n", iop->scsi_status);
1384 
1385  cam_freeccb(ccb);
1386 
1387  // mfip replacing PDT of the device so response does not make a sense
1388  // this sets PDT to 00h - direct-access block device
1389  if((!strcmp("mfi", m_camdev->sim_name) || !strcmp("mpt", m_camdev->sim_name))
1390  && iop->cmnd[0] == INQUIRY) {
1391  if (scsi_debugmode) {
1392  pout(" device on %s controller, patching PDT\n", m_camdev->sim_name);
1393  }
1394  iop->dxferp[0] = iop->dxferp[0] & 0xe0;
1395  }
1396 
1397  return true;
1398 }
1399 
1400 
1401 /////////////////////////////////////////////////////////////////////////////
1402 /// Areca RAID support
1403 
1404 ///////////////////////////////////////////////////////////////////
1405 // SATA(ATA) device behind Areca RAID Controller
1407 : public /*implements*/ areca_ata_device,
1408  public /*extends*/ freebsd_smart_device
1409 {
1410 public:
1411  freebsd_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
1412  virtual smart_device * autodetect_open() override;
1413  virtual bool arcmsr_lock() override;
1414  virtual bool arcmsr_unlock() override;
1415  virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop) override;
1416 };
1417 
1418 ///////////////////////////////////////////////////////////////////
1419 // SAS(SCSI) device behind Areca RAID Controller
1421 : public /*implements*/ areca_scsi_device,
1422  public /*extends*/ freebsd_smart_device
1423 {
1424 public:
1425  freebsd_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
1426  virtual smart_device * autodetect_open() override;
1427  virtual bool arcmsr_lock() override;
1428  virtual bool arcmsr_unlock() override;
1429  virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop) override;
1430 };
1431 
1432 
1433 // Areca RAID Controller(SATA Disk)
1434 freebsd_areca_ata_device::freebsd_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
1435 : smart_device(intf, dev_name, "areca", "areca"),
1437 {
1438  set_disknum(disknum);
1439  set_encnum(encnum);
1440  set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
1441 }
1442 
1443 
1445 {
1446  // autodetect device type
1447  int is_ata = arcmsr_get_dev_type();
1448  if(is_ata < 0)
1449  {
1450  set_err(EIO);
1451  return this;
1452  }
1453 
1454  if(is_ata == 1)
1455  {
1456  // SATA device
1457  return this;
1458  }
1459 
1460  // SAS device
1462  close();
1463  delete this;
1464  newdev->open(); // TODO: Can possibly pass open fd
1465 
1466  return newdev.release();
1467 }
1468 
1470 {
1471  int ioctlreturn = 0;
1472 
1473  if(!is_open()) {
1474  if(!open()){
1475  }
1476  }
1477 
1478  ioctlreturn = ioctl(get_fd(), ((sSRB_BUFFER *)(iop->dxferp))->srbioctl.ControlCode, iop->dxferp);
1479  if (ioctlreturn)
1480  {
1481  // errors found
1482  return -1;
1483  }
1484  return 0;
1485 }
1486 
1488 {
1489  return true;
1490 }
1491 
1492 
1494 {
1495  return true;
1496 }
1497 
1498 
1499 // Areca RAID Controller(SAS Device)
1500 freebsd_areca_scsi_device::freebsd_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
1501 : smart_device(intf, dev_name, "areca", "areca"),
1503 {
1504  set_disknum(disknum);
1505  set_encnum(encnum);
1506  set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
1507 }
1508 
1510 {
1511  return this;
1512 }
1513 
1515 {
1516  int ioctlreturn = 0;
1517 
1518  if(!is_open()) {
1519  if(!open()){
1520  }
1521  }
1522  ioctlreturn = ioctl(get_fd(), ((sSRB_BUFFER *)(iop->dxferp))->srbioctl.ControlCode, iop->dxferp);
1523  if (ioctlreturn)
1524  {
1525  // errors found
1526  return -1;
1527  }
1528 
1529  return 0;
1530 }
1531 
1533 {
1534  return true;
1535 }
1536 
1537 
1539 {
1540  return true;
1541 }
1542 
1543 
1544 /////////////////////////////////////////////////////////////////////////////
1545 /// Implement CCISS RAID support with old functions
1546 
1548 : public /*implements*/ scsi_device,
1549  public /*extends*/ freebsd_smart_device
1550 {
1551 public:
1552  freebsd_cciss_device(smart_interface * intf, const char * name, unsigned char disknum);
1553 
1554  virtual bool scsi_pass_through(scsi_cmnd_io * iop) override;
1555  virtual bool open() override;
1556 
1557 private:
1558  unsigned char m_disknum; ///< Disk number.
1559 };
1560 
1562 {
1563  const char *dev = get_dev_name();
1564  int fd;
1565  if ((fd = ::open(dev,O_RDWR))<0) {
1566  set_err(errno);
1567  return false;
1568  }
1569  set_fd(fd);
1570  return true;
1571 }
1572 
1574  const char * dev_name, unsigned char disknum)
1575 : smart_device(intf, dev_name, "cciss", "cciss"),
1577  m_disknum(disknum)
1578 {
1579  set_info().info_name = strprintf("%s [cciss_disk_%02d]", dev_name, disknum);
1580 }
1581 
1583 {
1584  int status = cciss_io_interface(get_fd(), m_disknum, iop, scsi_debugmode);
1585  if (status < 0)
1586  return set_err(-status);
1587  return true;
1588  // not reached
1589  return true;
1590 }
1591 
1592 
1593 /////////////////////////////////////////////////////////////////////////////
1594 /// SCSI open with autodetection support
1595 
1597 {
1598  // Open device
1599  if (!open())
1600  return this;
1601 
1602  // No Autodetection if device type was specified by user
1603  if (*get_req_type())
1604  return this;
1605 
1606  // The code below is based on smartd.cpp:SCSIFilterKnown()
1607 
1608  // Get INQUIRY
1609  unsigned char req_buff[64] = {0, };
1610  int req_len = 36;
1611  if (scsiStdInquiry(this, req_buff, req_len)) {
1612  // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices
1613  // watch this spot ... other devices could lock up here
1614  req_len = 64;
1615  if (scsiStdInquiry(this, req_buff, req_len)) {
1616  // device doesn't like INQUIRY commands
1617  close();
1618  set_err(EIO, "INQUIRY failed");
1619  return this;
1620  }
1621  }
1622 
1623  int avail_len = req_buff[4] + 5;
1624  int len = (avail_len < req_len ? avail_len : req_len);
1625  if (len < 36)
1626  return this;
1627 
1628  // Use INQUIRY to detect type
1629 
1630  // 3ware ?
1631  if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4) ||
1632  !strcmp("tws",m_camdev->sim_name) || !strcmp("twa",m_camdev->sim_name)) {
1633  close();
1634  set_err(EINVAL, "3ware/LSI controller, please try adding '-d 3ware,N',\n"
1635  "you may need to replace %s with /dev/twaN, /dev/tweN or /dev/twsN", get_dev_name());
1636  return this;
1637  }
1638 
1639  // DELL?
1640  if (!memcmp(req_buff + 8, "DELL PERC", 12) || !memcmp(req_buff + 8, "MegaRAID", 8)
1641  || !memcmp(req_buff + 16, "PERC ", 5) || !memcmp(req_buff + 8, "LSI\0",4)
1642  ) {
1643  close();
1644  set_err(EINVAL, "DELL or MegaRaid controller, use '-d megaraid,N'");
1645  return this;
1646  }
1647 
1648  // SAT or USB, skip MFI controllers because of bugs
1649  {
1650  smart_device * newdev = smi()->autodetect_sat_device(this, req_buff, len);
1651  if (newdev) {
1652  // NOTE: 'this' is now owned by '*newdev'
1653  if(!strcmp("mfi",m_camdev->sim_name)) {
1654  newdev->close();
1655  newdev->set_err(ENOSYS, "SATA device detected,\n"
1656  "MegaRAID SAT layer is reportedly buggy, use '-d sat' to try anyhow");
1657  }
1658  return newdev;
1659  }
1660  }
1661 
1662  // Nothing special found
1663  return this;
1664 }
1665 
1666 
1667 /////////////////////////////////////////////////////////////////////////////
1668 /// Implement platform interface with old functions.
1669 
1671 : public /*implements*/ smart_interface
1672 {
1673 public:
1674  virtual std::string get_os_version_str() override;
1675 
1676  virtual std::string get_app_examples(const char * appname) override;
1677 
1678  virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
1679  const char * pattern = 0) override;
1680 
1681 protected:
1682  virtual ata_device * get_ata_device(const char * name, const char * type) override;
1683 
1684 #if FREEBSDVER > 800100
1685  virtual ata_device * get_atacam_device(const char * name, const char * type);
1686 #endif
1687 
1688  virtual scsi_device * get_scsi_device(const char * name, const char * type) override;
1689 
1690  virtual nvme_device * get_nvme_device(const char * name, const char * type,
1691  unsigned nsid) override;
1692 
1693  virtual smart_device * autodetect_smart_device(const char * name) override;
1694 
1695  virtual smart_device * get_custom_smart_device(const char * name, const char * type) override;
1696 
1697  virtual std::string get_valid_custom_dev_types_str() override;
1698 private:
1699  bool get_nvme_devlist(smart_device_list & devlist, const char * type);
1700  bool get_dev_megaraid(smart_device_list & devlist);
1701  int megaraid_pd_add_list(const char * devname, smart_device_list & devlist);
1702  int megaraid_dcmd_cmd(const char * devname, uint32_t opcode, void *buf,
1703  size_t bufsize, uint8_t *mbox, size_t mboxlen, uint8_t *statusp);
1704 };
1705 
1706 
1707 //////////////////////////////////////////////////////////////////////
1708 
1710 {
1711  struct utsname osname;
1712  uname(&osname);
1713  return strprintf("%s %s %s", osname.sysname, osname.release, osname.machine);
1714 }
1715 
1716 std::string freebsd_smart_interface::get_app_examples(const char * appname)
1717 {
1718  if (!strcmp(appname, "smartctl"))
1719  return smartctl_examples;
1720  return "";
1721 }
1722 
1723 ata_device * freebsd_smart_interface::get_ata_device(const char * name, const char * type)
1724 {
1725  return new freebsd_ata_device(this, name, type);
1726 }
1727 
1728 #if FREEBSDVER > 800100
1729 ata_device * freebsd_smart_interface::get_atacam_device(const char * name, const char * type)
1730 {
1731  return new freebsd_atacam_device(this, name, type);
1732 }
1733 #endif
1734 
1735 scsi_device * freebsd_smart_interface::get_scsi_device(const char * name, const char * type)
1736 {
1737  return new freebsd_scsi_device(this, name, type);
1738 }
1739 
1740 nvme_device * freebsd_smart_interface::get_nvme_device(const char * name, const char * type,
1741  unsigned nsid)
1742 {
1743  return new freebsd_nvme_device(this, name, type, nsid);
1744 }
1745 
1746 // we are using CAM subsystem XPT enumerator to found all CAM (scsi/usb/ada/...)
1747 // devices on system despite of it's names
1748 //
1749 // If any errors occur, leave errno set as it was returned by the
1750 // system call, and return <0.
1751 //
1752 // arguments:
1753 // names: resulting array
1754 // show_all - export duplicate device name or not
1755 //
1756 // Return values:
1757 // -1: error
1758 // >=0: number of discovered devices
1759 
1760 bool get_dev_names_cam(std::vector<std::string> & names, bool show_all)
1761 {
1762  int fd;
1763  if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
1764  if (errno == ENOENT) /* There are no CAM device on this computer */
1765  return 0;
1766  int serrno = errno;
1767  pout("%s control device couldn't opened: %s\n", XPT_DEVICE, strerror(errno));
1768  errno = serrno;
1769  return false;
1770  }
1771 
1772  union ccb ccb;
1773  memset(&ccb, 0, sizeof(union ccb));
1774 
1775  ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
1776  ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1777  ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1778 
1779  ccb.ccb_h.func_code = XPT_DEV_MATCH;
1780  int bufsize = sizeof(struct dev_match_result) * MAX_NUM_DEV;
1781  ccb.cdm.match_buf_len = bufsize;
1782  // TODO: Use local buffer instead of malloc() if possible
1783  ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
1784  memset(ccb.cdm.matches, 0, bufsize); // clear ccb.cdm.matches structure
1785 
1786  if (ccb.cdm.matches == NULL) {
1787  close(fd);
1788  throw std::bad_alloc();
1789  }
1790  ccb.cdm.num_matches = 0;
1791  ccb.cdm.num_patterns = 0;
1792  ccb.cdm.pattern_buf_len = 0;
1793 
1794  /*
1795  * We do the ioctl multiple times if necessary, in case there are
1796  * more than MAX_NUM_DEV nodes in the EDT.
1797  */
1798  int skip_device = 0, skip_bus = 0, changed = 0; // TODO: bool
1799  std::string devname;
1800  do {
1801  if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1802  int serrno = errno;
1803  pout("error sending CAMIOCOMMAND ioctl: %s\n", strerror(errno));
1804  free(ccb.cdm.matches);
1805  close(fd);
1806  errno = serrno;
1807  return false;
1808  }
1809 
1810  if ((ccb.ccb_h.status != CAM_REQ_CMP)
1811  || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
1812  && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
1813  pout("got CAM error %#x, CDM error %d\n", ccb.ccb_h.status, ccb.cdm.status);
1814  free(ccb.cdm.matches);
1815  close(fd);
1816  errno = ENXIO;
1817  return false;
1818  }
1819 
1820  for (unsigned i = 0; i < ccb.cdm.num_matches; i++) {
1821  struct device_match_result *dev_result;
1822  struct periph_match_result *periph_result;
1823 
1824  if (ccb.cdm.matches[i].type == DEV_MATCH_BUS) {
1825  struct bus_match_result *bus_result;
1826 
1827  bus_result = &ccb.cdm.matches[i].result.bus_result;
1828 
1829  if (strcmp(bus_result->dev_name,"xpt") == 0) /* skip XPT bus at all */
1830  skip_bus = 1;
1831  else
1832  skip_bus = 0;
1833  changed = 1;
1834  } else if (ccb.cdm.matches[i].type == DEV_MATCH_DEVICE) {
1835  dev_result = &ccb.cdm.matches[i].result.device_result;
1836 
1837  if (dev_result->flags & DEV_RESULT_UNCONFIGURED || skip_bus == 1)
1838  skip_device = 1;
1839  else
1840  skip_device = 0;
1841 
1842  // skip ses devices
1843  if (dev_result->inq_data.device == T_ENCLOSURE)
1844  skip_device = 1;
1845 
1846  // /* Shall we skip non T_DIRECT devices ? */
1847  // if (dev_result->inq_data.device != T_DIRECT)
1848  // skip_device = 1;
1849  changed = 1;
1850  } else if (ccb.cdm.matches[i].type == DEV_MATCH_PERIPH &&
1851  (skip_device == 0 || show_all)) {
1852  /* One device may be populated as many peripherals (pass0 & da0 for example).
1853  * We are searching for best name
1854  */
1855  periph_result = &ccb.cdm.matches[i].result.periph_result;
1856  /* Prefer non-"pass" names */
1857  if (devname.empty() || strncmp(periph_result->periph_name, "pass", 4) != 0) {
1858  devname = strprintf("%s%s%d", _PATH_DEV, periph_result->periph_name, periph_result->unit_number);
1859  }
1860  changed = 0;
1861  };
1862  if ((changed == 1 || show_all) && !devname.empty()) {
1863  names.push_back(devname);
1864  devname.erase();
1865  changed = 0;
1866  };
1867  }
1868 
1869  } while ((ccb.ccb_h.status == CAM_REQ_CMP) && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
1870 
1871  if (!devname.empty())
1872  names.push_back(devname);
1873 
1874  free(ccb.cdm.matches);
1875  close(fd);
1876  return true;
1877 }
1878 
1879 // we are using ATA subsystem enumerator to found all ATA devices on system
1880 // despite of it's names
1881 //
1882 // If any errors occur, leave errno set as it was returned by the
1883 // system call, and return <0.
1884 
1885 // Return values:
1886 // -1: error
1887 // >=0: number of discovered devices
1888 int get_dev_names_ata(char*** names) {
1889  struct ata_ioc_devices devices;
1890  int fd=-1,maxchannel,serrno=-1,n=0;
1891  char **mp = NULL;
1892 
1893  *names=NULL;
1894 
1895  if ((fd = open(ATA_DEVICE, O_RDWR)) < 0) {
1896  if (errno == ENOENT) /* There are no ATA device on this computer */
1897  return 0;
1898  serrno = errno;
1899  pout("%s control device can't be opened: %s\n", ATA_DEVICE, strerror(errno));
1900  n = -1;
1901  goto end;
1902  };
1903 
1904  if (ioctl(fd, IOCATAGMAXCHANNEL, &maxchannel) < 0) {
1905  serrno = errno;
1906  pout("ioctl(IOCATAGMAXCHANNEL) on /dev/ata failed: %s\n", strerror(errno));
1907  n = -1;
1908  goto end;
1909  };
1910 
1911  // allocate space for up to MAX_NUM_DEV number of ATA devices
1912  mp = (char **)calloc(MAX_NUM_DEV, sizeof(char*));
1913  if (mp == NULL) {
1914  serrno=errno;
1915  pout("Out of memory constructing scan device list (on line %d)\n", __LINE__);
1916  n = -1;
1917  goto end;
1918  };
1919 
1920  for (devices.channel = 0; devices.channel < maxchannel && n < MAX_NUM_DEV; devices.channel++) {
1921  int j;
1922 
1923  if (ioctl(fd, IOCATADEVICES, &devices) < 0) {
1924  if (errno == ENXIO)
1925  continue; /* such channel not exist */
1926  pout("ioctl(IOCATADEVICES) on %s channel %d failed: %s\n", ATA_DEVICE, devices.channel, strerror(errno));
1927  n = -1;
1928  goto end;
1929  };
1930  for (j=0;j<=1 && n<MAX_NUM_DEV;j++) {
1931  if (devices.name[j][0] != '\0') {
1932  asprintf(mp+n, "%s%s", _PATH_DEV, devices.name[j]);
1933  if (mp[n] == NULL) {
1934  pout("Out of memory constructing scan ATA device list (on line %d)\n", __LINE__);
1935  n = -1;
1936  goto end;
1937  };
1938  n++;
1939  };
1940  };
1941  };
1942  if (n <= 0)
1943  goto end;
1944  mp = (char **)reallocf(mp,n*(sizeof (char*))); // shrink to correct size
1945  if (mp == NULL) {
1946  serrno=errno;
1947  pout("Out of memory constructing scan device list (on line %d)\n", __LINE__);
1948  n = -1;
1949  goto end;
1950  };
1951 
1952 end:
1953  if (fd>=0)
1954  close(fd);
1955  if (n <= 0) {
1956  free(mp);
1957  mp = NULL;
1958  }
1959 
1960  *names=mp;
1961 
1962  if (serrno>-1)
1963  errno=serrno;
1964  return n;
1965 }
1966 
1967 
1968 
1970  const char * type, const char * pattern /*= 0*/)
1971 {
1972  if (pattern) {
1973  set_err(EINVAL, "DEVICESCAN with pattern not implemented yet");
1974  return false;
1975  }
1976 
1977 #ifdef WITH_NVME_DEVICESCAN // TODO: Remove when NVMe support is no longer EXPERIMENTAL
1978  bool scan_nvme = !type || !strcmp(type, "nvme");
1979 #else
1980  bool scan_nvme = type && !strcmp(type, "nvme");
1981 #endif
1982 
1983  // Make namelists
1984  char * * atanames = 0; int numata = 0;
1985  if (!type || !strcmp(type, "ata")) {
1986  numata = get_dev_names_ata(&atanames);
1987  if (numata < 0) {
1988  set_err(ENOMEM);
1989  return false;
1990  }
1991  }
1992 
1993  std::vector<std::string> scsinames;
1994  if (!type || !strcmp(type, "scsi")) { // do not export duplicated names
1995  if (!get_dev_names_cam(scsinames, false)) {
1996  set_err(errno);
1997  return false;
1998  }
1999  }
2000 
2001  // Add to devlist
2002  int i;
2003  if (type==NULL)
2004  type="";
2005  for (i = 0; i < numata; i++) {
2006  ata_device * atadev = get_ata_device(atanames[i], type);
2007  if (atadev)
2008  devlist.push_back(atadev);
2009  free(atanames[i]);
2010  }
2011  if(numata) free(atanames);
2012 
2013  for (i = 0; i < (int)scsinames.size(); i++) {
2014  if(!*type) { // try USB autodetection if no type specified
2015  smart_device * smartdev = autodetect_smart_device(scsinames[i].c_str());
2016  if(smartdev)
2017  devlist.push_back(smartdev);
2018  }
2019  else {
2020  scsi_device * scsidev = get_scsi_device(scsinames[i].c_str(), type);
2021  if (scsidev)
2022  devlist.push_back(scsidev);
2023  }
2024  }
2025 
2026  // add devices from LSI MegaRaid controllers
2027  get_dev_megaraid(devlist);
2028 
2029  if (scan_nvme)
2030  get_nvme_devlist(devlist, type);
2031  return true;
2032 }
2033 
2035  const char * type)
2036 {
2037  char ctrlpath[64];
2038 
2039  for (int ctrlr = 0;; ctrlr++) {
2040  sprintf(ctrlpath, "%s%d", NVME_CTRLR_PREFIX, ctrlr);
2041  int fd = ::open(ctrlpath, O_RDWR);
2042  if (fd < 0)
2043  break;
2044  ::close(fd);
2045  nvme_device * nvmedev = get_nvme_device(ctrlpath, type, 0);
2046  if (nvmedev)
2047  devlist.push_back(nvmedev);
2048  else
2049  break;
2050  }
2051  return true;
2052 }
2053 
2054 // getting devices from LSI SAS MegaRaid, if available
2056 {
2057  /* Scanning of disks on MegaRaid device */
2058  char ctrlpath[64];
2059 
2060  // trying to add devices on first 32 buses, same as StorCLI does
2061  for(unsigned i = 0; i <=32; i++) {
2062  sprintf(ctrlpath, "%s%u", MFI_CTRLR_PREFIX, i);
2063  megaraid_pd_add_list(ctrlpath, devlist);
2064  sprintf(ctrlpath, "%s%u", MRSAS_CTRLR_PREFIX, i);
2065  megaraid_pd_add_list(ctrlpath, devlist);
2066  }
2067  return true;
2068 }
2069 
2070 int
2071 freebsd_smart_interface::megaraid_dcmd_cmd(const char * devname, uint32_t opcode, void *buf,
2072  size_t bufsize, uint8_t *mbox, size_t mboxlen, uint8_t *statusp)
2073 {
2074  struct mfi_ioc_packet ioc;
2075  struct mfi_dcmd_frame * dcmd;
2076 
2077  if ((mbox != NULL && (mboxlen == 0 || mboxlen > MFI_MBOX_SIZE)) ||
2078  (mbox == NULL && mboxlen != 0))
2079  {
2080  errno = EINVAL;
2081  return (-1);
2082  }
2083 
2084  memset(&ioc, 0, sizeof(ioc));
2085  dcmd = (struct mfi_dcmd_frame *)&ioc.mfi_frame.raw;
2086 
2087  if (mbox)
2088  memcpy(dcmd->mbox, mbox, mboxlen);
2089  dcmd->header.cmd = MFI_CMD_DCMD;
2090  dcmd->header.data_len = bufsize;
2091  dcmd->opcode = opcode;
2092 
2093  if (bufsize > 0) {
2094  ioc.mfi_sge_count = 1;
2095  ioc.mfi_sgl_off = offsetof(struct mfi_dcmd_frame,sgl);
2096  ioc.mfi_sgl[0].iov_base = buf;
2097  ioc.mfi_sgl[0].iov_len = bufsize;
2098  dcmd->header.sg_count = 1;
2099  dcmd->header.data_len = bufsize;
2100  // tested on amd64 kernel in native and 32bit mode
2101  dcmd->sgl.sg64[0].addr = (intptr_t)buf;
2102  dcmd->sgl.sg64[0].len = (uint32_t)bufsize;
2103  }
2104 
2105  int fd;
2106  if ((fd = ::open(devname, O_RDWR)) < 0) {
2107  return (errno);
2108  }
2109  // We are using MFI_CMD as it seems to be supported by all LSI BSD drivers
2110  int r = ioctl(fd, MFI_CMD, &ioc);
2111  ::close(fd);
2112  if (r < 0) {
2113  return (r);
2114  }
2115 
2116  if (statusp != NULL)
2117  *statusp = dcmd->header.cmd_status;
2118  else if (dcmd->header.cmd_status != MFI_STAT_OK) {
2119  fprintf(stderr, "command %x returned error status %x\n",
2120  opcode, dcmd->header.cmd_status);
2121  errno = EIO;
2122  return (-1);
2123  }
2124  return (0);
2125 }
2126 
2127 int
2129 {
2130  /*
2131  * Keep fetching the list in a loop until we have a large enough
2132  * buffer to hold the entire list.
2133  */
2134  mfi_pd_list * list = 0;
2135  for (unsigned list_size = 1024; ; ) {
2136  list = reinterpret_cast<mfi_pd_list *>(realloc(list, list_size));
2137  if (!list)
2138  throw std::bad_alloc();
2139  memset(list, 0, list_size);
2140  if (megaraid_dcmd_cmd(devname, MFI_DCMD_PD_GET_LIST, list, list_size, NULL, 0,
2141  NULL) < 0)
2142  {
2143  free(list);
2144  return (-1);
2145  }
2146  if (list->size <= list_size)
2147  break;
2148  list_size = list->size;
2149  }
2150 
2151  // adding all SCSI devices
2152  for (unsigned i = 0; i < list->count; i++) {
2153  if(list->addr[i].scsi_dev_type)
2154  continue; /* non disk device found */
2155  smart_device * dev = new freebsd_megaraid_device(this, devname, list->addr[i].device_id);
2156  devlist.push_back(dev);
2157  }
2158  free(list);
2159  return (0);
2160 }
2161 
2162 #if (FREEBSDVER < 800000) // without this build fail on FreeBSD 8
2163 static char done[USB_MAX_DEVICES];
2164 
2165 static int usbdevinfo(int f, int a, int rec, int busno, unsigned short & vendor_id,
2166  unsigned short & product_id, unsigned short & version)
2167 {
2168 
2169  struct usb_device_info di;
2170  int e, p, i;
2171  char devname[256];
2172 
2173  snprintf(devname, sizeof(devname),"umass%d",busno);
2174 
2175  di.udi_addr = a;
2176  e = ioctl(f, USB_DEVICEINFO, &di);
2177  if (e) {
2178  if (errno != ENXIO)
2179  printf("addr %d: I/O error\n", a);
2180  return 0;
2181  }
2182  done[a] = 1;
2183 
2184  // list devices
2185  for (i = 0; i < USB_MAX_DEVNAMES; i++) {
2186  if (di.udi_devnames[i][0]) {
2187  if(strcmp(di.udi_devnames[i],devname)==0) {
2188  // device found!
2189  vendor_id = di.udi_vendorNo;
2190  product_id = di.udi_productNo;
2191  version = di.udi_releaseNo;
2192  return 1;
2193  // FIXME
2194  }
2195  }
2196  }
2197  if (!rec)
2198  return 0;
2199  for (p = 0; p < di.udi_nports; p++) {
2200  int s = di.udi_ports[p];
2201  if (s >= USB_MAX_DEVICES) {
2202  continue;
2203  }
2204  if (s == 0)
2205  printf("addr 0 should never happen!\n");
2206  else {
2207  if(usbdevinfo(f, s, 1, busno, vendor_id, product_id, version)) return 1;
2208  }
2209  }
2210  return 0;
2211 }
2212 #endif
2213 
2214 
2215 static int usbdevlist(int busno,unsigned short & vendor_id,
2216  unsigned short & product_id, unsigned short & version)
2217 {
2218 #if (FREEBSDVER >= 800000) // libusb2 interface
2219  struct libusb20_device *pdev = NULL;
2220  struct libusb20_backend *pbe;
2221  uint32_t matches = 0;
2222  char buf[128]; // do not change!
2223  char devname[128];
2224  uint8_t n;
2225  struct LIBUSB20_DEVICE_DESC_DECODED *pdesc;
2226 
2227  pbe = libusb20_be_alloc_default();
2228 
2229  while ((pdev = libusb20_be_device_foreach(pbe, pdev))) {
2230  matches++;
2231 
2232  if (libusb20_dev_open(pdev, 0)) {
2233  warnx("libusb20_dev_open: could not open device");
2234  return 0;
2235  }
2236 
2237  pdesc=libusb20_dev_get_device_desc(pdev);
2238 
2239  snprintf(devname, sizeof(devname),"umass%d:",busno);
2240  for (n = 0; n != 255; n++) {
2241  if (libusb20_dev_get_iface_desc(pdev, n, buf, sizeof(buf)))
2242  break;
2243  if (buf[0] == 0)
2244  continue;
2245  if(strncmp(buf,devname,strlen(devname))==0){
2246  // found!
2247  vendor_id = pdesc->idVendor;
2248  product_id = pdesc->idProduct;
2249  version = pdesc->bcdDevice;
2250  libusb20_dev_close(pdev);
2251  libusb20_be_free(pbe);
2252  return 1;
2253  }
2254  }
2255 
2256  libusb20_dev_close(pdev);
2257  }
2258 
2259  if (matches == 0) {
2260  printf("No device match or lack of permissions.\n");
2261  }
2262 
2263  libusb20_be_free(pbe);
2264 
2265  return false;
2266 #else // freebsd < 8.0 USB stack, ioctl interface
2267 
2268  int i, a, rc;
2269  char buf[50];
2270  int ncont;
2271 
2272  for (ncont = 0, i = 0; i < 10; i++) {
2273  snprintf(buf, sizeof(buf), "%s%d", USBDEV, i);
2274  int f = open(buf, O_RDONLY);
2275  if (f >= 0) {
2276  memset(done, 0, sizeof done);
2277  for (a = 1; a < USB_MAX_DEVICES; a++) {
2278  if (!done[a]) {
2279  rc = usbdevinfo(f, a, 1, busno,vendor_id, product_id, version);
2280  if(rc) return 1;
2281  }
2282 
2283  }
2284  close(f);
2285  } else {
2286  if (errno == ENOENT || errno == ENXIO)
2287  continue;
2288  warn("%s", buf);
2289  }
2290  ncont++;
2291  }
2292  return 0;
2293 #endif
2294 }
2295 
2297 {
2298  unsigned short vendor_id = 0, product_id = 0, version = 0;
2299  struct cam_device *cam_dev;
2300  union ccb ccb;
2301  int i;
2302  const char * test_name = name;
2303 
2304  memset(&ccb, 0, sizeof(ccb));
2305 
2306  // if dev_name null, or string length zero
2307  if (!name || !*name)
2308  return 0;
2309 
2310  // Dereference symlinks
2311  struct stat st;
2312  std::string pathbuf;
2313  if (!lstat(name, &st) && S_ISLNK(st.st_mode)) {
2314  char * p = realpath(name, (char *)0);
2315  if (p) {
2316  pathbuf = p;
2317  free(p);
2318  test_name = pathbuf.c_str();
2319  }
2320  }
2321 
2322  // check ATA bus
2323  char * * atanames = 0; int numata = 0;
2324  numata = get_dev_names_ata(&atanames);
2325  if (numata > 0) {
2326  // check ATA/ATAPI devices
2327  for (i = 0; i < numata; i++) {
2328  if(!strcmp(atanames[i],test_name)) {
2329  for (int c = i; c < numata; c++) free(atanames[c]);
2330  free(atanames);
2331  return new freebsd_ata_device(this, test_name, "");
2332  }
2333  else free(atanames[i]);
2334  }
2335  free(atanames);
2336  }
2337  else {
2338  if (numata < 0)
2339  pout("Unable to get ATA device list\n");
2340  }
2341 
2342  // check CAM
2343  std::vector<std::string> scsinames;
2344  if (!get_dev_names_cam(scsinames, true))
2345  pout("Unable to get CAM device list\n");
2346  else if (!scsinames.empty()) {
2347  // check all devices on CAM bus
2348  for (i = 0; i < (int)scsinames.size(); i++) {
2349  if(strcmp(scsinames[i].c_str(), test_name)==0)
2350  { // our disk device is CAM
2351  if(strncmp(scsinames[i].c_str(), "/dev/pmp", strlen("/dev/pmp")) == 0) {
2352  pout("Skipping port multiplier [%s]\n", scsinames[i].c_str());
2353  set_err(EINVAL);
2354  return 0;
2355  }
2356  if ((cam_dev = cam_open_device(test_name, O_RDWR)) == NULL) {
2357  // open failure
2358  set_err(errno);
2359  return 0;
2360  }
2361  // zero the payload
2362  memset(&(&ccb.ccb_h)[1], 0, PATHINQ_SETTINGS_SIZE);
2363  ccb.ccb_h.func_code = XPT_PATH_INQ; // send PATH_INQ to the device
2364  if (ioctl(cam_dev->fd, CAMIOCOMMAND, &ccb) == -1) {
2365  warn("Get Transfer Settings CCB failed\n"
2366  "%s", strerror(errno));
2367  cam_close_device(cam_dev);
2368  return 0;
2369  }
2370  // now check if we are working with USB device, see umass.c
2371  if(strcmp(ccb.cpi.dev_name,"umass-sim") == 0) { // USB device found
2372  int bus=ccb.cpi.unit_number; // unit_number will match umass number
2373  cam_close_device(cam_dev);
2374  if(usbdevlist(bus,vendor_id, product_id, version)){
2375  const char * usbtype = get_usb_dev_type_by_id(vendor_id, product_id, version);
2376  if (usbtype)
2377  return get_scsi_passthrough_device(usbtype, new freebsd_scsi_device(this, test_name, ""));
2378  }
2379  return 0;
2380  }
2381 #if FREEBSDVER > 800100
2382  // check if we have ATA device connected to CAM (ada)
2383  if(ccb.cpi.protocol == PROTO_ATA){
2384  cam_close_device(cam_dev);
2385  return new freebsd_atacam_device(this, test_name, "");
2386  }
2387 #endif
2388  // close cam device, we don`t need it anymore
2389  cam_close_device(cam_dev);
2390  // handle as usual scsi
2391  return new freebsd_scsi_device(this, test_name, "");
2392  }
2393  }
2394  }
2395  // device is LSI raid supported by mfi driver
2396  if(!strncmp("/dev/mfid", test_name, strlen("/dev/mfid"))) {
2397  set_err(EINVAL, "To access disks on LSI RAID load mfip.ko and use /dev/passX or use -d 'megaraid,N' with /dev/mfiX devices");
2398  return 0;
2399  }
2400 
2401  if(!strncmp(MFI_CTRLR_PREFIX, test_name, strlen(MFI_CTRLR_PREFIX)) || !strncmp(MRSAS_CTRLR_PREFIX, test_name, strlen(MRSAS_CTRLR_PREFIX))) {
2402  set_err(EINVAL, "To access disks on %s use '-d megaraid,N' device type", test_name);
2403  return 0;
2404  }
2405 
2406  // form /dev/nvme* or nvme*
2407  if(!strncmp("/dev/nvme", test_name, strlen("/dev/nvme")))
2408  return new freebsd_nvme_device(this, name, "", 0 /* use default nsid */);
2409  if(!strncmp("/dev/nvd", test_name, strlen("/dev/nvd")))
2410  set_err(EINVAL, "To monitor NVMe disks use /dev/nvme* device names");
2411 
2412  // device type unknown
2413  return 0;
2414 }
2415 
2416 
2418 {
2419  int disknum = -1, n1 = -1, n2 = -1;
2420 
2421  if (sscanf(type, "3ware,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
2422  // 3Ware ?
2423  static const char * fbsd_dev_twe_ctrl = "/dev/twe";
2424  static const char * fbsd_dev_twa_ctrl = "/dev/twa";
2425  static const char * fbsd_dev_tws_ctrl = "/dev/tws";
2426  int contr = -1;
2427 
2428  if (n2 != (int)strlen(type)) {
2429  set_err(EINVAL, "Option -d 3ware,N requires N to be a non-negative integer");
2430  return 0;
2431  }
2432  if (!(0 <= disknum && disknum <= 127)) {
2433  set_err(EINVAL, "Option -d 3ware,N (N=%d) must have 0 <= N <= 127", disknum);
2434  return 0;
2435  }
2436 
2437  // guess 3ware device type based on device name
2438  if (str_starts_with(name, fbsd_dev_twa_ctrl) ||
2439  str_starts_with(name, fbsd_dev_tws_ctrl) ) {
2441  }
2442  if (!strncmp(fbsd_dev_twe_ctrl, name, strlen(fbsd_dev_twe_ctrl))){
2444  }
2445 
2446  if(contr == -1){
2447  set_err(EINVAL, "3ware controller type unknown, use %sX, %sX or %sX devices",
2448  fbsd_dev_twe_ctrl, fbsd_dev_twa_ctrl, fbsd_dev_tws_ctrl);
2449  return 0;
2450  }
2451  return new freebsd_escalade_device(this, name, contr, disknum);
2452  }
2453 
2454  // Highpoint ?
2455  int controller = -1, channel = -1; disknum = 1;
2456  n1 = n2 = -1; int n3 = -1;
2457  if (sscanf(type, "hpt,%n%d/%d%n/%d%n", &n1, &controller, &channel, &n2, &disknum, &n3) >= 2 || n1 == 4) {
2458  int len = strlen(type);
2459  if (!(n2 == len || n3 == len)) {
2460  set_err(EINVAL, "Option '-d hpt,L/M/N' supports 2-3 items");
2461  return 0;
2462  }
2463  if (!(1 <= controller && controller <= 8)) {
2464  set_err(EINVAL, "Option '-d hpt,L/M/N' invalid controller id L supplied");
2465  return 0;
2466  }
2467  if (!(1 <= channel && channel <= 128)) {
2468  set_err(EINVAL, "Option '-d hpt,L/M/N' invalid channel number M supplied");
2469  return 0;
2470  }
2471  if (!(1 <= disknum && disknum <= 15)) {
2472  set_err(EINVAL, "Option '-d hpt,L/M/N' invalid pmport number N supplied");
2473  return 0;
2474  }
2475  return new freebsd_highpoint_device(this, name, controller, channel, disknum);
2476  }
2477 
2478  // CCISS ?
2479  disknum = n1 = n2 = -1;
2480  if (sscanf(type, "cciss,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
2481  if (n2 != (int)strlen(type)) {
2482  set_err(EINVAL, "Option -d cciss,N requires N to be a non-negative integer");
2483  return 0;
2484  }
2485  if (!(0 <= disknum && disknum <= 127)) {
2486  set_err(EINVAL, "Option -d cciss,N (N=%d) must have 0 <= N <= 127", disknum);
2487  return 0;
2488  }
2489  return get_sat_device("sat,auto", new freebsd_cciss_device(this, name, disknum));
2490  }
2491 #if FREEBSDVER > 800100
2492  // adaX devices ?
2493  if(!strcmp(type,"atacam"))
2494  return new freebsd_atacam_device(this, name, "");
2495 #endif
2496  // Areca?
2497  disknum = n1 = n2 = -1;
2498  int encnum = 1;
2499  if (sscanf(type, "areca,%n%d/%d%n", &n1, &disknum, &encnum, &n2) >= 1 || n1 == 6) {
2500  if (!(1 <= disknum && disknum <= 128)) {
2501  set_err(EINVAL, "Option -d areca,N/E (N=%d) must have 1 <= N <= 128", disknum);
2502  return 0;
2503  }
2504  if (!(1 <= encnum && encnum <= 8)) {
2505  set_err(EINVAL, "Option -d areca,N/E (E=%d) must have 1 <= E <= 8", encnum);
2506  return 0;
2507  }
2508  return new freebsd_areca_ata_device(this, name, disknum, encnum);
2509  }
2510 
2511  if (sscanf(type, "megaraid,%d", &disknum) == 1) {
2512  return new freebsd_megaraid_device(this, name, disknum);
2513  }
2514 
2515  return 0;
2516 }
2517 
2519 {
2520  return "3ware,N, hpt,L/M/N, cciss,N, areca,N/E, megaraid,N"
2521 #if FREEBSDVER > 800100
2522  ", atacam"
2523 #endif
2524  ;
2525 }
2526 
2527 } // namespace
2528 
2529 /////////////////////////////////////////////////////////////////////////////
2530 /// Initialize platform interface and register with smi()
2531 
2532 void smart_interface::init()
2533 {
2534  static os_freebsd::freebsd_smart_interface the_interface;
2535  smart_interface::set(&the_interface);
2536 }
#define ATA_SMART_AUTO_OFFLINE
Definition: atacmds.h:94
#define ATA_IDENTIFY_DEVICE
Definition: atacmds.h:53
#define ATA_SMART_WRITE_LOG_SECTOR
Definition: atacmds.h:87
#define ATA_IDENTIFY_PACKET_DEVICE
Definition: atacmds.h:54
#define ATA_SMART_STATUS
Definition: atacmds.h:91
#define ATA_SMART_READ_VALUES
Definition: atacmds.h:81
#define ATA_SMART_READ_THRESHOLDS
Definition: atacmds.h:82
#define ATA_SMART_READ_LOG_SECTOR
Definition: atacmds.h:86
#define ATA_SMART_CMD
Definition: atacmds.h:56
#define ATA_SMART_IMMEDIATE_OFFLINE
Definition: atacmds.h:85
smart_command_set
Definition: atacmds.h:29
@ CHECK_POWER_MODE
Definition: atacmds.h:45
@ IDENTIFY
Definition: atacmds.h:42
@ STATUS_CHECK
Definition: atacmds.h:37
@ IMMEDIATE_OFFLINE
Definition: atacmds.h:34
@ AUTO_OFFLINE
Definition: atacmds.h:35
@ ENABLE
Definition: atacmds.h:31
@ WRITE_LOG
Definition: atacmds.h:47
@ READ_VALUES
Definition: atacmds.h:39
@ AUTOSAVE
Definition: atacmds.h:33
@ STATUS
Definition: atacmds.h:36
@ READ_THRESHOLDS
Definition: atacmds.h:40
@ DISABLE
Definition: atacmds.h:32
@ READ_LOG
Definition: atacmds.h:41
#define ATA_SMART_ENABLE
Definition: atacmds.h:89
#define ATA_SMART_AUTOSAVE
Definition: atacmds.h:83
#define ATA_SMART_DISABLE
Definition: atacmds.h:90
#define ATA_CHECK_POWER_MODE
Definition: atacmds.h:52
int cciss_io_interface(int device, int target, struct scsi_cmnd_io *iop, int report)
#define CCISS_H_CVSID
Definition: cciss.h:14
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.
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).
virtual int arcmsr_get_dev_type()
Definition: dev_areca.cpp:343
void set_disknum(int disknum)
Definition: dev_areca.h:119
void set_encnum(int encnum)
Definition: dev_areca.h:122
NVMe device access.
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.
freebsd_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_unlock() override
virtual bool arcmsr_lock() override
virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io *iop) override
virtual bool arcmsr_lock() 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_unlock() override
freebsd_areca_scsi_device(smart_interface *intf, const char *dev_name, int disknum, int encnum=1)
Implement standard ATA support.
Definition: os_freebsd.cpp:244
virtual int do_cmd(struct ata_ioc_request *request, bool is_48bit_cmd)
Definition: os_freebsd.cpp:259
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out) override
ATA pass through.
Definition: os_freebsd.cpp:270
freebsd_ata_device(smart_interface *intf, const char *dev_name, const char *req_type)
Definition: os_freebsd.cpp:253
Implement CCISS RAID support with old functions.
virtual bool open() override
Open device, return false on error.
virtual bool scsi_pass_through(scsi_cmnd_io *iop) override
SCSI pass through.
unsigned char m_disknum
Disk number.
freebsd_cciss_device(smart_interface *intf, const char *name, unsigned char disknum)
Implement AMCC/3ware RAID support.
Definition: os_freebsd.cpp:563
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out) override
ATA pass through.
Definition: os_freebsd.cpp:599
virtual bool open() override
Open device, return false on error.
Definition: os_freebsd.cpp:586
int m_escalade_type
Type string for escalade_command_interface().
Definition: os_freebsd.cpp:573
freebsd_escalade_device(smart_interface *intf, const char *dev_name, int escalade_type, int disknum)
Definition: os_freebsd.cpp:577
Implement Highpoint RAID support with old functions.
freebsd_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) override
Old ATA interface called by ata_pass_through()
virtual bool open() override
Open device, return false on error.
unsigned char m_hpt_data[3]
controller/channel/port
virtual bool close() override
Close device, return false on error.
Definition: os_freebsd.cpp:872
bool(freebsd_megaraid_device::* pt_cmd)(int cdblen, void *cdb, int dataLen, void *data, int senseLen, void *sense, int report, int direction, int timeout)
Definition: os_freebsd.cpp:793
virtual smart_device * autodetect_open() override
Open device with autodetection support.
Definition: os_freebsd.cpp:816
bool megasas_cmd(int cdbLen, void *cdb, int dataLen, void *data, int senseLen, void *sense, int report, int direction, int timeout)
Definition: os_freebsd.cpp:935
virtual bool open() override
Open device, return false on error.
Definition: os_freebsd.cpp:857
freebsd_megaraid_device(smart_interface *intf, const char *name, unsigned int tgt)
Definition: os_freebsd.cpp:799
virtual bool scsi_pass_through(scsi_cmnd_io *iop) override
SCSI pass through.
Definition: os_freebsd.cpp:881
freebsd_nvme_device(smart_interface *intf, const char *dev_name, const char *req_type, unsigned nsid)
Definition: os_freebsd.cpp:458
virtual bool nvme_pass_through(const nvme_cmd_in &in, nvme_cmd_out &out) override
NVMe pass through.
Definition: os_freebsd.cpp:517
virtual bool open() override
Open device, return false on error.
Definition: os_freebsd.cpp:466
Standard SCSI support.
freebsd_scsi_device(smart_interface *intf, const char *dev_name, const char *req_type)
virtual bool open() override
Open device, return false on error.
struct cam_device * m_camdev
virtual bool scsi_pass_through(scsi_cmnd_io *iop) override
SCSI pass through.
virtual bool close() override
Close device, return false on error.
virtual smart_device * autodetect_open() override
SCSI open with autodetection support.
Implement shared open/close routines with old functions.
Definition: os_freebsd.cpp:137
virtual bool open()
Open device, return false on error.
Definition: os_freebsd.cpp:215
virtual bool is_open() const
Return true if device is open.
Definition: os_freebsd.cpp:209
int get_fd() const
Return filedesc for derived classes.
Definition: os_freebsd.cpp:153
int m_fd
filedesc, -1 if not open.
Definition: os_freebsd.cpp:160
virtual bool close()
Close device, return false on error.
Definition: os_freebsd.cpp:225
Implement platform interface with old functions.
virtual scsi_device * get_scsi_device(const char *name, const char *type) override
Return standard SCSI device.
virtual smart_device * get_custom_smart_device(const char *name, const char *type) override
Return device for platform specific 'type'.
virtual std::string get_app_examples(const char *appname) override
Return example string for program 'appname'.
virtual smart_device * autodetect_smart_device(const char *name) override
Autodetect device if no device type specified.
int megaraid_pd_add_list(const char *devname, smart_device_list &devlist)
bool get_nvme_devlist(smart_device_list &devlist, const char *type)
int megaraid_dcmd_cmd(const char *devname, uint32_t opcode, void *buf, size_t bufsize, uint8_t *mbox, size_t mboxlen, uint8_t *statusp)
bool get_dev_megaraid(smart_device_list &devlist)
virtual ata_device * get_ata_device(const char *name, const char *type) override
Return standard ATA device.
virtual std::string get_os_version_str() override
Return info string about build host and/or OS version.
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 nvme_device * get_nvme_device(const char *name, const char *type, unsigned nsid) override
Return standard NVMe device.
SCSI device access.
List of devices for DEVICESCAN.
void push_back(smart_device *dev)
Base class for all devices.
Definition: dev_interface.h:33
const char * get_req_type() const
Get type requested by user, empty if none.
smart_interface * smi()
Get interface which produced this object.
virtual bool close()=0
Close device, return false on error.
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
const char * get_dev_name() const
Get device (path)name.
const char * get_dev_type() const
Get device type.
bool is_ata() const
Return true if ATA device.
Definition: dev_interface.h:86
void clear_err()
Clear last error info.
device_info & set_info()
R/W access to device info struct.
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.
Definition: scsiata.cpp:1514
virtual ata_device * get_sat_device(const char *type, scsi_device *scsidev)
Return ATA->SCSI filter for a SAT or USB 'type'.
Definition: scsiata.cpp:1401
static void init()
Initialize platform interface and register with smi().
Definition: dev_legacy.cpp:334
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.
Definition: scsiata.cpp:1482
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
#define NVME_CTRLR_PREFIX
#define NVME_PASSTHROUGH_CMD
#define NVME_NS_PREFIX
#define nvme_completion_is_error(cpl)
mega_passthru pthru
Definition: megaraid.h:14
uint8_t opcode
Definition: megaraid.h:0
#define MFI_FRAME_DIR_WRITE
Definition: megaraid.h:130
u8 cdb[16]
Definition: megaraid.h:21
#define MFI_STAT_OK
Definition: megaraid.h:122
u16 timeout
Definition: megaraid.h:15
#define MFI_FRAME_DIR_NONE
Definition: megaraid.h:129
#define MFI_DCMD_PD_GET_LIST
Definition: megaraid.h:123
union megasas_sgl sgl
Definition: megaraid.h:22
u16 s[6]
Definition: megaraid.h:18
struct megasas_dcmd_frame dcmd
Definition: megaraid.h:10
ptr_t data
Definition: megaraid.h:15
megacmd_t mbox
Definition: megaraid.h:13
#define MFI_FRAME_DIR_READ
Definition: megaraid.h:131
u32 size
Definition: megaraid.h:0
#define MFI_MBOX_SIZE
Definition: megaraid.h:127
static const char smartctl_examples[]
Definition: os_freebsd.cpp:183
static int usbdevlist(int busno, unsigned short &vendor_id, unsigned short &product_id, unsigned short &version)
bool get_dev_names_cam(std::vector< std::string > &names, bool show_all)
unsigned char m_controller_type
Definition: os_freebsd.cpp:179
static int usbdevinfo(int f, int a, int rec, int busno, unsigned short &vendor_id, unsigned short &product_id, unsigned short &version)
static char done[USB_MAX_DEVICES]
int get_dev_names_ata(char ***names)
unsigned char m_controller_port
Definition: os_freebsd.cpp:180
uint32_t nsid
static struct @44 devices[20]
#define CONTROLLER_3WARE_9000_CHAR
Definition: os_freebsd.cpp:72
#define USBDEV
Definition: os_freebsd.cpp:49
unsigned char failuretest_permissive
Definition: smartctl.cpp:1427
#define NO_DISK_3WARE
Definition: os_freebsd.cpp:84
#define ARGUSED(x)
Definition: os_freebsd.cpp:124
const char * os_XXXX_c_cvsid
Definition: os_freebsd.cpp:79
#define PATHINQ_SETTINGS_SIZE
Definition: os_freebsd.cpp:76
void printwarning(int msgNo, const char *extra)
Definition: os_freebsd.cpp:89
#define TW_IOCTL_BUFFER_SIZE
Definition: os_freebsd.cpp:118
#define MAX_MSG
Definition: os_freebsd.cpp:86
#define CONTROLLER_3WARE_678K_CHAR
Definition: os_freebsd.cpp:73
#define ATA_DEVICE
Definition: os_freebsd.cpp:121
#define BAD_SMART
Definition: os_freebsd.cpp:83
struct _HPT_PASS_THROUGH_HEADER * PHPT_PASS_THROUGH_HEADER
#define MRSAS_CTRLR_PREFIX
Definition: os_freebsd.h:615
#define TWE_OP_ATA_PASSTHROUGH
Definition: os_freebsd.h:89
#define HPT_IOCTL_GET_CHANNEL_INFO_V2
Definition: os_freebsd.h:554
#define OS_FREEBSD_H_CVSID
Definition: os_freebsd.h:72
#define HPT_IOCTL_IDE_PASS_THROUGH
Definition: os_freebsd.h:555
#define TWEIO_COMMAND
Definition: os_freebsd.h:292
@ MFI_CMD_PD_SCSI_IO
Definition: os_freebsd.h:645
@ MFI_CMD_DCMD
Definition: os_freebsd.h:646
#define MFI_CTRLR_PREFIX
Definition: os_freebsd.h:614
#define HPT_IOCTL_MAGIC
Definition: os_freebsd.h:560
#define MFI_CMD
Definition: os_freebsd.h:767
struct _HPT_CHANNEL_INFO HPT_CHANNEL_INFO
#define MAX_NUM_DEV
Definition: os_freebsd.h:74
struct _HPT_CHANNEL_INFO_V2 HPT_CHANNEL_INFO_V2
#define HPT_READ
Definition: os_freebsd.h:557
#define HPT_IOCTL_GET_CHANNEL_INFO
Definition: os_freebsd.h:553
#define TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH
Definition: os_freebsd.h:531
struct _HPT_PASS_THROUGH_HEADER HPT_PASS_THROUGH_HEADER
#define HPT_WRITE
Definition: os_freebsd.h:558
#define HPT_DO_IOCONTROL
Definition: os_freebsd.h:587
int scsiStdInquiry(scsi_device *device, uint8_t *pBuf, int bufLen)
Definition: scsicmds.cpp:870
const char * scsi_get_opcode_name(uint8_t opcode)
Definition: scsicmds.cpp:233
void dStrHex(const uint8_t *up, int len, int no_ascii)
Definition: scsicmds.cpp:78
unsigned char scsi_debugmode
Definition: scsicmds.cpp:45
#define SAT_ATA_PASSTHROUGH_12
Definition: scsicmds.h:89
#define DXFER_NONE
Definition: scsicmds.h:96
#define SCSICMDS_H_CVSID
Definition: scsicmds.h:22
#define DXFER_FROM_DEVICE
Definition: scsicmds.h:97
#define SCSI_TIMEOUT_DEFAULT
Definition: scsicmds.h:352
#define SAT_ATA_PASSTHROUGH_16
Definition: scsicmds.h:92
#define DXFER_TO_DEVICE
Definition: scsicmds.h:98
#define INQUIRY
Definition: scsicmds.h:55
void pout(const char *fmt,...)
Definition: smartd.cpp:1308
unsigned int devices[PMPORT_PER_CHANNEL]
Definition: os_freebsd.h:575
unsigned int magic
Definition: os_freebsd.h:579
unsigned int ctrl_code
Definition: os_freebsd.h:580
unsigned int out_size
Definition: os_freebsd.h:584
unsigned int in_size
Definition: os_freebsd.h:582
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.
bool is_48bit_cmd() const
Return true if 48-bit command.
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_48 lba_48
ata_reg_alias_16 lba_mid_16
ata_register device
ata_register features
ata_register command
ATA Output registers for 48-bit commands.
ata_reg_alias_48 lba_48
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
ata_register error
ata_register device
ata_register status
union megasas_dcmd_frame::@38 mbox
union megasas_sgl sgl
Definition: megaraid.h:228
uint8_t raw[128]
Definition: os_freebsd.h:726
struct iovec mfi_sgl[MAX_IOCTL_SGE]
Definition: os_freebsd.h:730
union mfi_ioc_packet::@50 mfi_frame
uint32_t mfi_sge_count
Definition: os_freebsd.h:722
uint32_t mfi_sense_off
Definition: os_freebsd.h:723
uint32_t mfi_sgl_off
Definition: os_freebsd.h:721
uint32_t mfi_sense_len
Definition: os_freebsd.h:724
uint16_t mfi_adapter_no
Definition: os_freebsd.h:719
uint32_t sense_addr_lo
Definition: os_freebsd.h:701
uint8_t scsi_dev_type
Definition: os_freebsd.h:755
uint16_t device_id
Definition: os_freebsd.h:751
uint32_t count
Definition: os_freebsd.h:763
uint32_t size
Definition: os_freebsd.h:762
struct mfi_pd_address addr[MAX_SYS_PDS]
Definition: os_freebsd.h:764
NVMe pass through input parameters.
unsigned cdw10
unsigned cdw13
unsigned cdw11
unsigned char opcode
Opcode (CDW0 07:00)
unsigned size
Size of buffer.
unsigned cdw14
unsigned cdw15
Cmd specific.
unsigned nsid
Namespace ID.
unsigned cdw12
void * buffer
Pointer to data buffer.
NVMe pass through output parameters.
unsigned result
Command specific result (DW0)
struct nvme_status status
struct nvme_command cmd
struct nvme_completion cpl
uint8_t * sensep
Definition: scsicmds.h:108
uint8_t * dxferp
Definition: scsicmds.h:106
int dxfer_dir
Definition: scsicmds.h:104
size_t cmnd_len
Definition: scsicmds.h:103
size_t resp_sense_len
Definition: scsicmds.h:112
size_t dxfer_len
Definition: scsicmds.h:107
size_t max_sense_len
Definition: scsicmds.h:110
uint8_t scsi_status
Definition: scsicmds.h:113
uint8_t * cmnd
Definition: scsicmds.h:102
unsigned timeout
Definition: scsicmds.h:111
std::string info_name
Informal name.
Definition: dev_interface.h:46
std::string dev_type
Actual device type.
Definition: dev_interface.h:47
union tw_cl_command_7k cmd_pkt_7k
Definition: os_freebsd.h:463
union tw_cl_command_packet::@48 command
TW_UINT32 buffer_length
Definition: os_freebsd.h:503
struct tw_cl_driver_packet driver_pkt
Definition: os_freebsd.h:523
struct tw_cl_command_packet cmd_pkt
Definition: os_freebsd.h:526
TWE_Command tu_command
Definition: os_freebsd.h:287
TWE_Command_ATA ata
Definition: os_freebsd.h:254
std::string strprintf(const char *fmt,...)
Definition: utility.cpp:772
bool nonempty(const void *data, int size)
Definition: utility.cpp:655
#define UTILITY_H_CVSID
Definition: utility.h:16
bool str_starts_with(const char *str, const char *prefix)
Definition: utility.h:51