4 * Home page of code is: http://smartmontools.sourceforge.net
6 * Copyright (C) 2003-10 Eduard Martinescu <smartmontools-support@lists.sourceforge.net>
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>
45 #include "os_freebsd.h"
47 #include "dev_interface.h"
48 #include "dev_ata_cmd_set.h"
49 #include "dev_areca.h"
51 #define USBDEV "/dev/usb"
52 #if defined(__FreeBSD_version)
54 // This way we define one variable for the GNU/kFreeBSD and FreeBSD
55 #define FREEBSDVER __FreeBSD_version
57 #define FREEBSDVER __FreeBSD_kernel_version
60 #if (FREEBSDVER >= 800000)
61 #include <libusb20_desc.h>
63 #elif defined(__DragonFly__)
64 #include <bus/usb/usb.h>
65 #include <bus/usb/usbhid.h>
67 #include <dev/usb/usb.h>
68 #include <dev/usb/usbhid.h>
71 #define CONTROLLER_3WARE_9000_CHAR 0x01
72 #define CONTROLLER_3WARE_678K_CHAR 0x02
74 #ifndef PATHINQ_SETTINGS_SIZE
75 #define PATHINQ_SETTINGS_SIZE 128
78 const char *os_XXXX_c_cvsid
="$Id: os_freebsd.cpp 3771 2013-02-10 15:36:55Z samm2 $" \
79 ATACMDS_H_CVSID CCISS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID
;
83 #define NO_DISK_3WARE 2
87 // Utility function for printing warnings
88 void printwarning(int msgNo
, const char* extra
) {
89 static int printed
[] = {0,0,0,0};
90 static const char* message
[]={
91 "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",
93 "Error SMART Status command failed\nPlease get assistance from \n" PACKAGE_HOMEPAGE
"\nRegister values returned from SMART Status command are:\n",
95 "You must specify a DISK # for 3ware drives with -d 3ware,<n> where <n> begins with 1 for first disk drive\n",
97 "ATA support is not provided for this kernel version. Please ugrade to a recent 5-CURRENT kernel (post 09/01/2003 or so)\n"
100 if (msgNo
>= 0 && msgNo
<= MAX_MSG
) {
101 if (!printed
[msgNo
]) {
103 pout("%s", message
[msgNo
]);
111 // Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c
113 #define BUFFER_LEN_678K_CHAR ( sizeof(struct twe_usercommand) ) // 520
114 #define BUFFER_LEN_9000_CHAR ( sizeof(TW_OSLI_IOCTL_NO_DATA_BUF) + sizeof(TWE_Command) ) // 2048
115 #define TW_IOCTL_BUFFER_SIZE ( MAX(BUFFER_LEN_678K_CHAR, BUFFER_LEN_9000_CHAR) )
118 #define ATA_DEVICE "/dev/ata"
121 #define ARGUSED(x) ((void)(x))
123 // global variable holding byte count of allocated memory
125 extern unsigned char failuretest_permissive
;
127 /////////////////////////////////////////////////////////////////////////////
129 namespace os_freebsd
{ // No need to publish anything, name provided for Doxygen
131 /////////////////////////////////////////////////////////////////////////////
132 /// Implement shared open/close routines with old functions.
134 class freebsd_smart_device
135 : virtual public /*implements*/ smart_device
138 explicit freebsd_smart_device(const char * mode
)
139 : smart_device(never_called
),
140 m_fd(-1), m_mode(mode
) { }
142 virtual ~freebsd_smart_device() throw();
144 virtual bool is_open() const;
148 virtual bool close();
151 /// Return filedesc for derived classes.
159 int m_fd
; ///< filedesc, -1 if not open.
160 const char * m_mode
; ///< Mode string for deviceopen().
164 static inline void * reallocf(void *ptr
, size_t size
) {
165 void *rv
= realloc(ptr
, size
);
166 if((rv
== NULL
) && (size
!= 0))
172 freebsd_smart_device::~freebsd_smart_device() throw()
175 os_freebsd::freebsd_smart_device::close();
178 // migration from the old_style
179 unsigned char m_controller_type
;
180 unsigned char m_controller_port
;
182 // examples for smartctl
183 static const char smartctl_examples
[] =
184 "=================================================== SMARTCTL EXAMPLES =====\n\n"
185 " smartctl -a /dev/ad0 (Prints all SMART information)\n\n"
186 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/ad0\n"
187 " (Enables SMART on first disk)\n\n"
188 " smartctl -t long /dev/ad0 (Executes extended disk self-test)\n\n"
189 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/ad0\n"
190 " (Prints Self-Test & Attribute errors)\n"
191 " (Prints Self-Test & Attribute errors)\n\n"
192 " smartctl -a --device=3ware,2 /dev/twa0\n"
193 " smartctl -a --device=3ware,2 /dev/twe0\n"
194 " smartctl -a --device=3ware,2 /dev/tws0\n"
195 " (Prints all SMART information for ATA disk on\n"
196 " third port of first 3ware RAID controller)\n"
197 " smartctl -a --device=cciss,0 /dev/ciss0\n"
198 " (Prints all SMART information for first disk \n"
199 " on Common Interface for SCSI-3 Support driver)\n"
200 " smartctl -a --device=areca,3/1 /dev/arcmsr0\n"
201 " (Prints all SMART information for 3rd disk in the 1st enclosure \n"
202 " on first ARECA RAID controller)\n"
206 bool freebsd_smart_device::is_open() const
212 bool freebsd_smart_device::open()
214 const char *dev
= get_dev_name();
215 if ((m_fd
= ::open(dev
,O_RDONLY
))<0) {
222 bool freebsd_smart_device::close()
225 // close device, if open
227 failed
=::close(get_fd());
231 if(failed
) return false;
235 /////////////////////////////////////////////////////////////////////////////
236 /// Implement standard ATA support
238 class freebsd_ata_device
239 : public /*implements*/ ata_device
,
240 public /*extends*/ freebsd_smart_device
243 freebsd_ata_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
);
244 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
247 virtual int do_cmd(struct ata_ioc_request
* request
, bool is_48bit_cmd
);
250 freebsd_ata_device::freebsd_ata_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
)
251 : smart_device(intf
, dev_name
, "ata", req_type
),
252 freebsd_smart_device("ATA")
256 int freebsd_ata_device::do_cmd( struct ata_ioc_request
* request
, bool is_48bit_cmd
)
258 int fd
= get_fd(), ret
;
259 ARGUSED(is_48bit_cmd
); // no support for 48 bit commands in the IOCATAREQUEST
260 ret
= ioctl(fd
, IOCATAREQUEST
, request
);
261 if (ret
) set_err(errno
);
267 bool freebsd_ata_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
269 bool ata_48bit
= false; // no ata_48bit_support via IOCATAREQUEST
270 if(!strcmp("atacam",get_dev_type())) // enable for atacam interface
273 if (!ata_cmd_is_ok(in
,
274 true, // data_out_support
275 true, // multi_sector_support
278 set_err(ENOSYS
, "48-bit ATA commands not implemented for legacy controllers");
282 struct ata_ioc_request request
;
283 bzero(&request
,sizeof(struct ata_ioc_request
));
285 request
.timeout
=SCSI_TIMEOUT_DEFAULT
;
286 request
.u
.ata
.command
=in
.in_regs
.command
;
287 request
.u
.ata
.feature
=in
.in_regs
.features
;
289 request
.u
.ata
.count
= in
.in_regs
.sector_count_16
;
290 request
.u
.ata
.lba
= in
.in_regs
.lba_48
;
292 switch (in
.direction
) {
293 case ata_cmd_in::no_data
:
294 request
.flags
=ATA_CMD_CONTROL
;
296 case ata_cmd_in::data_in
:
297 request
.flags
=ATA_CMD_READ
| ATA_CMD_CONTROL
;
298 request
.data
=(char *)in
.buffer
;
299 request
.count
=in
.size
;
301 case ata_cmd_in::data_out
:
302 request
.flags
=ATA_CMD_WRITE
| ATA_CMD_CONTROL
;
303 request
.data
=(char *)in
.buffer
;
304 request
.count
=in
.size
;
307 return set_err(ENOSYS
);
312 if (do_cmd(&request
, in
.in_regs
.is_48bit_cmd()))
315 return set_err(EIO
, "request failed, error code 0x%02x", request
.error
);
317 out
.out_regs
.error
= request
.error
;
318 out
.out_regs
.sector_count_16
= request
.u
.ata
.count
;
319 out
.out_regs
.lba_48
= request
.u
.ata
.lba
;
322 // Command specific processing
323 if (in
.in_regs
.command
== ATA_SMART_CMD
324 && in
.in_regs
.features
== ATA_SMART_STATUS
325 && in
.out_needed
.lba_high
)
327 unsigned const char normal_lo
=0x4f, normal_hi
=0xc2;
328 unsigned const char failed_lo
=0xf4, failed_hi
=0x2c;
330 // Cyl low and Cyl high unchanged means "Good SMART status"
331 if (!(out
.out_regs
.lba_mid
==normal_lo
&& out
.out_regs
.lba_high
==normal_hi
)
332 // These values mean "Bad SMART status"
333 && !(out
.out_regs
.lba_mid
==failed_lo
&& out
.out_regs
.lba_high
==failed_hi
))
336 // We haven't gotten output that makes sense; print out some debugging info
338 snprintf(buf
, sizeof(buf
),
339 "CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
340 (int)request
.u
.ata
.command
,
341 (int)request
.u
.ata
.feature
,
342 (int)request
.u
.ata
.count
,
343 (int)((request
.u
.ata
.lba
) & 0xff),
344 (int)((request
.u
.ata
.lba
>>8) & 0xff),
345 (int)((request
.u
.ata
.lba
>>16) & 0xff),
347 printwarning(BAD_SMART
,buf
);
348 out
.out_regs
.lba_high
= failed_hi
;
349 out
.out_regs
.lba_mid
= failed_lo
;
356 #if FREEBSDVER > 800100
357 class freebsd_atacam_device
: public freebsd_ata_device
360 freebsd_atacam_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
)
361 : smart_device(intf
, dev_name
, "atacam", req_type
), freebsd_ata_device(intf
, dev_name
, req_type
)
365 virtual bool close();
369 struct cam_device
*m_camdev
;
371 virtual int do_cmd( struct ata_ioc_request
* request
, bool is_48bit_cmd
);
374 bool freebsd_atacam_device::open(){
375 const char *dev
= get_dev_name();
377 if ((m_camdev
= cam_open_device(dev
, O_RDWR
)) == NULL
) {
381 set_fd(m_camdev
->fd
);
385 bool freebsd_atacam_device::close(){
386 cam_close_device(m_camdev
);
391 int freebsd_atacam_device::do_cmd( struct ata_ioc_request
* request
, bool is_48bit_cmd
)
397 // 48bit commands are broken in ATACAM before r242422/HEAD
398 // and may cause system hang
399 // Waiting for MFC to make sure that bug is fixed,
400 // later version check needs to be added
401 if(!strcmp("ata",m_camdev
->sim_name
) && is_48bit_cmd
) {
402 set_err(ENOSYS
, "48-bit ATA commands not implemented for legacy controllers");
406 memset(&ccb
, 0, sizeof(ccb
));
408 if (request
->count
== 0)
409 camflags
= CAM_DIR_NONE
;
410 else if (request
->flags
& ATA_CMD_READ
)
411 camflags
= CAM_DIR_IN
;
413 camflags
= CAM_DIR_OUT
;
415 cam_fill_ataio(&ccb
.ataio
,
420 (u_int8_t
*)request
->data
,
422 request
->timeout
* 1000); // timeout in seconds
424 ccb
.ataio
.cmd
.flags
= CAM_ATAIO_NEEDRESULT
|
425 (is_48bit_cmd
? CAM_ATAIO_48BIT
: 0);
427 ccb
.ataio
.cmd
.command
= request
->u
.ata
.command
;
428 ccb
.ataio
.cmd
.features
= request
->u
.ata
.feature
;
429 ccb
.ataio
.cmd
.lba_low
= request
->u
.ata
.lba
;
430 ccb
.ataio
.cmd
.lba_mid
= request
->u
.ata
.lba
>> 8;
431 ccb
.ataio
.cmd
.lba_high
= request
->u
.ata
.lba
>> 16;
433 ccb
.ataio
.cmd
.lba_low_exp
= request
->u
.ata
.lba
>> 24;
434 ccb
.ataio
.cmd
.lba_mid_exp
= request
->u
.ata
.lba
>> 32;
435 ccb
.ataio
.cmd
.lba_high_exp
= request
->u
.ata
.lba
>> 40;
436 ccb
.ataio
.cmd
.device
= 0x40 | ((request
->u
.ata
.lba
>> 24) & 0x0f);
437 ccb
.ataio
.cmd
.sector_count
= request
->u
.ata
.count
;
438 ccb
.ataio
.cmd
.sector_count_exp
= request
->u
.ata
.count
>> 8;;
440 ccb
.ccb_h
.flags
|= CAM_DEV_QFRZDIS
;
442 if (cam_send_ccb(m_camdev
, &ccb
) < 0) {
443 set_err(EIO
, "cam_send_ccb failed");
447 if ((ccb
.ccb_h
.status
& CAM_STATUS_MASK
) != CAM_REQ_CMP
) {
448 cam_error_print(m_camdev
, &ccb
, CAM_ESF_ALL
, CAM_EPF_ALL
, stderr
);
454 ((u_int64_t
)(ccb
.ataio
.res
.lba_low
)) |
455 ((u_int64_t
)(ccb
.ataio
.res
.lba_mid
) << 8) |
456 ((u_int64_t
)(ccb
.ataio
.res
.lba_high
) << 16) |
457 ((u_int64_t
)(ccb
.ataio
.res
.lba_low_exp
) << 24) |
458 ((u_int64_t
)(ccb
.ataio
.res
.lba_mid_exp
) << 32) |
459 ((u_int64_t
)(ccb
.ataio
.res
.lba_high_exp
) << 40);
461 request
->u
.ata
.count
= ccb
.ataio
.res
.sector_count
| (ccb
.ataio
.res
.sector_count_exp
<< 8);
462 request
->error
= ccb
.ataio
.res
.error
;
469 /////////////////////////////////////////////////////////////////////////////
470 /// Implement AMCC/3ware RAID support
472 class freebsd_escalade_device
473 : public /*implements*/ ata_device
,
474 public /*extends*/ freebsd_smart_device
477 freebsd_escalade_device(smart_interface
* intf
, const char * dev_name
,
478 int escalade_type
, int disknum
);
481 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
485 int m_escalade_type
; ///< Type string for escalade_command_interface().
486 int m_disknum
; ///< Disk number.
489 freebsd_escalade_device::freebsd_escalade_device(smart_interface
* intf
, const char * dev_name
,
490 int escalade_type
, int disknum
)
491 : smart_device(intf
, dev_name
, "3ware", "3ware"),
492 freebsd_smart_device(
493 escalade_type
==CONTROLLER_3WARE_9000_CHAR
? "ATA_3WARE_9000" :
494 escalade_type
==CONTROLLER_3WARE_678K_CHAR
? "ATA_3WARE_678K" :
495 /* CONTROLLER_3WARE_678K */ "ATA" ),
496 m_escalade_type(escalade_type
), m_disknum(disknum
)
498 set_info().info_name
= strprintf("%s [3ware_disk_%02d]", dev_name
, disknum
);
501 bool freebsd_escalade_device::open()
503 const char *dev
= get_dev_name();
506 if ((fd
= ::open(dev
,O_RDWR
))<0) {
514 bool freebsd_escalade_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
516 // to hold true file descriptor
519 if (!ata_cmd_is_ok(in
,
520 true, // data_out_support
521 false, // TODO: multi_sector_support
522 true) // ata_48bit_support
526 struct twe_usercommand
* cmd_twe
= NULL
;
527 TW_OSLI_IOCTL_NO_DATA_BUF
* cmd_twa
= NULL
;
528 TWE_Command_ATA
* ata
= NULL
;
530 // Used by both the SCSI and char interfaces
531 char ioctl_buffer
[TW_IOCTL_BUFFER_SIZE
];
534 printwarning(NO_DISK_3WARE
,NULL
);
538 memset(ioctl_buffer
, 0, TW_IOCTL_BUFFER_SIZE
);
540 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
541 cmd_twa
= (TW_OSLI_IOCTL_NO_DATA_BUF
*)ioctl_buffer
;
542 cmd_twa
->pdata
= ((TW_OSLI_IOCTL_WITH_PAYLOAD
*)cmd_twa
)->payload
.data_buf
;
543 cmd_twa
->driver_pkt
.buffer_length
= in
.size
;
544 // using "old" packet format to speak with SATA devices
545 ata
= (TWE_Command_ATA
*)&cmd_twa
->cmd_pkt
.command
.cmd_pkt_7k
;
546 } else if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
547 cmd_twe
= (struct twe_usercommand
*)ioctl_buffer
;
548 ata
= &cmd_twe
->tu_command
.ata
;
550 return set_err(ENOSYS
,
551 "Unrecognized escalade_type %d in linux_3ware_command_interface(disk %d)\n"
552 "Please contact " PACKAGE_BUGREPORT
"\n", (int)m_escalade_type
, m_disknum
);
555 ata
->opcode
= TWE_OP_ATA_PASSTHROUGH
;
557 // Same for (almost) all commands - but some reset below
558 ata
->request_id
= 0xFF;
559 ata
->unit
= m_disknum
;
562 ata
->size
= 0x5; // TODO: multisector support
565 const ata_in_regs_48bit
& r
= in
.in_regs
;
566 ata
->features
= r
.features_16
;
567 ata
->sector_count
= r
.sector_count_16
;
568 ata
->sector_num
= r
.lba_low_16
;
569 ata
->cylinder_lo
= r
.lba_mid_16
;
570 ata
->cylinder_hi
= r
.lba_high_16
;
571 ata
->drive_head
= r
.device
;
572 ata
->command
= r
.command
;
575 // Is this a command that reads or returns 512 bytes?
576 // passthru->param values are:
577 // 0x0 - non data command without TFR write check,
578 // 0x8 - non data command with TFR write check,
579 // 0xD - data command that returns data to host from device
580 // 0xF - data command that writes data from host to device
581 // passthru->size values are 0x5 for non-data and 0x07 for data
582 bool readdata
= false;
583 if (in
.direction
== ata_cmd_in::data_in
) {
584 if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
585 cmd_twe
->tu_data
= in
.buffer
;
586 cmd_twe
->tu_size
= 512;
590 ata
->sgl_offset
= 0x5;
592 // For 64-bit to work correctly, up the size of the command packet
593 // in dwords by 1 to account for the 64-bit single sgl 'address'
594 // field. Note that this doesn't agree with the typedefs but it's
595 // right (agree with kernel driver behavior/typedefs).
596 // if (sizeof(long)==8)
599 else if (in
.direction
== ata_cmd_in::no_data
) {
600 // Non data command -- but doesn't use large sector
601 // count register values.
602 ata
->sgl_offset
= 0x0;
604 ata
->sector_count
= 0x0;
606 else if (in
.direction
== ata_cmd_in::data_out
) {
607 ata
->sgl_offset
= 0x5;
608 ata
->param
= 0xF; // PIO data write
609 if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
610 cmd_twe
->tu_data
= in
.buffer
;
611 cmd_twe
->tu_size
= 512;
613 else if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
614 memcpy(cmd_twa
->pdata
, in
.buffer
, in
.size
);
618 return set_err(EINVAL
);
620 // 3WARE controller can NOT have packet device internally
621 if (in
.in_regs
.command
== ATA_IDENTIFY_PACKET_DEVICE
) {
622 return set_err(ENODEV
, "No drive on port %d", m_disknum
);
625 // Now send the command down through an ioctl()
627 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
628 ioctlreturn
=ioctl(fd
,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH
,cmd_twa
);
630 ioctlreturn
=ioctl(fd
,TWEIO_COMMAND
,cmd_twe
);
633 // Deal with the different error cases
638 // See if the ATA command failed. Now that we have returned from
639 // the ioctl() call, if passthru is valid, then:
640 // - ata->status contains the 3ware controller STATUS
641 // - ata->command contains the ATA STATUS register
642 // - ata->features contains the ATA ERROR register
644 // Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS
645 // If bit 0 (error bit) is set, then ATA ERROR register is valid.
646 // While we *might* decode the ATA ERROR register, at the moment it
647 // doesn't make much sense: we don't care in detail why the error
650 if (ata
->status
|| (ata
->command
& 0x21)) {
652 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
);
656 // If this is a read data command, copy data to output buffer
658 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
)
659 memcpy(in
.buffer
, cmd_twa
->pdata
, in
.size
);
660 else if(m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
661 memcpy(in
.buffer
, cmd_twe
->tu_data
, in
.size
); // untested
664 // Return register values
666 ata_out_regs_48bit
& r
= out
.out_regs
;
667 r
.error
= ata
->features
;
668 r
.sector_count_16
= ata
->sector_count
;
669 r
.lba_low_16
= ata
->sector_num
;
670 r
.lba_mid_16
= ata
->cylinder_lo
;
671 r
.lba_high_16
= ata
->cylinder_hi
;
672 r
.device
= ata
->drive_head
;
673 r
.status
= ata
->command
;
675 // look for nonexistent devices/ports
676 if (in
.in_regs
.command
== ATA_IDENTIFY_DEVICE
677 && !nonempty((unsigned char *)in
.buffer
, in
.size
)) {
678 return set_err(ENODEV
, "No drive on port %d", m_disknum
);
684 /////////////////////////////////////////////////////////////////////////////
685 /// Implement Highpoint RAID support with old functions
687 class freebsd_highpoint_device
688 : public /*implements*/ ata_device_with_command_set
,
689 public /*extends*/ freebsd_smart_device
692 freebsd_highpoint_device(smart_interface
* intf
, const char * dev_name
,
693 unsigned char controller
, unsigned char channel
, unsigned char port
);
696 virtual int ata_command_interface(smart_command_set command
, int select
, char * data
);
700 unsigned char m_hpt_data
[3]; ///< controller/channel/port
704 freebsd_highpoint_device::freebsd_highpoint_device(smart_interface
* intf
, const char * dev_name
,
705 unsigned char controller
, unsigned char channel
, unsigned char port
)
706 : smart_device(intf
, dev_name
, "hpt", "hpt"),
707 freebsd_smart_device("ATA")
709 m_hpt_data
[0] = controller
; m_hpt_data
[1] = channel
; m_hpt_data
[2] = port
;
710 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]);
713 bool freebsd_highpoint_device::open()
715 const char *dev
= get_dev_name();
718 if ((fd
= ::open(dev
,O_RDWR
))<0) {
726 int freebsd_highpoint_device::ata_command_interface(smart_command_set command
, int select
, char * data
)
730 HPT_IOCTL_PARAM param
;
731 HPT_CHANNEL_INFO_V2 info
;
732 unsigned char* buff
[512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER
)];
733 PHPT_PASS_THROUGH_HEADER pide_pt_hdr
, pide_pt_hdr_out
;
735 // get internal deviceid
736 ids
[0] = m_hpt_data
[0] - 1;
737 ids
[1] = m_hpt_data
[1] - 1;
739 memset(¶m
, 0, sizeof(HPT_IOCTL_PARAM
));
741 param
.magic
= HPT_IOCTL_MAGIC
;
742 param
.ctrl_code
= HPT_IOCTL_GET_CHANNEL_INFO_V2
;
743 param
.in
= (unsigned char *)ids
;
744 param
.in_size
= sizeof(unsigned int) * 2;
745 param
.out
= (unsigned char *)&info
;
746 param
.out_size
= sizeof(HPT_CHANNEL_INFO_V2
);
748 if (m_hpt_data
[2]==1) {
749 param
.ctrl_code
= HPT_IOCTL_GET_CHANNEL_INFO
;
750 param
.out_size
= sizeof(HPT_CHANNEL_INFO
);
752 if (ioctl(fd
, HPT_DO_IOCONTROL
, ¶m
)!=0 ||
753 info
.devices
[m_hpt_data
[2]-1]==0) {
757 // perform smart action
758 memset(buff
, 0, 512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER
));
759 pide_pt_hdr
= (PHPT_PASS_THROUGH_HEADER
)buff
;
761 pide_pt_hdr
->lbamid
= 0x4f;
762 pide_pt_hdr
->lbahigh
= 0xc2;
763 pide_pt_hdr
->command
= ATA_SMART_CMD
;
764 pide_pt_hdr
->id
= info
.devices
[m_hpt_data
[2] - 1];
768 pide_pt_hdr
->feature
=ATA_SMART_READ_VALUES
;
769 pide_pt_hdr
->protocol
=HPT_READ
;
771 case READ_THRESHOLDS
:
772 pide_pt_hdr
->feature
=ATA_SMART_READ_THRESHOLDS
;
773 pide_pt_hdr
->protocol
=HPT_READ
;
776 pide_pt_hdr
->feature
=ATA_SMART_READ_LOG_SECTOR
;
777 pide_pt_hdr
->lbalow
=select
;
778 pide_pt_hdr
->protocol
=HPT_READ
;
781 pide_pt_hdr
->command
=ATA_IDENTIFY_DEVICE
;
782 pide_pt_hdr
->protocol
=HPT_READ
;
785 pide_pt_hdr
->feature
=ATA_SMART_ENABLE
;
788 pide_pt_hdr
->feature
=ATA_SMART_DISABLE
;
791 pide_pt_hdr
->feature
=ATA_SMART_AUTO_OFFLINE
;
792 pide_pt_hdr
->sectorcount
=select
;
795 pide_pt_hdr
->feature
=ATA_SMART_AUTOSAVE
;
796 pide_pt_hdr
->sectorcount
=select
;
798 case IMMEDIATE_OFFLINE
:
799 pide_pt_hdr
->feature
=ATA_SMART_IMMEDIATE_OFFLINE
;
800 pide_pt_hdr
->lbalow
=select
;
804 pide_pt_hdr
->feature
=ATA_SMART_STATUS
;
806 case CHECK_POWER_MODE
:
807 pide_pt_hdr
->command
=ATA_CHECK_POWER_MODE
;
810 memcpy(buff
+sizeof(HPT_PASS_THROUGH_HEADER
), data
, 512);
811 pide_pt_hdr
->feature
=ATA_SMART_WRITE_LOG_SECTOR
;
812 pide_pt_hdr
->lbalow
=select
;
813 pide_pt_hdr
->protocol
=HPT_WRITE
;
816 pout("Unrecognized command %d in highpoint_command_interface()\n"
817 "Please contact " PACKAGE_BUGREPORT
"\n", command
);
821 if (pide_pt_hdr
->protocol
!=0) {
822 pide_pt_hdr
->sectors
= 1;
823 pide_pt_hdr
->sectorcount
= 1;
826 memset(¶m
, 0, sizeof(HPT_IOCTL_PARAM
));
828 param
.magic
= HPT_IOCTL_MAGIC
;
829 param
.ctrl_code
= HPT_IOCTL_IDE_PASS_THROUGH
;
830 param
.in
= (unsigned char *)buff
;
831 param
.in_size
= sizeof(HPT_PASS_THROUGH_HEADER
) + (pide_pt_hdr
->protocol
==HPT_READ
? 0 : pide_pt_hdr
->sectors
* 512);
832 param
.out
= (unsigned char *)buff
+param
.in_size
;
833 param
.out_size
= sizeof(HPT_PASS_THROUGH_HEADER
) + (pide_pt_hdr
->protocol
==HPT_READ
? pide_pt_hdr
->sectors
* 512 : 0);
835 pide_pt_hdr_out
= (PHPT_PASS_THROUGH_HEADER
)param
.out
;
837 if ((ioctl(fd
, HPT_DO_IOCONTROL
, ¶m
)!=0) ||
838 (pide_pt_hdr_out
->command
& 1)) {
842 if (command
==STATUS_CHECK
)
844 unsigned const char normal_lo
=0x4f, normal_hi
=0xc2;
845 unsigned const char failed_lo
=0xf4, failed_hi
=0x2c;
846 unsigned char low
,high
;
848 high
= pide_pt_hdr_out
->lbahigh
;
849 low
= pide_pt_hdr_out
->lbamid
;
851 // Cyl low and Cyl high unchanged means "Good SMART status"
852 if (low
==normal_lo
&& high
==normal_hi
)
855 // These values mean "Bad SMART status"
856 if (low
==failed_lo
&& high
==failed_hi
)
859 // We haven't gotten output that makes sense; print out some debugging info
861 snprintf(buf
, sizeof(buf
),
862 "CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
863 (int)pide_pt_hdr_out
->command
,
864 (int)pide_pt_hdr_out
->feature
,
865 (int)pide_pt_hdr_out
->sectorcount
,
866 (int)pide_pt_hdr_out
->lbalow
,
867 (int)pide_pt_hdr_out
->lbamid
,
868 (int)pide_pt_hdr_out
->lbahigh
,
869 (int)pide_pt_hdr_out
->sectors
);
870 printwarning(BAD_SMART
,buf
);
872 else if (command
==CHECK_POWER_MODE
)
873 data
[0] = pide_pt_hdr_out
->sectorcount
& 0xff;
874 else if (pide_pt_hdr
->protocol
==HPT_READ
)
875 memcpy(data
, (unsigned char *)buff
+ 2 * sizeof(HPT_PASS_THROUGH_HEADER
),
876 pide_pt_hdr
->sectors
* 512);
881 /////////////////////////////////////////////////////////////////////////////
882 /// Standard SCSI support
884 class freebsd_scsi_device
885 : public /*implements*/ scsi_device
,
886 public /*extends*/ freebsd_smart_device
889 freebsd_scsi_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
);
891 virtual smart_device
* autodetect_open();
893 virtual bool scsi_pass_through(scsi_cmnd_io
* iop
);
897 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("SCSI")
929 bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io
* iop
)
931 int report
=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
]);
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);
956 warnx("error: camdev=0!");
960 if (!(ccb
= cam_getccb(m_camdev
))) {
961 warnx("error allocating ccb");
964 // mfi SAT layer is known to be buggy
965 if(!strcmp("mfi",m_camdev
->sim_name
)) {
966 if (iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_12
|| iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_16
) {
967 // Controller does not return ATA output registers in SAT sense data
968 if (iop
->cmnd
[2] & (1 << 5)) // chk_cond
969 return set_err(ENOSYS
, "ATA return descriptor not supported by controller firmware");
971 // SMART WRITE LOG SECTOR causing media errors
972 if ((iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_16
973 && iop
->cmnd
[14] == ATA_SMART_CMD
&& iop
->cmnd
[3]==0 &&
974 iop
->cmnd
[4] == ATA_SMART_WRITE_LOG_SECTOR
) ||
975 (iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_12
976 && iop
->cmnd
[9] == ATA_SMART_CMD
&& iop
->cmnd
[3] == ATA_SMART_WRITE_LOG_SECTOR
))
978 if(!failuretest_permissive
)
979 return set_err(ENOSYS
, "SMART WRITE LOG SECTOR may cause problems, try with -T permissive to force");
982 // clear out structure, except for header that was filled in for us
983 bzero(&(&ccb
->ccb_h
)[1],
984 sizeof(struct ccb_scsiio
) - sizeof(struct ccb_hdr
));
986 cam_fill_csio(&ccb
->csio
,
989 /* flags */ (iop
->dxfer_dir
== DXFER_NONE
? CAM_DIR_NONE
:(iop
->dxfer_dir
== DXFER_FROM_DEVICE
? CAM_DIR_IN
: CAM_DIR_OUT
)),
990 /* tagaction */ MSG_SIMPLE_Q_TAG
,
991 /* dataptr */ iop
->dxferp
,
992 /* datalen */ iop
->dxfer_len
,
993 /* senselen */ iop
->max_sense_len
,
994 /* cdblen */ iop
->cmnd_len
,
995 /* timout (converted to seconds) */ iop
->timeout
*1000);
996 memcpy(ccb
->csio
.cdb_io
.cdb_bytes
,iop
->cmnd
,iop
->cmnd_len
);
998 if (cam_send_ccb(m_camdev
,ccb
) < 0) {
999 warn("error sending SCSI ccb");
1000 cam_error_print(m_camdev
,ccb
,CAM_ESF_ALL
,CAM_EPF_ALL
,stderr
);
1005 if (((ccb
->ccb_h
.status
& CAM_STATUS_MASK
) != CAM_REQ_CMP
) && ((ccb
->ccb_h
.status
& CAM_STATUS_MASK
) != CAM_SCSI_STATUS_ERROR
)) {
1006 cam_error_print(m_camdev
,ccb
,CAM_ESF_ALL
,CAM_EPF_ALL
,stderr
);
1012 iop
->resp_sense_len
= ccb
->csio
.sense_len
- ccb
->csio
.sense_resid
;
1013 memcpy(iop
->sensep
,&(ccb
->csio
.sense_data
),iop
->resp_sense_len
);
1016 iop
->scsi_status
= ccb
->csio
.scsi_status
;
1023 pout(" status=0\n");
1024 trunc
= (iop
->dxfer_len
> 256) ? 1 : 0;
1026 pout(" Incoming data, len=%d%s:\n", (int)iop
->dxfer_len
,
1027 (trunc
? " [only first 256 bytes shown]" : ""));
1028 dStrHex(iop
->dxferp
, (trunc
? 256 : iop
->dxfer_len
) , 1);
1031 // mfip replacing PDT of the device so response does not make a sense
1032 // this sets PDT to 00h - direct-access block device
1033 if((!strcmp("mfi", m_camdev
->sim_name
) || !strcmp("mpt", m_camdev
->sim_name
))
1034 && iop
->cmnd
[0] == INQUIRY
) {
1036 pout("device on %s controller, patching PDT\n", m_camdev
->sim_name
);
1038 iop
->dxferp
[0] = iop
->dxferp
[0] & 0xe0;
1045 /////////////////////////////////////////////////////////////////////////////
1046 /// Areca RAID support
1048 ///////////////////////////////////////////////////////////////////
1049 // SATA(ATA) device behind Areca RAID Controller
1050 class freebsd_areca_ata_device
1051 : public /*implements*/ areca_ata_device
,
1052 public /*extends*/ freebsd_smart_device
1055 freebsd_areca_ata_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
= 1);
1056 virtual smart_device
* autodetect_open();
1057 virtual bool arcmsr_lock();
1058 virtual bool arcmsr_unlock();
1059 virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
);
1062 ///////////////////////////////////////////////////////////////////
1063 // SAS(SCSI) device behind Areca RAID Controller
1064 class freebsd_areca_scsi_device
1065 : public /*implements*/ areca_scsi_device
,
1066 public /*extends*/ freebsd_smart_device
1069 freebsd_areca_scsi_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
= 1);
1070 virtual smart_device
* autodetect_open();
1071 virtual bool arcmsr_lock();
1072 virtual bool arcmsr_unlock();
1073 virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
);
1077 // Areca RAID Controller(SATA Disk)
1078 freebsd_areca_ata_device::freebsd_areca_ata_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
)
1079 : smart_device(intf
, dev_name
, "areca", "areca"),
1080 freebsd_smart_device("ATA")
1082 set_disknum(disknum
);
1084 set_info().info_name
= strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name
, disknum
, encnum
);
1088 smart_device
* freebsd_areca_ata_device::autodetect_open()
1092 // autodetect device type
1093 is_ata
= arcmsr_get_dev_type();
1107 smart_device_auto_ptr
newdev(new freebsd_areca_scsi_device(smi(), get_dev_name(), get_disknum(), get_encnum()));
1110 newdev
->open(); // TODO: Can possibly pass open fd
1112 return newdev
.release();
1115 int freebsd_areca_ata_device::arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
)
1117 int ioctlreturn
= 0;
1124 ioctlreturn
= ioctl(get_fd(), ((sSRB_BUFFER
*)(iop
->dxferp
))->srbioctl
.ControlCode
, iop
->dxferp
);
1134 bool freebsd_areca_ata_device::arcmsr_lock()
1140 bool freebsd_areca_ata_device::arcmsr_unlock()
1146 // Areca RAID Controller(SAS Device)
1147 freebsd_areca_scsi_device::freebsd_areca_scsi_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
)
1148 : smart_device(intf
, dev_name
, "areca", "areca"),
1149 freebsd_smart_device("SCSI")
1151 set_disknum(disknum
);
1153 set_info().info_name
= strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name
, disknum
, encnum
);
1156 smart_device
* freebsd_areca_scsi_device::autodetect_open()
1161 int freebsd_areca_scsi_device::arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
)
1163 int ioctlreturn
= 0;
1169 ioctlreturn
= ioctl(get_fd(), ((sSRB_BUFFER
*)(iop
->dxferp
))->srbioctl
.ControlCode
, iop
->dxferp
);
1179 bool freebsd_areca_scsi_device::arcmsr_lock()
1185 bool freebsd_areca_scsi_device::arcmsr_unlock()
1191 /////////////////////////////////////////////////////////////////////////////
1192 /// Implement CCISS RAID support with old functions
1194 class freebsd_cciss_device
1195 : public /*implements*/ scsi_device
,
1196 public /*extends*/ freebsd_smart_device
1199 freebsd_cciss_device(smart_interface
* intf
, const char * name
, unsigned char disknum
);
1201 virtual bool scsi_pass_through(scsi_cmnd_io
* iop
);
1202 virtual bool open();
1205 unsigned char m_disknum
; ///< Disk number.
1208 bool freebsd_cciss_device::open()
1210 const char *dev
= get_dev_name();
1212 if ((fd
= ::open(dev
,O_RDWR
))<0) {
1220 freebsd_cciss_device::freebsd_cciss_device(smart_interface
* intf
,
1221 const char * dev_name
, unsigned char disknum
)
1222 : smart_device(intf
, dev_name
, "cciss", "cciss"),
1223 freebsd_smart_device("SCSI"),
1226 set_info().info_name
= strprintf("%s [cciss_disk_%02d]", dev_name
, disknum
);
1229 bool freebsd_cciss_device::scsi_pass_through(scsi_cmnd_io
* iop
)
1231 int status
= cciss_io_interface(get_fd(), m_disknum
, iop
, scsi_debugmode
);
1233 return set_err(-status
);
1240 /////////////////////////////////////////////////////////////////////////////
1241 /// SCSI open with autodetection support
1243 smart_device
* freebsd_scsi_device::autodetect_open()
1249 // No Autodetection if device type was specified by user
1250 if (*get_req_type())
1253 // The code below is based on smartd.cpp:SCSIFilterKnown()
1256 unsigned char req_buff
[64] = {0, };
1258 if (scsiStdInquiry(this, req_buff
, req_len
)) {
1259 // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices
1260 // watch this spot ... other devices could lock up here
1262 if (scsiStdInquiry(this, req_buff
, req_len
)) {
1263 // device doesn't like INQUIRY commands
1265 set_err(EIO
, "INQUIRY failed");
1270 int avail_len
= req_buff
[4] + 5;
1271 int len
= (avail_len
< req_len
? avail_len
: req_len
);
1275 // Use INQUIRY to detect type
1278 if (!memcmp(req_buff
+ 8, "3ware", 5) || !memcmp(req_buff
+ 8, "AMCC", 4) ||
1279 !strcmp("tws",m_camdev
->sim_name
) || !strcmp("twa",m_camdev
->sim_name
)) {
1281 set_err(EINVAL
, "3ware/LSI controller, please try adding '-d 3ware,N',\n"
1282 "you may need to replace %s with /dev/twaN, /dev/tweN or /dev/twsN", get_dev_name());
1286 // SAT or USB, skip MFI controllers because of bugs
1288 smart_device
* newdev
= smi()->autodetect_sat_device(this, req_buff
, len
);
1290 // NOTE: 'this' is now owned by '*newdev'
1291 if(!strcmp("mfi",m_camdev
->sim_name
)) {
1293 newdev
->set_err(ENOSYS
, "SATA device detected,\n"
1294 "MegaRAID SAT layer is reportedly buggy, use '-d sat' to try anyhow");
1300 // Nothing special found
1305 /////////////////////////////////////////////////////////////////////////////
1306 /// Implement platform interface with old functions.
1308 class freebsd_smart_interface
1309 : public /*implements*/ smart_interface
1312 virtual std::string
get_os_version_str();
1314 virtual std::string
get_app_examples(const char * appname
);
1316 virtual bool scan_smart_devices(smart_device_list
& devlist
, const char * type
,
1317 const char * pattern
= 0);
1320 virtual ata_device
* get_ata_device(const char * name
, const char * type
);
1322 #if FREEBSDVER > 800100
1323 virtual ata_device
* get_atacam_device(const char * name
, const char * type
);
1326 virtual scsi_device
* get_scsi_device(const char * name
, const char * type
);
1328 virtual smart_device
* autodetect_smart_device(const char * name
);
1330 virtual smart_device
* get_custom_smart_device(const char * name
, const char * type
);
1332 virtual std::string
get_valid_custom_dev_types_str();
1336 //////////////////////////////////////////////////////////////////////
1338 std::string
freebsd_smart_interface::get_os_version_str()
1340 struct utsname osname
;
1342 return strprintf("%s %s %s", osname
.sysname
, osname
.release
, osname
.machine
);
1345 std::string
freebsd_smart_interface::get_app_examples(const char * appname
)
1347 if (!strcmp(appname
, "smartctl"))
1348 return smartctl_examples
;
1352 ata_device
* freebsd_smart_interface::get_ata_device(const char * name
, const char * type
)
1354 return new freebsd_ata_device(this, name
, type
);
1357 #if FREEBSDVER > 800100
1358 ata_device
* freebsd_smart_interface::get_atacam_device(const char * name
, const char * type
)
1360 return new freebsd_atacam_device(this, name
, type
);
1364 scsi_device
* freebsd_smart_interface::get_scsi_device(const char * name
, const char * type
)
1366 return new freebsd_scsi_device(this, name
, type
);
1369 // we are using CAM subsystem XPT enumerator to found all CAM (scsi/usb/ada/...)
1370 // devices on system despite of it's names
1372 // If any errors occur, leave errno set as it was returned by the
1373 // system call, and return <0.
1376 // names: resulting array
1377 // show_all - export duplicate device name or not
1381 // >=0: number of discovered devices
1383 bool get_dev_names_cam(std::vector
<std::string
> & names
, bool show_all
)
1386 if ((fd
= open(XPT_DEVICE
, O_RDWR
)) == -1) {
1387 if (errno
== ENOENT
) /* There are no CAM device on this computer */
1390 pout("%s control device couldn't opened: %s\n", XPT_DEVICE
, strerror(errno
));
1396 bzero(&ccb
, sizeof(union ccb
));
1398 ccb
.ccb_h
.path_id
= CAM_XPT_PATH_ID
;
1399 ccb
.ccb_h
.target_id
= CAM_TARGET_WILDCARD
;
1400 ccb
.ccb_h
.target_lun
= CAM_LUN_WILDCARD
;
1402 ccb
.ccb_h
.func_code
= XPT_DEV_MATCH
;
1403 int bufsize
= sizeof(struct dev_match_result
) * MAX_NUM_DEV
;
1404 ccb
.cdm
.match_buf_len
= bufsize
;
1405 // TODO: Use local buffer instead of malloc() if possible
1406 ccb
.cdm
.matches
= (struct dev_match_result
*)malloc(bufsize
);
1407 bzero(ccb
.cdm
.matches
,bufsize
); // clear ccb.cdm.matches structure
1409 if (ccb
.cdm
.matches
== NULL
) {
1411 throw std::bad_alloc();
1413 ccb
.cdm
.num_matches
= 0;
1414 ccb
.cdm
.num_patterns
= 0;
1415 ccb
.cdm
.pattern_buf_len
= 0;
1418 * We do the ioctl multiple times if necessary, in case there are
1419 * more than MAX_NUM_DEV nodes in the EDT.
1421 int skip_device
= 0, skip_bus
= 0, changed
= 0; // TODO: bool
1422 std::string devname
;
1424 if (ioctl(fd
, CAMIOCOMMAND
, &ccb
) == -1) {
1426 pout("error sending CAMIOCOMMAND ioctl: %s\n", strerror(errno
));
1427 free(ccb
.cdm
.matches
);
1433 if ((ccb
.ccb_h
.status
!= CAM_REQ_CMP
)
1434 || ((ccb
.cdm
.status
!= CAM_DEV_MATCH_LAST
)
1435 && (ccb
.cdm
.status
!= CAM_DEV_MATCH_MORE
))) {
1436 pout("got CAM error %#x, CDM error %d\n", ccb
.ccb_h
.status
, ccb
.cdm
.status
);
1437 free(ccb
.cdm
.matches
);
1443 for (unsigned i
= 0; i
< ccb
.cdm
.num_matches
; i
++) {
1444 struct bus_match_result
*bus_result
;
1445 struct device_match_result
*dev_result
;
1446 struct periph_match_result
*periph_result
;
1448 if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_BUS
) {
1449 bus_result
= &ccb
.cdm
.matches
[i
].result
.bus_result
;
1451 if (strcmp(bus_result
->dev_name
,"xpt") == 0) /* skip XPT bus at all */
1456 } else if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_DEVICE
) {
1457 dev_result
= &ccb
.cdm
.matches
[i
].result
.device_result
;
1459 if (dev_result
->flags
& DEV_RESULT_UNCONFIGURED
|| skip_bus
== 1)
1464 // /* Shall we skip non T_DIRECT devices ? */
1465 // if (dev_result->inq_data.device != T_DIRECT)
1468 } else if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_PERIPH
&&
1469 (skip_device
== 0 || show_all
)) {
1470 /* One device may be populated as many peripherals (pass0 & da0 for example).
1471 * We are searching for best name
1473 periph_result
= &ccb
.cdm
.matches
[i
].result
.periph_result
;
1474 /* Prefer non-"pass" names */
1475 if (devname
.empty() || strncmp(periph_result
->periph_name
, "pass", 4) != 0) {
1476 devname
= strprintf("%s%s%d", _PATH_DEV
, periph_result
->periph_name
, periph_result
->unit_number
);
1480 if ((changed
== 1 || show_all
) && !devname
.empty()) {
1481 names
.push_back(devname
);
1487 } while ((ccb
.ccb_h
.status
== CAM_REQ_CMP
) && (ccb
.cdm
.status
== CAM_DEV_MATCH_MORE
));
1489 if (!devname
.empty())
1490 names
.push_back(devname
);
1492 free(ccb
.cdm
.matches
);
1497 // we are using ATA subsystem enumerator to found all ATA devices on system
1498 // despite of it's names
1500 // If any errors occur, leave errno set as it was returned by the
1501 // system call, and return <0.
1505 // >=0: number of discovered devices
1506 int get_dev_names_ata(char*** names
) {
1507 struct ata_ioc_devices devices
;
1508 int fd
=-1,maxchannel
,serrno
=-1,n
=0;
1513 if ((fd
= open(ATA_DEVICE
, O_RDWR
)) < 0) {
1514 if (errno
== ENOENT
) /* There are no ATA device on this computer */
1517 pout("%s control device can't be opened: %s\n", ATA_DEVICE
, strerror(errno
));
1522 if (ioctl(fd
, IOCATAGMAXCHANNEL
, &maxchannel
) < 0) {
1524 pout("ioctl(IOCATAGMAXCHANNEL) on /dev/ata failed: %s\n", strerror(errno
));
1529 // allocate space for up to MAX_NUM_DEV number of ATA devices
1530 mp
= (char **)calloc(MAX_NUM_DEV
, sizeof(char*));
1533 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__
);
1538 for (devices
.channel
= 0; devices
.channel
< maxchannel
&& n
< MAX_NUM_DEV
; devices
.channel
++) {
1541 if (ioctl(fd
, IOCATADEVICES
, &devices
) < 0) {
1543 continue; /* such channel not exist */
1544 pout("ioctl(IOCATADEVICES) on %s channel %d failed: %s\n", ATA_DEVICE
, devices
.channel
, strerror(errno
));
1548 for (j
=0;j
<=1 && n
<MAX_NUM_DEV
;j
++) {
1549 if (devices
.name
[j
][0] != '\0') {
1550 asprintf(mp
+n
, "%s%s", _PATH_DEV
, devices
.name
[j
]);
1551 if (mp
[n
] == NULL
) {
1552 pout("Out of memory constructing scan ATA device list (on line %d)\n", __LINE__
);
1556 bytes
+=1+strlen(mp
[n
]);
1561 mp
= (char **)reallocf(mp
,n
*(sizeof (char*))); // shrink to correct size
1562 if (mp
== NULL
&& n
> 0 ) { // reallocf never fail for size=0, but may return NULL
1564 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__
);
1568 bytes
+= (n
)*(sizeof(char*)); // and set allocated byte count
1587 bool freebsd_smart_interface::scan_smart_devices(smart_device_list
& devlist
,
1588 const char * type
, const char * pattern
/*= 0*/)
1591 set_err(EINVAL
, "DEVICESCAN with pattern not implemented yet");
1596 char * * atanames
= 0; int numata
= 0;
1597 if (!type
|| !strcmp(type
, "ata")) {
1598 numata
= get_dev_names_ata(&atanames
);
1605 std::vector
<std::string
> scsinames
;
1606 if (!type
|| !strcmp(type
, "scsi")) { // do not export duplicated names
1607 if (!get_dev_names_cam(scsinames
, false)) {
1617 for (i
= 0; i
< numata
; i
++) {
1618 ata_device
* atadev
= get_ata_device(atanames
[i
], type
);
1620 devlist
.push_back(atadev
);
1623 if(numata
) free(atanames
);
1625 for (i
= 0; i
< (int)scsinames
.size(); i
++) {
1626 if(!*type
) { // try USB autodetection if no type specified
1627 smart_device
* smartdev
= autodetect_smart_device(scsinames
[i
].c_str());
1629 devlist
.push_back(smartdev
);
1632 scsi_device
* scsidev
= get_scsi_device(scsinames
[i
].c_str(), type
);
1634 devlist
.push_back(scsidev
);
1641 #if (FREEBSDVER < 800000) // without this build fail on FreeBSD 8
1642 static char done
[USB_MAX_DEVICES
];
1644 static int usbdevinfo(int f
, int a
, int rec
, int busno
, unsigned short & vendor_id
,
1645 unsigned short & product_id
, unsigned short & version
)
1648 struct usb_device_info di
;
1652 snprintf(devname
, sizeof(devname
),"umass%d",busno
);
1655 e
= ioctl(f
, USB_DEVICEINFO
, &di
);
1658 printf("addr %d: I/O error\n", a
);
1664 for (i
= 0; i
< USB_MAX_DEVNAMES
; i
++) {
1665 if (di
.udi_devnames
[i
][0]) {
1666 if(strcmp(di
.udi_devnames
[i
],devname
)==0) {
1668 vendor_id
= di
.udi_vendorNo
;
1669 product_id
= di
.udi_productNo
;
1670 version
= di
.udi_releaseNo
;
1678 for (p
= 0; p
< di
.udi_nports
; p
++) {
1679 int s
= di
.udi_ports
[p
];
1680 if (s
>= USB_MAX_DEVICES
) {
1684 printf("addr 0 should never happen!\n");
1686 if(usbdevinfo(f
, s
, 1, busno
, vendor_id
, product_id
, version
)) return 1;
1694 static int usbdevlist(int busno
,unsigned short & vendor_id
,
1695 unsigned short & product_id
, unsigned short & version
)
1697 #if (FREEBSDVER >= 800000) // libusb2 interface
1698 struct libusb20_device
*pdev
= NULL
;
1699 struct libusb20_backend
*pbe
;
1700 uint32_t matches
= 0;
1701 char buf
[128]; // do not change!
1704 struct LIBUSB20_DEVICE_DESC_DECODED
*pdesc
;
1706 pbe
= libusb20_be_alloc_default();
1708 while ((pdev
= libusb20_be_device_foreach(pbe
, pdev
))) {
1711 if (libusb20_dev_open(pdev
, 0)) {
1712 warnx("libusb20_dev_open: could not open device");
1716 pdesc
=libusb20_dev_get_device_desc(pdev
);
1718 snprintf(devname
, sizeof(devname
),"umass%d:",busno
);
1719 for (n
= 0; n
!= 255; n
++) {
1720 if (libusb20_dev_get_iface_desc(pdev
, n
, buf
, sizeof(buf
)))
1724 if(strncmp(buf
,devname
,strlen(devname
))==0){
1726 vendor_id
= pdesc
->idVendor
;
1727 product_id
= pdesc
->idProduct
;
1728 version
= pdesc
->bcdDevice
;
1729 libusb20_dev_close(pdev
);
1730 libusb20_be_free(pbe
);
1735 libusb20_dev_close(pdev
);
1739 printf("No device match or lack of permissions.\n");
1742 libusb20_be_free(pbe
);
1745 #else // freebsd < 8.0 USB stack, ioctl interface
1751 for (ncont
= 0, i
= 0; i
< 10; i
++) {
1752 snprintf(buf
, sizeof(buf
), "%s%d", USBDEV
, i
);
1753 f
= open(buf
, O_RDONLY
);
1755 memset(done
, 0, sizeof done
);
1756 for (a
= 1; a
< USB_MAX_DEVICES
; a
++) {
1758 rc
= usbdevinfo(f
, a
, 1, busno
,vendor_id
, product_id
, version
);
1765 if (errno
== ENOENT
|| errno
== ENXIO
)
1775 smart_device
* freebsd_smart_interface::autodetect_smart_device(const char * name
)
1777 unsigned short vendor_id
= 0, product_id
= 0, version
= 0;
1778 struct cam_device
*cam_dev
;
1783 const char * test_name
= name
;
1785 // if dev_name null, or string length zero
1786 if (!name
|| !(len
= strlen(name
)))
1789 // Dereference symlinks
1791 std::string pathbuf
;
1792 if (!lstat(name
, &st
) && S_ISLNK(st
.st_mode
)) {
1793 char * p
= realpath(name
, (char *)0);
1797 test_name
= pathbuf
.c_str();
1802 char * * atanames
= 0; int numata
= 0;
1803 numata
= get_dev_names_ata(&atanames
);
1805 // check ATA/ATAPI devices
1806 for (i
= 0; i
< numata
; i
++) {
1807 if(!strcmp(atanames
[i
],test_name
)) {
1808 for (c
= i
; c
< numata
; c
++) free(atanames
[c
]);
1810 return new freebsd_ata_device(this, test_name
, "");
1812 else free(atanames
[i
]);
1814 if(numata
) free(atanames
);
1818 pout("Unable to get ATA device list\n");
1822 std::vector
<std::string
> scsinames
;
1823 if (!get_dev_names_cam(scsinames
, true))
1824 pout("Unable to get CAM device list\n");
1825 else if (!scsinames
.empty()) {
1826 // check all devices on CAM bus
1827 for (i
= 0; i
< (int)scsinames
.size(); i
++) {
1828 if(strcmp(scsinames
[i
].c_str(), test_name
)==0)
1829 { // our disk device is CAM
1830 if ((cam_dev
= cam_open_device(test_name
, O_RDWR
)) == NULL
) {
1836 bzero(&(&ccb
.ccb_h
)[1], PATHINQ_SETTINGS_SIZE
);
1837 ccb
.ccb_h
.func_code
= XPT_PATH_INQ
; // send PATH_INQ to the device
1838 if (ioctl(cam_dev
->fd
, CAMIOCOMMAND
, &ccb
) == -1) {
1839 warn("Get Transfer Settings CCB failed\n"
1840 "%s", strerror(errno
));
1841 cam_close_device(cam_dev
);
1844 // now check if we are working with USB device, see umass.c
1845 if(strcmp(ccb
.cpi
.dev_name
,"umass-sim") == 0) { // USB device found
1846 usbdevlist(bus
,vendor_id
, product_id
, version
);
1847 int bus
=ccb
.cpi
.unit_number
; // unit_number will match umass number
1848 cam_close_device(cam_dev
);
1849 if(usbdevlist(bus
,vendor_id
, product_id
, version
)){
1850 const char * usbtype
= get_usb_dev_type_by_id(vendor_id
, product_id
, version
);
1852 return get_sat_device(usbtype
, new freebsd_scsi_device(this, test_name
, ""));
1856 #if FREEBSDVER > 800100
1857 // check if we have ATA device connected to CAM (ada)
1858 if(ccb
.cpi
.protocol
== PROTO_ATA
){
1859 cam_close_device(cam_dev
);
1860 return new freebsd_atacam_device(this, test_name
, "");
1863 // close cam device, we don`t need it anymore
1864 cam_close_device(cam_dev
);
1865 // handle as usual scsi
1866 return new freebsd_scsi_device(this, test_name
, "");
1870 // device is LSI raid supported by mfi driver
1871 if(!strncmp("/dev/mfid", test_name
, strlen("/dev/mfid")))
1872 set_err(EINVAL
, "To monitor disks on LSI RAID load mfip.ko module and run 'smartctl -a /dev/passX' to show SMART information");
1873 // device type unknown
1878 smart_device
* freebsd_smart_interface::get_custom_smart_device(const char * name
, const char * type
)
1881 static const char * fbsd_dev_twe_ctrl
= "/dev/twe";
1882 static const char * fbsd_dev_twa_ctrl
= "/dev/twa";
1883 static const char * fbsd_dev_tws_ctrl
= "/dev/tws";
1884 int disknum
= -1, n1
= -1, n2
= -1, contr
= -1;
1886 if (sscanf(type
, "3ware,%n%d%n", &n1
, &disknum
, &n2
) == 1 || n1
== 6) {
1887 if (n2
!= (int)strlen(type
)) {
1888 set_err(EINVAL
, "Option -d 3ware,N requires N to be a non-negative integer");
1891 if (!(0 <= disknum
&& disknum
<= 127)) {
1892 set_err(EINVAL
, "Option -d 3ware,N (N=%d) must have 0 <= N <= 127", disknum
);
1896 // guess 3ware device type based on device name
1897 if (str_starts_with(name
, fbsd_dev_twa_ctrl
) ||
1898 str_starts_with(name
, fbsd_dev_tws_ctrl
) ) {
1899 contr
=CONTROLLER_3WARE_9000_CHAR
;
1901 if (!strncmp(fbsd_dev_twe_ctrl
, name
, strlen(fbsd_dev_twe_ctrl
))){
1902 contr
=CONTROLLER_3WARE_678K_CHAR
;
1906 set_err(EINVAL
, "3ware controller type unknown, use %sX, %sX or %sX devices",
1907 fbsd_dev_twe_ctrl
, fbsd_dev_twa_ctrl
, fbsd_dev_tws_ctrl
);
1910 return new freebsd_escalade_device(this, name
, contr
, disknum
);
1914 int controller
= -1, channel
= -1; disknum
= 1;
1915 n1
= n2
= -1; int n3
= -1;
1916 if (sscanf(type
, "hpt,%n%d/%d%n/%d%n", &n1
, &controller
, &channel
, &n2
, &disknum
, &n3
) >= 2 || n1
== 4) {
1917 int len
= strlen(type
);
1918 if (!(n2
== len
|| n3
== len
)) {
1919 set_err(EINVAL
, "Option '-d hpt,L/M/N' supports 2-3 items");
1922 if (!(1 <= controller
&& controller
<= 8)) {
1923 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid controller id L supplied");
1926 if (!(1 <= channel
&& channel
<= 16)) {
1927 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid channel number M supplied");
1930 if (!(1 <= disknum
&& disknum
<= 15)) {
1931 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid pmport number N supplied");
1934 return new freebsd_highpoint_device(this, name
, controller
, channel
, disknum
);
1938 disknum
= n1
= n2
= -1;
1939 if (sscanf(type
, "cciss,%n%d%n", &n1
, &disknum
, &n2
) == 1 || n1
== 6) {
1940 if (n2
!= (int)strlen(type
)) {
1941 set_err(EINVAL
, "Option -d cciss,N requires N to be a non-negative integer");
1944 if (!(0 <= disknum
&& disknum
<= 127)) {
1945 set_err(EINVAL
, "Option -d cciss,N (N=%d) must have 0 <= N <= 127", disknum
);
1948 return get_sat_device("sat,auto", new freebsd_cciss_device(this, name
, disknum
));
1950 #if FREEBSDVER > 800100
1952 if(!strcmp(type
,"atacam"))
1953 return new freebsd_atacam_device(this, name
, "");
1956 disknum
= n1
= n2
= -1;
1958 if (sscanf(type
, "areca,%n%d/%d%n", &n1
, &disknum
, &encnum
, &n2
) >= 1 || n1
== 6) {
1959 if (!(1 <= disknum
&& disknum
<= 128)) {
1960 set_err(EINVAL
, "Option -d areca,N/E (N=%d) must have 1 <= N <= 128", disknum
);
1963 if (!(1 <= encnum
&& encnum
<= 8)) {
1964 set_err(EINVAL
, "Option -d areca,N/E (E=%d) must have 1 <= E <= 8", encnum
);
1967 return new freebsd_areca_ata_device(this, name
, disknum
, encnum
);
1973 std::string
freebsd_smart_interface::get_valid_custom_dev_types_str()
1975 return "3ware,N, hpt,L/M/N, cciss,N, areca,N/E"
1976 #if FREEBSDVER > 800100
1984 /////////////////////////////////////////////////////////////////////////////
1985 /// Initialize platform interface and register with smi()
1987 void smart_interface::init()
1989 static os_freebsd::freebsd_smart_interface the_interface
;
1990 smart_interface::set(&the_interface
);