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 #define CONTROLLER_3WARE_9000_CHAR 0x01
74 #define CONTROLLER_3WARE_678K_CHAR 0x02
76 #ifndef PATHINQ_SETTINGS_SIZE
77 #define PATHINQ_SETTINGS_SIZE 128
80 const char *os_XXXX_c_cvsid
="$Id: os_freebsd.cpp 4211 2016-01-24 07:56:06Z samm2 $" \
81 ATACMDS_H_CVSID CCISS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID
;
85 #define NO_DISK_3WARE 2
89 // Utility function for printing warnings
90 void printwarning(int msgNo
, const char* extra
) {
92 if (msgNo
>= 0 && msgNo
<= MAX_MSG
) {
93 static int printed
[] = {0,0,0,0};
94 if (!printed
[msgNo
]) {
96 static const char* message
[]={
97 "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",
99 "Error SMART Status command failed\nPlease get assistance from \n" PACKAGE_HOMEPAGE
"\nRegister values returned from SMART Status command are:\n",
101 "You must specify a DISK # for 3ware drives with -d 3ware,<n> where <n> begins with 1 for first disk drive\n",
103 "ATA support is not provided for this kernel version. Please ugrade to a recent 5-CURRENT kernel (post 09/01/2003 or so)\n"
107 pout("%s", message
[msgNo
]);
115 // Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c
117 #define BUFFER_LEN_678K_CHAR ( sizeof(struct twe_usercommand) ) // 520
118 #define BUFFER_LEN_9000_CHAR ( sizeof(TW_OSLI_IOCTL_NO_DATA_BUF) + sizeof(TWE_Command) ) // 2048
119 #define TW_IOCTL_BUFFER_SIZE ( MAX(BUFFER_LEN_678K_CHAR, BUFFER_LEN_9000_CHAR) )
122 #define ATA_DEVICE "/dev/ata"
125 #define ARGUSED(x) ((void)(x))
127 // global variable holding byte count of allocated memory
129 extern unsigned char failuretest_permissive
;
131 /////////////////////////////////////////////////////////////////////////////
133 namespace os_freebsd
{ // No need to publish anything, name provided for Doxygen
135 /////////////////////////////////////////////////////////////////////////////
136 /// Implement shared open/close routines with old functions.
138 class freebsd_smart_device
139 : virtual public /*implements*/ smart_device
142 explicit freebsd_smart_device()
143 : smart_device(never_called
),
146 virtual ~freebsd_smart_device() throw();
148 virtual bool is_open() const;
152 virtual bool close();
155 /// Return filedesc for derived classes.
163 int m_fd
; ///< filedesc, -1 if not open.
167 static inline void * reallocf(void *ptr
, size_t size
) {
168 void *rv
= realloc(ptr
, size
);
169 if((rv
== NULL
) && (size
!= 0))
175 freebsd_smart_device::~freebsd_smart_device() throw()
178 os_freebsd::freebsd_smart_device::close();
181 // migration from the old_style
182 unsigned char m_controller_type
;
183 unsigned char m_controller_port
;
185 // examples for smartctl
186 static const char smartctl_examples
[] =
187 "=================================================== SMARTCTL EXAMPLES =====\n\n"
188 " smartctl -a /dev/ad0 (Prints all SMART information)\n\n"
189 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/ad0\n"
190 " (Enables SMART on first disk)\n\n"
191 " smartctl -t long /dev/ad0 (Executes extended disk self-test)\n\n"
192 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/ad0\n"
193 " (Prints Self-Test & Attribute errors)\n"
194 " (Prints Self-Test & Attribute errors)\n\n"
195 " smartctl -a --device=3ware,2 /dev/twa0\n"
196 " smartctl -a --device=3ware,2 /dev/twe0\n"
197 " smartctl -a --device=3ware,2 /dev/tws0\n"
198 " (Prints all SMART information for ATA disk on\n"
199 " third port of first 3ware RAID controller)\n"
200 " smartctl -a --device=cciss,0 /dev/ciss0\n"
201 " (Prints all SMART information for first disk \n"
202 " on Common Interface for SCSI-3 Support driver)\n"
203 " smartctl -a --device=areca,3/1 /dev/arcmsr0\n"
204 " (Prints all SMART information for 3rd disk in the 1st enclosure \n"
205 " on first ARECA RAID controller)\n"
209 bool freebsd_smart_device::is_open() const
215 bool freebsd_smart_device::open()
217 const char *dev
= get_dev_name();
218 if ((m_fd
= ::open(dev
,O_RDONLY
))<0) {
225 bool freebsd_smart_device::close()
228 // close device, if open
230 failed
=::close(get_fd());
234 if(failed
) return false;
238 /////////////////////////////////////////////////////////////////////////////
239 /// Implement standard ATA support
241 class freebsd_ata_device
242 : public /*implements*/ ata_device
,
243 public /*extends*/ freebsd_smart_device
246 freebsd_ata_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
);
247 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
250 virtual int do_cmd(struct ata_ioc_request
* request
, bool is_48bit_cmd
);
253 freebsd_ata_device::freebsd_ata_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
)
254 : smart_device(intf
, dev_name
, "ata", req_type
),
255 freebsd_smart_device()
259 int freebsd_ata_device::do_cmd( struct ata_ioc_request
* request
, bool is_48bit_cmd
)
261 int fd
= get_fd(), ret
;
262 ARGUSED(is_48bit_cmd
); // no support for 48 bit commands in the IOCATAREQUEST
263 ret
= ioctl(fd
, IOCATAREQUEST
, request
);
264 if (ret
) set_err(errno
);
270 bool freebsd_ata_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
272 bool ata_48bit
= false; // no ata_48bit_support via IOCATAREQUEST
273 if(!strcmp("atacam",get_dev_type())) // enable for atacam interface
276 if (!ata_cmd_is_ok(in
,
277 true, // data_out_support
278 true, // multi_sector_support
281 set_err(ENOSYS
, "48-bit ATA commands not implemented for legacy controllers");
285 struct ata_ioc_request request
;
286 bzero(&request
,sizeof(struct ata_ioc_request
));
288 request
.timeout
=SCSI_TIMEOUT_DEFAULT
;
289 request
.u
.ata
.command
=in
.in_regs
.command
;
290 request
.u
.ata
.feature
=in
.in_regs
.features
;
292 request
.u
.ata
.count
= in
.in_regs
.sector_count_16
;
293 request
.u
.ata
.lba
= in
.in_regs
.lba_48
;
295 switch (in
.direction
) {
296 case ata_cmd_in::no_data
:
297 request
.flags
=ATA_CMD_CONTROL
;
299 case ata_cmd_in::data_in
:
300 request
.flags
=ATA_CMD_READ
| ATA_CMD_CONTROL
;
301 request
.data
=(char *)in
.buffer
;
302 request
.count
=in
.size
;
304 case ata_cmd_in::data_out
:
305 request
.flags
=ATA_CMD_WRITE
| ATA_CMD_CONTROL
;
306 request
.data
=(char *)in
.buffer
;
307 request
.count
=in
.size
;
310 return set_err(ENOSYS
);
315 if (do_cmd(&request
, in
.in_regs
.is_48bit_cmd()))
318 return set_err(EIO
, "request failed, error code 0x%02x", request
.error
);
320 out
.out_regs
.error
= request
.error
;
321 out
.out_regs
.sector_count_16
= request
.u
.ata
.count
;
322 out
.out_regs
.lba_48
= request
.u
.ata
.lba
;
325 // Command specific processing
326 if (in
.in_regs
.command
== ATA_SMART_CMD
327 && in
.in_regs
.features
== ATA_SMART_STATUS
328 && in
.out_needed
.lba_high
)
330 unsigned const char normal_lo
=0x4f, normal_hi
=0xc2;
331 unsigned const char failed_lo
=0xf4, failed_hi
=0x2c;
333 // Cyl low and Cyl high unchanged means "Good SMART status"
334 if (!(out
.out_regs
.lba_mid
==normal_lo
&& out
.out_regs
.lba_high
==normal_hi
)
335 // These values mean "Bad SMART status"
336 && !(out
.out_regs
.lba_mid
==failed_lo
&& out
.out_regs
.lba_high
==failed_hi
))
339 // We haven't gotten output that makes sense; print out some debugging info
341 snprintf(buf
, sizeof(buf
),
342 "CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
343 (int)request
.u
.ata
.command
,
344 (int)request
.u
.ata
.feature
,
345 (int)request
.u
.ata
.count
,
346 (int)((request
.u
.ata
.lba
) & 0xff),
347 (int)((request
.u
.ata
.lba
>>8) & 0xff),
348 (int)((request
.u
.ata
.lba
>>16) & 0xff),
350 printwarning(BAD_SMART
,buf
);
351 out
.out_regs
.lba_high
= failed_hi
;
352 out
.out_regs
.lba_mid
= failed_lo
;
359 #if FREEBSDVER > 800100
360 class freebsd_atacam_device
: public freebsd_ata_device
363 freebsd_atacam_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
)
364 : smart_device(intf
, dev_name
, "atacam", req_type
), freebsd_ata_device(intf
, dev_name
, req_type
)
368 virtual bool close();
372 struct cam_device
*m_camdev
;
374 virtual int do_cmd( struct ata_ioc_request
* request
, bool is_48bit_cmd
);
377 bool freebsd_atacam_device::open(){
378 const char *dev
= get_dev_name();
380 if ((m_camdev
= cam_open_device(dev
, O_RDWR
)) == NULL
) {
384 set_fd(m_camdev
->fd
);
388 bool freebsd_atacam_device::close(){
389 cam_close_device(m_camdev
);
394 int freebsd_atacam_device::do_cmd( struct ata_ioc_request
* request
, bool is_48bit_cmd
)
400 // 48bit commands are broken in ATACAM before r242422/HEAD
401 // and may cause system hang
402 // Waiting for MFC to make sure that bug is fixed,
403 // later version check needs to be added
404 if(!strcmp("ata",m_camdev
->sim_name
) && is_48bit_cmd
) {
405 set_err(ENOSYS
, "48-bit ATA commands not implemented for legacy controllers");
409 memset(&ccb
, 0, sizeof(ccb
));
411 if (request
->count
== 0)
412 camflags
= CAM_DIR_NONE
;
413 else if (request
->flags
& ATA_CMD_READ
)
414 camflags
= CAM_DIR_IN
;
416 camflags
= CAM_DIR_OUT
;
418 cam_fill_ataio(&ccb
.ataio
,
423 (u_int8_t
*)request
->data
,
425 request
->timeout
* 1000); // timeout in seconds
427 ccb
.ataio
.cmd
.flags
= CAM_ATAIO_NEEDRESULT
|
428 (is_48bit_cmd
? CAM_ATAIO_48BIT
: 0);
430 ccb
.ataio
.cmd
.command
= request
->u
.ata
.command
;
431 ccb
.ataio
.cmd
.features
= request
->u
.ata
.feature
;
432 ccb
.ataio
.cmd
.lba_low
= request
->u
.ata
.lba
;
433 ccb
.ataio
.cmd
.lba_mid
= request
->u
.ata
.lba
>> 8;
434 ccb
.ataio
.cmd
.lba_high
= request
->u
.ata
.lba
>> 16;
436 ccb
.ataio
.cmd
.lba_low_exp
= request
->u
.ata
.lba
>> 24;
437 ccb
.ataio
.cmd
.lba_mid_exp
= request
->u
.ata
.lba
>> 32;
438 ccb
.ataio
.cmd
.lba_high_exp
= request
->u
.ata
.lba
>> 40;
439 ccb
.ataio
.cmd
.device
= 0x40 | ((request
->u
.ata
.lba
>> 24) & 0x0f);
440 ccb
.ataio
.cmd
.sector_count
= request
->u
.ata
.count
;
441 ccb
.ataio
.cmd
.sector_count_exp
= request
->u
.ata
.count
>> 8;;
443 ccb
.ccb_h
.flags
|= CAM_DEV_QFRZDIS
;
445 if (cam_send_ccb(m_camdev
, &ccb
) < 0) {
446 set_err(EIO
, "cam_send_ccb failed");
450 if ((ccb
.ccb_h
.status
& CAM_STATUS_MASK
) != CAM_REQ_CMP
) {
451 if(scsi_debugmode
> 0)
452 cam_error_print(m_camdev
, &ccb
, CAM_ESF_ALL
, CAM_EPF_ALL
, stderr
);
458 ((u_int64_t
)(ccb
.ataio
.res
.lba_low
)) |
459 ((u_int64_t
)(ccb
.ataio
.res
.lba_mid
) << 8) |
460 ((u_int64_t
)(ccb
.ataio
.res
.lba_high
) << 16) |
461 ((u_int64_t
)(ccb
.ataio
.res
.lba_low_exp
) << 24) |
462 ((u_int64_t
)(ccb
.ataio
.res
.lba_mid_exp
) << 32) |
463 ((u_int64_t
)(ccb
.ataio
.res
.lba_high_exp
) << 40);
465 request
->u
.ata
.count
= ccb
.ataio
.res
.sector_count
| (ccb
.ataio
.res
.sector_count_exp
<< 8);
466 request
->error
= ccb
.ataio
.res
.error
;
473 /////////////////////////////////////////////////////////////////////////////
474 /// Implement AMCC/3ware RAID support
476 class freebsd_escalade_device
477 : public /*implements*/ ata_device
,
478 public /*extends*/ freebsd_smart_device
481 freebsd_escalade_device(smart_interface
* intf
, const char * dev_name
,
482 int escalade_type
, int disknum
);
485 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
489 int m_escalade_type
; ///< Type string for escalade_command_interface().
490 int m_disknum
; ///< Disk number.
493 freebsd_escalade_device::freebsd_escalade_device(smart_interface
* intf
, const char * dev_name
,
494 int escalade_type
, int disknum
)
495 : smart_device(intf
, dev_name
, "3ware", "3ware"),
496 freebsd_smart_device(),
497 m_escalade_type(escalade_type
), m_disknum(disknum
)
499 set_info().info_name
= strprintf("%s [3ware_disk_%02d]", dev_name
, disknum
);
502 bool freebsd_escalade_device::open()
504 const char *dev
= get_dev_name();
507 if ((fd
= ::open(dev
,O_RDWR
))<0) {
515 bool freebsd_escalade_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
517 // to hold true file descriptor
520 if (!ata_cmd_is_ok(in
,
521 true, // data_out_support
522 false, // TODO: multi_sector_support
523 true) // ata_48bit_support
527 struct twe_usercommand
* cmd_twe
= NULL
;
528 TW_OSLI_IOCTL_NO_DATA_BUF
* cmd_twa
= NULL
;
529 TWE_Command_ATA
* ata
= NULL
;
531 // Used by both the SCSI and char interfaces
532 char ioctl_buffer
[TW_IOCTL_BUFFER_SIZE
];
535 printwarning(NO_DISK_3WARE
,NULL
);
539 memset(ioctl_buffer
, 0, TW_IOCTL_BUFFER_SIZE
);
541 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
542 cmd_twa
= (TW_OSLI_IOCTL_NO_DATA_BUF
*)ioctl_buffer
;
543 cmd_twa
->pdata
= ((TW_OSLI_IOCTL_WITH_PAYLOAD
*)cmd_twa
)->payload
.data_buf
;
544 cmd_twa
->driver_pkt
.buffer_length
= in
.size
;
545 // using "old" packet format to speak with SATA devices
546 ata
= (TWE_Command_ATA
*)&cmd_twa
->cmd_pkt
.command
.cmd_pkt_7k
;
547 } else if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
548 cmd_twe
= (struct twe_usercommand
*)ioctl_buffer
;
549 ata
= &cmd_twe
->tu_command
.ata
;
551 return set_err(ENOSYS
,
552 "Unrecognized escalade_type %d in linux_3ware_command_interface(disk %d)\n"
553 "Please contact " PACKAGE_BUGREPORT
"\n", (int)m_escalade_type
, m_disknum
);
556 ata
->opcode
= TWE_OP_ATA_PASSTHROUGH
;
558 // Same for (almost) all commands - but some reset below
559 ata
->request_id
= 0xFF;
560 ata
->unit
= m_disknum
;
563 ata
->size
= 0x5; // TODO: multisector support
566 const ata_in_regs_48bit
& r
= in
.in_regs
;
567 ata
->features
= r
.features_16
;
568 ata
->sector_count
= r
.sector_count_16
;
569 ata
->sector_num
= r
.lba_low_16
;
570 ata
->cylinder_lo
= r
.lba_mid_16
;
571 ata
->cylinder_hi
= r
.lba_high_16
;
572 ata
->drive_head
= r
.device
;
573 ata
->command
= r
.command
;
576 // Is this a command that reads or returns 512 bytes?
577 // passthru->param values are:
578 // 0x0 - non data command without TFR write check,
579 // 0x8 - non data command with TFR write check,
580 // 0xD - data command that returns data to host from device
581 // 0xF - data command that writes data from host to device
582 // passthru->size values are 0x5 for non-data and 0x07 for data
583 bool readdata
= false;
584 if (in
.direction
== ata_cmd_in::data_in
) {
585 if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
586 cmd_twe
->tu_data
= in
.buffer
;
587 cmd_twe
->tu_size
= 512;
591 ata
->sgl_offset
= 0x5;
593 // For 64-bit to work correctly, up the size of the command packet
594 // in dwords by 1 to account for the 64-bit single sgl 'address'
595 // field. Note that this doesn't agree with the typedefs but it's
596 // right (agree with kernel driver behavior/typedefs).
597 // if (sizeof(long)==8)
600 else if (in
.direction
== ata_cmd_in::no_data
) {
601 // Non data command -- but doesn't use large sector
602 // count register values.
603 ata
->sgl_offset
= 0x0;
605 ata
->sector_count
= 0x0;
607 else if (in
.direction
== ata_cmd_in::data_out
) {
608 ata
->sgl_offset
= 0x5;
609 ata
->param
= 0xF; // PIO data write
610 if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
611 cmd_twe
->tu_data
= in
.buffer
;
612 cmd_twe
->tu_size
= 512;
614 else if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
615 memcpy(cmd_twa
->pdata
, in
.buffer
, in
.size
);
619 return set_err(EINVAL
);
621 // 3WARE controller can NOT have packet device internally
622 if (in
.in_regs
.command
== ATA_IDENTIFY_PACKET_DEVICE
) {
623 return set_err(ENODEV
, "No drive on port %d", m_disknum
);
626 // Now send the command down through an ioctl()
628 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
629 ioctlreturn
=ioctl(fd
,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH
,cmd_twa
);
631 ioctlreturn
=ioctl(fd
,TWEIO_COMMAND
,cmd_twe
);
634 // Deal with the different error cases
639 // See if the ATA command failed. Now that we have returned from
640 // the ioctl() call, if passthru is valid, then:
641 // - ata->status contains the 3ware controller STATUS
642 // - ata->command contains the ATA STATUS register
643 // - ata->features contains the ATA ERROR register
645 // Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS
646 // If bit 0 (error bit) is set, then ATA ERROR register is valid.
647 // While we *might* decode the ATA ERROR register, at the moment it
648 // doesn't make much sense: we don't care in detail why the error
651 if (ata
->status
|| (ata
->command
& 0x21)) {
653 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
);
657 // If this is a read data command, copy data to output buffer
659 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
)
660 memcpy(in
.buffer
, cmd_twa
->pdata
, in
.size
);
661 else if(m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
662 memcpy(in
.buffer
, cmd_twe
->tu_data
, in
.size
); // untested
665 // Return register values
667 ata_out_regs_48bit
& r
= out
.out_regs
;
668 r
.error
= ata
->features
;
669 r
.sector_count_16
= ata
->sector_count
;
670 r
.lba_low_16
= ata
->sector_num
;
671 r
.lba_mid_16
= ata
->cylinder_lo
;
672 r
.lba_high_16
= ata
->cylinder_hi
;
673 r
.device
= ata
->drive_head
;
674 r
.status
= ata
->command
;
676 // look for nonexistent devices/ports
677 if (in
.in_regs
.command
== ATA_IDENTIFY_DEVICE
678 && !nonempty((unsigned char *)in
.buffer
, in
.size
)) {
679 return set_err(ENODEV
, "No drive on port %d", m_disknum
);
685 /////////////////////////////////////////////////////////////////////////////
686 /// Implement Highpoint RAID support with old functions
688 class freebsd_highpoint_device
689 : public /*implements*/ ata_device_with_command_set
,
690 public /*extends*/ freebsd_smart_device
693 freebsd_highpoint_device(smart_interface
* intf
, const char * dev_name
,
694 unsigned char controller
, unsigned char channel
, unsigned char port
);
697 virtual int ata_command_interface(smart_command_set command
, int select
, char * data
);
701 unsigned char m_hpt_data
[3]; ///< controller/channel/port
705 freebsd_highpoint_device::freebsd_highpoint_device(smart_interface
* intf
, const char * dev_name
,
706 unsigned char controller
, unsigned char channel
, unsigned char port
)
707 : smart_device(intf
, dev_name
, "hpt", "hpt"),
708 freebsd_smart_device()
710 m_hpt_data
[0] = controller
; m_hpt_data
[1] = channel
; m_hpt_data
[2] = port
;
711 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]);
714 bool freebsd_highpoint_device::open()
716 const char *dev
= get_dev_name();
719 if ((fd
= ::open(dev
,O_RDWR
))<0) {
727 int freebsd_highpoint_device::ata_command_interface(smart_command_set command
, int select
, char * data
)
731 HPT_IOCTL_PARAM param
;
732 HPT_CHANNEL_INFO_V2 info
;
733 unsigned char* buff
[512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER
)];
734 PHPT_PASS_THROUGH_HEADER pide_pt_hdr
, pide_pt_hdr_out
;
736 // get internal deviceid
737 ids
[0] = m_hpt_data
[0] - 1;
738 ids
[1] = m_hpt_data
[1] - 1;
740 memset(¶m
, 0, sizeof(HPT_IOCTL_PARAM
));
742 param
.magic
= HPT_IOCTL_MAGIC
;
743 param
.ctrl_code
= HPT_IOCTL_GET_CHANNEL_INFO_V2
;
744 param
.in
= (unsigned char *)ids
;
745 param
.in_size
= sizeof(unsigned int) * 2;
746 param
.out
= (unsigned char *)&info
;
747 param
.out_size
= sizeof(HPT_CHANNEL_INFO_V2
);
749 if (m_hpt_data
[2]==1) {
750 param
.ctrl_code
= HPT_IOCTL_GET_CHANNEL_INFO
;
751 param
.out_size
= sizeof(HPT_CHANNEL_INFO
);
753 if (ioctl(fd
, HPT_DO_IOCONTROL
, ¶m
)!=0 ||
754 info
.devices
[m_hpt_data
[2]-1]==0) {
758 // perform smart action
759 memset(buff
, 0, 512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER
));
760 pide_pt_hdr
= (PHPT_PASS_THROUGH_HEADER
)buff
;
762 pide_pt_hdr
->lbamid
= 0x4f;
763 pide_pt_hdr
->lbahigh
= 0xc2;
764 pide_pt_hdr
->command
= ATA_SMART_CMD
;
765 pide_pt_hdr
->id
= info
.devices
[m_hpt_data
[2] - 1];
769 pide_pt_hdr
->feature
=ATA_SMART_READ_VALUES
;
770 pide_pt_hdr
->protocol
=HPT_READ
;
772 case READ_THRESHOLDS
:
773 pide_pt_hdr
->feature
=ATA_SMART_READ_THRESHOLDS
;
774 pide_pt_hdr
->protocol
=HPT_READ
;
777 pide_pt_hdr
->feature
=ATA_SMART_READ_LOG_SECTOR
;
778 pide_pt_hdr
->lbalow
=select
;
779 pide_pt_hdr
->protocol
=HPT_READ
;
782 pide_pt_hdr
->command
=ATA_IDENTIFY_DEVICE
;
783 pide_pt_hdr
->protocol
=HPT_READ
;
786 pide_pt_hdr
->feature
=ATA_SMART_ENABLE
;
789 pide_pt_hdr
->feature
=ATA_SMART_DISABLE
;
792 pide_pt_hdr
->feature
=ATA_SMART_AUTO_OFFLINE
;
793 pide_pt_hdr
->sectorcount
=select
;
796 pide_pt_hdr
->feature
=ATA_SMART_AUTOSAVE
;
797 pide_pt_hdr
->sectorcount
=select
;
799 case IMMEDIATE_OFFLINE
:
800 pide_pt_hdr
->feature
=ATA_SMART_IMMEDIATE_OFFLINE
;
801 pide_pt_hdr
->lbalow
=select
;
805 pide_pt_hdr
->feature
=ATA_SMART_STATUS
;
807 case CHECK_POWER_MODE
:
808 pide_pt_hdr
->command
=ATA_CHECK_POWER_MODE
;
811 memcpy(buff
+sizeof(HPT_PASS_THROUGH_HEADER
), data
, 512);
812 pide_pt_hdr
->feature
=ATA_SMART_WRITE_LOG_SECTOR
;
813 pide_pt_hdr
->lbalow
=select
;
814 pide_pt_hdr
->protocol
=HPT_WRITE
;
817 pout("Unrecognized command %d in highpoint_command_interface()\n"
818 "Please contact " PACKAGE_BUGREPORT
"\n", command
);
822 if (pide_pt_hdr
->protocol
!=0) {
823 pide_pt_hdr
->sectors
= 1;
824 pide_pt_hdr
->sectorcount
= 1;
827 memset(¶m
, 0, sizeof(HPT_IOCTL_PARAM
));
829 param
.magic
= HPT_IOCTL_MAGIC
;
830 param
.ctrl_code
= HPT_IOCTL_IDE_PASS_THROUGH
;
831 param
.in
= (unsigned char *)buff
;
832 param
.in_size
= sizeof(HPT_PASS_THROUGH_HEADER
) + (pide_pt_hdr
->protocol
==HPT_READ
? 0 : pide_pt_hdr
->sectors
* 512);
833 param
.out
= (unsigned char *)buff
+param
.in_size
;
834 param
.out_size
= sizeof(HPT_PASS_THROUGH_HEADER
) + (pide_pt_hdr
->protocol
==HPT_READ
? pide_pt_hdr
->sectors
* 512 : 0);
836 pide_pt_hdr_out
= (PHPT_PASS_THROUGH_HEADER
)param
.out
;
838 if ((ioctl(fd
, HPT_DO_IOCONTROL
, ¶m
)!=0) ||
839 (pide_pt_hdr_out
->command
& 1)) {
843 if (command
==STATUS_CHECK
)
845 unsigned const char normal_lo
=0x4f, normal_hi
=0xc2;
846 unsigned const char failed_lo
=0xf4, failed_hi
=0x2c;
847 unsigned char low
,high
;
849 high
= pide_pt_hdr_out
->lbahigh
;
850 low
= pide_pt_hdr_out
->lbamid
;
852 // Cyl low and Cyl high unchanged means "Good SMART status"
853 if (low
==normal_lo
&& high
==normal_hi
)
856 // These values mean "Bad SMART status"
857 if (low
==failed_lo
&& high
==failed_hi
)
860 // We haven't gotten output that makes sense; print out some debugging info
862 snprintf(buf
, sizeof(buf
),
863 "CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
864 (int)pide_pt_hdr_out
->command
,
865 (int)pide_pt_hdr_out
->feature
,
866 (int)pide_pt_hdr_out
->sectorcount
,
867 (int)pide_pt_hdr_out
->lbalow
,
868 (int)pide_pt_hdr_out
->lbamid
,
869 (int)pide_pt_hdr_out
->lbahigh
,
870 (int)pide_pt_hdr_out
->sectors
);
871 printwarning(BAD_SMART
,buf
);
873 else if (command
==CHECK_POWER_MODE
)
874 data
[0] = pide_pt_hdr_out
->sectorcount
& 0xff;
875 else if (pide_pt_hdr
->protocol
==HPT_READ
)
876 memcpy(data
, (unsigned char *)buff
+ 2 * sizeof(HPT_PASS_THROUGH_HEADER
),
877 pide_pt_hdr
->sectors
* 512);
882 /////////////////////////////////////////////////////////////////////////////
883 /// Standard SCSI support
885 class freebsd_scsi_device
886 : public /*implements*/ scsi_device
,
887 public /*extends*/ freebsd_smart_device
890 freebsd_scsi_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
);
892 virtual smart_device
* autodetect_open();
894 virtual bool scsi_pass_through(scsi_cmnd_io
* iop
);
898 virtual bool close();
901 struct cam_device
*m_camdev
;
904 bool freebsd_scsi_device::open(){
905 const char *dev
= get_dev_name();
907 if ((m_camdev
= cam_open_device(dev
, O_RDWR
)) == NULL
) {
911 set_fd(m_camdev
->fd
);
915 bool freebsd_scsi_device::close(){
916 cam_close_device(m_camdev
);
921 freebsd_scsi_device::freebsd_scsi_device(smart_interface
* intf
,
922 const char * dev_name
, const char * req_type
)
923 : smart_device(intf
, dev_name
, "scsi", req_type
),
924 freebsd_smart_device(),
930 bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io
* iop
)
934 if (scsi_debugmode
) {
936 const unsigned char * ucp
= iop
->cmnd
;
939 np
= scsi_get_opcode_name(ucp
[0]);
940 pout(" [%s: ", np
? np
: "<unknown opcode>");
941 for (k
= 0; k
< iop
->cmnd_len
; ++k
)
942 pout("%02x ", ucp
[k
]);
943 if ((scsi_debugmode
> 1) &&
944 (DXFER_TO_DEVICE
== iop
->dxfer_dir
) && (iop
->dxferp
)) {
945 int trunc
= (iop
->dxfer_len
> 256) ? 1 : 0;
947 pout("]\n Outgoing data, len=%d%s:\n", (int)iop
->dxfer_len
,
948 (trunc
? " [only first 256 bytes shown]" : ""));
949 dStrHex(iop
->dxferp
, (trunc
? 256 : iop
->dxfer_len
) , 1);
957 pout(" error: camdev=0!\n");
958 return set_err(ENOTTY
);
961 if (!(ccb
= cam_getccb(m_camdev
))) {
963 pout(" error allocating ccb\n");
964 return set_err(ENOMEM
);
967 // mfi SAT layer is known to be buggy
968 if(!strcmp("mfi",m_camdev
->sim_name
)) {
969 if (iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_12
|| iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_16
) {
970 // Controller does not return ATA output registers in SAT sense data
971 if (iop
->cmnd
[2] & (1 << 5)) // chk_cond
972 return set_err(ENOSYS
, "ATA return descriptor not supported by controller firmware");
974 // SMART WRITE LOG SECTOR causing media errors
975 if ((iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_16
976 && iop
->cmnd
[14] == ATA_SMART_CMD
&& iop
->cmnd
[3]==0 &&
977 iop
->cmnd
[4] == ATA_SMART_WRITE_LOG_SECTOR
) ||
978 (iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_12
979 && iop
->cmnd
[9] == ATA_SMART_CMD
&& iop
->cmnd
[3] == ATA_SMART_WRITE_LOG_SECTOR
))
981 if(!failuretest_permissive
)
982 return set_err(ENOSYS
, "SMART WRITE LOG SECTOR may cause problems, try with -T permissive to force");
985 // clear out structure, except for header that was filled in for us
986 bzero(&(&ccb
->ccb_h
)[1],
987 sizeof(struct ccb_scsiio
) - sizeof(struct ccb_hdr
));
989 cam_fill_csio(&ccb
->csio
,
992 /* flags */ (iop
->dxfer_dir
== DXFER_NONE
? CAM_DIR_NONE
:(iop
->dxfer_dir
== DXFER_FROM_DEVICE
? CAM_DIR_IN
: CAM_DIR_OUT
)),
993 /* tagaction */ MSG_SIMPLE_Q_TAG
,
994 /* dataptr */ iop
->dxferp
,
995 /* datalen */ iop
->dxfer_len
,
996 /* senselen */ iop
->max_sense_len
,
997 /* cdblen */ iop
->cmnd_len
,
998 /* timout (converted to seconds) */ iop
->timeout
*1000);
999 memcpy(ccb
->csio
.cdb_io
.cdb_bytes
,iop
->cmnd
,iop
->cmnd_len
);
1001 if (cam_send_ccb(m_camdev
,ccb
) < 0) {
1002 if (scsi_debugmode
) {
1003 pout(" error sending SCSI ccb\n");
1004 cam_error_print(m_camdev
,ccb
,CAM_ESF_ALL
,CAM_EPF_ALL
,stderr
);
1007 return set_err(EIO
);
1010 if (scsi_debugmode
) {
1011 pout(" CAM status=0x%x, SCSI status=0x%x, resid=0x%x\n",
1012 ccb
->ccb_h
.status
, ccb
->csio
.scsi_status
, ccb
->csio
.resid
);
1013 if ((scsi_debugmode
> 1) && (DXFER_FROM_DEVICE
== iop
->dxfer_dir
)) {
1016 len
= iop
->dxfer_len
- ccb
->csio
.resid
;
1017 trunc
= (len
> 256) ? 1 : 0;
1019 pout(" Incoming data, len=%d%s:\n", len
,
1020 (trunc
? " [only first 256 bytes shown]" : ""));
1021 dStrHex(iop
->dxferp
, (trunc
? 256 : len
), 1);
1024 pout(" Incoming data trimmed to nothing by resid\n");
1028 if (((ccb
->ccb_h
.status
& CAM_STATUS_MASK
) != CAM_REQ_CMP
) && ((ccb
->ccb_h
.status
& CAM_STATUS_MASK
) != CAM_SCSI_STATUS_ERROR
)) {
1030 cam_error_print(m_camdev
,ccb
,CAM_ESF_ALL
,CAM_EPF_ALL
,stderr
);
1032 return set_err(EIO
);
1035 iop
->resid
= ccb
->csio
.resid
;
1036 iop
->scsi_status
= ccb
->csio
.scsi_status
;
1037 if (iop
->sensep
&& (ccb
->ccb_h
.status
& CAM_AUTOSNS_VALID
) != 0) {
1039 pout(" sense_len=0x%x, sense_resid=0x%x\n",
1040 ccb
->csio
.sense_len
, ccb
->csio
.sense_resid
);
1041 iop
->resp_sense_len
= ccb
->csio
.sense_len
- ccb
->csio
.sense_resid
;
1042 /* Some SCSI controller device drivers miscalculate the sense_resid
1043 field so cap resp_sense_len on max_sense_len. */
1044 if (iop
->resp_sense_len
> iop
->max_sense_len
)
1045 iop
->resp_sense_len
= iop
->max_sense_len
;
1046 if (iop
->resp_sense_len
> 0) {
1047 memcpy(iop
->sensep
, &(ccb
->csio
.sense_data
), iop
->resp_sense_len
);
1048 if (scsi_debugmode
) {
1049 if (scsi_debugmode
> 1) {
1050 pout(" >>> Sense buffer, len=%zu:\n", iop
->resp_sense_len
);
1051 dStrHex(iop
->sensep
, iop
->resp_sense_len
, 1);
1053 if ((iop
->sensep
[0] & 0x7f) > 0x71)
1054 pout(" status=0x%x: [desc] sense_key=0x%x asc=0x%x ascq=0x%x\n",
1055 iop
->scsi_status
, iop
->sensep
[1] & 0xf,
1056 iop
->sensep
[2], iop
->sensep
[3]);
1058 pout(" status=0x%x: sense_key=0x%x asc=0x%x ascq=0x%x\n",
1059 iop
->scsi_status
, iop
->sensep
[2] & 0xf,
1060 iop
->sensep
[12], iop
->sensep
[13]);
1063 else if (scsi_debugmode
)
1064 pout(" status=0x%x\n", iop
->scsi_status
);
1066 else if (scsi_debugmode
)
1067 pout(" status=0x%x\n", iop
->scsi_status
);
1071 // mfip replacing PDT of the device so response does not make a sense
1072 // this sets PDT to 00h - direct-access block device
1073 if((!strcmp("mfi", m_camdev
->sim_name
) || !strcmp("mpt", m_camdev
->sim_name
))
1074 && iop
->cmnd
[0] == INQUIRY
) {
1075 if (scsi_debugmode
) {
1076 pout(" device on %s controller, patching PDT\n", m_camdev
->sim_name
);
1078 iop
->dxferp
[0] = iop
->dxferp
[0] & 0xe0;
1085 /////////////////////////////////////////////////////////////////////////////
1086 /// Areca RAID support
1088 ///////////////////////////////////////////////////////////////////
1089 // SATA(ATA) device behind Areca RAID Controller
1090 class freebsd_areca_ata_device
1091 : public /*implements*/ areca_ata_device
,
1092 public /*extends*/ freebsd_smart_device
1095 freebsd_areca_ata_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
= 1);
1096 virtual smart_device
* autodetect_open();
1097 virtual bool arcmsr_lock();
1098 virtual bool arcmsr_unlock();
1099 virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
);
1102 ///////////////////////////////////////////////////////////////////
1103 // SAS(SCSI) device behind Areca RAID Controller
1104 class freebsd_areca_scsi_device
1105 : public /*implements*/ areca_scsi_device
,
1106 public /*extends*/ freebsd_smart_device
1109 freebsd_areca_scsi_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
= 1);
1110 virtual smart_device
* autodetect_open();
1111 virtual bool arcmsr_lock();
1112 virtual bool arcmsr_unlock();
1113 virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
);
1117 // Areca RAID Controller(SATA Disk)
1118 freebsd_areca_ata_device::freebsd_areca_ata_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
)
1119 : smart_device(intf
, dev_name
, "areca", "areca"),
1120 freebsd_smart_device()
1122 set_disknum(disknum
);
1124 set_info().info_name
= strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name
, disknum
, encnum
);
1128 smart_device
* freebsd_areca_ata_device::autodetect_open()
1130 // autodetect device type
1131 int is_ata
= arcmsr_get_dev_type();
1145 smart_device_auto_ptr
newdev(new freebsd_areca_scsi_device(smi(), get_dev_name(), get_disknum(), get_encnum()));
1148 newdev
->open(); // TODO: Can possibly pass open fd
1150 return newdev
.release();
1153 int freebsd_areca_ata_device::arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
)
1155 int ioctlreturn
= 0;
1162 ioctlreturn
= ioctl(get_fd(), ((sSRB_BUFFER
*)(iop
->dxferp
))->srbioctl
.ControlCode
, iop
->dxferp
);
1172 bool freebsd_areca_ata_device::arcmsr_lock()
1178 bool freebsd_areca_ata_device::arcmsr_unlock()
1184 // Areca RAID Controller(SAS Device)
1185 freebsd_areca_scsi_device::freebsd_areca_scsi_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
)
1186 : smart_device(intf
, dev_name
, "areca", "areca"),
1187 freebsd_smart_device()
1189 set_disknum(disknum
);
1191 set_info().info_name
= strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name
, disknum
, encnum
);
1194 smart_device
* freebsd_areca_scsi_device::autodetect_open()
1199 int freebsd_areca_scsi_device::arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
)
1201 int ioctlreturn
= 0;
1207 ioctlreturn
= ioctl(get_fd(), ((sSRB_BUFFER
*)(iop
->dxferp
))->srbioctl
.ControlCode
, iop
->dxferp
);
1217 bool freebsd_areca_scsi_device::arcmsr_lock()
1223 bool freebsd_areca_scsi_device::arcmsr_unlock()
1229 /////////////////////////////////////////////////////////////////////////////
1230 /// Implement CCISS RAID support with old functions
1232 class freebsd_cciss_device
1233 : public /*implements*/ scsi_device
,
1234 public /*extends*/ freebsd_smart_device
1237 freebsd_cciss_device(smart_interface
* intf
, const char * name
, unsigned char disknum
);
1239 virtual bool scsi_pass_through(scsi_cmnd_io
* iop
);
1240 virtual bool open();
1243 unsigned char m_disknum
; ///< Disk number.
1246 bool freebsd_cciss_device::open()
1248 const char *dev
= get_dev_name();
1250 if ((fd
= ::open(dev
,O_RDWR
))<0) {
1258 freebsd_cciss_device::freebsd_cciss_device(smart_interface
* intf
,
1259 const char * dev_name
, unsigned char disknum
)
1260 : smart_device(intf
, dev_name
, "cciss", "cciss"),
1261 freebsd_smart_device(),
1264 set_info().info_name
= strprintf("%s [cciss_disk_%02d]", dev_name
, disknum
);
1267 bool freebsd_cciss_device::scsi_pass_through(scsi_cmnd_io
* iop
)
1269 int status
= cciss_io_interface(get_fd(), m_disknum
, iop
, scsi_debugmode
);
1271 return set_err(-status
);
1278 /////////////////////////////////////////////////////////////////////////////
1279 /// SCSI open with autodetection support
1281 smart_device
* freebsd_scsi_device::autodetect_open()
1287 // No Autodetection if device type was specified by user
1288 if (*get_req_type())
1291 // The code below is based on smartd.cpp:SCSIFilterKnown()
1294 unsigned char req_buff
[64] = {0, };
1296 if (scsiStdInquiry(this, req_buff
, req_len
)) {
1297 // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices
1298 // watch this spot ... other devices could lock up here
1300 if (scsiStdInquiry(this, req_buff
, req_len
)) {
1301 // device doesn't like INQUIRY commands
1303 set_err(EIO
, "INQUIRY failed");
1308 int avail_len
= req_buff
[4] + 5;
1309 int len
= (avail_len
< req_len
? avail_len
: req_len
);
1313 // Use INQUIRY to detect type
1316 if (!memcmp(req_buff
+ 8, "3ware", 5) || !memcmp(req_buff
+ 8, "AMCC", 4) ||
1317 !strcmp("tws",m_camdev
->sim_name
) || !strcmp("twa",m_camdev
->sim_name
)) {
1319 set_err(EINVAL
, "3ware/LSI controller, please try adding '-d 3ware,N',\n"
1320 "you may need to replace %s with /dev/twaN, /dev/tweN or /dev/twsN", get_dev_name());
1324 // SAT or USB, skip MFI controllers because of bugs
1326 smart_device
* newdev
= smi()->autodetect_sat_device(this, req_buff
, len
);
1328 // NOTE: 'this' is now owned by '*newdev'
1329 if(!strcmp("mfi",m_camdev
->sim_name
)) {
1331 newdev
->set_err(ENOSYS
, "SATA device detected,\n"
1332 "MegaRAID SAT layer is reportedly buggy, use '-d sat' to try anyhow");
1338 // Nothing special found
1343 /////////////////////////////////////////////////////////////////////////////
1344 /// Implement platform interface with old functions.
1346 class freebsd_smart_interface
1347 : public /*implements*/ smart_interface
1350 virtual std::string
get_os_version_str();
1352 virtual std::string
get_app_examples(const char * appname
);
1354 virtual bool scan_smart_devices(smart_device_list
& devlist
, const char * type
,
1355 const char * pattern
= 0);
1358 virtual ata_device
* get_ata_device(const char * name
, const char * type
);
1360 #if FREEBSDVER > 800100
1361 virtual ata_device
* get_atacam_device(const char * name
, const char * type
);
1364 virtual scsi_device
* get_scsi_device(const char * name
, const char * type
);
1366 virtual smart_device
* autodetect_smart_device(const char * name
);
1368 virtual smart_device
* get_custom_smart_device(const char * name
, const char * type
);
1370 virtual std::string
get_valid_custom_dev_types_str();
1374 //////////////////////////////////////////////////////////////////////
1376 std::string
freebsd_smart_interface::get_os_version_str()
1378 struct utsname osname
;
1380 return strprintf("%s %s %s", osname
.sysname
, osname
.release
, osname
.machine
);
1383 std::string
freebsd_smart_interface::get_app_examples(const char * appname
)
1385 if (!strcmp(appname
, "smartctl"))
1386 return smartctl_examples
;
1390 ata_device
* freebsd_smart_interface::get_ata_device(const char * name
, const char * type
)
1392 return new freebsd_ata_device(this, name
, type
);
1395 #if FREEBSDVER > 800100
1396 ata_device
* freebsd_smart_interface::get_atacam_device(const char * name
, const char * type
)
1398 return new freebsd_atacam_device(this, name
, type
);
1402 scsi_device
* freebsd_smart_interface::get_scsi_device(const char * name
, const char * type
)
1404 return new freebsd_scsi_device(this, name
, type
);
1407 // we are using CAM subsystem XPT enumerator to found all CAM (scsi/usb/ada/...)
1408 // devices on system despite of it's names
1410 // If any errors occur, leave errno set as it was returned by the
1411 // system call, and return <0.
1414 // names: resulting array
1415 // show_all - export duplicate device name or not
1419 // >=0: number of discovered devices
1421 bool get_dev_names_cam(std::vector
<std::string
> & names
, bool show_all
)
1424 if ((fd
= open(XPT_DEVICE
, O_RDWR
)) == -1) {
1425 if (errno
== ENOENT
) /* There are no CAM device on this computer */
1428 pout("%s control device couldn't opened: %s\n", XPT_DEVICE
, strerror(errno
));
1434 bzero(&ccb
, sizeof(union ccb
));
1436 ccb
.ccb_h
.path_id
= CAM_XPT_PATH_ID
;
1437 ccb
.ccb_h
.target_id
= CAM_TARGET_WILDCARD
;
1438 ccb
.ccb_h
.target_lun
= CAM_LUN_WILDCARD
;
1440 ccb
.ccb_h
.func_code
= XPT_DEV_MATCH
;
1441 int bufsize
= sizeof(struct dev_match_result
) * MAX_NUM_DEV
;
1442 ccb
.cdm
.match_buf_len
= bufsize
;
1443 // TODO: Use local buffer instead of malloc() if possible
1444 ccb
.cdm
.matches
= (struct dev_match_result
*)malloc(bufsize
);
1445 bzero(ccb
.cdm
.matches
,bufsize
); // clear ccb.cdm.matches structure
1447 if (ccb
.cdm
.matches
== NULL
) {
1449 throw std::bad_alloc();
1451 ccb
.cdm
.num_matches
= 0;
1452 ccb
.cdm
.num_patterns
= 0;
1453 ccb
.cdm
.pattern_buf_len
= 0;
1456 * We do the ioctl multiple times if necessary, in case there are
1457 * more than MAX_NUM_DEV nodes in the EDT.
1459 int skip_device
= 0, skip_bus
= 0, changed
= 0; // TODO: bool
1460 std::string devname
;
1462 if (ioctl(fd
, CAMIOCOMMAND
, &ccb
) == -1) {
1464 pout("error sending CAMIOCOMMAND ioctl: %s\n", strerror(errno
));
1465 free(ccb
.cdm
.matches
);
1471 if ((ccb
.ccb_h
.status
!= CAM_REQ_CMP
)
1472 || ((ccb
.cdm
.status
!= CAM_DEV_MATCH_LAST
)
1473 && (ccb
.cdm
.status
!= CAM_DEV_MATCH_MORE
))) {
1474 pout("got CAM error %#x, CDM error %d\n", ccb
.ccb_h
.status
, ccb
.cdm
.status
);
1475 free(ccb
.cdm
.matches
);
1481 for (unsigned i
= 0; i
< ccb
.cdm
.num_matches
; i
++) {
1482 struct device_match_result
*dev_result
;
1483 struct periph_match_result
*periph_result
;
1485 if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_BUS
) {
1486 struct bus_match_result
*bus_result
;
1488 bus_result
= &ccb
.cdm
.matches
[i
].result
.bus_result
;
1490 if (strcmp(bus_result
->dev_name
,"xpt") == 0) /* skip XPT bus at all */
1495 } else if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_DEVICE
) {
1496 dev_result
= &ccb
.cdm
.matches
[i
].result
.device_result
;
1498 if (dev_result
->flags
& DEV_RESULT_UNCONFIGURED
|| skip_bus
== 1)
1503 // /* Shall we skip non T_DIRECT devices ? */
1504 // if (dev_result->inq_data.device != T_DIRECT)
1507 } else if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_PERIPH
&&
1508 (skip_device
== 0 || show_all
)) {
1509 /* One device may be populated as many peripherals (pass0 & da0 for example).
1510 * We are searching for best name
1512 periph_result
= &ccb
.cdm
.matches
[i
].result
.periph_result
;
1513 /* Prefer non-"pass" names */
1514 if (devname
.empty() || strncmp(periph_result
->periph_name
, "pass", 4) != 0) {
1515 devname
= strprintf("%s%s%d", _PATH_DEV
, periph_result
->periph_name
, periph_result
->unit_number
);
1519 if ((changed
== 1 || show_all
) && !devname
.empty()) {
1520 names
.push_back(devname
);
1526 } while ((ccb
.ccb_h
.status
== CAM_REQ_CMP
) && (ccb
.cdm
.status
== CAM_DEV_MATCH_MORE
));
1528 if (!devname
.empty())
1529 names
.push_back(devname
);
1531 free(ccb
.cdm
.matches
);
1536 // we are using ATA subsystem enumerator to found all ATA devices on system
1537 // despite of it's names
1539 // If any errors occur, leave errno set as it was returned by the
1540 // system call, and return <0.
1544 // >=0: number of discovered devices
1545 int get_dev_names_ata(char*** names
) {
1546 struct ata_ioc_devices devices
;
1547 int fd
=-1,maxchannel
,serrno
=-1,n
=0;
1552 if ((fd
= open(ATA_DEVICE
, O_RDWR
)) < 0) {
1553 if (errno
== ENOENT
) /* There are no ATA device on this computer */
1556 pout("%s control device can't be opened: %s\n", ATA_DEVICE
, strerror(errno
));
1561 if (ioctl(fd
, IOCATAGMAXCHANNEL
, &maxchannel
) < 0) {
1563 pout("ioctl(IOCATAGMAXCHANNEL) on /dev/ata failed: %s\n", strerror(errno
));
1568 // allocate space for up to MAX_NUM_DEV number of ATA devices
1569 mp
= (char **)calloc(MAX_NUM_DEV
, sizeof(char*));
1572 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__
);
1577 for (devices
.channel
= 0; devices
.channel
< maxchannel
&& n
< MAX_NUM_DEV
; devices
.channel
++) {
1580 if (ioctl(fd
, IOCATADEVICES
, &devices
) < 0) {
1582 continue; /* such channel not exist */
1583 pout("ioctl(IOCATADEVICES) on %s channel %d failed: %s\n", ATA_DEVICE
, devices
.channel
, strerror(errno
));
1587 for (j
=0;j
<=1 && n
<MAX_NUM_DEV
;j
++) {
1588 if (devices
.name
[j
][0] != '\0') {
1589 asprintf(mp
+n
, "%s%s", _PATH_DEV
, devices
.name
[j
]);
1590 if (mp
[n
] == NULL
) {
1591 pout("Out of memory constructing scan ATA device list (on line %d)\n", __LINE__
);
1595 bytes
+=1+strlen(mp
[n
]);
1602 mp
= (char **)reallocf(mp
,n
*(sizeof (char*))); // shrink to correct size
1605 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__
);
1609 bytes
+= (n
)*(sizeof(char*)); // and set allocated byte count
1628 bool freebsd_smart_interface::scan_smart_devices(smart_device_list
& devlist
,
1629 const char * type
, const char * pattern
/*= 0*/)
1632 set_err(EINVAL
, "DEVICESCAN with pattern not implemented yet");
1637 char * * atanames
= 0; int numata
= 0;
1638 if (!type
|| !strcmp(type
, "ata")) {
1639 numata
= get_dev_names_ata(&atanames
);
1646 std::vector
<std::string
> scsinames
;
1647 if (!type
|| !strcmp(type
, "scsi")) { // do not export duplicated names
1648 if (!get_dev_names_cam(scsinames
, false)) {
1658 for (i
= 0; i
< numata
; i
++) {
1659 ata_device
* atadev
= get_ata_device(atanames
[i
], type
);
1661 devlist
.push_back(atadev
);
1664 if(numata
) free(atanames
);
1666 for (i
= 0; i
< (int)scsinames
.size(); i
++) {
1667 if(!*type
) { // try USB autodetection if no type specified
1668 smart_device
* smartdev
= autodetect_smart_device(scsinames
[i
].c_str());
1670 devlist
.push_back(smartdev
);
1673 scsi_device
* scsidev
= get_scsi_device(scsinames
[i
].c_str(), type
);
1675 devlist
.push_back(scsidev
);
1682 #if (FREEBSDVER < 800000) // without this build fail on FreeBSD 8
1683 static char done
[USB_MAX_DEVICES
];
1685 static int usbdevinfo(int f
, int a
, int rec
, int busno
, unsigned short & vendor_id
,
1686 unsigned short & product_id
, unsigned short & version
)
1689 struct usb_device_info di
;
1693 snprintf(devname
, sizeof(devname
),"umass%d",busno
);
1696 e
= ioctl(f
, USB_DEVICEINFO
, &di
);
1699 printf("addr %d: I/O error\n", a
);
1705 for (i
= 0; i
< USB_MAX_DEVNAMES
; i
++) {
1706 if (di
.udi_devnames
[i
][0]) {
1707 if(strcmp(di
.udi_devnames
[i
],devname
)==0) {
1709 vendor_id
= di
.udi_vendorNo
;
1710 product_id
= di
.udi_productNo
;
1711 version
= di
.udi_releaseNo
;
1719 for (p
= 0; p
< di
.udi_nports
; p
++) {
1720 int s
= di
.udi_ports
[p
];
1721 if (s
>= USB_MAX_DEVICES
) {
1725 printf("addr 0 should never happen!\n");
1727 if(usbdevinfo(f
, s
, 1, busno
, vendor_id
, product_id
, version
)) return 1;
1735 static int usbdevlist(int busno
,unsigned short & vendor_id
,
1736 unsigned short & product_id
, unsigned short & version
)
1738 #if (FREEBSDVER >= 800000) // libusb2 interface
1739 struct libusb20_device
*pdev
= NULL
;
1740 struct libusb20_backend
*pbe
;
1741 uint32_t matches
= 0;
1742 char buf
[128]; // do not change!
1745 struct LIBUSB20_DEVICE_DESC_DECODED
*pdesc
;
1747 pbe
= libusb20_be_alloc_default();
1749 while ((pdev
= libusb20_be_device_foreach(pbe
, pdev
))) {
1752 if (libusb20_dev_open(pdev
, 0)) {
1753 warnx("libusb20_dev_open: could not open device");
1757 pdesc
=libusb20_dev_get_device_desc(pdev
);
1759 snprintf(devname
, sizeof(devname
),"umass%d:",busno
);
1760 for (n
= 0; n
!= 255; n
++) {
1761 if (libusb20_dev_get_iface_desc(pdev
, n
, buf
, sizeof(buf
)))
1765 if(strncmp(buf
,devname
,strlen(devname
))==0){
1767 vendor_id
= pdesc
->idVendor
;
1768 product_id
= pdesc
->idProduct
;
1769 version
= pdesc
->bcdDevice
;
1770 libusb20_dev_close(pdev
);
1771 libusb20_be_free(pbe
);
1776 libusb20_dev_close(pdev
);
1780 printf("No device match or lack of permissions.\n");
1783 libusb20_be_free(pbe
);
1786 #else // freebsd < 8.0 USB stack, ioctl interface
1792 for (ncont
= 0, i
= 0; i
< 10; i
++) {
1793 snprintf(buf
, sizeof(buf
), "%s%d", USBDEV
, i
);
1794 int f
= open(buf
, O_RDONLY
);
1796 memset(done
, 0, sizeof done
);
1797 for (a
= 1; a
< USB_MAX_DEVICES
; a
++) {
1799 rc
= usbdevinfo(f
, a
, 1, busno
,vendor_id
, product_id
, version
);
1806 if (errno
== ENOENT
|| errno
== ENXIO
)
1816 smart_device
* freebsd_smart_interface::autodetect_smart_device(const char * name
)
1818 unsigned short vendor_id
= 0, product_id
= 0, version
= 0;
1819 struct cam_device
*cam_dev
;
1823 const char * test_name
= name
;
1825 // if dev_name null, or string length zero
1826 if (!name
|| !*name
)
1829 // Dereference symlinks
1831 std::string pathbuf
;
1832 if (!lstat(name
, &st
) && S_ISLNK(st
.st_mode
)) {
1833 char * p
= realpath(name
, (char *)0);
1837 test_name
= pathbuf
.c_str();
1842 char * * atanames
= 0; int numata
= 0;
1843 numata
= get_dev_names_ata(&atanames
);
1845 // check ATA/ATAPI devices
1846 for (i
= 0; i
< numata
; i
++) {
1847 if(!strcmp(atanames
[i
],test_name
)) {
1848 for (int c
= i
; c
< numata
; c
++) free(atanames
[c
]);
1850 return new freebsd_ata_device(this, test_name
, "");
1852 else free(atanames
[i
]);
1854 if(numata
) free(atanames
);
1858 pout("Unable to get ATA device list\n");
1862 std::vector
<std::string
> scsinames
;
1863 if (!get_dev_names_cam(scsinames
, true))
1864 pout("Unable to get CAM device list\n");
1865 else if (!scsinames
.empty()) {
1866 // check all devices on CAM bus
1867 for (i
= 0; i
< (int)scsinames
.size(); i
++) {
1868 if(strcmp(scsinames
[i
].c_str(), test_name
)==0)
1869 { // our disk device is CAM
1870 if(strncmp(scsinames
[i
].c_str(), "/dev/pmp", strlen("/dev/pmp")) == 0) {
1871 pout("Skipping port multiplier [%s]\n", scsinames
[i
].c_str());
1875 if ((cam_dev
= cam_open_device(test_name
, O_RDWR
)) == NULL
) {
1881 bzero(&(&ccb
.ccb_h
)[1], PATHINQ_SETTINGS_SIZE
);
1882 ccb
.ccb_h
.func_code
= XPT_PATH_INQ
; // send PATH_INQ to the device
1883 if (ioctl(cam_dev
->fd
, CAMIOCOMMAND
, &ccb
) == -1) {
1884 warn("Get Transfer Settings CCB failed\n"
1885 "%s", strerror(errno
));
1886 cam_close_device(cam_dev
);
1889 // now check if we are working with USB device, see umass.c
1890 if(strcmp(ccb
.cpi
.dev_name
,"umass-sim") == 0) { // USB device found
1891 usbdevlist(bus
,vendor_id
, product_id
, version
);
1892 int bus
=ccb
.cpi
.unit_number
; // unit_number will match umass number
1893 cam_close_device(cam_dev
);
1894 if(usbdevlist(bus
,vendor_id
, product_id
, version
)){
1895 const char * usbtype
= get_usb_dev_type_by_id(vendor_id
, product_id
, version
);
1897 return get_sat_device(usbtype
, new freebsd_scsi_device(this, test_name
, ""));
1901 #if FREEBSDVER > 800100
1902 // check if we have ATA device connected to CAM (ada)
1903 if(ccb
.cpi
.protocol
== PROTO_ATA
){
1904 cam_close_device(cam_dev
);
1905 return new freebsd_atacam_device(this, test_name
, "");
1908 // close cam device, we don`t need it anymore
1909 cam_close_device(cam_dev
);
1910 // handle as usual scsi
1911 return new freebsd_scsi_device(this, test_name
, "");
1915 // device is LSI raid supported by mfi driver
1916 if(!strncmp("/dev/mfid", test_name
, strlen("/dev/mfid")))
1917 set_err(EINVAL
, "To monitor disks on LSI RAID load mfip.ko module and run 'smartctl -a /dev/passX' to show SMART information");
1918 // device type unknown
1923 smart_device
* freebsd_smart_interface::get_custom_smart_device(const char * name
, const char * type
)
1925 int disknum
= -1, n1
= -1, n2
= -1;
1927 if (sscanf(type
, "3ware,%n%d%n", &n1
, &disknum
, &n2
) == 1 || n1
== 6) {
1929 static const char * fbsd_dev_twe_ctrl
= "/dev/twe";
1930 static const char * fbsd_dev_twa_ctrl
= "/dev/twa";
1931 static const char * fbsd_dev_tws_ctrl
= "/dev/tws";
1934 if (n2
!= (int)strlen(type
)) {
1935 set_err(EINVAL
, "Option -d 3ware,N requires N to be a non-negative integer");
1938 if (!(0 <= disknum
&& disknum
<= 127)) {
1939 set_err(EINVAL
, "Option -d 3ware,N (N=%d) must have 0 <= N <= 127", disknum
);
1943 // guess 3ware device type based on device name
1944 if (str_starts_with(name
, fbsd_dev_twa_ctrl
) ||
1945 str_starts_with(name
, fbsd_dev_tws_ctrl
) ) {
1946 contr
=CONTROLLER_3WARE_9000_CHAR
;
1948 if (!strncmp(fbsd_dev_twe_ctrl
, name
, strlen(fbsd_dev_twe_ctrl
))){
1949 contr
=CONTROLLER_3WARE_678K_CHAR
;
1953 set_err(EINVAL
, "3ware controller type unknown, use %sX, %sX or %sX devices",
1954 fbsd_dev_twe_ctrl
, fbsd_dev_twa_ctrl
, fbsd_dev_tws_ctrl
);
1957 return new freebsd_escalade_device(this, name
, contr
, disknum
);
1961 int controller
= -1, channel
= -1; disknum
= 1;
1962 n1
= n2
= -1; int n3
= -1;
1963 if (sscanf(type
, "hpt,%n%d/%d%n/%d%n", &n1
, &controller
, &channel
, &n2
, &disknum
, &n3
) >= 2 || n1
== 4) {
1964 int len
= strlen(type
);
1965 if (!(n2
== len
|| n3
== len
)) {
1966 set_err(EINVAL
, "Option '-d hpt,L/M/N' supports 2-3 items");
1969 if (!(1 <= controller
&& controller
<= 8)) {
1970 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid controller id L supplied");
1973 if (!(1 <= channel
&& channel
<= 128)) {
1974 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid channel number M supplied");
1977 if (!(1 <= disknum
&& disknum
<= 15)) {
1978 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid pmport number N supplied");
1981 return new freebsd_highpoint_device(this, name
, controller
, channel
, disknum
);
1985 disknum
= n1
= n2
= -1;
1986 if (sscanf(type
, "cciss,%n%d%n", &n1
, &disknum
, &n2
) == 1 || n1
== 6) {
1987 if (n2
!= (int)strlen(type
)) {
1988 set_err(EINVAL
, "Option -d cciss,N requires N to be a non-negative integer");
1991 if (!(0 <= disknum
&& disknum
<= 127)) {
1992 set_err(EINVAL
, "Option -d cciss,N (N=%d) must have 0 <= N <= 127", disknum
);
1995 return get_sat_device("sat,auto", new freebsd_cciss_device(this, name
, disknum
));
1997 #if FREEBSDVER > 800100
1999 if(!strcmp(type
,"atacam"))
2000 return new freebsd_atacam_device(this, name
, "");
2003 disknum
= n1
= n2
= -1;
2005 if (sscanf(type
, "areca,%n%d/%d%n", &n1
, &disknum
, &encnum
, &n2
) >= 1 || n1
== 6) {
2006 if (!(1 <= disknum
&& disknum
<= 128)) {
2007 set_err(EINVAL
, "Option -d areca,N/E (N=%d) must have 1 <= N <= 128", disknum
);
2010 if (!(1 <= encnum
&& encnum
<= 8)) {
2011 set_err(EINVAL
, "Option -d areca,N/E (E=%d) must have 1 <= E <= 8", encnum
);
2014 return new freebsd_areca_ata_device(this, name
, disknum
, encnum
);
2020 std::string
freebsd_smart_interface::get_valid_custom_dev_types_str()
2022 return "3ware,N, hpt,L/M/N, cciss,N, areca,N/E"
2023 #if FREEBSDVER > 800100
2031 /////////////////////////////////////////////////////////////////////////////
2032 /// Initialize platform interface and register with smi()
2034 void smart_interface::init()
2036 static os_freebsd::freebsd_smart_interface the_interface
;
2037 smart_interface::set(&the_interface
);