4 * Home page of code is: http://www.smartmontools.org
6 * Copyright (C) 2003-10 Eduard Martinescu
8 * SPDX-License-Identifier: GPL-2.0-or-later
11 #include <sys/param.h>
13 #include <sys/types.h>
19 #include <cam/scsi/scsi_message.h>
20 #include <cam/scsi/scsi_pass.h>
21 #if defined(__DragonFly__)
31 #include <sys/utsname.h>
35 // set by /usr/include/sys/ata.h, suppress warning
36 #undef ATA_READ_LOG_EXT
41 #include "os_freebsd.h"
43 #include "dev_interface.h"
44 #include "dev_ata_cmd_set.h"
45 #include "dev_areca.h"
47 #define USBDEV "/dev/usb"
48 #if defined(__FreeBSD_version)
50 // This way we define one variable for the GNU/kFreeBSD and FreeBSD
51 #define FREEBSDVER __FreeBSD_version
53 #define FREEBSDVER __FreeBSD_kernel_version
56 #if (FREEBSDVER >= 800000)
57 #include <libusb20_desc.h>
59 #elif defined(__DragonFly__)
60 #include <bus/usb/usb.h>
61 #include <bus/usb/usbhid.h>
63 #include <dev/usb/usb.h>
64 #include <dev/usb/usbhid.h>
67 // based on "/sys/dev/nvme/nvme.h" from FreeBSD kernel sources
68 #include "freebsd_nvme_ioctl.h" // NVME_PASSTHROUGH_CMD, nvme_completion_is_error
70 #define CONTROLLER_3WARE_9000_CHAR 0x01
71 #define CONTROLLER_3WARE_678K_CHAR 0x02
73 #ifndef PATHINQ_SETTINGS_SIZE
74 #define PATHINQ_SETTINGS_SIZE 128
77 const char *os_XXXX_c_cvsid
="$Id: os_freebsd.cpp 4848 2018-12-05 18:30:46Z chrfranke $" \
78 ATACMDS_H_CVSID CCISS_H_CVSID CONFIG_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID
;
82 #define NO_DISK_3WARE 2
86 // Utility function for printing warnings
87 void printwarning(int msgNo
, const char* extra
) {
89 if (msgNo
>= 0 && msgNo
<= MAX_MSG
) {
90 static int printed
[] = {0,0,0,0};
91 if (!printed
[msgNo
]) {
93 static const char* message
[]={
94 "The SMART RETURN STATUS return value (smartmontools -H option/Directive)\n can not be retrieved with this version of ATAng, please do not rely on this value\nYou should update to at least 5.2\n",
96 "Error SMART Status command failed\nPlease get assistance from \n" PACKAGE_HOMEPAGE
"\nRegister values returned from SMART Status command are:\n",
98 "You must specify a DISK # for 3ware drives with -d 3ware,<n> where <n> begins with 1 for first disk drive\n",
100 "ATA support is not provided for this kernel version. Please ugrade to a recent 5-CURRENT kernel (post 09/01/2003 or so)\n"
104 pout("%s", message
[msgNo
]);
112 // Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c
114 #define BUFFER_LEN_678K_CHAR ( sizeof(struct twe_usercommand) ) // 520
115 #define BUFFER_LEN_9000_CHAR ( sizeof(TW_OSLI_IOCTL_NO_DATA_BUF) + sizeof(TWE_Command) ) // 2048
116 #define TW_IOCTL_BUFFER_SIZE ( MAX(BUFFER_LEN_678K_CHAR, BUFFER_LEN_9000_CHAR) )
119 #define ATA_DEVICE "/dev/ata"
122 #define ARGUSED(x) ((void)(x))
124 extern unsigned char failuretest_permissive
;
126 /////////////////////////////////////////////////////////////////////////////
128 namespace os_freebsd
{ // No need to publish anything, name provided for Doxygen
130 /////////////////////////////////////////////////////////////////////////////
131 /// Implement shared open/close routines with old functions.
133 class freebsd_smart_device
134 : virtual public /*implements*/ smart_device
137 explicit freebsd_smart_device()
138 : smart_device(never_called
),
141 virtual ~freebsd_smart_device() throw();
143 virtual bool is_open() const;
147 virtual bool close();
150 /// Return filedesc for derived classes.
158 int m_fd
; ///< filedesc, -1 if not open.
162 static inline void * reallocf(void *ptr
, size_t size
) {
163 void *rv
= realloc(ptr
, size
);
164 if((rv
== NULL
) && (size
!= 0))
170 freebsd_smart_device::~freebsd_smart_device() throw()
173 os_freebsd::freebsd_smart_device::close();
176 // migration from the old_style
177 unsigned char m_controller_type
;
178 unsigned char m_controller_port
;
180 // examples for smartctl
181 static const char smartctl_examples
[] =
182 "=================================================== SMARTCTL EXAMPLES =====\n\n"
183 " smartctl -a /dev/ad0 (Prints all SMART information)\n\n"
184 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/ad0\n"
185 " (Enables SMART on first disk)\n\n"
186 " smartctl -t long /dev/ad0 (Executes extended disk self-test)\n\n"
187 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/ad0\n"
188 " (Prints Self-Test & Attribute errors)\n"
189 " (Prints Self-Test & Attribute errors)\n\n"
190 " smartctl -a --device=3ware,2 /dev/twa0\n"
191 " smartctl -a --device=3ware,2 /dev/twe0\n"
192 " smartctl -a --device=3ware,2 /dev/tws0\n"
193 " (Prints all SMART information for ATA disk on\n"
194 " third port of first 3ware RAID controller)\n"
195 " smartctl -a --device=cciss,0 /dev/ciss0\n"
196 " (Prints all SMART information for first disk \n"
197 " on Common Interface for SCSI-3 Support driver)\n"
198 " smartctl -a --device=areca,3/1 /dev/arcmsr0\n"
199 " (Prints all SMART information for 3rd disk in the 1st enclosure \n"
200 " on first ARECA RAID controller)\n"
204 bool freebsd_smart_device::is_open() const
210 bool freebsd_smart_device::open()
212 const char *dev
= get_dev_name();
213 if ((m_fd
= ::open(dev
,O_RDONLY
))<0) {
220 bool freebsd_smart_device::close()
223 // close device, if open
225 failed
=::close(get_fd());
229 if(failed
) return false;
233 /////////////////////////////////////////////////////////////////////////////
234 /// Implement standard ATA support
236 class freebsd_ata_device
237 : public /*implements*/ ata_device
,
238 public /*extends*/ freebsd_smart_device
241 freebsd_ata_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
);
242 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
245 virtual int do_cmd(struct ata_ioc_request
* request
, bool is_48bit_cmd
);
248 freebsd_ata_device::freebsd_ata_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
)
249 : smart_device(intf
, dev_name
, "ata", req_type
),
250 freebsd_smart_device()
254 int freebsd_ata_device::do_cmd( struct ata_ioc_request
* request
, bool is_48bit_cmd
)
256 int fd
= get_fd(), ret
;
257 ARGUSED(is_48bit_cmd
); // no support for 48 bit commands in the IOCATAREQUEST
258 ret
= ioctl(fd
, IOCATAREQUEST
, request
);
259 if (ret
) set_err(errno
);
265 bool freebsd_ata_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
267 bool ata_48bit
= false; // no ata_48bit_support via IOCATAREQUEST
268 if(!strcmp("atacam",get_dev_type())) // enable for atacam interface
271 if (!ata_cmd_is_ok(in
,
272 true, // data_out_support
273 true, // multi_sector_support
276 set_err(ENOSYS
, "48-bit ATA commands not implemented for legacy controllers");
280 struct ata_ioc_request request
;
281 bzero(&request
,sizeof(struct ata_ioc_request
));
283 request
.timeout
=SCSI_TIMEOUT_DEFAULT
;
284 request
.u
.ata
.command
=in
.in_regs
.command
;
285 request
.u
.ata
.feature
=in
.in_regs
.features
;
287 request
.u
.ata
.count
= in
.in_regs
.sector_count_16
;
288 request
.u
.ata
.lba
= in
.in_regs
.lba_48
;
290 switch (in
.direction
) {
291 case ata_cmd_in::no_data
:
292 request
.flags
=ATA_CMD_CONTROL
;
294 case ata_cmd_in::data_in
:
295 request
.flags
=ATA_CMD_READ
| ATA_CMD_CONTROL
;
296 request
.data
=(char *)in
.buffer
;
297 request
.count
=in
.size
;
299 case ata_cmd_in::data_out
:
300 request
.flags
=ATA_CMD_WRITE
| ATA_CMD_CONTROL
;
301 request
.data
=(char *)in
.buffer
;
302 request
.count
=in
.size
;
305 return set_err(ENOSYS
);
310 if (do_cmd(&request
, in
.in_regs
.is_48bit_cmd()))
313 return set_err(EIO
, "request failed, error code 0x%02x", request
.error
);
315 out
.out_regs
.error
= request
.error
;
316 out
.out_regs
.sector_count_16
= request
.u
.ata
.count
;
317 out
.out_regs
.lba_48
= request
.u
.ata
.lba
;
322 #if FREEBSDVER > 800100
323 class freebsd_atacam_device
: public freebsd_ata_device
326 freebsd_atacam_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
)
327 : smart_device(intf
, dev_name
, "atacam", req_type
), freebsd_ata_device(intf
, dev_name
, req_type
)
331 virtual bool close();
335 struct cam_device
*m_camdev
;
337 virtual int do_cmd( struct ata_ioc_request
* request
, bool is_48bit_cmd
);
340 bool freebsd_atacam_device::open(){
341 const char *dev
= get_dev_name();
343 if ((m_camdev
= cam_open_device(dev
, O_RDWR
)) == NULL
) {
347 set_fd(m_camdev
->fd
);
351 bool freebsd_atacam_device::close(){
352 cam_close_device(m_camdev
);
357 int freebsd_atacam_device::do_cmd( struct ata_ioc_request
* request
, bool is_48bit_cmd
)
362 // 48bit commands are broken in ATACAM before r242422/HEAD
363 // and may cause system hang
364 // First version with working support should be FreeBSD 9.2.0/RELEASE
366 #if (FREEBSDVER < 902001)
367 if(!strcmp("ata",m_camdev
->sim_name
) && is_48bit_cmd
) {
368 set_err(ENOSYS
, "48-bit ATA commands not implemented for legacy controllers");
373 memset(&ccb
, 0, sizeof(ccb
));
375 if (request
->count
== 0)
376 camflags
= CAM_DIR_NONE
;
377 else if (request
->flags
& ATA_CMD_READ
)
378 camflags
= CAM_DIR_IN
;
380 camflags
= CAM_DIR_OUT
;
382 cam_fill_ataio(&ccb
.ataio
,
387 (u_int8_t
*)request
->data
,
389 request
->timeout
* 1000); // timeout in seconds
391 ccb
.ataio
.cmd
.flags
= CAM_ATAIO_NEEDRESULT
|
392 (is_48bit_cmd
? CAM_ATAIO_48BIT
: 0);
394 ccb
.ataio
.cmd
.command
= request
->u
.ata
.command
;
395 ccb
.ataio
.cmd
.features
= request
->u
.ata
.feature
;
396 ccb
.ataio
.cmd
.lba_low
= request
->u
.ata
.lba
;
397 ccb
.ataio
.cmd
.lba_mid
= request
->u
.ata
.lba
>> 8;
398 ccb
.ataio
.cmd
.lba_high
= request
->u
.ata
.lba
>> 16;
400 ccb
.ataio
.cmd
.lba_low_exp
= request
->u
.ata
.lba
>> 24;
401 ccb
.ataio
.cmd
.lba_mid_exp
= request
->u
.ata
.lba
>> 32;
402 ccb
.ataio
.cmd
.lba_high_exp
= request
->u
.ata
.lba
>> 40;
403 ccb
.ataio
.cmd
.device
= 0x40 | ((request
->u
.ata
.lba
>> 24) & 0x0f);
404 ccb
.ataio
.cmd
.sector_count
= request
->u
.ata
.count
;
405 ccb
.ataio
.cmd
.sector_count_exp
= request
->u
.ata
.count
>> 8;;
407 ccb
.ccb_h
.flags
|= CAM_DEV_QFRZDIS
;
409 if (cam_send_ccb(m_camdev
, &ccb
) < 0) {
410 set_err(EIO
, "cam_send_ccb failed");
414 if ((ccb
.ccb_h
.status
& CAM_STATUS_MASK
) != CAM_REQ_CMP
) {
415 if(scsi_debugmode
> 0)
416 cam_error_print(m_camdev
, &ccb
, CAM_ESF_ALL
, CAM_EPF_ALL
, stderr
);
422 ((u_int64_t
)(ccb
.ataio
.res
.lba_low
)) |
423 ((u_int64_t
)(ccb
.ataio
.res
.lba_mid
) << 8) |
424 ((u_int64_t
)(ccb
.ataio
.res
.lba_high
) << 16) |
425 ((u_int64_t
)(ccb
.ataio
.res
.lba_low_exp
) << 24) |
426 ((u_int64_t
)(ccb
.ataio
.res
.lba_mid_exp
) << 32) |
427 ((u_int64_t
)(ccb
.ataio
.res
.lba_high_exp
) << 40);
429 request
->u
.ata
.count
= ccb
.ataio
.res
.sector_count
| (ccb
.ataio
.res
.sector_count_exp
<< 8);
430 request
->error
= ccb
.ataio
.res
.error
;
437 /////////////////////////////////////////////////////////////////////////////
440 class freebsd_nvme_device
441 : public /*implements*/ nvme_device
,
442 public /*extends*/ freebsd_smart_device
445 freebsd_nvme_device(smart_interface
* intf
, const char * dev_name
,
446 const char * req_type
, unsigned nsid
);
450 virtual bool nvme_pass_through(const nvme_cmd_in
& in
, nvme_cmd_out
& out
);
453 freebsd_nvme_device::freebsd_nvme_device(smart_interface
* intf
, const char * dev_name
,
454 const char * req_type
, unsigned nsid
)
455 : smart_device(intf
, dev_name
, "nvme", req_type
),
457 freebsd_smart_device()
461 bool freebsd_nvme_device::open()
463 const char *dev
= get_dev_name();
464 if (!strnstr(dev
, NVME_CTRLR_PREFIX
, strlen(NVME_CTRLR_PREFIX
))) {
465 set_err(EINVAL
, "NVMe controller controller/namespace ids must begin with '%s'",
470 int nsid
= -1, ctrlid
= -1;
473 if(sscanf(dev
, NVME_CTRLR_PREFIX
"%d%c", &ctrlid
, &tmp
) == 1)
476 set_err(EINVAL
, "Invalid NVMe controller number");
479 nsid
= 0xFFFFFFFF; // broadcast id
481 else if (sscanf(dev
, NVME_CTRLR_PREFIX
"%d" NVME_NS_PREFIX
"%d%c",
482 &ctrlid
, &nsid
, &tmp
) == 2)
484 if(ctrlid
< 0 || nsid
< 0) {
485 set_err(EINVAL
, "Invalid NVMe controller/namespace number");
490 set_err(EINVAL
, "Invalid NVMe controller/namespace syntax");
494 // we should always open controller, not namespace device
496 snprintf(full_path
, sizeof(full_path
), NVME_CTRLR_PREFIX
"%d", ctrlid
);
499 if ((fd
= ::open(full_path
, O_RDWR
))<0) {
512 bool freebsd_nvme_device::nvme_pass_through(const nvme_cmd_in
& in
, nvme_cmd_out
& out
)
514 // nvme_passthru_cmd pt;
515 struct nvme_pt_command pt
;
516 struct nvme_completion
*cp_p
;
517 memset(&pt
, 0, sizeof(pt
));
519 #if __FreeBSD_version >= 1200058 && __FreeBSD_version < 1200081
520 pt
.cmd
.opc_fuse
= NVME_CMD_SET_OPC(in
.opcode
);
522 pt
.cmd
.opc
= in
.opcode
;
524 pt
.cmd
.opc
= in
.opcode
;
525 pt
.cmd
.nsid
= in
.nsid
;
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()?
536 int status
= ioctl(get_fd(), NVME_PASSTHROUGH_CMD
, &pt
);
539 return set_err(errno
, "NVME_PASSTHROUGH_CMD: %s", strerror(errno
));
542 out
.result
=cp_p
->cdw0
; // Command specific result (DW0)
544 if (nvme_completion_is_error(cp_p
)) { /* ignore DNR and More bits */
545 uint16_t nvme_status
= ((cp_p
->status
.sct
<< 8) | cp_p
->status
.sc
) & 0x3ff;
547 return set_nvme_err(out
, nvme_status
);
553 /////////////////////////////////////////////////////////////////////////////
554 /// Implement AMCC/3ware RAID support
556 class freebsd_escalade_device
557 : public /*implements*/ ata_device
,
558 public /*extends*/ freebsd_smart_device
561 freebsd_escalade_device(smart_interface
* intf
, const char * dev_name
,
562 int escalade_type
, int disknum
);
565 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
569 int m_escalade_type
; ///< Type string for escalade_command_interface().
570 int m_disknum
; ///< Disk number.
573 freebsd_escalade_device::freebsd_escalade_device(smart_interface
* intf
, const char * dev_name
,
574 int escalade_type
, int disknum
)
575 : smart_device(intf
, dev_name
, "3ware", "3ware"),
576 freebsd_smart_device(),
577 m_escalade_type(escalade_type
), m_disknum(disknum
)
579 set_info().info_name
= strprintf("%s [3ware_disk_%02d]", dev_name
, disknum
);
582 bool freebsd_escalade_device::open()
584 const char *dev
= get_dev_name();
587 if ((fd
= ::open(dev
,O_RDWR
))<0) {
595 bool freebsd_escalade_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
597 // to hold true file descriptor
600 if (!ata_cmd_is_ok(in
,
601 true, // data_out_support
602 false, // TODO: multi_sector_support
603 true) // ata_48bit_support
607 struct twe_usercommand
* cmd_twe
= NULL
;
608 TW_OSLI_IOCTL_NO_DATA_BUF
* cmd_twa
= NULL
;
609 TWE_Command_ATA
* ata
= NULL
;
611 // Used by both the SCSI and char interfaces
612 char ioctl_buffer
[TW_IOCTL_BUFFER_SIZE
];
615 printwarning(NO_DISK_3WARE
,NULL
);
619 memset(ioctl_buffer
, 0, TW_IOCTL_BUFFER_SIZE
);
621 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
622 cmd_twa
= (TW_OSLI_IOCTL_NO_DATA_BUF
*)ioctl_buffer
;
623 cmd_twa
->pdata
= ((TW_OSLI_IOCTL_WITH_PAYLOAD
*)cmd_twa
)->payload
.data_buf
;
624 cmd_twa
->driver_pkt
.buffer_length
= in
.size
;
625 // using "old" packet format to speak with SATA devices
626 ata
= (TWE_Command_ATA
*)&cmd_twa
->cmd_pkt
.command
.cmd_pkt_7k
;
627 } else if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
628 cmd_twe
= (struct twe_usercommand
*)ioctl_buffer
;
629 ata
= &cmd_twe
->tu_command
.ata
;
631 return set_err(ENOSYS
,
632 "Unrecognized escalade_type %d in linux_3ware_command_interface(disk %d)\n"
633 "Please contact " PACKAGE_BUGREPORT
"\n", (int)m_escalade_type
, m_disknum
);
636 ata
->opcode
= TWE_OP_ATA_PASSTHROUGH
;
638 // Same for (almost) all commands - but some reset below
639 ata
->request_id
= 0xFF;
640 ata
->unit
= m_disknum
;
643 ata
->size
= 0x5; // TODO: multisector support
646 const ata_in_regs_48bit
& r
= in
.in_regs
;
647 ata
->features
= r
.features_16
;
648 ata
->sector_count
= r
.sector_count_16
;
649 ata
->sector_num
= r
.lba_low_16
;
650 ata
->cylinder_lo
= r
.lba_mid_16
;
651 ata
->cylinder_hi
= r
.lba_high_16
;
652 ata
->drive_head
= r
.device
;
653 ata
->command
= r
.command
;
656 // Is this a command that reads or returns 512 bytes?
657 // passthru->param values are:
658 // 0x0 - non data command without TFR write check,
659 // 0x8 - non data command with TFR write check,
660 // 0xD - data command that returns data to host from device
661 // 0xF - data command that writes data from host to device
662 // passthru->size values are 0x5 for non-data and 0x07 for data
663 bool readdata
= false;
664 if (in
.direction
== ata_cmd_in::data_in
) {
665 if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
666 cmd_twe
->tu_data
= in
.buffer
;
667 cmd_twe
->tu_size
= 512;
671 ata
->sgl_offset
= 0x5;
673 // For 64-bit to work correctly, up the size of the command packet
674 // in dwords by 1 to account for the 64-bit single sgl 'address'
675 // field. Note that this doesn't agree with the typedefs but it's
676 // right (agree with kernel driver behavior/typedefs).
677 // if (sizeof(long)==8)
680 else if (in
.direction
== ata_cmd_in::no_data
) {
681 // Non data command -- but doesn't use large sector
682 // count register values.
683 ata
->sgl_offset
= 0x0;
685 ata
->sector_count
= 0x0;
687 else if (in
.direction
== ata_cmd_in::data_out
) {
688 ata
->sgl_offset
= 0x5;
689 ata
->param
= 0xF; // PIO data write
690 if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
691 cmd_twe
->tu_data
= in
.buffer
;
692 cmd_twe
->tu_size
= 512;
694 else if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
695 memcpy(cmd_twa
->pdata
, in
.buffer
, in
.size
);
699 return set_err(EINVAL
);
701 // 3WARE controller can NOT have packet device internally
702 if (in
.in_regs
.command
== ATA_IDENTIFY_PACKET_DEVICE
) {
703 return set_err(ENODEV
, "No drive on port %d", m_disknum
);
706 // Now send the command down through an ioctl()
708 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
709 ioctlreturn
=ioctl(fd
,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH
,cmd_twa
);
711 ioctlreturn
=ioctl(fd
,TWEIO_COMMAND
,cmd_twe
);
714 // Deal with the different error cases
719 // See if the ATA command failed. Now that we have returned from
720 // the ioctl() call, if passthru is valid, then:
721 // - ata->status contains the 3ware controller STATUS
722 // - ata->command contains the ATA STATUS register
723 // - ata->features contains the ATA ERROR register
725 // Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS
726 // If bit 0 (error bit) is set, then ATA ERROR register is valid.
727 // While we *might* decode the ATA ERROR register, at the moment it
728 // doesn't make much sense: we don't care in detail why the error
731 if (ata
->status
|| (ata
->command
& 0x21)) {
733 pout("Command failed, ata.status=(0x%2.2x), ata.command=(0x%2.2x), ata.flags=(0x%2.2x)\n",ata
->status
,ata
->command
,ata
->flags
);
737 // If this is a read data command, copy data to output buffer
739 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
)
740 memcpy(in
.buffer
, cmd_twa
->pdata
, in
.size
);
741 else if(m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
742 memcpy(in
.buffer
, cmd_twe
->tu_data
, in
.size
); // untested
745 // Return register values
747 ata_out_regs_48bit
& r
= out
.out_regs
;
748 r
.error
= ata
->features
;
749 r
.sector_count_16
= ata
->sector_count
;
750 r
.lba_low_16
= ata
->sector_num
;
751 r
.lba_mid_16
= ata
->cylinder_lo
;
752 r
.lba_high_16
= ata
->cylinder_hi
;
753 r
.device
= ata
->drive_head
;
754 r
.status
= ata
->command
;
756 // look for nonexistent devices/ports
757 if (in
.in_regs
.command
== ATA_IDENTIFY_DEVICE
758 && !nonempty((unsigned char *)in
.buffer
, in
.size
)) {
759 return set_err(ENODEV
, "No drive on port %d", m_disknum
);
765 /////////////////////////////////////////////////////////////////////////////
766 /// Implement Highpoint RAID support with old functions
768 class freebsd_highpoint_device
769 : public /*implements*/ ata_device_with_command_set
,
770 public /*extends*/ freebsd_smart_device
773 freebsd_highpoint_device(smart_interface
* intf
, const char * dev_name
,
774 unsigned char controller
, unsigned char channel
, unsigned char port
);
777 virtual int ata_command_interface(smart_command_set command
, int select
, char * data
);
781 unsigned char m_hpt_data
[3]; ///< controller/channel/port
785 freebsd_highpoint_device::freebsd_highpoint_device(smart_interface
* intf
, const char * dev_name
,
786 unsigned char controller
, unsigned char channel
, unsigned char port
)
787 : smart_device(intf
, dev_name
, "hpt", "hpt"),
788 freebsd_smart_device()
790 m_hpt_data
[0] = controller
; m_hpt_data
[1] = channel
; m_hpt_data
[2] = port
;
791 set_info().info_name
= strprintf("%s [hpt_disk_%u/%u/%u]", dev_name
, m_hpt_data
[0], m_hpt_data
[1], m_hpt_data
[2]);
794 bool freebsd_highpoint_device::open()
796 const char *dev
= get_dev_name();
799 if ((fd
= ::open(dev
,O_RDWR
))<0) {
807 int freebsd_highpoint_device::ata_command_interface(smart_command_set command
, int select
, char * data
)
811 HPT_IOCTL_PARAM param
;
812 HPT_CHANNEL_INFO_V2 info
;
813 unsigned char* buff
[512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER
)];
814 PHPT_PASS_THROUGH_HEADER pide_pt_hdr
, pide_pt_hdr_out
;
816 // get internal deviceid
817 ids
[0] = m_hpt_data
[0] - 1;
818 ids
[1] = m_hpt_data
[1] - 1;
820 memset(¶m
, 0, sizeof(HPT_IOCTL_PARAM
));
822 param
.magic
= HPT_IOCTL_MAGIC
;
823 param
.ctrl_code
= HPT_IOCTL_GET_CHANNEL_INFO_V2
;
824 param
.in
= (unsigned char *)ids
;
825 param
.in_size
= sizeof(unsigned int) * 2;
826 param
.out
= (unsigned char *)&info
;
827 param
.out_size
= sizeof(HPT_CHANNEL_INFO_V2
);
829 if (m_hpt_data
[2]==1) {
830 param
.ctrl_code
= HPT_IOCTL_GET_CHANNEL_INFO
;
831 param
.out_size
= sizeof(HPT_CHANNEL_INFO
);
833 if (ioctl(fd
, HPT_DO_IOCONTROL
, ¶m
)!=0 ||
834 info
.devices
[m_hpt_data
[2]-1]==0) {
838 // perform smart action
839 memset(buff
, 0, 512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER
));
840 pide_pt_hdr
= (PHPT_PASS_THROUGH_HEADER
)buff
;
842 pide_pt_hdr
->lbamid
= 0x4f;
843 pide_pt_hdr
->lbahigh
= 0xc2;
844 pide_pt_hdr
->command
= ATA_SMART_CMD
;
845 pide_pt_hdr
->id
= info
.devices
[m_hpt_data
[2] - 1];
849 pide_pt_hdr
->feature
=ATA_SMART_READ_VALUES
;
850 pide_pt_hdr
->protocol
=HPT_READ
;
852 case READ_THRESHOLDS
:
853 pide_pt_hdr
->feature
=ATA_SMART_READ_THRESHOLDS
;
854 pide_pt_hdr
->protocol
=HPT_READ
;
857 pide_pt_hdr
->feature
=ATA_SMART_READ_LOG_SECTOR
;
858 pide_pt_hdr
->lbalow
=select
;
859 pide_pt_hdr
->protocol
=HPT_READ
;
862 pide_pt_hdr
->command
=ATA_IDENTIFY_DEVICE
;
863 pide_pt_hdr
->protocol
=HPT_READ
;
866 pide_pt_hdr
->feature
=ATA_SMART_ENABLE
;
869 pide_pt_hdr
->feature
=ATA_SMART_DISABLE
;
872 pide_pt_hdr
->feature
=ATA_SMART_AUTO_OFFLINE
;
873 pide_pt_hdr
->sectorcount
=select
;
876 pide_pt_hdr
->feature
=ATA_SMART_AUTOSAVE
;
877 pide_pt_hdr
->sectorcount
=select
;
879 case IMMEDIATE_OFFLINE
:
880 pide_pt_hdr
->feature
=ATA_SMART_IMMEDIATE_OFFLINE
;
881 pide_pt_hdr
->lbalow
=select
;
885 pide_pt_hdr
->feature
=ATA_SMART_STATUS
;
887 case CHECK_POWER_MODE
:
888 pide_pt_hdr
->command
=ATA_CHECK_POWER_MODE
;
891 memcpy(buff
+sizeof(HPT_PASS_THROUGH_HEADER
), data
, 512);
892 pide_pt_hdr
->feature
=ATA_SMART_WRITE_LOG_SECTOR
;
893 pide_pt_hdr
->lbalow
=select
;
894 pide_pt_hdr
->protocol
=HPT_WRITE
;
897 pout("Unrecognized command %d in highpoint_command_interface()\n"
898 "Please contact " PACKAGE_BUGREPORT
"\n", command
);
902 if (pide_pt_hdr
->protocol
!=0) {
903 pide_pt_hdr
->sectors
= 1;
904 pide_pt_hdr
->sectorcount
= 1;
907 memset(¶m
, 0, sizeof(HPT_IOCTL_PARAM
));
909 param
.magic
= HPT_IOCTL_MAGIC
;
910 param
.ctrl_code
= HPT_IOCTL_IDE_PASS_THROUGH
;
911 param
.in
= (unsigned char *)buff
;
912 param
.in_size
= sizeof(HPT_PASS_THROUGH_HEADER
) + (pide_pt_hdr
->protocol
==HPT_READ
? 0 : pide_pt_hdr
->sectors
* 512);
913 param
.out
= (unsigned char *)buff
+param
.in_size
;
914 param
.out_size
= sizeof(HPT_PASS_THROUGH_HEADER
) + (pide_pt_hdr
->protocol
==HPT_READ
? pide_pt_hdr
->sectors
* 512 : 0);
916 pide_pt_hdr_out
= (PHPT_PASS_THROUGH_HEADER
)param
.out
;
918 if ((ioctl(fd
, HPT_DO_IOCONTROL
, ¶m
)!=0) ||
919 (pide_pt_hdr_out
->command
& 1)) {
923 if (command
==STATUS_CHECK
)
925 unsigned const char normal_lo
=0x4f, normal_hi
=0xc2;
926 unsigned const char failed_lo
=0xf4, failed_hi
=0x2c;
927 unsigned char low
,high
;
929 high
= pide_pt_hdr_out
->lbahigh
;
930 low
= pide_pt_hdr_out
->lbamid
;
932 // Cyl low and Cyl high unchanged means "Good SMART status"
933 if (low
==normal_lo
&& high
==normal_hi
)
936 // These values mean "Bad SMART status"
937 if (low
==failed_lo
&& high
==failed_hi
)
940 // We haven't gotten output that makes sense; print out some debugging info
942 snprintf(buf
, sizeof(buf
),
943 "CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
944 (int)pide_pt_hdr_out
->command
,
945 (int)pide_pt_hdr_out
->feature
,
946 (int)pide_pt_hdr_out
->sectorcount
,
947 (int)pide_pt_hdr_out
->lbalow
,
948 (int)pide_pt_hdr_out
->lbamid
,
949 (int)pide_pt_hdr_out
->lbahigh
,
950 (int)pide_pt_hdr_out
->sectors
);
951 printwarning(BAD_SMART
,buf
);
953 else if (command
==CHECK_POWER_MODE
)
954 data
[0] = pide_pt_hdr_out
->sectorcount
& 0xff;
955 else if (pide_pt_hdr
->protocol
==HPT_READ
)
956 memcpy(data
, (unsigned char *)buff
+ 2 * sizeof(HPT_PASS_THROUGH_HEADER
),
957 pide_pt_hdr
->sectors
* 512);
962 /////////////////////////////////////////////////////////////////////////////
963 /// Standard SCSI support
965 class freebsd_scsi_device
966 : public /*implements*/ scsi_device
,
967 public /*extends*/ freebsd_smart_device
970 freebsd_scsi_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
);
972 virtual smart_device
* autodetect_open();
974 virtual bool scsi_pass_through(scsi_cmnd_io
* iop
);
978 virtual bool close();
981 struct cam_device
*m_camdev
;
984 bool freebsd_scsi_device::open(){
985 const char *dev
= get_dev_name();
987 if ((m_camdev
= cam_open_device(dev
, O_RDWR
)) == NULL
) {
991 set_fd(m_camdev
->fd
);
995 bool freebsd_scsi_device::close(){
996 cam_close_device(m_camdev
);
1001 freebsd_scsi_device::freebsd_scsi_device(smart_interface
* intf
,
1002 const char * dev_name
, const char * req_type
)
1003 : smart_device(intf
, dev_name
, "scsi", req_type
),
1004 freebsd_smart_device(),
1010 bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io
* iop
)
1014 if (scsi_debugmode
) {
1016 const unsigned char * ucp
= iop
->cmnd
;
1019 np
= scsi_get_opcode_name(ucp
[0]);
1020 pout(" [%s: ", np
? np
: "<unknown opcode>");
1021 for (k
= 0; k
< iop
->cmnd_len
; ++k
)
1022 pout("%02x ", ucp
[k
]);
1023 if ((scsi_debugmode
> 1) &&
1024 (DXFER_TO_DEVICE
== iop
->dxfer_dir
) && (iop
->dxferp
)) {
1025 int trunc
= (iop
->dxfer_len
> 256) ? 1 : 0;
1027 pout("]\n Outgoing data, len=%d%s:\n", (int)iop
->dxfer_len
,
1028 (trunc
? " [only first 256 bytes shown]" : ""));
1029 dStrHex(iop
->dxferp
, (trunc
? 256 : iop
->dxfer_len
) , 1);
1035 if(m_camdev
==NULL
) {
1037 pout(" error: camdev=0!\n");
1038 return set_err(ENOTTY
);
1041 if (!(ccb
= cam_getccb(m_camdev
))) {
1043 pout(" error allocating ccb\n");
1044 return set_err(ENOMEM
);
1047 // mfi SAT layer is known to be buggy
1048 if(!strcmp("mfi",m_camdev
->sim_name
)) {
1049 if (iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_12
|| iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_16
) {
1050 // Controller does not return ATA output registers in SAT sense data
1051 if (iop
->cmnd
[2] & (1 << 5)) // chk_cond
1052 return set_err(ENOSYS
, "ATA return descriptor not supported by controller firmware");
1054 // SMART WRITE LOG SECTOR causing media errors
1055 if ((iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_16
1056 && iop
->cmnd
[14] == ATA_SMART_CMD
&& iop
->cmnd
[3]==0 &&
1057 iop
->cmnd
[4] == ATA_SMART_WRITE_LOG_SECTOR
) ||
1058 (iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_12
1059 && iop
->cmnd
[9] == ATA_SMART_CMD
&& iop
->cmnd
[3] == ATA_SMART_WRITE_LOG_SECTOR
))
1061 if(!failuretest_permissive
)
1062 return set_err(ENOSYS
, "SMART WRITE LOG SECTOR may cause problems, try with -T permissive to force");
1065 // clear out structure, except for header that was filled in for us
1066 bzero(&(&ccb
->ccb_h
)[1],
1067 sizeof(struct ccb_scsiio
) - sizeof(struct ccb_hdr
));
1069 cam_fill_csio(&ccb
->csio
,
1072 /* flags */ (iop
->dxfer_dir
== DXFER_NONE
? CAM_DIR_NONE
:(iop
->dxfer_dir
== DXFER_FROM_DEVICE
? CAM_DIR_IN
: CAM_DIR_OUT
)),
1073 /* tagaction */ MSG_SIMPLE_Q_TAG
,
1074 /* dataptr */ iop
->dxferp
,
1075 /* datalen */ iop
->dxfer_len
,
1076 /* senselen */ iop
->max_sense_len
,
1077 /* cdblen */ iop
->cmnd_len
,
1078 /* timeout (converted to seconds) */ iop
->timeout
*1000);
1079 memcpy(ccb
->csio
.cdb_io
.cdb_bytes
,iop
->cmnd
,iop
->cmnd_len
);
1081 if (cam_send_ccb(m_camdev
,ccb
) < 0) {
1082 if (scsi_debugmode
) {
1083 pout(" error sending SCSI ccb\n");
1084 cam_error_print(m_camdev
,ccb
,CAM_ESF_ALL
,CAM_EPF_ALL
,stderr
);
1087 return set_err(EIO
);
1090 if (scsi_debugmode
) {
1091 pout(" CAM status=0x%x, SCSI status=0x%x, resid=0x%x\n",
1092 ccb
->ccb_h
.status
, ccb
->csio
.scsi_status
, ccb
->csio
.resid
);
1093 if ((scsi_debugmode
> 1) && (DXFER_FROM_DEVICE
== iop
->dxfer_dir
)) {
1096 len
= iop
->dxfer_len
- ccb
->csio
.resid
;
1097 trunc
= (len
> 256) ? 1 : 0;
1099 pout(" Incoming data, len=%d%s:\n", len
,
1100 (trunc
? " [only first 256 bytes shown]" : ""));
1101 dStrHex(iop
->dxferp
, (trunc
? 256 : len
), 1);
1104 pout(" Incoming data trimmed to nothing by resid\n");
1108 if (((ccb
->ccb_h
.status
& CAM_STATUS_MASK
) != CAM_REQ_CMP
) && ((ccb
->ccb_h
.status
& CAM_STATUS_MASK
) != CAM_SCSI_STATUS_ERROR
)) {
1110 cam_error_print(m_camdev
,ccb
,CAM_ESF_ALL
,CAM_EPF_ALL
,stderr
);
1112 return set_err(EIO
);
1115 iop
->resid
= ccb
->csio
.resid
;
1116 iop
->scsi_status
= ccb
->csio
.scsi_status
;
1117 if (iop
->sensep
&& (ccb
->ccb_h
.status
& CAM_AUTOSNS_VALID
) != 0) {
1119 pout(" sense_len=0x%x, sense_resid=0x%x\n",
1120 ccb
->csio
.sense_len
, ccb
->csio
.sense_resid
);
1121 iop
->resp_sense_len
= ccb
->csio
.sense_len
- ccb
->csio
.sense_resid
;
1122 /* Some SCSI controller device drivers miscalculate the sense_resid
1123 field so cap resp_sense_len on max_sense_len. */
1124 if (iop
->resp_sense_len
> iop
->max_sense_len
)
1125 iop
->resp_sense_len
= iop
->max_sense_len
;
1126 if (iop
->resp_sense_len
> 0) {
1127 memcpy(iop
->sensep
, &(ccb
->csio
.sense_data
), iop
->resp_sense_len
);
1128 if (scsi_debugmode
) {
1129 if (scsi_debugmode
> 1) {
1130 pout(" >>> Sense buffer, len=%zu:\n", iop
->resp_sense_len
);
1131 dStrHex(iop
->sensep
, iop
->resp_sense_len
, 1);
1133 if ((iop
->sensep
[0] & 0x7f) > 0x71)
1134 pout(" status=0x%x: [desc] sense_key=0x%x asc=0x%x ascq=0x%x\n",
1135 iop
->scsi_status
, iop
->sensep
[1] & 0xf,
1136 iop
->sensep
[2], iop
->sensep
[3]);
1138 pout(" status=0x%x: sense_key=0x%x asc=0x%x ascq=0x%x\n",
1139 iop
->scsi_status
, iop
->sensep
[2] & 0xf,
1140 iop
->sensep
[12], iop
->sensep
[13]);
1143 else if (scsi_debugmode
)
1144 pout(" status=0x%x\n", iop
->scsi_status
);
1146 else if (scsi_debugmode
)
1147 pout(" status=0x%x\n", iop
->scsi_status
);
1151 // mfip replacing PDT of the device so response does not make a sense
1152 // this sets PDT to 00h - direct-access block device
1153 if((!strcmp("mfi", m_camdev
->sim_name
) || !strcmp("mpt", m_camdev
->sim_name
))
1154 && iop
->cmnd
[0] == INQUIRY
) {
1155 if (scsi_debugmode
) {
1156 pout(" device on %s controller, patching PDT\n", m_camdev
->sim_name
);
1158 iop
->dxferp
[0] = iop
->dxferp
[0] & 0xe0;
1165 /////////////////////////////////////////////////////////////////////////////
1166 /// Areca RAID support
1168 ///////////////////////////////////////////////////////////////////
1169 // SATA(ATA) device behind Areca RAID Controller
1170 class freebsd_areca_ata_device
1171 : public /*implements*/ areca_ata_device
,
1172 public /*extends*/ freebsd_smart_device
1175 freebsd_areca_ata_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
= 1);
1176 virtual smart_device
* autodetect_open();
1177 virtual bool arcmsr_lock();
1178 virtual bool arcmsr_unlock();
1179 virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
);
1182 ///////////////////////////////////////////////////////////////////
1183 // SAS(SCSI) device behind Areca RAID Controller
1184 class freebsd_areca_scsi_device
1185 : public /*implements*/ areca_scsi_device
,
1186 public /*extends*/ freebsd_smart_device
1189 freebsd_areca_scsi_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
= 1);
1190 virtual smart_device
* autodetect_open();
1191 virtual bool arcmsr_lock();
1192 virtual bool arcmsr_unlock();
1193 virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
);
1197 // Areca RAID Controller(SATA Disk)
1198 freebsd_areca_ata_device::freebsd_areca_ata_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
)
1199 : smart_device(intf
, dev_name
, "areca", "areca"),
1200 freebsd_smart_device()
1202 set_disknum(disknum
);
1204 set_info().info_name
= strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name
, disknum
, encnum
);
1208 smart_device
* freebsd_areca_ata_device::autodetect_open()
1210 // autodetect device type
1211 int is_ata
= arcmsr_get_dev_type();
1225 smart_device_auto_ptr
newdev(new freebsd_areca_scsi_device(smi(), get_dev_name(), get_disknum(), get_encnum()));
1228 newdev
->open(); // TODO: Can possibly pass open fd
1230 return newdev
.release();
1233 int freebsd_areca_ata_device::arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
)
1235 int ioctlreturn
= 0;
1242 ioctlreturn
= ioctl(get_fd(), ((sSRB_BUFFER
*)(iop
->dxferp
))->srbioctl
.ControlCode
, iop
->dxferp
);
1252 bool freebsd_areca_ata_device::arcmsr_lock()
1258 bool freebsd_areca_ata_device::arcmsr_unlock()
1264 // Areca RAID Controller(SAS Device)
1265 freebsd_areca_scsi_device::freebsd_areca_scsi_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
)
1266 : smart_device(intf
, dev_name
, "areca", "areca"),
1267 freebsd_smart_device()
1269 set_disknum(disknum
);
1271 set_info().info_name
= strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name
, disknum
, encnum
);
1274 smart_device
* freebsd_areca_scsi_device::autodetect_open()
1279 int freebsd_areca_scsi_device::arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
)
1281 int ioctlreturn
= 0;
1287 ioctlreturn
= ioctl(get_fd(), ((sSRB_BUFFER
*)(iop
->dxferp
))->srbioctl
.ControlCode
, iop
->dxferp
);
1297 bool freebsd_areca_scsi_device::arcmsr_lock()
1303 bool freebsd_areca_scsi_device::arcmsr_unlock()
1309 /////////////////////////////////////////////////////////////////////////////
1310 /// Implement CCISS RAID support with old functions
1312 class freebsd_cciss_device
1313 : public /*implements*/ scsi_device
,
1314 public /*extends*/ freebsd_smart_device
1317 freebsd_cciss_device(smart_interface
* intf
, const char * name
, unsigned char disknum
);
1319 virtual bool scsi_pass_through(scsi_cmnd_io
* iop
);
1320 virtual bool open();
1323 unsigned char m_disknum
; ///< Disk number.
1326 bool freebsd_cciss_device::open()
1328 const char *dev
= get_dev_name();
1330 if ((fd
= ::open(dev
,O_RDWR
))<0) {
1338 freebsd_cciss_device::freebsd_cciss_device(smart_interface
* intf
,
1339 const char * dev_name
, unsigned char disknum
)
1340 : smart_device(intf
, dev_name
, "cciss", "cciss"),
1341 freebsd_smart_device(),
1344 set_info().info_name
= strprintf("%s [cciss_disk_%02d]", dev_name
, disknum
);
1347 bool freebsd_cciss_device::scsi_pass_through(scsi_cmnd_io
* iop
)
1349 int status
= cciss_io_interface(get_fd(), m_disknum
, iop
, scsi_debugmode
);
1351 return set_err(-status
);
1358 /////////////////////////////////////////////////////////////////////////////
1359 /// SCSI open with autodetection support
1361 smart_device
* freebsd_scsi_device::autodetect_open()
1367 // No Autodetection if device type was specified by user
1368 if (*get_req_type())
1371 // The code below is based on smartd.cpp:SCSIFilterKnown()
1374 unsigned char req_buff
[64] = {0, };
1376 if (scsiStdInquiry(this, req_buff
, req_len
)) {
1377 // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices
1378 // watch this spot ... other devices could lock up here
1380 if (scsiStdInquiry(this, req_buff
, req_len
)) {
1381 // device doesn't like INQUIRY commands
1383 set_err(EIO
, "INQUIRY failed");
1388 int avail_len
= req_buff
[4] + 5;
1389 int len
= (avail_len
< req_len
? avail_len
: req_len
);
1393 // Use INQUIRY to detect type
1396 if (!memcmp(req_buff
+ 8, "3ware", 5) || !memcmp(req_buff
+ 8, "AMCC", 4) ||
1397 !strcmp("tws",m_camdev
->sim_name
) || !strcmp("twa",m_camdev
->sim_name
)) {
1399 set_err(EINVAL
, "3ware/LSI controller, please try adding '-d 3ware,N',\n"
1400 "you may need to replace %s with /dev/twaN, /dev/tweN or /dev/twsN", get_dev_name());
1404 // SAT or USB, skip MFI controllers because of bugs
1406 smart_device
* newdev
= smi()->autodetect_sat_device(this, req_buff
, len
);
1408 // NOTE: 'this' is now owned by '*newdev'
1409 if(!strcmp("mfi",m_camdev
->sim_name
)) {
1411 newdev
->set_err(ENOSYS
, "SATA device detected,\n"
1412 "MegaRAID SAT layer is reportedly buggy, use '-d sat' to try anyhow");
1418 // Nothing special found
1423 /////////////////////////////////////////////////////////////////////////////
1424 /// Implement platform interface with old functions.
1426 class freebsd_smart_interface
1427 : public /*implements*/ smart_interface
1430 virtual std::string
get_os_version_str();
1432 virtual std::string
get_app_examples(const char * appname
);
1434 virtual bool scan_smart_devices(smart_device_list
& devlist
, const char * type
,
1435 const char * pattern
= 0);
1438 virtual ata_device
* get_ata_device(const char * name
, const char * type
);
1440 #if FREEBSDVER > 800100
1441 virtual ata_device
* get_atacam_device(const char * name
, const char * type
);
1444 virtual scsi_device
* get_scsi_device(const char * name
, const char * type
);
1446 virtual nvme_device
* get_nvme_device(const char * name
, const char * type
,
1449 virtual smart_device
* autodetect_smart_device(const char * name
);
1451 virtual smart_device
* get_custom_smart_device(const char * name
, const char * type
);
1453 virtual std::string
get_valid_custom_dev_types_str();
1455 bool get_nvme_devlist(smart_device_list
& devlist
, const char * type
);
1459 //////////////////////////////////////////////////////////////////////
1461 std::string
freebsd_smart_interface::get_os_version_str()
1463 struct utsname osname
;
1465 return strprintf("%s %s %s", osname
.sysname
, osname
.release
, osname
.machine
);
1468 std::string
freebsd_smart_interface::get_app_examples(const char * appname
)
1470 if (!strcmp(appname
, "smartctl"))
1471 return smartctl_examples
;
1475 ata_device
* freebsd_smart_interface::get_ata_device(const char * name
, const char * type
)
1477 return new freebsd_ata_device(this, name
, type
);
1480 #if FREEBSDVER > 800100
1481 ata_device
* freebsd_smart_interface::get_atacam_device(const char * name
, const char * type
)
1483 return new freebsd_atacam_device(this, name
, type
);
1487 scsi_device
* freebsd_smart_interface::get_scsi_device(const char * name
, const char * type
)
1489 return new freebsd_scsi_device(this, name
, type
);
1492 nvme_device
* freebsd_smart_interface::get_nvme_device(const char * name
, const char * type
,
1495 return new freebsd_nvme_device(this, name
, type
, nsid
);
1498 // we are using CAM subsystem XPT enumerator to found all CAM (scsi/usb/ada/...)
1499 // devices on system despite of it's names
1501 // If any errors occur, leave errno set as it was returned by the
1502 // system call, and return <0.
1505 // names: resulting array
1506 // show_all - export duplicate device name or not
1510 // >=0: number of discovered devices
1512 bool get_dev_names_cam(std::vector
<std::string
> & names
, bool show_all
)
1515 if ((fd
= open(XPT_DEVICE
, O_RDWR
)) == -1) {
1516 if (errno
== ENOENT
) /* There are no CAM device on this computer */
1519 pout("%s control device couldn't opened: %s\n", XPT_DEVICE
, strerror(errno
));
1525 bzero(&ccb
, sizeof(union ccb
));
1527 ccb
.ccb_h
.path_id
= CAM_XPT_PATH_ID
;
1528 ccb
.ccb_h
.target_id
= CAM_TARGET_WILDCARD
;
1529 ccb
.ccb_h
.target_lun
= CAM_LUN_WILDCARD
;
1531 ccb
.ccb_h
.func_code
= XPT_DEV_MATCH
;
1532 int bufsize
= sizeof(struct dev_match_result
) * MAX_NUM_DEV
;
1533 ccb
.cdm
.match_buf_len
= bufsize
;
1534 // TODO: Use local buffer instead of malloc() if possible
1535 ccb
.cdm
.matches
= (struct dev_match_result
*)malloc(bufsize
);
1536 bzero(ccb
.cdm
.matches
,bufsize
); // clear ccb.cdm.matches structure
1538 if (ccb
.cdm
.matches
== NULL
) {
1540 throw std::bad_alloc();
1542 ccb
.cdm
.num_matches
= 0;
1543 ccb
.cdm
.num_patterns
= 0;
1544 ccb
.cdm
.pattern_buf_len
= 0;
1547 * We do the ioctl multiple times if necessary, in case there are
1548 * more than MAX_NUM_DEV nodes in the EDT.
1550 int skip_device
= 0, skip_bus
= 0, changed
= 0; // TODO: bool
1551 std::string devname
;
1553 if (ioctl(fd
, CAMIOCOMMAND
, &ccb
) == -1) {
1555 pout("error sending CAMIOCOMMAND ioctl: %s\n", strerror(errno
));
1556 free(ccb
.cdm
.matches
);
1562 if ((ccb
.ccb_h
.status
!= CAM_REQ_CMP
)
1563 || ((ccb
.cdm
.status
!= CAM_DEV_MATCH_LAST
)
1564 && (ccb
.cdm
.status
!= CAM_DEV_MATCH_MORE
))) {
1565 pout("got CAM error %#x, CDM error %d\n", ccb
.ccb_h
.status
, ccb
.cdm
.status
);
1566 free(ccb
.cdm
.matches
);
1572 for (unsigned i
= 0; i
< ccb
.cdm
.num_matches
; i
++) {
1573 struct device_match_result
*dev_result
;
1574 struct periph_match_result
*periph_result
;
1576 if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_BUS
) {
1577 struct bus_match_result
*bus_result
;
1579 bus_result
= &ccb
.cdm
.matches
[i
].result
.bus_result
;
1581 if (strcmp(bus_result
->dev_name
,"xpt") == 0) /* skip XPT bus at all */
1586 } else if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_DEVICE
) {
1587 dev_result
= &ccb
.cdm
.matches
[i
].result
.device_result
;
1589 if (dev_result
->flags
& DEV_RESULT_UNCONFIGURED
|| skip_bus
== 1)
1594 // /* Shall we skip non T_DIRECT devices ? */
1595 // if (dev_result->inq_data.device != T_DIRECT)
1598 } else if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_PERIPH
&&
1599 (skip_device
== 0 || show_all
)) {
1600 /* One device may be populated as many peripherals (pass0 & da0 for example).
1601 * We are searching for best name
1603 periph_result
= &ccb
.cdm
.matches
[i
].result
.periph_result
;
1604 /* Prefer non-"pass" names */
1605 if (devname
.empty() || strncmp(periph_result
->periph_name
, "pass", 4) != 0) {
1606 devname
= strprintf("%s%s%d", _PATH_DEV
, periph_result
->periph_name
, periph_result
->unit_number
);
1610 if ((changed
== 1 || show_all
) && !devname
.empty()) {
1611 names
.push_back(devname
);
1617 } while ((ccb
.ccb_h
.status
== CAM_REQ_CMP
) && (ccb
.cdm
.status
== CAM_DEV_MATCH_MORE
));
1619 if (!devname
.empty())
1620 names
.push_back(devname
);
1622 free(ccb
.cdm
.matches
);
1627 // we are using ATA subsystem enumerator to found all ATA devices on system
1628 // despite of it's names
1630 // If any errors occur, leave errno set as it was returned by the
1631 // system call, and return <0.
1635 // >=0: number of discovered devices
1636 int get_dev_names_ata(char*** names
) {
1637 struct ata_ioc_devices devices
;
1638 int fd
=-1,maxchannel
,serrno
=-1,n
=0;
1643 if ((fd
= open(ATA_DEVICE
, O_RDWR
)) < 0) {
1644 if (errno
== ENOENT
) /* There are no ATA device on this computer */
1647 pout("%s control device can't be opened: %s\n", ATA_DEVICE
, strerror(errno
));
1652 if (ioctl(fd
, IOCATAGMAXCHANNEL
, &maxchannel
) < 0) {
1654 pout("ioctl(IOCATAGMAXCHANNEL) on /dev/ata failed: %s\n", strerror(errno
));
1659 // allocate space for up to MAX_NUM_DEV number of ATA devices
1660 mp
= (char **)calloc(MAX_NUM_DEV
, sizeof(char*));
1663 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__
);
1668 for (devices
.channel
= 0; devices
.channel
< maxchannel
&& n
< MAX_NUM_DEV
; devices
.channel
++) {
1671 if (ioctl(fd
, IOCATADEVICES
, &devices
) < 0) {
1673 continue; /* such channel not exist */
1674 pout("ioctl(IOCATADEVICES) on %s channel %d failed: %s\n", ATA_DEVICE
, devices
.channel
, strerror(errno
));
1678 for (j
=0;j
<=1 && n
<MAX_NUM_DEV
;j
++) {
1679 if (devices
.name
[j
][0] != '\0') {
1680 asprintf(mp
+n
, "%s%s", _PATH_DEV
, devices
.name
[j
]);
1681 if (mp
[n
] == NULL
) {
1682 pout("Out of memory constructing scan ATA device list (on line %d)\n", __LINE__
);
1692 mp
= (char **)reallocf(mp
,n
*(sizeof (char*))); // shrink to correct size
1695 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__
);
1717 bool freebsd_smart_interface::scan_smart_devices(smart_device_list
& devlist
,
1718 const char * type
, const char * pattern
/*= 0*/)
1721 set_err(EINVAL
, "DEVICESCAN with pattern not implemented yet");
1725 #ifdef WITH_NVME_DEVICESCAN // TODO: Remove when NVMe support is no longer EXPERIMENTAL
1726 bool scan_nvme
= !type
|| !strcmp(type
, "nvme");
1728 bool scan_nvme
= type
&& !strcmp(type
, "nvme");
1732 char * * atanames
= 0; int numata
= 0;
1733 if (!type
|| !strcmp(type
, "ata")) {
1734 numata
= get_dev_names_ata(&atanames
);
1741 std::vector
<std::string
> scsinames
;
1742 if (!type
|| !strcmp(type
, "scsi")) { // do not export duplicated names
1743 if (!get_dev_names_cam(scsinames
, false)) {
1753 for (i
= 0; i
< numata
; i
++) {
1754 ata_device
* atadev
= get_ata_device(atanames
[i
], type
);
1756 devlist
.push_back(atadev
);
1759 if(numata
) free(atanames
);
1761 for (i
= 0; i
< (int)scsinames
.size(); i
++) {
1762 if(!*type
) { // try USB autodetection if no type specified
1763 smart_device
* smartdev
= autodetect_smart_device(scsinames
[i
].c_str());
1765 devlist
.push_back(smartdev
);
1768 scsi_device
* scsidev
= get_scsi_device(scsinames
[i
].c_str(), type
);
1770 devlist
.push_back(scsidev
);
1775 get_nvme_devlist(devlist
, type
);
1779 bool freebsd_smart_interface::get_nvme_devlist(smart_device_list
& devlist
,
1784 for (int ctrlr
= 0;; ctrlr
++) {
1785 sprintf(ctrlpath
, "%s%d", NVME_CTRLR_PREFIX
, ctrlr
);
1786 int fd
= ::open(ctrlpath
, O_RDWR
);
1790 nvme_device
* nvmedev
= get_nvme_device(ctrlpath
, type
, 0);
1792 devlist
.push_back(nvmedev
);
1799 #if (FREEBSDVER < 800000) // without this build fail on FreeBSD 8
1800 static char done
[USB_MAX_DEVICES
];
1802 static int usbdevinfo(int f
, int a
, int rec
, int busno
, unsigned short & vendor_id
,
1803 unsigned short & product_id
, unsigned short & version
)
1806 struct usb_device_info di
;
1810 snprintf(devname
, sizeof(devname
),"umass%d",busno
);
1813 e
= ioctl(f
, USB_DEVICEINFO
, &di
);
1816 printf("addr %d: I/O error\n", a
);
1822 for (i
= 0; i
< USB_MAX_DEVNAMES
; i
++) {
1823 if (di
.udi_devnames
[i
][0]) {
1824 if(strcmp(di
.udi_devnames
[i
],devname
)==0) {
1826 vendor_id
= di
.udi_vendorNo
;
1827 product_id
= di
.udi_productNo
;
1828 version
= di
.udi_releaseNo
;
1836 for (p
= 0; p
< di
.udi_nports
; p
++) {
1837 int s
= di
.udi_ports
[p
];
1838 if (s
>= USB_MAX_DEVICES
) {
1842 printf("addr 0 should never happen!\n");
1844 if(usbdevinfo(f
, s
, 1, busno
, vendor_id
, product_id
, version
)) return 1;
1852 static int usbdevlist(int busno
,unsigned short & vendor_id
,
1853 unsigned short & product_id
, unsigned short & version
)
1855 #if (FREEBSDVER >= 800000) // libusb2 interface
1856 struct libusb20_device
*pdev
= NULL
;
1857 struct libusb20_backend
*pbe
;
1858 uint32_t matches
= 0;
1859 char buf
[128]; // do not change!
1862 struct LIBUSB20_DEVICE_DESC_DECODED
*pdesc
;
1864 pbe
= libusb20_be_alloc_default();
1866 while ((pdev
= libusb20_be_device_foreach(pbe
, pdev
))) {
1869 if (libusb20_dev_open(pdev
, 0)) {
1870 warnx("libusb20_dev_open: could not open device");
1874 pdesc
=libusb20_dev_get_device_desc(pdev
);
1876 snprintf(devname
, sizeof(devname
),"umass%d:",busno
);
1877 for (n
= 0; n
!= 255; n
++) {
1878 if (libusb20_dev_get_iface_desc(pdev
, n
, buf
, sizeof(buf
)))
1882 if(strncmp(buf
,devname
,strlen(devname
))==0){
1884 vendor_id
= pdesc
->idVendor
;
1885 product_id
= pdesc
->idProduct
;
1886 version
= pdesc
->bcdDevice
;
1887 libusb20_dev_close(pdev
);
1888 libusb20_be_free(pbe
);
1893 libusb20_dev_close(pdev
);
1897 printf("No device match or lack of permissions.\n");
1900 libusb20_be_free(pbe
);
1903 #else // freebsd < 8.0 USB stack, ioctl interface
1909 for (ncont
= 0, i
= 0; i
< 10; i
++) {
1910 snprintf(buf
, sizeof(buf
), "%s%d", USBDEV
, i
);
1911 int f
= open(buf
, O_RDONLY
);
1913 memset(done
, 0, sizeof done
);
1914 for (a
= 1; a
< USB_MAX_DEVICES
; a
++) {
1916 rc
= usbdevinfo(f
, a
, 1, busno
,vendor_id
, product_id
, version
);
1923 if (errno
== ENOENT
|| errno
== ENXIO
)
1933 smart_device
* freebsd_smart_interface::autodetect_smart_device(const char * name
)
1935 unsigned short vendor_id
= 0, product_id
= 0, version
= 0;
1936 struct cam_device
*cam_dev
;
1940 const char * test_name
= name
;
1942 memset(&ccb
, 0, sizeof(ccb
));
1944 // if dev_name null, or string length zero
1945 if (!name
|| !*name
)
1948 // Dereference symlinks
1950 std::string pathbuf
;
1951 if (!lstat(name
, &st
) && S_ISLNK(st
.st_mode
)) {
1952 char * p
= realpath(name
, (char *)0);
1956 test_name
= pathbuf
.c_str();
1961 char * * atanames
= 0; int numata
= 0;
1962 numata
= get_dev_names_ata(&atanames
);
1964 // check ATA/ATAPI devices
1965 for (i
= 0; i
< numata
; i
++) {
1966 if(!strcmp(atanames
[i
],test_name
)) {
1967 for (int c
= i
; c
< numata
; c
++) free(atanames
[c
]);
1969 return new freebsd_ata_device(this, test_name
, "");
1971 else free(atanames
[i
]);
1973 if(numata
) free(atanames
);
1977 pout("Unable to get ATA device list\n");
1981 std::vector
<std::string
> scsinames
;
1982 if (!get_dev_names_cam(scsinames
, true))
1983 pout("Unable to get CAM device list\n");
1984 else if (!scsinames
.empty()) {
1985 // check all devices on CAM bus
1986 for (i
= 0; i
< (int)scsinames
.size(); i
++) {
1987 if(strcmp(scsinames
[i
].c_str(), test_name
)==0)
1988 { // our disk device is CAM
1989 if(strncmp(scsinames
[i
].c_str(), "/dev/pmp", strlen("/dev/pmp")) == 0) {
1990 pout("Skipping port multiplier [%s]\n", scsinames
[i
].c_str());
1994 if ((cam_dev
= cam_open_device(test_name
, O_RDWR
)) == NULL
) {
2000 bzero(&(&ccb
.ccb_h
)[1], PATHINQ_SETTINGS_SIZE
);
2001 ccb
.ccb_h
.func_code
= XPT_PATH_INQ
; // send PATH_INQ to the device
2002 if (ioctl(cam_dev
->fd
, CAMIOCOMMAND
, &ccb
) == -1) {
2003 warn("Get Transfer Settings CCB failed\n"
2004 "%s", strerror(errno
));
2005 cam_close_device(cam_dev
);
2008 // now check if we are working with USB device, see umass.c
2009 if(strcmp(ccb
.cpi
.dev_name
,"umass-sim") == 0) { // USB device found
2010 usbdevlist(bus
,vendor_id
, product_id
, version
);
2011 int bus
=ccb
.cpi
.unit_number
; // unit_number will match umass number
2012 cam_close_device(cam_dev
);
2013 if(usbdevlist(bus
,vendor_id
, product_id
, version
)){
2014 const char * usbtype
= get_usb_dev_type_by_id(vendor_id
, product_id
, version
);
2016 return get_scsi_passthrough_device(usbtype
, new freebsd_scsi_device(this, test_name
, ""));
2020 #if FREEBSDVER > 800100
2021 // check if we have ATA device connected to CAM (ada)
2022 if(ccb
.cpi
.protocol
== PROTO_ATA
){
2023 cam_close_device(cam_dev
);
2024 return new freebsd_atacam_device(this, test_name
, "");
2027 // close cam device, we don`t need it anymore
2028 cam_close_device(cam_dev
);
2029 // handle as usual scsi
2030 return new freebsd_scsi_device(this, test_name
, "");
2034 // device is LSI raid supported by mfi driver
2035 if(!strncmp("/dev/mfid", test_name
, strlen("/dev/mfid")))
2036 set_err(EINVAL
, "To monitor disks on LSI RAID load mfip.ko module and run 'smartctl -a /dev/passX' to show SMART information");
2038 // form /dev/nvme* or nvme*
2039 if(!strncmp("/dev/nvme", test_name
, strlen("/dev/nvme")))
2040 return new freebsd_nvme_device(this, name
, "", 0 /* use default nsid */);
2041 if(!strncmp("/dev/nvd", test_name
, strlen("/dev/nvd")))
2042 set_err(EINVAL
, "To monitor NVMe disks use /dev/nvme* device names");
2044 // device type unknown
2049 smart_device
* freebsd_smart_interface::get_custom_smart_device(const char * name
, const char * type
)
2051 int disknum
= -1, n1
= -1, n2
= -1;
2053 if (sscanf(type
, "3ware,%n%d%n", &n1
, &disknum
, &n2
) == 1 || n1
== 6) {
2055 static const char * fbsd_dev_twe_ctrl
= "/dev/twe";
2056 static const char * fbsd_dev_twa_ctrl
= "/dev/twa";
2057 static const char * fbsd_dev_tws_ctrl
= "/dev/tws";
2060 if (n2
!= (int)strlen(type
)) {
2061 set_err(EINVAL
, "Option -d 3ware,N requires N to be a non-negative integer");
2064 if (!(0 <= disknum
&& disknum
<= 127)) {
2065 set_err(EINVAL
, "Option -d 3ware,N (N=%d) must have 0 <= N <= 127", disknum
);
2069 // guess 3ware device type based on device name
2070 if (str_starts_with(name
, fbsd_dev_twa_ctrl
) ||
2071 str_starts_with(name
, fbsd_dev_tws_ctrl
) ) {
2072 contr
=CONTROLLER_3WARE_9000_CHAR
;
2074 if (!strncmp(fbsd_dev_twe_ctrl
, name
, strlen(fbsd_dev_twe_ctrl
))){
2075 contr
=CONTROLLER_3WARE_678K_CHAR
;
2079 set_err(EINVAL
, "3ware controller type unknown, use %sX, %sX or %sX devices",
2080 fbsd_dev_twe_ctrl
, fbsd_dev_twa_ctrl
, fbsd_dev_tws_ctrl
);
2083 return new freebsd_escalade_device(this, name
, contr
, disknum
);
2087 int controller
= -1, channel
= -1; disknum
= 1;
2088 n1
= n2
= -1; int n3
= -1;
2089 if (sscanf(type
, "hpt,%n%d/%d%n/%d%n", &n1
, &controller
, &channel
, &n2
, &disknum
, &n3
) >= 2 || n1
== 4) {
2090 int len
= strlen(type
);
2091 if (!(n2
== len
|| n3
== len
)) {
2092 set_err(EINVAL
, "Option '-d hpt,L/M/N' supports 2-3 items");
2095 if (!(1 <= controller
&& controller
<= 8)) {
2096 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid controller id L supplied");
2099 if (!(1 <= channel
&& channel
<= 128)) {
2100 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid channel number M supplied");
2103 if (!(1 <= disknum
&& disknum
<= 15)) {
2104 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid pmport number N supplied");
2107 return new freebsd_highpoint_device(this, name
, controller
, channel
, disknum
);
2111 disknum
= n1
= n2
= -1;
2112 if (sscanf(type
, "cciss,%n%d%n", &n1
, &disknum
, &n2
) == 1 || n1
== 6) {
2113 if (n2
!= (int)strlen(type
)) {
2114 set_err(EINVAL
, "Option -d cciss,N requires N to be a non-negative integer");
2117 if (!(0 <= disknum
&& disknum
<= 127)) {
2118 set_err(EINVAL
, "Option -d cciss,N (N=%d) must have 0 <= N <= 127", disknum
);
2121 return get_sat_device("sat,auto", new freebsd_cciss_device(this, name
, disknum
));
2123 #if FREEBSDVER > 800100
2125 if(!strcmp(type
,"atacam"))
2126 return new freebsd_atacam_device(this, name
, "");
2129 disknum
= n1
= n2
= -1;
2131 if (sscanf(type
, "areca,%n%d/%d%n", &n1
, &disknum
, &encnum
, &n2
) >= 1 || n1
== 6) {
2132 if (!(1 <= disknum
&& disknum
<= 128)) {
2133 set_err(EINVAL
, "Option -d areca,N/E (N=%d) must have 1 <= N <= 128", disknum
);
2136 if (!(1 <= encnum
&& encnum
<= 8)) {
2137 set_err(EINVAL
, "Option -d areca,N/E (E=%d) must have 1 <= E <= 8", encnum
);
2140 return new freebsd_areca_ata_device(this, name
, disknum
, encnum
);
2146 std::string
freebsd_smart_interface::get_valid_custom_dev_types_str()
2148 return "3ware,N, hpt,L/M/N, cciss,N, areca,N/E"
2149 #if FREEBSDVER > 800100
2157 /////////////////////////////////////////////////////////////////////////////
2158 /// Initialize platform interface and register with smi()
2160 void smart_interface::init()
2162 static os_freebsd::freebsd_smart_interface the_interface
;
2163 smart_interface::set(&the_interface
);