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