4 * Home page of code is: http://www.smartmontools.org
6 * Copyright (C) 2003-10 Eduard Martinescu
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
13 * You should have received a copy of the GNU General Public License
14 * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
25 #include <cam/scsi/scsi_message.h>
26 #include <cam/scsi/scsi_pass.h>
27 #if defined(__DragonFly__)
37 #include <sys/utsname.h>
41 // set by /usr/include/sys/ata.h, suppress warning
42 #undef ATA_READ_LOG_EXT
47 #include "os_freebsd.h"
49 #include "dev_interface.h"
50 #include "dev_ata_cmd_set.h"
51 #include "dev_areca.h"
53 #define USBDEV "/dev/usb"
54 #if defined(__FreeBSD_version)
56 // This way we define one variable for the GNU/kFreeBSD and FreeBSD
57 #define FREEBSDVER __FreeBSD_version
59 #define FREEBSDVER __FreeBSD_kernel_version
62 #if (FREEBSDVER >= 800000)
63 #include <libusb20_desc.h>
65 #elif defined(__DragonFly__)
66 #include <bus/usb/usb.h>
67 #include <bus/usb/usbhid.h>
69 #include <dev/usb/usb.h>
70 #include <dev/usb/usbhid.h>
73 // based on "/sys/dev/nvme/nvme.h" from FreeBSD kernel sources
74 #include "freebsd_nvme_ioctl.h" // NVME_PASSTHROUGH_CMD, nvme_completion_is_error
76 #define CONTROLLER_3WARE_9000_CHAR 0x01
77 #define CONTROLLER_3WARE_678K_CHAR 0x02
79 #ifndef PATHINQ_SETTINGS_SIZE
80 #define PATHINQ_SETTINGS_SIZE 128
83 const char *os_XXXX_c_cvsid
="$Id: os_freebsd.cpp 4425 2017-04-24 16:34:16Z samm2 $" \
84 ATACMDS_H_CVSID CCISS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID
;
88 #define NO_DISK_3WARE 2
92 // Utility function for printing warnings
93 void printwarning(int msgNo
, const char* extra
) {
95 if (msgNo
>= 0 && msgNo
<= MAX_MSG
) {
96 static int printed
[] = {0,0,0,0};
97 if (!printed
[msgNo
]) {
99 static const char* message
[]={
100 "The SMART RETURN STATUS return value (smartmontools -H option/Directive)\n can not be retrieved with this version of ATAng, please do not rely on this value\nYou should update to at least 5.2\n",
102 "Error SMART Status command failed\nPlease get assistance from \n" PACKAGE_HOMEPAGE
"\nRegister values returned from SMART Status command are:\n",
104 "You must specify a DISK # for 3ware drives with -d 3ware,<n> where <n> begins with 1 for first disk drive\n",
106 "ATA support is not provided for this kernel version. Please ugrade to a recent 5-CURRENT kernel (post 09/01/2003 or so)\n"
110 pout("%s", message
[msgNo
]);
118 // Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c
120 #define BUFFER_LEN_678K_CHAR ( sizeof(struct twe_usercommand) ) // 520
121 #define BUFFER_LEN_9000_CHAR ( sizeof(TW_OSLI_IOCTL_NO_DATA_BUF) + sizeof(TWE_Command) ) // 2048
122 #define TW_IOCTL_BUFFER_SIZE ( MAX(BUFFER_LEN_678K_CHAR, BUFFER_LEN_9000_CHAR) )
125 #define ATA_DEVICE "/dev/ata"
128 #define ARGUSED(x) ((void)(x))
130 extern unsigned char failuretest_permissive
;
132 /////////////////////////////////////////////////////////////////////////////
134 namespace os_freebsd
{ // No need to publish anything, name provided for Doxygen
136 /////////////////////////////////////////////////////////////////////////////
137 /// Implement shared open/close routines with old functions.
139 class freebsd_smart_device
140 : virtual public /*implements*/ smart_device
143 explicit freebsd_smart_device()
144 : smart_device(never_called
),
147 virtual ~freebsd_smart_device() throw();
149 virtual bool is_open() const;
153 virtual bool close();
156 /// Return filedesc for derived classes.
164 int m_fd
; ///< filedesc, -1 if not open.
168 static inline void * reallocf(void *ptr
, size_t size
) {
169 void *rv
= realloc(ptr
, size
);
170 if((rv
== NULL
) && (size
!= 0))
176 freebsd_smart_device::~freebsd_smart_device() throw()
179 os_freebsd::freebsd_smart_device::close();
182 // migration from the old_style
183 unsigned char m_controller_type
;
184 unsigned char m_controller_port
;
186 // examples for smartctl
187 static const char smartctl_examples
[] =
188 "=================================================== SMARTCTL EXAMPLES =====\n\n"
189 " smartctl -a /dev/ad0 (Prints all SMART information)\n\n"
190 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/ad0\n"
191 " (Enables SMART on first disk)\n\n"
192 " smartctl -t long /dev/ad0 (Executes extended disk self-test)\n\n"
193 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/ad0\n"
194 " (Prints Self-Test & Attribute errors)\n"
195 " (Prints Self-Test & Attribute errors)\n\n"
196 " smartctl -a --device=3ware,2 /dev/twa0\n"
197 " smartctl -a --device=3ware,2 /dev/twe0\n"
198 " smartctl -a --device=3ware,2 /dev/tws0\n"
199 " (Prints all SMART information for ATA disk on\n"
200 " third port of first 3ware RAID controller)\n"
201 " smartctl -a --device=cciss,0 /dev/ciss0\n"
202 " (Prints all SMART information for first disk \n"
203 " on Common Interface for SCSI-3 Support driver)\n"
204 " smartctl -a --device=areca,3/1 /dev/arcmsr0\n"
205 " (Prints all SMART information for 3rd disk in the 1st enclosure \n"
206 " on first ARECA RAID controller)\n"
210 bool freebsd_smart_device::is_open() const
216 bool freebsd_smart_device::open()
218 const char *dev
= get_dev_name();
219 if ((m_fd
= ::open(dev
,O_RDONLY
))<0) {
226 bool freebsd_smart_device::close()
229 // close device, if open
231 failed
=::close(get_fd());
235 if(failed
) return false;
239 /////////////////////////////////////////////////////////////////////////////
240 /// Implement standard ATA support
242 class freebsd_ata_device
243 : public /*implements*/ ata_device
,
244 public /*extends*/ freebsd_smart_device
247 freebsd_ata_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
);
248 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
251 virtual int do_cmd(struct ata_ioc_request
* request
, bool is_48bit_cmd
);
254 freebsd_ata_device::freebsd_ata_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
)
255 : smart_device(intf
, dev_name
, "ata", req_type
),
256 freebsd_smart_device()
260 int freebsd_ata_device::do_cmd( struct ata_ioc_request
* request
, bool is_48bit_cmd
)
262 int fd
= get_fd(), ret
;
263 ARGUSED(is_48bit_cmd
); // no support for 48 bit commands in the IOCATAREQUEST
264 ret
= ioctl(fd
, IOCATAREQUEST
, request
);
265 if (ret
) set_err(errno
);
271 bool freebsd_ata_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
273 bool ata_48bit
= false; // no ata_48bit_support via IOCATAREQUEST
274 if(!strcmp("atacam",get_dev_type())) // enable for atacam interface
277 if (!ata_cmd_is_ok(in
,
278 true, // data_out_support
279 true, // multi_sector_support
282 set_err(ENOSYS
, "48-bit ATA commands not implemented for legacy controllers");
286 struct ata_ioc_request request
;
287 bzero(&request
,sizeof(struct ata_ioc_request
));
289 request
.timeout
=SCSI_TIMEOUT_DEFAULT
;
290 request
.u
.ata
.command
=in
.in_regs
.command
;
291 request
.u
.ata
.feature
=in
.in_regs
.features
;
293 request
.u
.ata
.count
= in
.in_regs
.sector_count_16
;
294 request
.u
.ata
.lba
= in
.in_regs
.lba_48
;
296 switch (in
.direction
) {
297 case ata_cmd_in::no_data
:
298 request
.flags
=ATA_CMD_CONTROL
;
300 case ata_cmd_in::data_in
:
301 request
.flags
=ATA_CMD_READ
| ATA_CMD_CONTROL
;
302 request
.data
=(char *)in
.buffer
;
303 request
.count
=in
.size
;
305 case ata_cmd_in::data_out
:
306 request
.flags
=ATA_CMD_WRITE
| ATA_CMD_CONTROL
;
307 request
.data
=(char *)in
.buffer
;
308 request
.count
=in
.size
;
311 return set_err(ENOSYS
);
316 if (do_cmd(&request
, in
.in_regs
.is_48bit_cmd()))
319 return set_err(EIO
, "request failed, error code 0x%02x", request
.error
);
321 out
.out_regs
.error
= request
.error
;
322 out
.out_regs
.sector_count_16
= request
.u
.ata
.count
;
323 out
.out_regs
.lba_48
= request
.u
.ata
.lba
;
328 #if FREEBSDVER > 800100
329 class freebsd_atacam_device
: public freebsd_ata_device
332 freebsd_atacam_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
)
333 : smart_device(intf
, dev_name
, "atacam", req_type
), freebsd_ata_device(intf
, dev_name
, req_type
)
337 virtual bool close();
341 struct cam_device
*m_camdev
;
343 virtual int do_cmd( struct ata_ioc_request
* request
, bool is_48bit_cmd
);
346 bool freebsd_atacam_device::open(){
347 const char *dev
= get_dev_name();
349 if ((m_camdev
= cam_open_device(dev
, O_RDWR
)) == NULL
) {
353 set_fd(m_camdev
->fd
);
357 bool freebsd_atacam_device::close(){
358 cam_close_device(m_camdev
);
363 int freebsd_atacam_device::do_cmd( struct ata_ioc_request
* request
, bool is_48bit_cmd
)
368 // 48bit commands are broken in ATACAM before r242422/HEAD
369 // and may cause system hang
370 // First version with working support should be FreeBSD 9.2.0/RELEASE
372 #if (FREEBSDVER < 902001)
373 if(!strcmp("ata",m_camdev
->sim_name
) && is_48bit_cmd
) {
374 set_err(ENOSYS
, "48-bit ATA commands not implemented for legacy controllers");
379 memset(&ccb
, 0, sizeof(ccb
));
381 if (request
->count
== 0)
382 camflags
= CAM_DIR_NONE
;
383 else if (request
->flags
& ATA_CMD_READ
)
384 camflags
= CAM_DIR_IN
;
386 camflags
= CAM_DIR_OUT
;
388 cam_fill_ataio(&ccb
.ataio
,
393 (u_int8_t
*)request
->data
,
395 request
->timeout
* 1000); // timeout in seconds
397 ccb
.ataio
.cmd
.flags
= CAM_ATAIO_NEEDRESULT
|
398 (is_48bit_cmd
? CAM_ATAIO_48BIT
: 0);
400 ccb
.ataio
.cmd
.command
= request
->u
.ata
.command
;
401 ccb
.ataio
.cmd
.features
= request
->u
.ata
.feature
;
402 ccb
.ataio
.cmd
.lba_low
= request
->u
.ata
.lba
;
403 ccb
.ataio
.cmd
.lba_mid
= request
->u
.ata
.lba
>> 8;
404 ccb
.ataio
.cmd
.lba_high
= request
->u
.ata
.lba
>> 16;
406 ccb
.ataio
.cmd
.lba_low_exp
= request
->u
.ata
.lba
>> 24;
407 ccb
.ataio
.cmd
.lba_mid_exp
= request
->u
.ata
.lba
>> 32;
408 ccb
.ataio
.cmd
.lba_high_exp
= request
->u
.ata
.lba
>> 40;
409 ccb
.ataio
.cmd
.device
= 0x40 | ((request
->u
.ata
.lba
>> 24) & 0x0f);
410 ccb
.ataio
.cmd
.sector_count
= request
->u
.ata
.count
;
411 ccb
.ataio
.cmd
.sector_count_exp
= request
->u
.ata
.count
>> 8;;
413 ccb
.ccb_h
.flags
|= CAM_DEV_QFRZDIS
;
415 if (cam_send_ccb(m_camdev
, &ccb
) < 0) {
416 set_err(EIO
, "cam_send_ccb failed");
420 if ((ccb
.ccb_h
.status
& CAM_STATUS_MASK
) != CAM_REQ_CMP
) {
421 if(scsi_debugmode
> 0)
422 cam_error_print(m_camdev
, &ccb
, CAM_ESF_ALL
, CAM_EPF_ALL
, stderr
);
428 ((u_int64_t
)(ccb
.ataio
.res
.lba_low
)) |
429 ((u_int64_t
)(ccb
.ataio
.res
.lba_mid
) << 8) |
430 ((u_int64_t
)(ccb
.ataio
.res
.lba_high
) << 16) |
431 ((u_int64_t
)(ccb
.ataio
.res
.lba_low_exp
) << 24) |
432 ((u_int64_t
)(ccb
.ataio
.res
.lba_mid_exp
) << 32) |
433 ((u_int64_t
)(ccb
.ataio
.res
.lba_high_exp
) << 40);
435 request
->u
.ata
.count
= ccb
.ataio
.res
.sector_count
| (ccb
.ataio
.res
.sector_count_exp
<< 8);
436 request
->error
= ccb
.ataio
.res
.error
;
443 /////////////////////////////////////////////////////////////////////////////
446 class freebsd_nvme_device
447 : public /*implements*/ nvme_device
,
448 public /*extends*/ freebsd_smart_device
451 freebsd_nvme_device(smart_interface
* intf
, const char * dev_name
,
452 const char * req_type
, unsigned nsid
);
456 virtual bool nvme_pass_through(const nvme_cmd_in
& in
, nvme_cmd_out
& out
);
459 freebsd_nvme_device::freebsd_nvme_device(smart_interface
* intf
, const char * dev_name
,
460 const char * req_type
, unsigned nsid
)
461 : smart_device(intf
, dev_name
, "nvme", req_type
),
463 freebsd_smart_device()
467 bool freebsd_nvme_device::open()
469 const char *dev
= get_dev_name();
470 if (!strnstr(dev
, NVME_CTRLR_PREFIX
, strlen(NVME_CTRLR_PREFIX
))) {
471 set_err(EINVAL
, "NVMe controller controller/namespace ids must begin with '%s'",
476 int nsid
= -1, ctrlid
= -1;
479 if(sscanf(dev
, NVME_CTRLR_PREFIX
"%d%c", &ctrlid
, &tmp
) == 1)
482 set_err(EINVAL
, "Invalid NVMe controller number");
485 nsid
= 0xFFFFFFFF; // broadcast id
487 else if (sscanf(dev
, NVME_CTRLR_PREFIX
"%d"NVME_NS_PREFIX
"%d%c",
488 &ctrlid
, &nsid
, &tmp
) == 2)
490 if(ctrlid
< 0 || nsid
< 0) {
491 set_err(EINVAL
, "Invalid NVMe controller/namespace number");
496 set_err(EINVAL
, "Invalid NVMe controller/namespace syntax");
500 // we should always open controller, not namespace device
502 snprintf(full_path
, sizeof(full_path
), NVME_CTRLR_PREFIX
"%d", ctrlid
);
505 if ((fd
= ::open(full_path
, O_RDWR
))<0) {
518 bool freebsd_nvme_device::nvme_pass_through(const nvme_cmd_in
& in
, nvme_cmd_out
& out
)
520 // nvme_passthru_cmd pt;
521 struct nvme_pt_command pt
;
522 memset(&pt
, 0, sizeof(pt
));
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
));
541 out
.result
=pt
.cpl
.cdw0
; // Command specific result (DW0)
543 if (nvme_completion_is_error(&pt
.cpl
))
544 return set_nvme_err(out
, nvme_completion_is_error(&pt
.cpl
));
549 /////////////////////////////////////////////////////////////////////////////
550 /// Implement AMCC/3ware RAID support
552 class freebsd_escalade_device
553 : public /*implements*/ ata_device
,
554 public /*extends*/ freebsd_smart_device
557 freebsd_escalade_device(smart_interface
* intf
, const char * dev_name
,
558 int escalade_type
, int disknum
);
561 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
565 int m_escalade_type
; ///< Type string for escalade_command_interface().
566 int m_disknum
; ///< Disk number.
569 freebsd_escalade_device::freebsd_escalade_device(smart_interface
* intf
, const char * dev_name
,
570 int escalade_type
, int disknum
)
571 : smart_device(intf
, dev_name
, "3ware", "3ware"),
572 freebsd_smart_device(),
573 m_escalade_type(escalade_type
), m_disknum(disknum
)
575 set_info().info_name
= strprintf("%s [3ware_disk_%02d]", dev_name
, disknum
);
578 bool freebsd_escalade_device::open()
580 const char *dev
= get_dev_name();
583 if ((fd
= ::open(dev
,O_RDWR
))<0) {
591 bool freebsd_escalade_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
593 // to hold true file descriptor
596 if (!ata_cmd_is_ok(in
,
597 true, // data_out_support
598 false, // TODO: multi_sector_support
599 true) // ata_48bit_support
603 struct twe_usercommand
* cmd_twe
= NULL
;
604 TW_OSLI_IOCTL_NO_DATA_BUF
* cmd_twa
= NULL
;
605 TWE_Command_ATA
* ata
= NULL
;
607 // Used by both the SCSI and char interfaces
608 char ioctl_buffer
[TW_IOCTL_BUFFER_SIZE
];
611 printwarning(NO_DISK_3WARE
,NULL
);
615 memset(ioctl_buffer
, 0, TW_IOCTL_BUFFER_SIZE
);
617 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
618 cmd_twa
= (TW_OSLI_IOCTL_NO_DATA_BUF
*)ioctl_buffer
;
619 cmd_twa
->pdata
= ((TW_OSLI_IOCTL_WITH_PAYLOAD
*)cmd_twa
)->payload
.data_buf
;
620 cmd_twa
->driver_pkt
.buffer_length
= in
.size
;
621 // using "old" packet format to speak with SATA devices
622 ata
= (TWE_Command_ATA
*)&cmd_twa
->cmd_pkt
.command
.cmd_pkt_7k
;
623 } else if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
624 cmd_twe
= (struct twe_usercommand
*)ioctl_buffer
;
625 ata
= &cmd_twe
->tu_command
.ata
;
627 return set_err(ENOSYS
,
628 "Unrecognized escalade_type %d in linux_3ware_command_interface(disk %d)\n"
629 "Please contact " PACKAGE_BUGREPORT
"\n", (int)m_escalade_type
, m_disknum
);
632 ata
->opcode
= TWE_OP_ATA_PASSTHROUGH
;
634 // Same for (almost) all commands - but some reset below
635 ata
->request_id
= 0xFF;
636 ata
->unit
= m_disknum
;
639 ata
->size
= 0x5; // TODO: multisector support
642 const ata_in_regs_48bit
& r
= in
.in_regs
;
643 ata
->features
= r
.features_16
;
644 ata
->sector_count
= r
.sector_count_16
;
645 ata
->sector_num
= r
.lba_low_16
;
646 ata
->cylinder_lo
= r
.lba_mid_16
;
647 ata
->cylinder_hi
= r
.lba_high_16
;
648 ata
->drive_head
= r
.device
;
649 ata
->command
= r
.command
;
652 // Is this a command that reads or returns 512 bytes?
653 // passthru->param values are:
654 // 0x0 - non data command without TFR write check,
655 // 0x8 - non data command with TFR write check,
656 // 0xD - data command that returns data to host from device
657 // 0xF - data command that writes data from host to device
658 // passthru->size values are 0x5 for non-data and 0x07 for data
659 bool readdata
= false;
660 if (in
.direction
== ata_cmd_in::data_in
) {
661 if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
662 cmd_twe
->tu_data
= in
.buffer
;
663 cmd_twe
->tu_size
= 512;
667 ata
->sgl_offset
= 0x5;
669 // For 64-bit to work correctly, up the size of the command packet
670 // in dwords by 1 to account for the 64-bit single sgl 'address'
671 // field. Note that this doesn't agree with the typedefs but it's
672 // right (agree with kernel driver behavior/typedefs).
673 // if (sizeof(long)==8)
676 else if (in
.direction
== ata_cmd_in::no_data
) {
677 // Non data command -- but doesn't use large sector
678 // count register values.
679 ata
->sgl_offset
= 0x0;
681 ata
->sector_count
= 0x0;
683 else if (in
.direction
== ata_cmd_in::data_out
) {
684 ata
->sgl_offset
= 0x5;
685 ata
->param
= 0xF; // PIO data write
686 if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
687 cmd_twe
->tu_data
= in
.buffer
;
688 cmd_twe
->tu_size
= 512;
690 else if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
691 memcpy(cmd_twa
->pdata
, in
.buffer
, in
.size
);
695 return set_err(EINVAL
);
697 // 3WARE controller can NOT have packet device internally
698 if (in
.in_regs
.command
== ATA_IDENTIFY_PACKET_DEVICE
) {
699 return set_err(ENODEV
, "No drive on port %d", m_disknum
);
702 // Now send the command down through an ioctl()
704 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
705 ioctlreturn
=ioctl(fd
,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH
,cmd_twa
);
707 ioctlreturn
=ioctl(fd
,TWEIO_COMMAND
,cmd_twe
);
710 // Deal with the different error cases
715 // See if the ATA command failed. Now that we have returned from
716 // the ioctl() call, if passthru is valid, then:
717 // - ata->status contains the 3ware controller STATUS
718 // - ata->command contains the ATA STATUS register
719 // - ata->features contains the ATA ERROR register
721 // Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS
722 // If bit 0 (error bit) is set, then ATA ERROR register is valid.
723 // While we *might* decode the ATA ERROR register, at the moment it
724 // doesn't make much sense: we don't care in detail why the error
727 if (ata
->status
|| (ata
->command
& 0x21)) {
729 pout("Command failed, ata.status=(0x%2.2x), ata.command=(0x%2.2x), ata.flags=(0x%2.2x)\n",ata
->status
,ata
->command
,ata
->flags
);
733 // If this is a read data command, copy data to output buffer
735 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
)
736 memcpy(in
.buffer
, cmd_twa
->pdata
, in
.size
);
737 else if(m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
738 memcpy(in
.buffer
, cmd_twe
->tu_data
, in
.size
); // untested
741 // Return register values
743 ata_out_regs_48bit
& r
= out
.out_regs
;
744 r
.error
= ata
->features
;
745 r
.sector_count_16
= ata
->sector_count
;
746 r
.lba_low_16
= ata
->sector_num
;
747 r
.lba_mid_16
= ata
->cylinder_lo
;
748 r
.lba_high_16
= ata
->cylinder_hi
;
749 r
.device
= ata
->drive_head
;
750 r
.status
= ata
->command
;
752 // look for nonexistent devices/ports
753 if (in
.in_regs
.command
== ATA_IDENTIFY_DEVICE
754 && !nonempty((unsigned char *)in
.buffer
, in
.size
)) {
755 return set_err(ENODEV
, "No drive on port %d", m_disknum
);
761 /////////////////////////////////////////////////////////////////////////////
762 /// Implement Highpoint RAID support with old functions
764 class freebsd_highpoint_device
765 : public /*implements*/ ata_device_with_command_set
,
766 public /*extends*/ freebsd_smart_device
769 freebsd_highpoint_device(smart_interface
* intf
, const char * dev_name
,
770 unsigned char controller
, unsigned char channel
, unsigned char port
);
773 virtual int ata_command_interface(smart_command_set command
, int select
, char * data
);
777 unsigned char m_hpt_data
[3]; ///< controller/channel/port
781 freebsd_highpoint_device::freebsd_highpoint_device(smart_interface
* intf
, const char * dev_name
,
782 unsigned char controller
, unsigned char channel
, unsigned char port
)
783 : smart_device(intf
, dev_name
, "hpt", "hpt"),
784 freebsd_smart_device()
786 m_hpt_data
[0] = controller
; m_hpt_data
[1] = channel
; m_hpt_data
[2] = port
;
787 set_info().info_name
= strprintf("%s [hpt_disk_%u/%u/%u]", dev_name
, m_hpt_data
[0], m_hpt_data
[1], m_hpt_data
[2]);
790 bool freebsd_highpoint_device::open()
792 const char *dev
= get_dev_name();
795 if ((fd
= ::open(dev
,O_RDWR
))<0) {
803 int freebsd_highpoint_device::ata_command_interface(smart_command_set command
, int select
, char * data
)
807 HPT_IOCTL_PARAM param
;
808 HPT_CHANNEL_INFO_V2 info
;
809 unsigned char* buff
[512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER
)];
810 PHPT_PASS_THROUGH_HEADER pide_pt_hdr
, pide_pt_hdr_out
;
812 // get internal deviceid
813 ids
[0] = m_hpt_data
[0] - 1;
814 ids
[1] = m_hpt_data
[1] - 1;
816 memset(¶m
, 0, sizeof(HPT_IOCTL_PARAM
));
818 param
.magic
= HPT_IOCTL_MAGIC
;
819 param
.ctrl_code
= HPT_IOCTL_GET_CHANNEL_INFO_V2
;
820 param
.in
= (unsigned char *)ids
;
821 param
.in_size
= sizeof(unsigned int) * 2;
822 param
.out
= (unsigned char *)&info
;
823 param
.out_size
= sizeof(HPT_CHANNEL_INFO_V2
);
825 if (m_hpt_data
[2]==1) {
826 param
.ctrl_code
= HPT_IOCTL_GET_CHANNEL_INFO
;
827 param
.out_size
= sizeof(HPT_CHANNEL_INFO
);
829 if (ioctl(fd
, HPT_DO_IOCONTROL
, ¶m
)!=0 ||
830 info
.devices
[m_hpt_data
[2]-1]==0) {
834 // perform smart action
835 memset(buff
, 0, 512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER
));
836 pide_pt_hdr
= (PHPT_PASS_THROUGH_HEADER
)buff
;
838 pide_pt_hdr
->lbamid
= 0x4f;
839 pide_pt_hdr
->lbahigh
= 0xc2;
840 pide_pt_hdr
->command
= ATA_SMART_CMD
;
841 pide_pt_hdr
->id
= info
.devices
[m_hpt_data
[2] - 1];
845 pide_pt_hdr
->feature
=ATA_SMART_READ_VALUES
;
846 pide_pt_hdr
->protocol
=HPT_READ
;
848 case READ_THRESHOLDS
:
849 pide_pt_hdr
->feature
=ATA_SMART_READ_THRESHOLDS
;
850 pide_pt_hdr
->protocol
=HPT_READ
;
853 pide_pt_hdr
->feature
=ATA_SMART_READ_LOG_SECTOR
;
854 pide_pt_hdr
->lbalow
=select
;
855 pide_pt_hdr
->protocol
=HPT_READ
;
858 pide_pt_hdr
->command
=ATA_IDENTIFY_DEVICE
;
859 pide_pt_hdr
->protocol
=HPT_READ
;
862 pide_pt_hdr
->feature
=ATA_SMART_ENABLE
;
865 pide_pt_hdr
->feature
=ATA_SMART_DISABLE
;
868 pide_pt_hdr
->feature
=ATA_SMART_AUTO_OFFLINE
;
869 pide_pt_hdr
->sectorcount
=select
;
872 pide_pt_hdr
->feature
=ATA_SMART_AUTOSAVE
;
873 pide_pt_hdr
->sectorcount
=select
;
875 case IMMEDIATE_OFFLINE
:
876 pide_pt_hdr
->feature
=ATA_SMART_IMMEDIATE_OFFLINE
;
877 pide_pt_hdr
->lbalow
=select
;
881 pide_pt_hdr
->feature
=ATA_SMART_STATUS
;
883 case CHECK_POWER_MODE
:
884 pide_pt_hdr
->command
=ATA_CHECK_POWER_MODE
;
887 memcpy(buff
+sizeof(HPT_PASS_THROUGH_HEADER
), data
, 512);
888 pide_pt_hdr
->feature
=ATA_SMART_WRITE_LOG_SECTOR
;
889 pide_pt_hdr
->lbalow
=select
;
890 pide_pt_hdr
->protocol
=HPT_WRITE
;
893 pout("Unrecognized command %d in highpoint_command_interface()\n"
894 "Please contact " PACKAGE_BUGREPORT
"\n", command
);
898 if (pide_pt_hdr
->protocol
!=0) {
899 pide_pt_hdr
->sectors
= 1;
900 pide_pt_hdr
->sectorcount
= 1;
903 memset(¶m
, 0, sizeof(HPT_IOCTL_PARAM
));
905 param
.magic
= HPT_IOCTL_MAGIC
;
906 param
.ctrl_code
= HPT_IOCTL_IDE_PASS_THROUGH
;
907 param
.in
= (unsigned char *)buff
;
908 param
.in_size
= sizeof(HPT_PASS_THROUGH_HEADER
) + (pide_pt_hdr
->protocol
==HPT_READ
? 0 : pide_pt_hdr
->sectors
* 512);
909 param
.out
= (unsigned char *)buff
+param
.in_size
;
910 param
.out_size
= sizeof(HPT_PASS_THROUGH_HEADER
) + (pide_pt_hdr
->protocol
==HPT_READ
? pide_pt_hdr
->sectors
* 512 : 0);
912 pide_pt_hdr_out
= (PHPT_PASS_THROUGH_HEADER
)param
.out
;
914 if ((ioctl(fd
, HPT_DO_IOCONTROL
, ¶m
)!=0) ||
915 (pide_pt_hdr_out
->command
& 1)) {
919 if (command
==STATUS_CHECK
)
921 unsigned const char normal_lo
=0x4f, normal_hi
=0xc2;
922 unsigned const char failed_lo
=0xf4, failed_hi
=0x2c;
923 unsigned char low
,high
;
925 high
= pide_pt_hdr_out
->lbahigh
;
926 low
= pide_pt_hdr_out
->lbamid
;
928 // Cyl low and Cyl high unchanged means "Good SMART status"
929 if (low
==normal_lo
&& high
==normal_hi
)
932 // These values mean "Bad SMART status"
933 if (low
==failed_lo
&& high
==failed_hi
)
936 // We haven't gotten output that makes sense; print out some debugging info
938 snprintf(buf
, sizeof(buf
),
939 "CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
940 (int)pide_pt_hdr_out
->command
,
941 (int)pide_pt_hdr_out
->feature
,
942 (int)pide_pt_hdr_out
->sectorcount
,
943 (int)pide_pt_hdr_out
->lbalow
,
944 (int)pide_pt_hdr_out
->lbamid
,
945 (int)pide_pt_hdr_out
->lbahigh
,
946 (int)pide_pt_hdr_out
->sectors
);
947 printwarning(BAD_SMART
,buf
);
949 else if (command
==CHECK_POWER_MODE
)
950 data
[0] = pide_pt_hdr_out
->sectorcount
& 0xff;
951 else if (pide_pt_hdr
->protocol
==HPT_READ
)
952 memcpy(data
, (unsigned char *)buff
+ 2 * sizeof(HPT_PASS_THROUGH_HEADER
),
953 pide_pt_hdr
->sectors
* 512);
958 /////////////////////////////////////////////////////////////////////////////
959 /// Standard SCSI support
961 class freebsd_scsi_device
962 : public /*implements*/ scsi_device
,
963 public /*extends*/ freebsd_smart_device
966 freebsd_scsi_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
);
968 virtual smart_device
* autodetect_open();
970 virtual bool scsi_pass_through(scsi_cmnd_io
* iop
);
974 virtual bool close();
977 struct cam_device
*m_camdev
;
980 bool freebsd_scsi_device::open(){
981 const char *dev
= get_dev_name();
983 if ((m_camdev
= cam_open_device(dev
, O_RDWR
)) == NULL
) {
987 set_fd(m_camdev
->fd
);
991 bool freebsd_scsi_device::close(){
992 cam_close_device(m_camdev
);
997 freebsd_scsi_device::freebsd_scsi_device(smart_interface
* intf
,
998 const char * dev_name
, const char * req_type
)
999 : smart_device(intf
, dev_name
, "scsi", req_type
),
1000 freebsd_smart_device(),
1006 bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io
* iop
)
1010 if (scsi_debugmode
) {
1012 const unsigned char * ucp
= iop
->cmnd
;
1015 np
= scsi_get_opcode_name(ucp
[0]);
1016 pout(" [%s: ", np
? np
: "<unknown opcode>");
1017 for (k
= 0; k
< iop
->cmnd_len
; ++k
)
1018 pout("%02x ", ucp
[k
]);
1019 if ((scsi_debugmode
> 1) &&
1020 (DXFER_TO_DEVICE
== iop
->dxfer_dir
) && (iop
->dxferp
)) {
1021 int trunc
= (iop
->dxfer_len
> 256) ? 1 : 0;
1023 pout("]\n Outgoing data, len=%d%s:\n", (int)iop
->dxfer_len
,
1024 (trunc
? " [only first 256 bytes shown]" : ""));
1025 dStrHex(iop
->dxferp
, (trunc
? 256 : iop
->dxfer_len
) , 1);
1031 if(m_camdev
==NULL
) {
1033 pout(" error: camdev=0!\n");
1034 return set_err(ENOTTY
);
1037 if (!(ccb
= cam_getccb(m_camdev
))) {
1039 pout(" error allocating ccb\n");
1040 return set_err(ENOMEM
);
1043 // mfi SAT layer is known to be buggy
1044 if(!strcmp("mfi",m_camdev
->sim_name
)) {
1045 if (iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_12
|| iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_16
) {
1046 // Controller does not return ATA output registers in SAT sense data
1047 if (iop
->cmnd
[2] & (1 << 5)) // chk_cond
1048 return set_err(ENOSYS
, "ATA return descriptor not supported by controller firmware");
1050 // SMART WRITE LOG SECTOR causing media errors
1051 if ((iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_16
1052 && iop
->cmnd
[14] == ATA_SMART_CMD
&& iop
->cmnd
[3]==0 &&
1053 iop
->cmnd
[4] == ATA_SMART_WRITE_LOG_SECTOR
) ||
1054 (iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_12
1055 && iop
->cmnd
[9] == ATA_SMART_CMD
&& iop
->cmnd
[3] == ATA_SMART_WRITE_LOG_SECTOR
))
1057 if(!failuretest_permissive
)
1058 return set_err(ENOSYS
, "SMART WRITE LOG SECTOR may cause problems, try with -T permissive to force");
1061 // clear out structure, except for header that was filled in for us
1062 bzero(&(&ccb
->ccb_h
)[1],
1063 sizeof(struct ccb_scsiio
) - sizeof(struct ccb_hdr
));
1065 cam_fill_csio(&ccb
->csio
,
1068 /* flags */ (iop
->dxfer_dir
== DXFER_NONE
? CAM_DIR_NONE
:(iop
->dxfer_dir
== DXFER_FROM_DEVICE
? CAM_DIR_IN
: CAM_DIR_OUT
)),
1069 /* tagaction */ MSG_SIMPLE_Q_TAG
,
1070 /* dataptr */ iop
->dxferp
,
1071 /* datalen */ iop
->dxfer_len
,
1072 /* senselen */ iop
->max_sense_len
,
1073 /* cdblen */ iop
->cmnd_len
,
1074 /* timout (converted to seconds) */ iop
->timeout
*1000);
1075 memcpy(ccb
->csio
.cdb_io
.cdb_bytes
,iop
->cmnd
,iop
->cmnd_len
);
1077 if (cam_send_ccb(m_camdev
,ccb
) < 0) {
1078 if (scsi_debugmode
) {
1079 pout(" error sending SCSI ccb\n");
1080 cam_error_print(m_camdev
,ccb
,CAM_ESF_ALL
,CAM_EPF_ALL
,stderr
);
1083 return set_err(EIO
);
1086 if (scsi_debugmode
) {
1087 pout(" CAM status=0x%x, SCSI status=0x%x, resid=0x%x\n",
1088 ccb
->ccb_h
.status
, ccb
->csio
.scsi_status
, ccb
->csio
.resid
);
1089 if ((scsi_debugmode
> 1) && (DXFER_FROM_DEVICE
== iop
->dxfer_dir
)) {
1092 len
= iop
->dxfer_len
- ccb
->csio
.resid
;
1093 trunc
= (len
> 256) ? 1 : 0;
1095 pout(" Incoming data, len=%d%s:\n", len
,
1096 (trunc
? " [only first 256 bytes shown]" : ""));
1097 dStrHex(iop
->dxferp
, (trunc
? 256 : len
), 1);
1100 pout(" Incoming data trimmed to nothing by resid\n");
1104 if (((ccb
->ccb_h
.status
& CAM_STATUS_MASK
) != CAM_REQ_CMP
) && ((ccb
->ccb_h
.status
& CAM_STATUS_MASK
) != CAM_SCSI_STATUS_ERROR
)) {
1106 cam_error_print(m_camdev
,ccb
,CAM_ESF_ALL
,CAM_EPF_ALL
,stderr
);
1108 return set_err(EIO
);
1111 iop
->resid
= ccb
->csio
.resid
;
1112 iop
->scsi_status
= ccb
->csio
.scsi_status
;
1113 if (iop
->sensep
&& (ccb
->ccb_h
.status
& CAM_AUTOSNS_VALID
) != 0) {
1115 pout(" sense_len=0x%x, sense_resid=0x%x\n",
1116 ccb
->csio
.sense_len
, ccb
->csio
.sense_resid
);
1117 iop
->resp_sense_len
= ccb
->csio
.sense_len
- ccb
->csio
.sense_resid
;
1118 /* Some SCSI controller device drivers miscalculate the sense_resid
1119 field so cap resp_sense_len on max_sense_len. */
1120 if (iop
->resp_sense_len
> iop
->max_sense_len
)
1121 iop
->resp_sense_len
= iop
->max_sense_len
;
1122 if (iop
->resp_sense_len
> 0) {
1123 memcpy(iop
->sensep
, &(ccb
->csio
.sense_data
), iop
->resp_sense_len
);
1124 if (scsi_debugmode
) {
1125 if (scsi_debugmode
> 1) {
1126 pout(" >>> Sense buffer, len=%zu:\n", iop
->resp_sense_len
);
1127 dStrHex(iop
->sensep
, iop
->resp_sense_len
, 1);
1129 if ((iop
->sensep
[0] & 0x7f) > 0x71)
1130 pout(" status=0x%x: [desc] sense_key=0x%x asc=0x%x ascq=0x%x\n",
1131 iop
->scsi_status
, iop
->sensep
[1] & 0xf,
1132 iop
->sensep
[2], iop
->sensep
[3]);
1134 pout(" status=0x%x: sense_key=0x%x asc=0x%x ascq=0x%x\n",
1135 iop
->scsi_status
, iop
->sensep
[2] & 0xf,
1136 iop
->sensep
[12], iop
->sensep
[13]);
1139 else if (scsi_debugmode
)
1140 pout(" status=0x%x\n", iop
->scsi_status
);
1142 else if (scsi_debugmode
)
1143 pout(" status=0x%x\n", iop
->scsi_status
);
1147 // mfip replacing PDT of the device so response does not make a sense
1148 // this sets PDT to 00h - direct-access block device
1149 if((!strcmp("mfi", m_camdev
->sim_name
) || !strcmp("mpt", m_camdev
->sim_name
))
1150 && iop
->cmnd
[0] == INQUIRY
) {
1151 if (scsi_debugmode
) {
1152 pout(" device on %s controller, patching PDT\n", m_camdev
->sim_name
);
1154 iop
->dxferp
[0] = iop
->dxferp
[0] & 0xe0;
1161 /////////////////////////////////////////////////////////////////////////////
1162 /// Areca RAID support
1164 ///////////////////////////////////////////////////////////////////
1165 // SATA(ATA) device behind Areca RAID Controller
1166 class freebsd_areca_ata_device
1167 : public /*implements*/ areca_ata_device
,
1168 public /*extends*/ freebsd_smart_device
1171 freebsd_areca_ata_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
= 1);
1172 virtual smart_device
* autodetect_open();
1173 virtual bool arcmsr_lock();
1174 virtual bool arcmsr_unlock();
1175 virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
);
1178 ///////////////////////////////////////////////////////////////////
1179 // SAS(SCSI) device behind Areca RAID Controller
1180 class freebsd_areca_scsi_device
1181 : public /*implements*/ areca_scsi_device
,
1182 public /*extends*/ freebsd_smart_device
1185 freebsd_areca_scsi_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
= 1);
1186 virtual smart_device
* autodetect_open();
1187 virtual bool arcmsr_lock();
1188 virtual bool arcmsr_unlock();
1189 virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
);
1193 // Areca RAID Controller(SATA Disk)
1194 freebsd_areca_ata_device::freebsd_areca_ata_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
)
1195 : smart_device(intf
, dev_name
, "areca", "areca"),
1196 freebsd_smart_device()
1198 set_disknum(disknum
);
1200 set_info().info_name
= strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name
, disknum
, encnum
);
1204 smart_device
* freebsd_areca_ata_device::autodetect_open()
1206 // autodetect device type
1207 int is_ata
= arcmsr_get_dev_type();
1221 smart_device_auto_ptr
newdev(new freebsd_areca_scsi_device(smi(), get_dev_name(), get_disknum(), get_encnum()));
1224 newdev
->open(); // TODO: Can possibly pass open fd
1226 return newdev
.release();
1229 int freebsd_areca_ata_device::arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
)
1231 int ioctlreturn
= 0;
1238 ioctlreturn
= ioctl(get_fd(), ((sSRB_BUFFER
*)(iop
->dxferp
))->srbioctl
.ControlCode
, iop
->dxferp
);
1248 bool freebsd_areca_ata_device::arcmsr_lock()
1254 bool freebsd_areca_ata_device::arcmsr_unlock()
1260 // Areca RAID Controller(SAS Device)
1261 freebsd_areca_scsi_device::freebsd_areca_scsi_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
)
1262 : smart_device(intf
, dev_name
, "areca", "areca"),
1263 freebsd_smart_device()
1265 set_disknum(disknum
);
1267 set_info().info_name
= strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name
, disknum
, encnum
);
1270 smart_device
* freebsd_areca_scsi_device::autodetect_open()
1275 int freebsd_areca_scsi_device::arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
)
1277 int ioctlreturn
= 0;
1283 ioctlreturn
= ioctl(get_fd(), ((sSRB_BUFFER
*)(iop
->dxferp
))->srbioctl
.ControlCode
, iop
->dxferp
);
1293 bool freebsd_areca_scsi_device::arcmsr_lock()
1299 bool freebsd_areca_scsi_device::arcmsr_unlock()
1305 /////////////////////////////////////////////////////////////////////////////
1306 /// Implement CCISS RAID support with old functions
1308 class freebsd_cciss_device
1309 : public /*implements*/ scsi_device
,
1310 public /*extends*/ freebsd_smart_device
1313 freebsd_cciss_device(smart_interface
* intf
, const char * name
, unsigned char disknum
);
1315 virtual bool scsi_pass_through(scsi_cmnd_io
* iop
);
1316 virtual bool open();
1319 unsigned char m_disknum
; ///< Disk number.
1322 bool freebsd_cciss_device::open()
1324 const char *dev
= get_dev_name();
1326 if ((fd
= ::open(dev
,O_RDWR
))<0) {
1334 freebsd_cciss_device::freebsd_cciss_device(smart_interface
* intf
,
1335 const char * dev_name
, unsigned char disknum
)
1336 : smart_device(intf
, dev_name
, "cciss", "cciss"),
1337 freebsd_smart_device(),
1340 set_info().info_name
= strprintf("%s [cciss_disk_%02d]", dev_name
, disknum
);
1343 bool freebsd_cciss_device::scsi_pass_through(scsi_cmnd_io
* iop
)
1345 int status
= cciss_io_interface(get_fd(), m_disknum
, iop
, scsi_debugmode
);
1347 return set_err(-status
);
1354 /////////////////////////////////////////////////////////////////////////////
1355 /// SCSI open with autodetection support
1357 smart_device
* freebsd_scsi_device::autodetect_open()
1363 // No Autodetection if device type was specified by user
1364 if (*get_req_type())
1367 // The code below is based on smartd.cpp:SCSIFilterKnown()
1370 unsigned char req_buff
[64] = {0, };
1372 if (scsiStdInquiry(this, req_buff
, req_len
)) {
1373 // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices
1374 // watch this spot ... other devices could lock up here
1376 if (scsiStdInquiry(this, req_buff
, req_len
)) {
1377 // device doesn't like INQUIRY commands
1379 set_err(EIO
, "INQUIRY failed");
1384 int avail_len
= req_buff
[4] + 5;
1385 int len
= (avail_len
< req_len
? avail_len
: req_len
);
1389 // Use INQUIRY to detect type
1392 if (!memcmp(req_buff
+ 8, "3ware", 5) || !memcmp(req_buff
+ 8, "AMCC", 4) ||
1393 !strcmp("tws",m_camdev
->sim_name
) || !strcmp("twa",m_camdev
->sim_name
)) {
1395 set_err(EINVAL
, "3ware/LSI controller, please try adding '-d 3ware,N',\n"
1396 "you may need to replace %s with /dev/twaN, /dev/tweN or /dev/twsN", get_dev_name());
1400 // SAT or USB, skip MFI controllers because of bugs
1402 smart_device
* newdev
= smi()->autodetect_sat_device(this, req_buff
, len
);
1404 // NOTE: 'this' is now owned by '*newdev'
1405 if(!strcmp("mfi",m_camdev
->sim_name
)) {
1407 newdev
->set_err(ENOSYS
, "SATA device detected,\n"
1408 "MegaRAID SAT layer is reportedly buggy, use '-d sat' to try anyhow");
1414 // Nothing special found
1419 /////////////////////////////////////////////////////////////////////////////
1420 /// Implement platform interface with old functions.
1422 class freebsd_smart_interface
1423 : public /*implements*/ smart_interface
1426 virtual std::string
get_os_version_str();
1428 virtual std::string
get_app_examples(const char * appname
);
1430 virtual bool scan_smart_devices(smart_device_list
& devlist
, const char * type
,
1431 const char * pattern
= 0);
1434 virtual ata_device
* get_ata_device(const char * name
, const char * type
);
1436 #if FREEBSDVER > 800100
1437 virtual ata_device
* get_atacam_device(const char * name
, const char * type
);
1440 virtual scsi_device
* get_scsi_device(const char * name
, const char * type
);
1442 virtual nvme_device
* get_nvme_device(const char * name
, const char * type
,
1445 virtual smart_device
* autodetect_smart_device(const char * name
);
1447 virtual smart_device
* get_custom_smart_device(const char * name
, const char * type
);
1449 virtual std::string
get_valid_custom_dev_types_str();
1453 //////////////////////////////////////////////////////////////////////
1455 std::string
freebsd_smart_interface::get_os_version_str()
1457 struct utsname osname
;
1459 return strprintf("%s %s %s", osname
.sysname
, osname
.release
, osname
.machine
);
1462 std::string
freebsd_smart_interface::get_app_examples(const char * appname
)
1464 if (!strcmp(appname
, "smartctl"))
1465 return smartctl_examples
;
1469 ata_device
* freebsd_smart_interface::get_ata_device(const char * name
, const char * type
)
1471 return new freebsd_ata_device(this, name
, type
);
1474 #if FREEBSDVER > 800100
1475 ata_device
* freebsd_smart_interface::get_atacam_device(const char * name
, const char * type
)
1477 return new freebsd_atacam_device(this, name
, type
);
1481 scsi_device
* freebsd_smart_interface::get_scsi_device(const char * name
, const char * type
)
1483 return new freebsd_scsi_device(this, name
, type
);
1486 nvme_device
* freebsd_smart_interface::get_nvme_device(const char * name
, const char * type
,
1489 return new freebsd_nvme_device(this, name
, type
, nsid
);
1492 // we are using CAM subsystem XPT enumerator to found all CAM (scsi/usb/ada/...)
1493 // devices on system despite of it's names
1495 // If any errors occur, leave errno set as it was returned by the
1496 // system call, and return <0.
1499 // names: resulting array
1500 // show_all - export duplicate device name or not
1504 // >=0: number of discovered devices
1506 bool get_dev_names_cam(std::vector
<std::string
> & names
, bool show_all
)
1509 if ((fd
= open(XPT_DEVICE
, O_RDWR
)) == -1) {
1510 if (errno
== ENOENT
) /* There are no CAM device on this computer */
1513 pout("%s control device couldn't opened: %s\n", XPT_DEVICE
, strerror(errno
));
1519 bzero(&ccb
, sizeof(union ccb
));
1521 ccb
.ccb_h
.path_id
= CAM_XPT_PATH_ID
;
1522 ccb
.ccb_h
.target_id
= CAM_TARGET_WILDCARD
;
1523 ccb
.ccb_h
.target_lun
= CAM_LUN_WILDCARD
;
1525 ccb
.ccb_h
.func_code
= XPT_DEV_MATCH
;
1526 int bufsize
= sizeof(struct dev_match_result
) * MAX_NUM_DEV
;
1527 ccb
.cdm
.match_buf_len
= bufsize
;
1528 // TODO: Use local buffer instead of malloc() if possible
1529 ccb
.cdm
.matches
= (struct dev_match_result
*)malloc(bufsize
);
1530 bzero(ccb
.cdm
.matches
,bufsize
); // clear ccb.cdm.matches structure
1532 if (ccb
.cdm
.matches
== NULL
) {
1534 throw std::bad_alloc();
1536 ccb
.cdm
.num_matches
= 0;
1537 ccb
.cdm
.num_patterns
= 0;
1538 ccb
.cdm
.pattern_buf_len
= 0;
1541 * We do the ioctl multiple times if necessary, in case there are
1542 * more than MAX_NUM_DEV nodes in the EDT.
1544 int skip_device
= 0, skip_bus
= 0, changed
= 0; // TODO: bool
1545 std::string devname
;
1547 if (ioctl(fd
, CAMIOCOMMAND
, &ccb
) == -1) {
1549 pout("error sending CAMIOCOMMAND ioctl: %s\n", strerror(errno
));
1550 free(ccb
.cdm
.matches
);
1556 if ((ccb
.ccb_h
.status
!= CAM_REQ_CMP
)
1557 || ((ccb
.cdm
.status
!= CAM_DEV_MATCH_LAST
)
1558 && (ccb
.cdm
.status
!= CAM_DEV_MATCH_MORE
))) {
1559 pout("got CAM error %#x, CDM error %d\n", ccb
.ccb_h
.status
, ccb
.cdm
.status
);
1560 free(ccb
.cdm
.matches
);
1566 for (unsigned i
= 0; i
< ccb
.cdm
.num_matches
; i
++) {
1567 struct device_match_result
*dev_result
;
1568 struct periph_match_result
*periph_result
;
1570 if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_BUS
) {
1571 struct bus_match_result
*bus_result
;
1573 bus_result
= &ccb
.cdm
.matches
[i
].result
.bus_result
;
1575 if (strcmp(bus_result
->dev_name
,"xpt") == 0) /* skip XPT bus at all */
1580 } else if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_DEVICE
) {
1581 dev_result
= &ccb
.cdm
.matches
[i
].result
.device_result
;
1583 if (dev_result
->flags
& DEV_RESULT_UNCONFIGURED
|| skip_bus
== 1)
1588 // /* Shall we skip non T_DIRECT devices ? */
1589 // if (dev_result->inq_data.device != T_DIRECT)
1592 } else if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_PERIPH
&&
1593 (skip_device
== 0 || show_all
)) {
1594 /* One device may be populated as many peripherals (pass0 & da0 for example).
1595 * We are searching for best name
1597 periph_result
= &ccb
.cdm
.matches
[i
].result
.periph_result
;
1598 /* Prefer non-"pass" names */
1599 if (devname
.empty() || strncmp(periph_result
->periph_name
, "pass", 4) != 0) {
1600 devname
= strprintf("%s%s%d", _PATH_DEV
, periph_result
->periph_name
, periph_result
->unit_number
);
1604 if ((changed
== 1 || show_all
) && !devname
.empty()) {
1605 names
.push_back(devname
);
1611 } while ((ccb
.ccb_h
.status
== CAM_REQ_CMP
) && (ccb
.cdm
.status
== CAM_DEV_MATCH_MORE
));
1613 if (!devname
.empty())
1614 names
.push_back(devname
);
1616 free(ccb
.cdm
.matches
);
1621 // we are using ATA subsystem enumerator to found all ATA devices on system
1622 // despite of it's names
1624 // If any errors occur, leave errno set as it was returned by the
1625 // system call, and return <0.
1629 // >=0: number of discovered devices
1630 int get_dev_names_ata(char*** names
) {
1631 struct ata_ioc_devices devices
;
1632 int fd
=-1,maxchannel
,serrno
=-1,n
=0;
1637 if ((fd
= open(ATA_DEVICE
, O_RDWR
)) < 0) {
1638 if (errno
== ENOENT
) /* There are no ATA device on this computer */
1641 pout("%s control device can't be opened: %s\n", ATA_DEVICE
, strerror(errno
));
1646 if (ioctl(fd
, IOCATAGMAXCHANNEL
, &maxchannel
) < 0) {
1648 pout("ioctl(IOCATAGMAXCHANNEL) on /dev/ata failed: %s\n", strerror(errno
));
1653 // allocate space for up to MAX_NUM_DEV number of ATA devices
1654 mp
= (char **)calloc(MAX_NUM_DEV
, sizeof(char*));
1657 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__
);
1662 for (devices
.channel
= 0; devices
.channel
< maxchannel
&& n
< MAX_NUM_DEV
; devices
.channel
++) {
1665 if (ioctl(fd
, IOCATADEVICES
, &devices
) < 0) {
1667 continue; /* such channel not exist */
1668 pout("ioctl(IOCATADEVICES) on %s channel %d failed: %s\n", ATA_DEVICE
, devices
.channel
, strerror(errno
));
1672 for (j
=0;j
<=1 && n
<MAX_NUM_DEV
;j
++) {
1673 if (devices
.name
[j
][0] != '\0') {
1674 asprintf(mp
+n
, "%s%s", _PATH_DEV
, devices
.name
[j
]);
1675 if (mp
[n
] == NULL
) {
1676 pout("Out of memory constructing scan ATA device list (on line %d)\n", __LINE__
);
1686 mp
= (char **)reallocf(mp
,n
*(sizeof (char*))); // shrink to correct size
1689 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__
);
1711 bool freebsd_smart_interface::scan_smart_devices(smart_device_list
& devlist
,
1712 const char * type
, const char * pattern
/*= 0*/)
1715 set_err(EINVAL
, "DEVICESCAN with pattern not implemented yet");
1720 char * * atanames
= 0; int numata
= 0;
1721 if (!type
|| !strcmp(type
, "ata")) {
1722 numata
= get_dev_names_ata(&atanames
);
1729 std::vector
<std::string
> scsinames
;
1730 if (!type
|| !strcmp(type
, "scsi")) { // do not export duplicated names
1731 if (!get_dev_names_cam(scsinames
, false)) {
1741 for (i
= 0; i
< numata
; i
++) {
1742 ata_device
* atadev
= get_ata_device(atanames
[i
], type
);
1744 devlist
.push_back(atadev
);
1747 if(numata
) free(atanames
);
1749 for (i
= 0; i
< (int)scsinames
.size(); i
++) {
1750 if(!*type
) { // try USB autodetection if no type specified
1751 smart_device
* smartdev
= autodetect_smart_device(scsinames
[i
].c_str());
1753 devlist
.push_back(smartdev
);
1756 scsi_device
* scsidev
= get_scsi_device(scsinames
[i
].c_str(), type
);
1758 devlist
.push_back(scsidev
);
1765 #if (FREEBSDVER < 800000) // without this build fail on FreeBSD 8
1766 static char done
[USB_MAX_DEVICES
];
1768 static int usbdevinfo(int f
, int a
, int rec
, int busno
, unsigned short & vendor_id
,
1769 unsigned short & product_id
, unsigned short & version
)
1772 struct usb_device_info di
;
1776 snprintf(devname
, sizeof(devname
),"umass%d",busno
);
1779 e
= ioctl(f
, USB_DEVICEINFO
, &di
);
1782 printf("addr %d: I/O error\n", a
);
1788 for (i
= 0; i
< USB_MAX_DEVNAMES
; i
++) {
1789 if (di
.udi_devnames
[i
][0]) {
1790 if(strcmp(di
.udi_devnames
[i
],devname
)==0) {
1792 vendor_id
= di
.udi_vendorNo
;
1793 product_id
= di
.udi_productNo
;
1794 version
= di
.udi_releaseNo
;
1802 for (p
= 0; p
< di
.udi_nports
; p
++) {
1803 int s
= di
.udi_ports
[p
];
1804 if (s
>= USB_MAX_DEVICES
) {
1808 printf("addr 0 should never happen!\n");
1810 if(usbdevinfo(f
, s
, 1, busno
, vendor_id
, product_id
, version
)) return 1;
1818 static int usbdevlist(int busno
,unsigned short & vendor_id
,
1819 unsigned short & product_id
, unsigned short & version
)
1821 #if (FREEBSDVER >= 800000) // libusb2 interface
1822 struct libusb20_device
*pdev
= NULL
;
1823 struct libusb20_backend
*pbe
;
1824 uint32_t matches
= 0;
1825 char buf
[128]; // do not change!
1828 struct LIBUSB20_DEVICE_DESC_DECODED
*pdesc
;
1830 pbe
= libusb20_be_alloc_default();
1832 while ((pdev
= libusb20_be_device_foreach(pbe
, pdev
))) {
1835 if (libusb20_dev_open(pdev
, 0)) {
1836 warnx("libusb20_dev_open: could not open device");
1840 pdesc
=libusb20_dev_get_device_desc(pdev
);
1842 snprintf(devname
, sizeof(devname
),"umass%d:",busno
);
1843 for (n
= 0; n
!= 255; n
++) {
1844 if (libusb20_dev_get_iface_desc(pdev
, n
, buf
, sizeof(buf
)))
1848 if(strncmp(buf
,devname
,strlen(devname
))==0){
1850 vendor_id
= pdesc
->idVendor
;
1851 product_id
= pdesc
->idProduct
;
1852 version
= pdesc
->bcdDevice
;
1853 libusb20_dev_close(pdev
);
1854 libusb20_be_free(pbe
);
1859 libusb20_dev_close(pdev
);
1863 printf("No device match or lack of permissions.\n");
1866 libusb20_be_free(pbe
);
1869 #else // freebsd < 8.0 USB stack, ioctl interface
1875 for (ncont
= 0, i
= 0; i
< 10; i
++) {
1876 snprintf(buf
, sizeof(buf
), "%s%d", USBDEV
, i
);
1877 int f
= open(buf
, O_RDONLY
);
1879 memset(done
, 0, sizeof done
);
1880 for (a
= 1; a
< USB_MAX_DEVICES
; a
++) {
1882 rc
= usbdevinfo(f
, a
, 1, busno
,vendor_id
, product_id
, version
);
1889 if (errno
== ENOENT
|| errno
== ENXIO
)
1899 smart_device
* freebsd_smart_interface::autodetect_smart_device(const char * name
)
1901 unsigned short vendor_id
= 0, product_id
= 0, version
= 0;
1902 struct cam_device
*cam_dev
;
1906 const char * test_name
= name
;
1908 memset(&ccb
, 0, sizeof(ccb
));
1910 // if dev_name null, or string length zero
1911 if (!name
|| !*name
)
1914 // Dereference symlinks
1916 std::string pathbuf
;
1917 if (!lstat(name
, &st
) && S_ISLNK(st
.st_mode
)) {
1918 char * p
= realpath(name
, (char *)0);
1922 test_name
= pathbuf
.c_str();
1927 char * * atanames
= 0; int numata
= 0;
1928 numata
= get_dev_names_ata(&atanames
);
1930 // check ATA/ATAPI devices
1931 for (i
= 0; i
< numata
; i
++) {
1932 if(!strcmp(atanames
[i
],test_name
)) {
1933 for (int c
= i
; c
< numata
; c
++) free(atanames
[c
]);
1935 return new freebsd_ata_device(this, test_name
, "");
1937 else free(atanames
[i
]);
1939 if(numata
) free(atanames
);
1943 pout("Unable to get ATA device list\n");
1947 std::vector
<std::string
> scsinames
;
1948 if (!get_dev_names_cam(scsinames
, true))
1949 pout("Unable to get CAM device list\n");
1950 else if (!scsinames
.empty()) {
1951 // check all devices on CAM bus
1952 for (i
= 0; i
< (int)scsinames
.size(); i
++) {
1953 if(strcmp(scsinames
[i
].c_str(), test_name
)==0)
1954 { // our disk device is CAM
1955 if(strncmp(scsinames
[i
].c_str(), "/dev/pmp", strlen("/dev/pmp")) == 0) {
1956 pout("Skipping port multiplier [%s]\n", scsinames
[i
].c_str());
1960 if ((cam_dev
= cam_open_device(test_name
, O_RDWR
)) == NULL
) {
1966 bzero(&(&ccb
.ccb_h
)[1], PATHINQ_SETTINGS_SIZE
);
1967 ccb
.ccb_h
.func_code
= XPT_PATH_INQ
; // send PATH_INQ to the device
1968 if (ioctl(cam_dev
->fd
, CAMIOCOMMAND
, &ccb
) == -1) {
1969 warn("Get Transfer Settings CCB failed\n"
1970 "%s", strerror(errno
));
1971 cam_close_device(cam_dev
);
1974 // now check if we are working with USB device, see umass.c
1975 if(strcmp(ccb
.cpi
.dev_name
,"umass-sim") == 0) { // USB device found
1976 usbdevlist(bus
,vendor_id
, product_id
, version
);
1977 int bus
=ccb
.cpi
.unit_number
; // unit_number will match umass number
1978 cam_close_device(cam_dev
);
1979 if(usbdevlist(bus
,vendor_id
, product_id
, version
)){
1980 const char * usbtype
= get_usb_dev_type_by_id(vendor_id
, product_id
, version
);
1982 return get_sat_device(usbtype
, new freebsd_scsi_device(this, test_name
, ""));
1986 #if FREEBSDVER > 800100
1987 // check if we have ATA device connected to CAM (ada)
1988 if(ccb
.cpi
.protocol
== PROTO_ATA
){
1989 cam_close_device(cam_dev
);
1990 return new freebsd_atacam_device(this, test_name
, "");
1993 // close cam device, we don`t need it anymore
1994 cam_close_device(cam_dev
);
1995 // handle as usual scsi
1996 return new freebsd_scsi_device(this, test_name
, "");
2000 // device is LSI raid supported by mfi driver
2001 if(!strncmp("/dev/mfid", test_name
, strlen("/dev/mfid")))
2002 set_err(EINVAL
, "To monitor disks on LSI RAID load mfip.ko module and run 'smartctl -a /dev/passX' to show SMART information");
2004 // form /dev/nvme* or nvme*
2005 if(!strncmp("/dev/nvme", test_name
, strlen("/dev/nvme")))
2006 return new freebsd_nvme_device(this, name
, "", 0 /* use default nsid */);
2008 // device type unknown
2013 smart_device
* freebsd_smart_interface::get_custom_smart_device(const char * name
, const char * type
)
2015 int disknum
= -1, n1
= -1, n2
= -1;
2017 if (sscanf(type
, "3ware,%n%d%n", &n1
, &disknum
, &n2
) == 1 || n1
== 6) {
2019 static const char * fbsd_dev_twe_ctrl
= "/dev/twe";
2020 static const char * fbsd_dev_twa_ctrl
= "/dev/twa";
2021 static const char * fbsd_dev_tws_ctrl
= "/dev/tws";
2024 if (n2
!= (int)strlen(type
)) {
2025 set_err(EINVAL
, "Option -d 3ware,N requires N to be a non-negative integer");
2028 if (!(0 <= disknum
&& disknum
<= 127)) {
2029 set_err(EINVAL
, "Option -d 3ware,N (N=%d) must have 0 <= N <= 127", disknum
);
2033 // guess 3ware device type based on device name
2034 if (str_starts_with(name
, fbsd_dev_twa_ctrl
) ||
2035 str_starts_with(name
, fbsd_dev_tws_ctrl
) ) {
2036 contr
=CONTROLLER_3WARE_9000_CHAR
;
2038 if (!strncmp(fbsd_dev_twe_ctrl
, name
, strlen(fbsd_dev_twe_ctrl
))){
2039 contr
=CONTROLLER_3WARE_678K_CHAR
;
2043 set_err(EINVAL
, "3ware controller type unknown, use %sX, %sX or %sX devices",
2044 fbsd_dev_twe_ctrl
, fbsd_dev_twa_ctrl
, fbsd_dev_tws_ctrl
);
2047 return new freebsd_escalade_device(this, name
, contr
, disknum
);
2051 int controller
= -1, channel
= -1; disknum
= 1;
2052 n1
= n2
= -1; int n3
= -1;
2053 if (sscanf(type
, "hpt,%n%d/%d%n/%d%n", &n1
, &controller
, &channel
, &n2
, &disknum
, &n3
) >= 2 || n1
== 4) {
2054 int len
= strlen(type
);
2055 if (!(n2
== len
|| n3
== len
)) {
2056 set_err(EINVAL
, "Option '-d hpt,L/M/N' supports 2-3 items");
2059 if (!(1 <= controller
&& controller
<= 8)) {
2060 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid controller id L supplied");
2063 if (!(1 <= channel
&& channel
<= 128)) {
2064 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid channel number M supplied");
2067 if (!(1 <= disknum
&& disknum
<= 15)) {
2068 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid pmport number N supplied");
2071 return new freebsd_highpoint_device(this, name
, controller
, channel
, disknum
);
2075 disknum
= n1
= n2
= -1;
2076 if (sscanf(type
, "cciss,%n%d%n", &n1
, &disknum
, &n2
) == 1 || n1
== 6) {
2077 if (n2
!= (int)strlen(type
)) {
2078 set_err(EINVAL
, "Option -d cciss,N requires N to be a non-negative integer");
2081 if (!(0 <= disknum
&& disknum
<= 127)) {
2082 set_err(EINVAL
, "Option -d cciss,N (N=%d) must have 0 <= N <= 127", disknum
);
2085 return get_sat_device("sat,auto", new freebsd_cciss_device(this, name
, disknum
));
2087 #if FREEBSDVER > 800100
2089 if(!strcmp(type
,"atacam"))
2090 return new freebsd_atacam_device(this, name
, "");
2093 disknum
= n1
= n2
= -1;
2095 if (sscanf(type
, "areca,%n%d/%d%n", &n1
, &disknum
, &encnum
, &n2
) >= 1 || n1
== 6) {
2096 if (!(1 <= disknum
&& disknum
<= 128)) {
2097 set_err(EINVAL
, "Option -d areca,N/E (N=%d) must have 1 <= N <= 128", disknum
);
2100 if (!(1 <= encnum
&& encnum
<= 8)) {
2101 set_err(EINVAL
, "Option -d areca,N/E (E=%d) must have 1 <= E <= 8", encnum
);
2104 return new freebsd_areca_ata_device(this, name
, disknum
, encnum
);
2110 std::string
freebsd_smart_interface::get_valid_custom_dev_types_str()
2112 return "3ware,N, hpt,L/M/N, cciss,N, areca,N/E"
2113 #if FREEBSDVER > 800100
2121 /////////////////////////////////////////////////////////////////////////////
2122 /// Initialize platform interface and register with smi()
2124 void smart_interface::init()
2126 static os_freebsd::freebsd_smart_interface the_interface
;
2127 smart_interface::set(&the_interface
);