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(¶m, 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, ¶m)!=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(¶m, 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, ¶m)!=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