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 3902 2014-05-23 19:14:15Z 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()
139 : smart_device(never_called
),
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.
163 static inline void * reallocf(void *ptr
, size_t size
) {
164 void *rv
= realloc(ptr
, size
);
165 if((rv
== NULL
) && (size
!= 0))
171 freebsd_smart_device::~freebsd_smart_device() throw()
174 os_freebsd::freebsd_smart_device::close();
177 // migration from the old_style
178 unsigned char m_controller_type
;
179 unsigned char m_controller_port
;
181 // examples for smartctl
182 static const char smartctl_examples
[] =
183 "=================================================== SMARTCTL EXAMPLES =====\n\n"
184 " smartctl -a /dev/ad0 (Prints all SMART information)\n\n"
185 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/ad0\n"
186 " (Enables SMART on first disk)\n\n"
187 " smartctl -t long /dev/ad0 (Executes extended disk self-test)\n\n"
188 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/ad0\n"
189 " (Prints Self-Test & Attribute errors)\n"
190 " (Prints Self-Test & Attribute errors)\n\n"
191 " smartctl -a --device=3ware,2 /dev/twa0\n"
192 " smartctl -a --device=3ware,2 /dev/twe0\n"
193 " smartctl -a --device=3ware,2 /dev/tws0\n"
194 " (Prints all SMART information for ATA disk on\n"
195 " third port of first 3ware RAID controller)\n"
196 " smartctl -a --device=cciss,0 /dev/ciss0\n"
197 " (Prints all SMART information for first disk \n"
198 " on Common Interface for SCSI-3 Support driver)\n"
199 " smartctl -a --device=areca,3/1 /dev/arcmsr0\n"
200 " (Prints all SMART information for 3rd disk in the 1st enclosure \n"
201 " on first ARECA RAID controller)\n"
205 bool freebsd_smart_device::is_open() const
211 bool freebsd_smart_device::open()
213 const char *dev
= get_dev_name();
214 if ((m_fd
= ::open(dev
,O_RDONLY
))<0) {
221 bool freebsd_smart_device::close()
224 // close device, if open
226 failed
=::close(get_fd());
230 if(failed
) return false;
234 /////////////////////////////////////////////////////////////////////////////
235 /// Implement standard ATA support
237 class freebsd_ata_device
238 : public /*implements*/ ata_device
,
239 public /*extends*/ freebsd_smart_device
242 freebsd_ata_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
);
243 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
246 virtual int do_cmd(struct ata_ioc_request
* request
, bool is_48bit_cmd
);
249 freebsd_ata_device::freebsd_ata_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
)
250 : smart_device(intf
, dev_name
, "ata", req_type
),
251 freebsd_smart_device()
255 int freebsd_ata_device::do_cmd( struct ata_ioc_request
* request
, bool is_48bit_cmd
)
257 int fd
= get_fd(), ret
;
258 ARGUSED(is_48bit_cmd
); // no support for 48 bit commands in the IOCATAREQUEST
259 ret
= ioctl(fd
, IOCATAREQUEST
, request
);
260 if (ret
) set_err(errno
);
266 bool freebsd_ata_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
268 bool ata_48bit
= false; // no ata_48bit_support via IOCATAREQUEST
269 if(!strcmp("atacam",get_dev_type())) // enable for atacam interface
272 if (!ata_cmd_is_ok(in
,
273 true, // data_out_support
274 true, // multi_sector_support
277 set_err(ENOSYS
, "48-bit ATA commands not implemented for legacy controllers");
281 struct ata_ioc_request request
;
282 bzero(&request
,sizeof(struct ata_ioc_request
));
284 request
.timeout
=SCSI_TIMEOUT_DEFAULT
;
285 request
.u
.ata
.command
=in
.in_regs
.command
;
286 request
.u
.ata
.feature
=in
.in_regs
.features
;
288 request
.u
.ata
.count
= in
.in_regs
.sector_count_16
;
289 request
.u
.ata
.lba
= in
.in_regs
.lba_48
;
291 switch (in
.direction
) {
292 case ata_cmd_in::no_data
:
293 request
.flags
=ATA_CMD_CONTROL
;
295 case ata_cmd_in::data_in
:
296 request
.flags
=ATA_CMD_READ
| ATA_CMD_CONTROL
;
297 request
.data
=(char *)in
.buffer
;
298 request
.count
=in
.size
;
300 case ata_cmd_in::data_out
:
301 request
.flags
=ATA_CMD_WRITE
| ATA_CMD_CONTROL
;
302 request
.data
=(char *)in
.buffer
;
303 request
.count
=in
.size
;
306 return set_err(ENOSYS
);
311 if (do_cmd(&request
, in
.in_regs
.is_48bit_cmd()))
314 return set_err(EIO
, "request failed, error code 0x%02x", request
.error
);
316 out
.out_regs
.error
= request
.error
;
317 out
.out_regs
.sector_count_16
= request
.u
.ata
.count
;
318 out
.out_regs
.lba_48
= request
.u
.ata
.lba
;
321 // Command specific processing
322 if (in
.in_regs
.command
== ATA_SMART_CMD
323 && in
.in_regs
.features
== ATA_SMART_STATUS
324 && in
.out_needed
.lba_high
)
326 unsigned const char normal_lo
=0x4f, normal_hi
=0xc2;
327 unsigned const char failed_lo
=0xf4, failed_hi
=0x2c;
329 // Cyl low and Cyl high unchanged means "Good SMART status"
330 if (!(out
.out_regs
.lba_mid
==normal_lo
&& out
.out_regs
.lba_high
==normal_hi
)
331 // These values mean "Bad SMART status"
332 && !(out
.out_regs
.lba_mid
==failed_lo
&& out
.out_regs
.lba_high
==failed_hi
))
335 // We haven't gotten output that makes sense; print out some debugging info
337 snprintf(buf
, sizeof(buf
),
338 "CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
339 (int)request
.u
.ata
.command
,
340 (int)request
.u
.ata
.feature
,
341 (int)request
.u
.ata
.count
,
342 (int)((request
.u
.ata
.lba
) & 0xff),
343 (int)((request
.u
.ata
.lba
>>8) & 0xff),
344 (int)((request
.u
.ata
.lba
>>16) & 0xff),
346 printwarning(BAD_SMART
,buf
);
347 out
.out_regs
.lba_high
= failed_hi
;
348 out
.out_regs
.lba_mid
= failed_lo
;
355 #if FREEBSDVER > 800100
356 class freebsd_atacam_device
: public freebsd_ata_device
359 freebsd_atacam_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
)
360 : smart_device(intf
, dev_name
, "atacam", req_type
), freebsd_ata_device(intf
, dev_name
, req_type
)
364 virtual bool close();
368 struct cam_device
*m_camdev
;
370 virtual int do_cmd( struct ata_ioc_request
* request
, bool is_48bit_cmd
);
373 bool freebsd_atacam_device::open(){
374 const char *dev
= get_dev_name();
376 if ((m_camdev
= cam_open_device(dev
, O_RDWR
)) == NULL
) {
380 set_fd(m_camdev
->fd
);
384 bool freebsd_atacam_device::close(){
385 cam_close_device(m_camdev
);
390 int freebsd_atacam_device::do_cmd( struct ata_ioc_request
* request
, bool is_48bit_cmd
)
396 // 48bit commands are broken in ATACAM before r242422/HEAD
397 // and may cause system hang
398 // Waiting for MFC to make sure that bug is fixed,
399 // later version check needs to be added
400 if(!strcmp("ata",m_camdev
->sim_name
) && is_48bit_cmd
) {
401 set_err(ENOSYS
, "48-bit ATA commands not implemented for legacy controllers");
405 memset(&ccb
, 0, sizeof(ccb
));
407 if (request
->count
== 0)
408 camflags
= CAM_DIR_NONE
;
409 else if (request
->flags
& ATA_CMD_READ
)
410 camflags
= CAM_DIR_IN
;
412 camflags
= CAM_DIR_OUT
;
414 cam_fill_ataio(&ccb
.ataio
,
419 (u_int8_t
*)request
->data
,
421 request
->timeout
* 1000); // timeout in seconds
423 ccb
.ataio
.cmd
.flags
= CAM_ATAIO_NEEDRESULT
|
424 (is_48bit_cmd
? CAM_ATAIO_48BIT
: 0);
426 ccb
.ataio
.cmd
.command
= request
->u
.ata
.command
;
427 ccb
.ataio
.cmd
.features
= request
->u
.ata
.feature
;
428 ccb
.ataio
.cmd
.lba_low
= request
->u
.ata
.lba
;
429 ccb
.ataio
.cmd
.lba_mid
= request
->u
.ata
.lba
>> 8;
430 ccb
.ataio
.cmd
.lba_high
= request
->u
.ata
.lba
>> 16;
432 ccb
.ataio
.cmd
.lba_low_exp
= request
->u
.ata
.lba
>> 24;
433 ccb
.ataio
.cmd
.lba_mid_exp
= request
->u
.ata
.lba
>> 32;
434 ccb
.ataio
.cmd
.lba_high_exp
= request
->u
.ata
.lba
>> 40;
435 ccb
.ataio
.cmd
.device
= 0x40 | ((request
->u
.ata
.lba
>> 24) & 0x0f);
436 ccb
.ataio
.cmd
.sector_count
= request
->u
.ata
.count
;
437 ccb
.ataio
.cmd
.sector_count_exp
= request
->u
.ata
.count
>> 8;;
439 ccb
.ccb_h
.flags
|= CAM_DEV_QFRZDIS
;
441 if (cam_send_ccb(m_camdev
, &ccb
) < 0) {
442 set_err(EIO
, "cam_send_ccb failed");
446 if ((ccb
.ccb_h
.status
& CAM_STATUS_MASK
) != CAM_REQ_CMP
) {
447 if(scsi_debugmode
> 0)
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 m_escalade_type(escalade_type
), m_disknum(disknum
)
495 set_info().info_name
= strprintf("%s [3ware_disk_%02d]", dev_name
, disknum
);
498 bool freebsd_escalade_device::open()
500 const char *dev
= get_dev_name();
503 if ((fd
= ::open(dev
,O_RDWR
))<0) {
511 bool freebsd_escalade_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
513 // to hold true file descriptor
516 if (!ata_cmd_is_ok(in
,
517 true, // data_out_support
518 false, // TODO: multi_sector_support
519 true) // ata_48bit_support
523 struct twe_usercommand
* cmd_twe
= NULL
;
524 TW_OSLI_IOCTL_NO_DATA_BUF
* cmd_twa
= NULL
;
525 TWE_Command_ATA
* ata
= NULL
;
527 // Used by both the SCSI and char interfaces
528 char ioctl_buffer
[TW_IOCTL_BUFFER_SIZE
];
531 printwarning(NO_DISK_3WARE
,NULL
);
535 memset(ioctl_buffer
, 0, TW_IOCTL_BUFFER_SIZE
);
537 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
538 cmd_twa
= (TW_OSLI_IOCTL_NO_DATA_BUF
*)ioctl_buffer
;
539 cmd_twa
->pdata
= ((TW_OSLI_IOCTL_WITH_PAYLOAD
*)cmd_twa
)->payload
.data_buf
;
540 cmd_twa
->driver_pkt
.buffer_length
= in
.size
;
541 // using "old" packet format to speak with SATA devices
542 ata
= (TWE_Command_ATA
*)&cmd_twa
->cmd_pkt
.command
.cmd_pkt_7k
;
543 } else if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
544 cmd_twe
= (struct twe_usercommand
*)ioctl_buffer
;
545 ata
= &cmd_twe
->tu_command
.ata
;
547 return set_err(ENOSYS
,
548 "Unrecognized escalade_type %d in linux_3ware_command_interface(disk %d)\n"
549 "Please contact " PACKAGE_BUGREPORT
"\n", (int)m_escalade_type
, m_disknum
);
552 ata
->opcode
= TWE_OP_ATA_PASSTHROUGH
;
554 // Same for (almost) all commands - but some reset below
555 ata
->request_id
= 0xFF;
556 ata
->unit
= m_disknum
;
559 ata
->size
= 0x5; // TODO: multisector support
562 const ata_in_regs_48bit
& r
= in
.in_regs
;
563 ata
->features
= r
.features_16
;
564 ata
->sector_count
= r
.sector_count_16
;
565 ata
->sector_num
= r
.lba_low_16
;
566 ata
->cylinder_lo
= r
.lba_mid_16
;
567 ata
->cylinder_hi
= r
.lba_high_16
;
568 ata
->drive_head
= r
.device
;
569 ata
->command
= r
.command
;
572 // Is this a command that reads or returns 512 bytes?
573 // passthru->param values are:
574 // 0x0 - non data command without TFR write check,
575 // 0x8 - non data command with TFR write check,
576 // 0xD - data command that returns data to host from device
577 // 0xF - data command that writes data from host to device
578 // passthru->size values are 0x5 for non-data and 0x07 for data
579 bool readdata
= false;
580 if (in
.direction
== ata_cmd_in::data_in
) {
581 if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
582 cmd_twe
->tu_data
= in
.buffer
;
583 cmd_twe
->tu_size
= 512;
587 ata
->sgl_offset
= 0x5;
589 // For 64-bit to work correctly, up the size of the command packet
590 // in dwords by 1 to account for the 64-bit single sgl 'address'
591 // field. Note that this doesn't agree with the typedefs but it's
592 // right (agree with kernel driver behavior/typedefs).
593 // if (sizeof(long)==8)
596 else if (in
.direction
== ata_cmd_in::no_data
) {
597 // Non data command -- but doesn't use large sector
598 // count register values.
599 ata
->sgl_offset
= 0x0;
601 ata
->sector_count
= 0x0;
603 else if (in
.direction
== ata_cmd_in::data_out
) {
604 ata
->sgl_offset
= 0x5;
605 ata
->param
= 0xF; // PIO data write
606 if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
607 cmd_twe
->tu_data
= in
.buffer
;
608 cmd_twe
->tu_size
= 512;
610 else if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
611 memcpy(cmd_twa
->pdata
, in
.buffer
, in
.size
);
615 return set_err(EINVAL
);
617 // 3WARE controller can NOT have packet device internally
618 if (in
.in_regs
.command
== ATA_IDENTIFY_PACKET_DEVICE
) {
619 return set_err(ENODEV
, "No drive on port %d", m_disknum
);
622 // Now send the command down through an ioctl()
624 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
625 ioctlreturn
=ioctl(fd
,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH
,cmd_twa
);
627 ioctlreturn
=ioctl(fd
,TWEIO_COMMAND
,cmd_twe
);
630 // Deal with the different error cases
635 // See if the ATA command failed. Now that we have returned from
636 // the ioctl() call, if passthru is valid, then:
637 // - ata->status contains the 3ware controller STATUS
638 // - ata->command contains the ATA STATUS register
639 // - ata->features contains the ATA ERROR register
641 // Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS
642 // If bit 0 (error bit) is set, then ATA ERROR register is valid.
643 // While we *might* decode the ATA ERROR register, at the moment it
644 // doesn't make much sense: we don't care in detail why the error
647 if (ata
->status
|| (ata
->command
& 0x21)) {
649 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
);
653 // If this is a read data command, copy data to output buffer
655 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
)
656 memcpy(in
.buffer
, cmd_twa
->pdata
, in
.size
);
657 else if(m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
658 memcpy(in
.buffer
, cmd_twe
->tu_data
, in
.size
); // untested
661 // Return register values
663 ata_out_regs_48bit
& r
= out
.out_regs
;
664 r
.error
= ata
->features
;
665 r
.sector_count_16
= ata
->sector_count
;
666 r
.lba_low_16
= ata
->sector_num
;
667 r
.lba_mid_16
= ata
->cylinder_lo
;
668 r
.lba_high_16
= ata
->cylinder_hi
;
669 r
.device
= ata
->drive_head
;
670 r
.status
= ata
->command
;
672 // look for nonexistent devices/ports
673 if (in
.in_regs
.command
== ATA_IDENTIFY_DEVICE
674 && !nonempty((unsigned char *)in
.buffer
, in
.size
)) {
675 return set_err(ENODEV
, "No drive on port %d", m_disknum
);
681 /////////////////////////////////////////////////////////////////////////////
682 /// Implement Highpoint RAID support with old functions
684 class freebsd_highpoint_device
685 : public /*implements*/ ata_device_with_command_set
,
686 public /*extends*/ freebsd_smart_device
689 freebsd_highpoint_device(smart_interface
* intf
, const char * dev_name
,
690 unsigned char controller
, unsigned char channel
, unsigned char port
);
693 virtual int ata_command_interface(smart_command_set command
, int select
, char * data
);
697 unsigned char m_hpt_data
[3]; ///< controller/channel/port
701 freebsd_highpoint_device::freebsd_highpoint_device(smart_interface
* intf
, const char * dev_name
,
702 unsigned char controller
, unsigned char channel
, unsigned char port
)
703 : smart_device(intf
, dev_name
, "hpt", "hpt"),
704 freebsd_smart_device()
706 m_hpt_data
[0] = controller
; m_hpt_data
[1] = channel
; m_hpt_data
[2] = port
;
707 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]);
710 bool freebsd_highpoint_device::open()
712 const char *dev
= get_dev_name();
715 if ((fd
= ::open(dev
,O_RDWR
))<0) {
723 int freebsd_highpoint_device::ata_command_interface(smart_command_set command
, int select
, char * data
)
727 HPT_IOCTL_PARAM param
;
728 HPT_CHANNEL_INFO_V2 info
;
729 unsigned char* buff
[512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER
)];
730 PHPT_PASS_THROUGH_HEADER pide_pt_hdr
, pide_pt_hdr_out
;
732 // get internal deviceid
733 ids
[0] = m_hpt_data
[0] - 1;
734 ids
[1] = m_hpt_data
[1] - 1;
736 memset(¶m
, 0, sizeof(HPT_IOCTL_PARAM
));
738 param
.magic
= HPT_IOCTL_MAGIC
;
739 param
.ctrl_code
= HPT_IOCTL_GET_CHANNEL_INFO_V2
;
740 param
.in
= (unsigned char *)ids
;
741 param
.in_size
= sizeof(unsigned int) * 2;
742 param
.out
= (unsigned char *)&info
;
743 param
.out_size
= sizeof(HPT_CHANNEL_INFO_V2
);
745 if (m_hpt_data
[2]==1) {
746 param
.ctrl_code
= HPT_IOCTL_GET_CHANNEL_INFO
;
747 param
.out_size
= sizeof(HPT_CHANNEL_INFO
);
749 if (ioctl(fd
, HPT_DO_IOCONTROL
, ¶m
)!=0 ||
750 info
.devices
[m_hpt_data
[2]-1]==0) {
754 // perform smart action
755 memset(buff
, 0, 512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER
));
756 pide_pt_hdr
= (PHPT_PASS_THROUGH_HEADER
)buff
;
758 pide_pt_hdr
->lbamid
= 0x4f;
759 pide_pt_hdr
->lbahigh
= 0xc2;
760 pide_pt_hdr
->command
= ATA_SMART_CMD
;
761 pide_pt_hdr
->id
= info
.devices
[m_hpt_data
[2] - 1];
765 pide_pt_hdr
->feature
=ATA_SMART_READ_VALUES
;
766 pide_pt_hdr
->protocol
=HPT_READ
;
768 case READ_THRESHOLDS
:
769 pide_pt_hdr
->feature
=ATA_SMART_READ_THRESHOLDS
;
770 pide_pt_hdr
->protocol
=HPT_READ
;
773 pide_pt_hdr
->feature
=ATA_SMART_READ_LOG_SECTOR
;
774 pide_pt_hdr
->lbalow
=select
;
775 pide_pt_hdr
->protocol
=HPT_READ
;
778 pide_pt_hdr
->command
=ATA_IDENTIFY_DEVICE
;
779 pide_pt_hdr
->protocol
=HPT_READ
;
782 pide_pt_hdr
->feature
=ATA_SMART_ENABLE
;
785 pide_pt_hdr
->feature
=ATA_SMART_DISABLE
;
788 pide_pt_hdr
->feature
=ATA_SMART_AUTO_OFFLINE
;
789 pide_pt_hdr
->sectorcount
=select
;
792 pide_pt_hdr
->feature
=ATA_SMART_AUTOSAVE
;
793 pide_pt_hdr
->sectorcount
=select
;
795 case IMMEDIATE_OFFLINE
:
796 pide_pt_hdr
->feature
=ATA_SMART_IMMEDIATE_OFFLINE
;
797 pide_pt_hdr
->lbalow
=select
;
801 pide_pt_hdr
->feature
=ATA_SMART_STATUS
;
803 case CHECK_POWER_MODE
:
804 pide_pt_hdr
->command
=ATA_CHECK_POWER_MODE
;
807 memcpy(buff
+sizeof(HPT_PASS_THROUGH_HEADER
), data
, 512);
808 pide_pt_hdr
->feature
=ATA_SMART_WRITE_LOG_SECTOR
;
809 pide_pt_hdr
->lbalow
=select
;
810 pide_pt_hdr
->protocol
=HPT_WRITE
;
813 pout("Unrecognized command %d in highpoint_command_interface()\n"
814 "Please contact " PACKAGE_BUGREPORT
"\n", command
);
818 if (pide_pt_hdr
->protocol
!=0) {
819 pide_pt_hdr
->sectors
= 1;
820 pide_pt_hdr
->sectorcount
= 1;
823 memset(¶m
, 0, sizeof(HPT_IOCTL_PARAM
));
825 param
.magic
= HPT_IOCTL_MAGIC
;
826 param
.ctrl_code
= HPT_IOCTL_IDE_PASS_THROUGH
;
827 param
.in
= (unsigned char *)buff
;
828 param
.in_size
= sizeof(HPT_PASS_THROUGH_HEADER
) + (pide_pt_hdr
->protocol
==HPT_READ
? 0 : pide_pt_hdr
->sectors
* 512);
829 param
.out
= (unsigned char *)buff
+param
.in_size
;
830 param
.out_size
= sizeof(HPT_PASS_THROUGH_HEADER
) + (pide_pt_hdr
->protocol
==HPT_READ
? pide_pt_hdr
->sectors
* 512 : 0);
832 pide_pt_hdr_out
= (PHPT_PASS_THROUGH_HEADER
)param
.out
;
834 if ((ioctl(fd
, HPT_DO_IOCONTROL
, ¶m
)!=0) ||
835 (pide_pt_hdr_out
->command
& 1)) {
839 if (command
==STATUS_CHECK
)
841 unsigned const char normal_lo
=0x4f, normal_hi
=0xc2;
842 unsigned const char failed_lo
=0xf4, failed_hi
=0x2c;
843 unsigned char low
,high
;
845 high
= pide_pt_hdr_out
->lbahigh
;
846 low
= pide_pt_hdr_out
->lbamid
;
848 // Cyl low and Cyl high unchanged means "Good SMART status"
849 if (low
==normal_lo
&& high
==normal_hi
)
852 // These values mean "Bad SMART status"
853 if (low
==failed_lo
&& high
==failed_hi
)
856 // We haven't gotten output that makes sense; print out some debugging info
858 snprintf(buf
, sizeof(buf
),
859 "CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
860 (int)pide_pt_hdr_out
->command
,
861 (int)pide_pt_hdr_out
->feature
,
862 (int)pide_pt_hdr_out
->sectorcount
,
863 (int)pide_pt_hdr_out
->lbalow
,
864 (int)pide_pt_hdr_out
->lbamid
,
865 (int)pide_pt_hdr_out
->lbahigh
,
866 (int)pide_pt_hdr_out
->sectors
);
867 printwarning(BAD_SMART
,buf
);
869 else if (command
==CHECK_POWER_MODE
)
870 data
[0] = pide_pt_hdr_out
->sectorcount
& 0xff;
871 else if (pide_pt_hdr
->protocol
==HPT_READ
)
872 memcpy(data
, (unsigned char *)buff
+ 2 * sizeof(HPT_PASS_THROUGH_HEADER
),
873 pide_pt_hdr
->sectors
* 512);
878 /////////////////////////////////////////////////////////////////////////////
879 /// Standard SCSI support
881 class freebsd_scsi_device
882 : public /*implements*/ scsi_device
,
883 public /*extends*/ freebsd_smart_device
886 freebsd_scsi_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
);
888 virtual smart_device
* autodetect_open();
890 virtual bool scsi_pass_through(scsi_cmnd_io
* iop
);
894 virtual bool close();
897 struct cam_device
*m_camdev
;
900 bool freebsd_scsi_device::open(){
901 const char *dev
= get_dev_name();
903 if ((m_camdev
= cam_open_device(dev
, O_RDWR
)) == NULL
) {
907 set_fd(m_camdev
->fd
);
911 bool freebsd_scsi_device::close(){
912 cam_close_device(m_camdev
);
917 freebsd_scsi_device::freebsd_scsi_device(smart_interface
* intf
,
918 const char * dev_name
, const char * req_type
)
919 : smart_device(intf
, dev_name
, "scsi", req_type
),
920 freebsd_smart_device()
925 bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io
* iop
)
929 if (scsi_debugmode
) {
931 const unsigned char * ucp
= iop
->cmnd
;
934 np
= scsi_get_opcode_name(ucp
[0]);
935 pout(" [%s: ", np
? np
: "<unknown opcode>");
936 for (k
= 0; k
< iop
->cmnd_len
; ++k
)
937 pout("%02x ", ucp
[k
]);
938 if ((scsi_debugmode
> 1) &&
939 (DXFER_TO_DEVICE
== iop
->dxfer_dir
) && (iop
->dxferp
)) {
940 int trunc
= (iop
->dxfer_len
> 256) ? 1 : 0;
942 pout("]\n Outgoing data, len=%d%s:\n", (int)iop
->dxfer_len
,
943 (trunc
? " [only first 256 bytes shown]" : ""));
944 dStrHex(iop
->dxferp
, (trunc
? 256 : iop
->dxfer_len
) , 1);
952 pout(" error: camdev=0!\n");
953 return set_err(ENOTTY
);
956 if (!(ccb
= cam_getccb(m_camdev
))) {
958 pout(" error allocating ccb\n");
959 return set_err(ENOMEM
);
962 // mfi SAT layer is known to be buggy
963 if(!strcmp("mfi",m_camdev
->sim_name
)) {
964 if (iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_12
|| iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_16
) {
965 // Controller does not return ATA output registers in SAT sense data
966 if (iop
->cmnd
[2] & (1 << 5)) // chk_cond
967 return set_err(ENOSYS
, "ATA return descriptor not supported by controller firmware");
969 // SMART WRITE LOG SECTOR causing media errors
970 if ((iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_16
971 && iop
->cmnd
[14] == ATA_SMART_CMD
&& iop
->cmnd
[3]==0 &&
972 iop
->cmnd
[4] == ATA_SMART_WRITE_LOG_SECTOR
) ||
973 (iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_12
974 && iop
->cmnd
[9] == ATA_SMART_CMD
&& iop
->cmnd
[3] == ATA_SMART_WRITE_LOG_SECTOR
))
976 if(!failuretest_permissive
)
977 return set_err(ENOSYS
, "SMART WRITE LOG SECTOR may cause problems, try with -T permissive to force");
980 // clear out structure, except for header that was filled in for us
981 bzero(&(&ccb
->ccb_h
)[1],
982 sizeof(struct ccb_scsiio
) - sizeof(struct ccb_hdr
));
984 cam_fill_csio(&ccb
->csio
,
987 /* flags */ (iop
->dxfer_dir
== DXFER_NONE
? CAM_DIR_NONE
:(iop
->dxfer_dir
== DXFER_FROM_DEVICE
? CAM_DIR_IN
: CAM_DIR_OUT
)),
988 /* tagaction */ MSG_SIMPLE_Q_TAG
,
989 /* dataptr */ iop
->dxferp
,
990 /* datalen */ iop
->dxfer_len
,
991 /* senselen */ iop
->max_sense_len
,
992 /* cdblen */ iop
->cmnd_len
,
993 /* timout (converted to seconds) */ iop
->timeout
*1000);
994 memcpy(ccb
->csio
.cdb_io
.cdb_bytes
,iop
->cmnd
,iop
->cmnd_len
);
996 if (cam_send_ccb(m_camdev
,ccb
) < 0) {
997 if (scsi_debugmode
) {
998 pout(" error sending SCSI ccb\n");
999 cam_error_print(m_camdev
,ccb
,CAM_ESF_ALL
,CAM_EPF_ALL
,stderr
);
1002 return set_err(EIO
);
1005 if (scsi_debugmode
) {
1006 pout(" CAM status=0x%x, SCSI status=0x%x, resid=0x%x\n",
1007 ccb
->ccb_h
.status
, ccb
->csio
.scsi_status
, ccb
->csio
.resid
);
1008 if ((scsi_debugmode
> 1) && (DXFER_FROM_DEVICE
== iop
->dxfer_dir
)) {
1011 len
= iop
->dxfer_len
- ccb
->csio
.resid
;
1012 trunc
= (len
> 256) ? 1 : 0;
1014 pout(" Incoming data, len=%d%s:\n", len
,
1015 (trunc
? " [only first 256 bytes shown]" : ""));
1016 dStrHex(iop
->dxferp
, (trunc
? 256 : len
), 1);
1019 pout(" Incoming data trimmed to nothing by resid\n");
1023 if (((ccb
->ccb_h
.status
& CAM_STATUS_MASK
) != CAM_REQ_CMP
) && ((ccb
->ccb_h
.status
& CAM_STATUS_MASK
) != CAM_SCSI_STATUS_ERROR
)) {
1025 cam_error_print(m_camdev
,ccb
,CAM_ESF_ALL
,CAM_EPF_ALL
,stderr
);
1027 return set_err(EIO
);
1030 iop
->resid
= ccb
->csio
.resid
;
1031 iop
->scsi_status
= ccb
->csio
.scsi_status
;
1032 if (iop
->sensep
&& (ccb
->ccb_h
.status
& CAM_AUTOSNS_VALID
) != 0) {
1034 pout(" sense_len=0x%x, sense_resid=0x%x\n",
1035 ccb
->csio
.sense_len
, ccb
->csio
.sense_resid
);
1036 iop
->resp_sense_len
= ccb
->csio
.sense_len
- ccb
->csio
.sense_resid
;
1037 /* Some SCSI controller device drivers miscalculate the sense_resid
1038 field so cap resp_sense_len on max_sense_len. */
1039 if (iop
->resp_sense_len
> iop
->max_sense_len
)
1040 iop
->resp_sense_len
= iop
->max_sense_len
;
1041 if (iop
->resp_sense_len
> 0) {
1042 memcpy(iop
->sensep
, &(ccb
->csio
.sense_data
), iop
->resp_sense_len
);
1043 if (scsi_debugmode
) {
1044 if (scsi_debugmode
> 1) {
1045 pout(" >>> Sense buffer, len=%zu:\n", iop
->resp_sense_len
);
1046 dStrHex(iop
->sensep
, iop
->resp_sense_len
, 1);
1048 if ((iop
->sensep
[0] & 0x7f) > 0x71)
1049 pout(" status=0x%x: [desc] sense_key=0x%x asc=0x%x ascq=0x%x\n",
1050 iop
->scsi_status
, iop
->sensep
[1] & 0xf,
1051 iop
->sensep
[2], iop
->sensep
[3]);
1053 pout(" status=0x%x: sense_key=0x%x asc=0x%x ascq=0x%x\n",
1054 iop
->scsi_status
, iop
->sensep
[2] & 0xf,
1055 iop
->sensep
[12], iop
->sensep
[13]);
1058 else if (scsi_debugmode
)
1059 pout(" status=0x%x\n", iop
->scsi_status
);
1061 else if (scsi_debugmode
)
1062 pout(" status=0x%x\n", iop
->scsi_status
);
1066 // mfip replacing PDT of the device so response does not make a sense
1067 // this sets PDT to 00h - direct-access block device
1068 if((!strcmp("mfi", m_camdev
->sim_name
) || !strcmp("mpt", m_camdev
->sim_name
))
1069 && iop
->cmnd
[0] == INQUIRY
) {
1070 if (scsi_debugmode
) {
1071 pout(" device on %s controller, patching PDT\n", m_camdev
->sim_name
);
1073 iop
->dxferp
[0] = iop
->dxferp
[0] & 0xe0;
1080 /////////////////////////////////////////////////////////////////////////////
1081 /// Areca RAID support
1083 ///////////////////////////////////////////////////////////////////
1084 // SATA(ATA) device behind Areca RAID Controller
1085 class freebsd_areca_ata_device
1086 : public /*implements*/ areca_ata_device
,
1087 public /*extends*/ freebsd_smart_device
1090 freebsd_areca_ata_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
= 1);
1091 virtual smart_device
* autodetect_open();
1092 virtual bool arcmsr_lock();
1093 virtual bool arcmsr_unlock();
1094 virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
);
1097 ///////////////////////////////////////////////////////////////////
1098 // SAS(SCSI) device behind Areca RAID Controller
1099 class freebsd_areca_scsi_device
1100 : public /*implements*/ areca_scsi_device
,
1101 public /*extends*/ freebsd_smart_device
1104 freebsd_areca_scsi_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
= 1);
1105 virtual smart_device
* autodetect_open();
1106 virtual bool arcmsr_lock();
1107 virtual bool arcmsr_unlock();
1108 virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
);
1112 // Areca RAID Controller(SATA Disk)
1113 freebsd_areca_ata_device::freebsd_areca_ata_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
)
1114 : smart_device(intf
, dev_name
, "areca", "areca"),
1115 freebsd_smart_device()
1117 set_disknum(disknum
);
1119 set_info().info_name
= strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name
, disknum
, encnum
);
1123 smart_device
* freebsd_areca_ata_device::autodetect_open()
1127 // autodetect device type
1128 is_ata
= arcmsr_get_dev_type();
1142 smart_device_auto_ptr
newdev(new freebsd_areca_scsi_device(smi(), get_dev_name(), get_disknum(), get_encnum()));
1145 newdev
->open(); // TODO: Can possibly pass open fd
1147 return newdev
.release();
1150 int freebsd_areca_ata_device::arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
)
1152 int ioctlreturn
= 0;
1159 ioctlreturn
= ioctl(get_fd(), ((sSRB_BUFFER
*)(iop
->dxferp
))->srbioctl
.ControlCode
, iop
->dxferp
);
1169 bool freebsd_areca_ata_device::arcmsr_lock()
1175 bool freebsd_areca_ata_device::arcmsr_unlock()
1181 // Areca RAID Controller(SAS Device)
1182 freebsd_areca_scsi_device::freebsd_areca_scsi_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
)
1183 : smart_device(intf
, dev_name
, "areca", "areca"),
1184 freebsd_smart_device()
1186 set_disknum(disknum
);
1188 set_info().info_name
= strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name
, disknum
, encnum
);
1191 smart_device
* freebsd_areca_scsi_device::autodetect_open()
1196 int freebsd_areca_scsi_device::arcmsr_do_scsi_io(struct scsi_cmnd_io
* iop
)
1198 int ioctlreturn
= 0;
1204 ioctlreturn
= ioctl(get_fd(), ((sSRB_BUFFER
*)(iop
->dxferp
))->srbioctl
.ControlCode
, iop
->dxferp
);
1214 bool freebsd_areca_scsi_device::arcmsr_lock()
1220 bool freebsd_areca_scsi_device::arcmsr_unlock()
1226 /////////////////////////////////////////////////////////////////////////////
1227 /// Implement CCISS RAID support with old functions
1229 class freebsd_cciss_device
1230 : public /*implements*/ scsi_device
,
1231 public /*extends*/ freebsd_smart_device
1234 freebsd_cciss_device(smart_interface
* intf
, const char * name
, unsigned char disknum
);
1236 virtual bool scsi_pass_through(scsi_cmnd_io
* iop
);
1237 virtual bool open();
1240 unsigned char m_disknum
; ///< Disk number.
1243 bool freebsd_cciss_device::open()
1245 const char *dev
= get_dev_name();
1247 if ((fd
= ::open(dev
,O_RDWR
))<0) {
1255 freebsd_cciss_device::freebsd_cciss_device(smart_interface
* intf
,
1256 const char * dev_name
, unsigned char disknum
)
1257 : smart_device(intf
, dev_name
, "cciss", "cciss"),
1258 freebsd_smart_device(),
1261 set_info().info_name
= strprintf("%s [cciss_disk_%02d]", dev_name
, disknum
);
1264 bool freebsd_cciss_device::scsi_pass_through(scsi_cmnd_io
* iop
)
1266 int status
= cciss_io_interface(get_fd(), m_disknum
, iop
, scsi_debugmode
);
1268 return set_err(-status
);
1275 /////////////////////////////////////////////////////////////////////////////
1276 /// SCSI open with autodetection support
1278 smart_device
* freebsd_scsi_device::autodetect_open()
1284 // No Autodetection if device type was specified by user
1285 if (*get_req_type())
1288 // The code below is based on smartd.cpp:SCSIFilterKnown()
1291 unsigned char req_buff
[64] = {0, };
1293 if (scsiStdInquiry(this, req_buff
, req_len
)) {
1294 // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices
1295 // watch this spot ... other devices could lock up here
1297 if (scsiStdInquiry(this, req_buff
, req_len
)) {
1298 // device doesn't like INQUIRY commands
1300 set_err(EIO
, "INQUIRY failed");
1305 int avail_len
= req_buff
[4] + 5;
1306 int len
= (avail_len
< req_len
? avail_len
: req_len
);
1310 // Use INQUIRY to detect type
1313 if (!memcmp(req_buff
+ 8, "3ware", 5) || !memcmp(req_buff
+ 8, "AMCC", 4) ||
1314 !strcmp("tws",m_camdev
->sim_name
) || !strcmp("twa",m_camdev
->sim_name
)) {
1316 set_err(EINVAL
, "3ware/LSI controller, please try adding '-d 3ware,N',\n"
1317 "you may need to replace %s with /dev/twaN, /dev/tweN or /dev/twsN", get_dev_name());
1321 // SAT or USB, skip MFI controllers because of bugs
1323 smart_device
* newdev
= smi()->autodetect_sat_device(this, req_buff
, len
);
1325 // NOTE: 'this' is now owned by '*newdev'
1326 if(!strcmp("mfi",m_camdev
->sim_name
)) {
1328 newdev
->set_err(ENOSYS
, "SATA device detected,\n"
1329 "MegaRAID SAT layer is reportedly buggy, use '-d sat' to try anyhow");
1335 // Nothing special found
1340 /////////////////////////////////////////////////////////////////////////////
1341 /// Implement platform interface with old functions.
1343 class freebsd_smart_interface
1344 : public /*implements*/ smart_interface
1347 virtual std::string
get_os_version_str();
1349 virtual std::string
get_app_examples(const char * appname
);
1351 virtual bool scan_smart_devices(smart_device_list
& devlist
, const char * type
,
1352 const char * pattern
= 0);
1355 virtual ata_device
* get_ata_device(const char * name
, const char * type
);
1357 #if FREEBSDVER > 800100
1358 virtual ata_device
* get_atacam_device(const char * name
, const char * type
);
1361 virtual scsi_device
* get_scsi_device(const char * name
, const char * type
);
1363 virtual smart_device
* autodetect_smart_device(const char * name
);
1365 virtual smart_device
* get_custom_smart_device(const char * name
, const char * type
);
1367 virtual std::string
get_valid_custom_dev_types_str();
1371 //////////////////////////////////////////////////////////////////////
1373 std::string
freebsd_smart_interface::get_os_version_str()
1375 struct utsname osname
;
1377 return strprintf("%s %s %s", osname
.sysname
, osname
.release
, osname
.machine
);
1380 std::string
freebsd_smart_interface::get_app_examples(const char * appname
)
1382 if (!strcmp(appname
, "smartctl"))
1383 return smartctl_examples
;
1387 ata_device
* freebsd_smart_interface::get_ata_device(const char * name
, const char * type
)
1389 return new freebsd_ata_device(this, name
, type
);
1392 #if FREEBSDVER > 800100
1393 ata_device
* freebsd_smart_interface::get_atacam_device(const char * name
, const char * type
)
1395 return new freebsd_atacam_device(this, name
, type
);
1399 scsi_device
* freebsd_smart_interface::get_scsi_device(const char * name
, const char * type
)
1401 return new freebsd_scsi_device(this, name
, type
);
1404 // we are using CAM subsystem XPT enumerator to found all CAM (scsi/usb/ada/...)
1405 // devices on system despite of it's names
1407 // If any errors occur, leave errno set as it was returned by the
1408 // system call, and return <0.
1411 // names: resulting array
1412 // show_all - export duplicate device name or not
1416 // >=0: number of discovered devices
1418 bool get_dev_names_cam(std::vector
<std::string
> & names
, bool show_all
)
1421 if ((fd
= open(XPT_DEVICE
, O_RDWR
)) == -1) {
1422 if (errno
== ENOENT
) /* There are no CAM device on this computer */
1425 pout("%s control device couldn't opened: %s\n", XPT_DEVICE
, strerror(errno
));
1431 bzero(&ccb
, sizeof(union ccb
));
1433 ccb
.ccb_h
.path_id
= CAM_XPT_PATH_ID
;
1434 ccb
.ccb_h
.target_id
= CAM_TARGET_WILDCARD
;
1435 ccb
.ccb_h
.target_lun
= CAM_LUN_WILDCARD
;
1437 ccb
.ccb_h
.func_code
= XPT_DEV_MATCH
;
1438 int bufsize
= sizeof(struct dev_match_result
) * MAX_NUM_DEV
;
1439 ccb
.cdm
.match_buf_len
= bufsize
;
1440 // TODO: Use local buffer instead of malloc() if possible
1441 ccb
.cdm
.matches
= (struct dev_match_result
*)malloc(bufsize
);
1442 bzero(ccb
.cdm
.matches
,bufsize
); // clear ccb.cdm.matches structure
1444 if (ccb
.cdm
.matches
== NULL
) {
1446 throw std::bad_alloc();
1448 ccb
.cdm
.num_matches
= 0;
1449 ccb
.cdm
.num_patterns
= 0;
1450 ccb
.cdm
.pattern_buf_len
= 0;
1453 * We do the ioctl multiple times if necessary, in case there are
1454 * more than MAX_NUM_DEV nodes in the EDT.
1456 int skip_device
= 0, skip_bus
= 0, changed
= 0; // TODO: bool
1457 std::string devname
;
1459 if (ioctl(fd
, CAMIOCOMMAND
, &ccb
) == -1) {
1461 pout("error sending CAMIOCOMMAND ioctl: %s\n", strerror(errno
));
1462 free(ccb
.cdm
.matches
);
1468 if ((ccb
.ccb_h
.status
!= CAM_REQ_CMP
)
1469 || ((ccb
.cdm
.status
!= CAM_DEV_MATCH_LAST
)
1470 && (ccb
.cdm
.status
!= CAM_DEV_MATCH_MORE
))) {
1471 pout("got CAM error %#x, CDM error %d\n", ccb
.ccb_h
.status
, ccb
.cdm
.status
);
1472 free(ccb
.cdm
.matches
);
1478 for (unsigned i
= 0; i
< ccb
.cdm
.num_matches
; i
++) {
1479 struct bus_match_result
*bus_result
;
1480 struct device_match_result
*dev_result
;
1481 struct periph_match_result
*periph_result
;
1483 if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_BUS
) {
1484 bus_result
= &ccb
.cdm
.matches
[i
].result
.bus_result
;
1486 if (strcmp(bus_result
->dev_name
,"xpt") == 0) /* skip XPT bus at all */
1491 } else if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_DEVICE
) {
1492 dev_result
= &ccb
.cdm
.matches
[i
].result
.device_result
;
1494 if (dev_result
->flags
& DEV_RESULT_UNCONFIGURED
|| skip_bus
== 1)
1499 // /* Shall we skip non T_DIRECT devices ? */
1500 // if (dev_result->inq_data.device != T_DIRECT)
1503 } else if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_PERIPH
&&
1504 (skip_device
== 0 || show_all
)) {
1505 /* One device may be populated as many peripherals (pass0 & da0 for example).
1506 * We are searching for best name
1508 periph_result
= &ccb
.cdm
.matches
[i
].result
.periph_result
;
1509 /* Prefer non-"pass" names */
1510 if (devname
.empty() || strncmp(periph_result
->periph_name
, "pass", 4) != 0) {
1511 devname
= strprintf("%s%s%d", _PATH_DEV
, periph_result
->periph_name
, periph_result
->unit_number
);
1515 if ((changed
== 1 || show_all
) && !devname
.empty()) {
1516 names
.push_back(devname
);
1522 } while ((ccb
.ccb_h
.status
== CAM_REQ_CMP
) && (ccb
.cdm
.status
== CAM_DEV_MATCH_MORE
));
1524 if (!devname
.empty())
1525 names
.push_back(devname
);
1527 free(ccb
.cdm
.matches
);
1532 // we are using ATA subsystem enumerator to found all ATA devices on system
1533 // despite of it's names
1535 // If any errors occur, leave errno set as it was returned by the
1536 // system call, and return <0.
1540 // >=0: number of discovered devices
1541 int get_dev_names_ata(char*** names
) {
1542 struct ata_ioc_devices devices
;
1543 int fd
=-1,maxchannel
,serrno
=-1,n
=0;
1548 if ((fd
= open(ATA_DEVICE
, O_RDWR
)) < 0) {
1549 if (errno
== ENOENT
) /* There are no ATA device on this computer */
1552 pout("%s control device can't be opened: %s\n", ATA_DEVICE
, strerror(errno
));
1557 if (ioctl(fd
, IOCATAGMAXCHANNEL
, &maxchannel
) < 0) {
1559 pout("ioctl(IOCATAGMAXCHANNEL) on /dev/ata failed: %s\n", strerror(errno
));
1564 // allocate space for up to MAX_NUM_DEV number of ATA devices
1565 mp
= (char **)calloc(MAX_NUM_DEV
, sizeof(char*));
1568 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__
);
1573 for (devices
.channel
= 0; devices
.channel
< maxchannel
&& n
< MAX_NUM_DEV
; devices
.channel
++) {
1576 if (ioctl(fd
, IOCATADEVICES
, &devices
) < 0) {
1578 continue; /* such channel not exist */
1579 pout("ioctl(IOCATADEVICES) on %s channel %d failed: %s\n", ATA_DEVICE
, devices
.channel
, strerror(errno
));
1583 for (j
=0;j
<=1 && n
<MAX_NUM_DEV
;j
++) {
1584 if (devices
.name
[j
][0] != '\0') {
1585 asprintf(mp
+n
, "%s%s", _PATH_DEV
, devices
.name
[j
]);
1586 if (mp
[n
] == NULL
) {
1587 pout("Out of memory constructing scan ATA device list (on line %d)\n", __LINE__
);
1591 bytes
+=1+strlen(mp
[n
]);
1596 mp
= (char **)reallocf(mp
,n
*(sizeof (char*))); // shrink to correct size
1597 if (mp
== NULL
&& n
> 0 ) { // reallocf never fail for size=0, but may return NULL
1599 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__
);
1603 bytes
+= (n
)*(sizeof(char*)); // and set allocated byte count
1622 bool freebsd_smart_interface::scan_smart_devices(smart_device_list
& devlist
,
1623 const char * type
, const char * pattern
/*= 0*/)
1626 set_err(EINVAL
, "DEVICESCAN with pattern not implemented yet");
1631 char * * atanames
= 0; int numata
= 0;
1632 if (!type
|| !strcmp(type
, "ata")) {
1633 numata
= get_dev_names_ata(&atanames
);
1640 std::vector
<std::string
> scsinames
;
1641 if (!type
|| !strcmp(type
, "scsi")) { // do not export duplicated names
1642 if (!get_dev_names_cam(scsinames
, false)) {
1652 for (i
= 0; i
< numata
; i
++) {
1653 ata_device
* atadev
= get_ata_device(atanames
[i
], type
);
1655 devlist
.push_back(atadev
);
1658 if(numata
) free(atanames
);
1660 for (i
= 0; i
< (int)scsinames
.size(); i
++) {
1661 if(!*type
) { // try USB autodetection if no type specified
1662 smart_device
* smartdev
= autodetect_smart_device(scsinames
[i
].c_str());
1664 devlist
.push_back(smartdev
);
1667 scsi_device
* scsidev
= get_scsi_device(scsinames
[i
].c_str(), type
);
1669 devlist
.push_back(scsidev
);
1676 #if (FREEBSDVER < 800000) // without this build fail on FreeBSD 8
1677 static char done
[USB_MAX_DEVICES
];
1679 static int usbdevinfo(int f
, int a
, int rec
, int busno
, unsigned short & vendor_id
,
1680 unsigned short & product_id
, unsigned short & version
)
1683 struct usb_device_info di
;
1687 snprintf(devname
, sizeof(devname
),"umass%d",busno
);
1690 e
= ioctl(f
, USB_DEVICEINFO
, &di
);
1693 printf("addr %d: I/O error\n", a
);
1699 for (i
= 0; i
< USB_MAX_DEVNAMES
; i
++) {
1700 if (di
.udi_devnames
[i
][0]) {
1701 if(strcmp(di
.udi_devnames
[i
],devname
)==0) {
1703 vendor_id
= di
.udi_vendorNo
;
1704 product_id
= di
.udi_productNo
;
1705 version
= di
.udi_releaseNo
;
1713 for (p
= 0; p
< di
.udi_nports
; p
++) {
1714 int s
= di
.udi_ports
[p
];
1715 if (s
>= USB_MAX_DEVICES
) {
1719 printf("addr 0 should never happen!\n");
1721 if(usbdevinfo(f
, s
, 1, busno
, vendor_id
, product_id
, version
)) return 1;
1729 static int usbdevlist(int busno
,unsigned short & vendor_id
,
1730 unsigned short & product_id
, unsigned short & version
)
1732 #if (FREEBSDVER >= 800000) // libusb2 interface
1733 struct libusb20_device
*pdev
= NULL
;
1734 struct libusb20_backend
*pbe
;
1735 uint32_t matches
= 0;
1736 char buf
[128]; // do not change!
1739 struct LIBUSB20_DEVICE_DESC_DECODED
*pdesc
;
1741 pbe
= libusb20_be_alloc_default();
1743 while ((pdev
= libusb20_be_device_foreach(pbe
, pdev
))) {
1746 if (libusb20_dev_open(pdev
, 0)) {
1747 warnx("libusb20_dev_open: could not open device");
1751 pdesc
=libusb20_dev_get_device_desc(pdev
);
1753 snprintf(devname
, sizeof(devname
),"umass%d:",busno
);
1754 for (n
= 0; n
!= 255; n
++) {
1755 if (libusb20_dev_get_iface_desc(pdev
, n
, buf
, sizeof(buf
)))
1759 if(strncmp(buf
,devname
,strlen(devname
))==0){
1761 vendor_id
= pdesc
->idVendor
;
1762 product_id
= pdesc
->idProduct
;
1763 version
= pdesc
->bcdDevice
;
1764 libusb20_dev_close(pdev
);
1765 libusb20_be_free(pbe
);
1770 libusb20_dev_close(pdev
);
1774 printf("No device match or lack of permissions.\n");
1777 libusb20_be_free(pbe
);
1780 #else // freebsd < 8.0 USB stack, ioctl interface
1786 for (ncont
= 0, i
= 0; i
< 10; i
++) {
1787 snprintf(buf
, sizeof(buf
), "%s%d", USBDEV
, i
);
1788 f
= open(buf
, O_RDONLY
);
1790 memset(done
, 0, sizeof done
);
1791 for (a
= 1; a
< USB_MAX_DEVICES
; a
++) {
1793 rc
= usbdevinfo(f
, a
, 1, busno
,vendor_id
, product_id
, version
);
1800 if (errno
== ENOENT
|| errno
== ENXIO
)
1810 smart_device
* freebsd_smart_interface::autodetect_smart_device(const char * name
)
1812 unsigned short vendor_id
= 0, product_id
= 0, version
= 0;
1813 struct cam_device
*cam_dev
;
1818 const char * test_name
= name
;
1820 // if dev_name null, or string length zero
1821 if (!name
|| !(len
= strlen(name
)))
1824 // Dereference symlinks
1826 std::string pathbuf
;
1827 if (!lstat(name
, &st
) && S_ISLNK(st
.st_mode
)) {
1828 char * p
= realpath(name
, (char *)0);
1832 test_name
= pathbuf
.c_str();
1837 char * * atanames
= 0; int numata
= 0;
1838 numata
= get_dev_names_ata(&atanames
);
1840 // check ATA/ATAPI devices
1841 for (i
= 0; i
< numata
; i
++) {
1842 if(!strcmp(atanames
[i
],test_name
)) {
1843 for (c
= i
; c
< numata
; c
++) free(atanames
[c
]);
1845 return new freebsd_ata_device(this, test_name
, "");
1847 else free(atanames
[i
]);
1849 if(numata
) free(atanames
);
1853 pout("Unable to get ATA device list\n");
1857 std::vector
<std::string
> scsinames
;
1858 if (!get_dev_names_cam(scsinames
, true))
1859 pout("Unable to get CAM device list\n");
1860 else if (!scsinames
.empty()) {
1861 // check all devices on CAM bus
1862 for (i
= 0; i
< (int)scsinames
.size(); i
++) {
1863 if(strcmp(scsinames
[i
].c_str(), test_name
)==0)
1864 { // our disk device is CAM
1865 if(strncmp(scsinames
[i
].c_str(), "/dev/pmp", strlen("/dev/pmp")) == 0) {
1866 pout("Skipping port multiplier [%s]\n", scsinames
[i
].c_str());
1870 if ((cam_dev
= cam_open_device(test_name
, O_RDWR
)) == NULL
) {
1876 bzero(&(&ccb
.ccb_h
)[1], PATHINQ_SETTINGS_SIZE
);
1877 ccb
.ccb_h
.func_code
= XPT_PATH_INQ
; // send PATH_INQ to the device
1878 if (ioctl(cam_dev
->fd
, CAMIOCOMMAND
, &ccb
) == -1) {
1879 warn("Get Transfer Settings CCB failed\n"
1880 "%s", strerror(errno
));
1881 cam_close_device(cam_dev
);
1884 // now check if we are working with USB device, see umass.c
1885 if(strcmp(ccb
.cpi
.dev_name
,"umass-sim") == 0) { // USB device found
1886 usbdevlist(bus
,vendor_id
, product_id
, version
);
1887 int bus
=ccb
.cpi
.unit_number
; // unit_number will match umass number
1888 cam_close_device(cam_dev
);
1889 if(usbdevlist(bus
,vendor_id
, product_id
, version
)){
1890 const char * usbtype
= get_usb_dev_type_by_id(vendor_id
, product_id
, version
);
1892 return get_sat_device(usbtype
, new freebsd_scsi_device(this, test_name
, ""));
1896 #if FREEBSDVER > 800100
1897 // check if we have ATA device connected to CAM (ada)
1898 if(ccb
.cpi
.protocol
== PROTO_ATA
){
1899 cam_close_device(cam_dev
);
1900 return new freebsd_atacam_device(this, test_name
, "");
1903 // close cam device, we don`t need it anymore
1904 cam_close_device(cam_dev
);
1905 // handle as usual scsi
1906 return new freebsd_scsi_device(this, test_name
, "");
1910 // device is LSI raid supported by mfi driver
1911 if(!strncmp("/dev/mfid", test_name
, strlen("/dev/mfid")))
1912 set_err(EINVAL
, "To monitor disks on LSI RAID load mfip.ko module and run 'smartctl -a /dev/passX' to show SMART information");
1913 // device type unknown
1918 smart_device
* freebsd_smart_interface::get_custom_smart_device(const char * name
, const char * type
)
1921 static const char * fbsd_dev_twe_ctrl
= "/dev/twe";
1922 static const char * fbsd_dev_twa_ctrl
= "/dev/twa";
1923 static const char * fbsd_dev_tws_ctrl
= "/dev/tws";
1924 int disknum
= -1, n1
= -1, n2
= -1, contr
= -1;
1926 if (sscanf(type
, "3ware,%n%d%n", &n1
, &disknum
, &n2
) == 1 || n1
== 6) {
1927 if (n2
!= (int)strlen(type
)) {
1928 set_err(EINVAL
, "Option -d 3ware,N requires N to be a non-negative integer");
1931 if (!(0 <= disknum
&& disknum
<= 127)) {
1932 set_err(EINVAL
, "Option -d 3ware,N (N=%d) must have 0 <= N <= 127", disknum
);
1936 // guess 3ware device type based on device name
1937 if (str_starts_with(name
, fbsd_dev_twa_ctrl
) ||
1938 str_starts_with(name
, fbsd_dev_tws_ctrl
) ) {
1939 contr
=CONTROLLER_3WARE_9000_CHAR
;
1941 if (!strncmp(fbsd_dev_twe_ctrl
, name
, strlen(fbsd_dev_twe_ctrl
))){
1942 contr
=CONTROLLER_3WARE_678K_CHAR
;
1946 set_err(EINVAL
, "3ware controller type unknown, use %sX, %sX or %sX devices",
1947 fbsd_dev_twe_ctrl
, fbsd_dev_twa_ctrl
, fbsd_dev_tws_ctrl
);
1950 return new freebsd_escalade_device(this, name
, contr
, disknum
);
1954 int controller
= -1, channel
= -1; disknum
= 1;
1955 n1
= n2
= -1; int n3
= -1;
1956 if (sscanf(type
, "hpt,%n%d/%d%n/%d%n", &n1
, &controller
, &channel
, &n2
, &disknum
, &n3
) >= 2 || n1
== 4) {
1957 int len
= strlen(type
);
1958 if (!(n2
== len
|| n3
== len
)) {
1959 set_err(EINVAL
, "Option '-d hpt,L/M/N' supports 2-3 items");
1962 if (!(1 <= controller
&& controller
<= 8)) {
1963 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid controller id L supplied");
1966 if (!(1 <= channel
&& channel
<= 128)) {
1967 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid channel number M supplied");
1970 if (!(1 <= disknum
&& disknum
<= 15)) {
1971 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid pmport number N supplied");
1974 return new freebsd_highpoint_device(this, name
, controller
, channel
, disknum
);
1978 disknum
= n1
= n2
= -1;
1979 if (sscanf(type
, "cciss,%n%d%n", &n1
, &disknum
, &n2
) == 1 || n1
== 6) {
1980 if (n2
!= (int)strlen(type
)) {
1981 set_err(EINVAL
, "Option -d cciss,N requires N to be a non-negative integer");
1984 if (!(0 <= disknum
&& disknum
<= 127)) {
1985 set_err(EINVAL
, "Option -d cciss,N (N=%d) must have 0 <= N <= 127", disknum
);
1988 return get_sat_device("sat,auto", new freebsd_cciss_device(this, name
, disknum
));
1990 #if FREEBSDVER > 800100
1992 if(!strcmp(type
,"atacam"))
1993 return new freebsd_atacam_device(this, name
, "");
1996 disknum
= n1
= n2
= -1;
1998 if (sscanf(type
, "areca,%n%d/%d%n", &n1
, &disknum
, &encnum
, &n2
) >= 1 || n1
== 6) {
1999 if (!(1 <= disknum
&& disknum
<= 128)) {
2000 set_err(EINVAL
, "Option -d areca,N/E (N=%d) must have 1 <= N <= 128", disknum
);
2003 if (!(1 <= encnum
&& encnum
<= 8)) {
2004 set_err(EINVAL
, "Option -d areca,N/E (E=%d) must have 1 <= E <= 8", encnum
);
2007 return new freebsd_areca_ata_device(this, name
, disknum
, encnum
);
2013 std::string
freebsd_smart_interface::get_valid_custom_dev_types_str()
2015 return "3ware,N, hpt,L/M/N, cciss,N, areca,N/E"
2016 #if FREEBSDVER > 800100
2024 /////////////////////////////////////////////////////////////////////////////
2025 /// Initialize platform interface and register with smi()
2027 void smart_interface::init()
2029 static os_freebsd::freebsd_smart_interface the_interface
;
2030 smart_interface::set(&the_interface
);