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