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