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