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