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