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