4 * Home page of code is: http://smartmontools.sourceforge.net
6 * Copyright (C) 2003-8 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, write to the Free
15 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #include <sys/types.h>
24 #include <cam/scsi/scsi_message.h>
25 #include <cam/scsi/scsi_pass.h>
26 #if defined(__DragonFly__)
36 #include <sys/utsname.h>
45 #include "os_freebsd.h"
47 #include "dev_interface.h"
48 #include "dev_ata_cmd_set.h"
50 #define USBDEV "/dev/usb"
51 #if defined(__FreeBSD_version)
53 // This way we define one variable for the GNU/kFreeBSD and FreeBSD
54 #define FREEBSDVER __FreeBSD_version
56 #define FREEBSDVER __FreeBSD_kernel_version
59 #if (FREEBSDVER >= 800000)
60 #include <libusb20_desc.h>
63 #include <dev/usb/usb.h>
64 #include <dev/usb/usbhid.h>
67 #define CONTROLLER_3WARE_9000_CHAR 0x01
68 #define CONTROLLER_3WARE_678K_CHAR 0x02
70 #ifndef PATHINQ_SETTINGS_SIZE
71 #define PATHINQ_SETTINGS_SIZE 128
74 static __unused
const char *filenameandversion
="$Id: os_freebsd.cpp 2973 2009-10-26 22:38:19Z chrfranke $";
76 const char *os_XXXX_c_cvsid
="$Id: os_freebsd.cpp 2973 2009-10-26 22:38:19Z chrfranke $" \
77 ATACMDS_H_CVSID CCISS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID
;
79 extern smartmonctrl
* con
;
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 // global variable holding byte count of allocated memory
124 const char * dev_freebsd_cpp_cvsid
= "$Id: os_freebsd.cpp 2973 2009-10-26 22:38:19Z chrfranke $"
125 DEV_INTERFACE_H_CVSID
;
127 extern smartmonctrl
* con
; // con->reportscsiioctl
129 /////////////////////////////////////////////////////////////////////////////
131 namespace os_freebsd
{ // No need to publish anything, name provided for Doxygen
133 /////////////////////////////////////////////////////////////////////////////
134 /// Implement shared open/close routines with old functions.
136 class freebsd_smart_device
137 : virtual public /*implements*/ smart_device
140 explicit freebsd_smart_device(const char * mode
)
141 : smart_device(never_called
),
142 m_fd(-1), m_mode(mode
) { }
144 virtual ~freebsd_smart_device() throw();
146 virtual bool is_open() const;
150 virtual bool close();
153 /// Return filedesc for derived classes.
161 int m_fd
; ///< filedesc, -1 if not open.
162 const char * m_mode
; ///< Mode string for deviceopen().
166 static inline void * reallocf(void *ptr
, size_t size
) {
167 void *rv
= realloc(ptr
, size
);
174 freebsd_smart_device::~freebsd_smart_device() throw()
177 os_freebsd::freebsd_smart_device::close();
180 // migration from the old_style
181 unsigned char m_controller_type
;
182 unsigned char m_controller_port
;
184 // examples for smartctl
185 static const char smartctl_examples
[] =
186 "=================================================== SMARTCTL EXAMPLES =====\n\n"
187 " smartctl -a /dev/ad0 (Prints all SMART information)\n\n"
188 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/ad0\n"
189 " (Enables SMART on first disk)\n\n"
190 " smartctl -t long /dev/ad0 (Executes extended disk self-test)\n\n"
191 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/ad0\n"
192 " (Prints Self-Test & Attribute errors)\n"
193 " (Prints Self-Test & Attribute errors)\n\n"
194 " smartctl -a --device=3ware,2 /dev/twa0\n"
195 " smartctl -a --device=3ware,2 /dev/twe0\n"
196 " (Prints all SMART information for ATA disk on\n"
197 " third port of first 3ware RAID controller)\n"
198 " smartctl -a --device=cciss,0 /dev/ciss0\n"
199 " (Prints all SMART information for first disk \n"
200 " on Common Interface for SCSI-3 Support driver)\n"
204 bool freebsd_smart_device::is_open() const
210 bool freebsd_smart_device::open()
212 const char *dev
= get_dev_name();
213 if ((m_fd
= ::open(dev
,O_RDONLY
))<0) {
220 bool freebsd_smart_device::close()
223 // close device, if open
225 failed
=::close(get_fd());
229 if(failed
) return false;
233 /////////////////////////////////////////////////////////////////////////////
234 /// Implement standard ATA support with old functions
236 class freebsd_ata_device
237 : public /*implements*/ ata_device_with_command_set
,
238 public /*extends*/ freebsd_smart_device
241 freebsd_ata_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
);
244 virtual int ata_command_interface(smart_command_set command
, int select
, char * data
);
245 virtual int do_cmd(struct ata_ioc_request
* request
);
248 freebsd_ata_device::freebsd_ata_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
)
249 : smart_device(intf
, dev_name
, "ata", req_type
),
250 freebsd_smart_device("ATA")
254 int freebsd_ata_device::do_cmd( struct ata_ioc_request
* request
)
257 return ioctl(fd
, IOCATAREQUEST
, request
);
260 #if FREEBSDVER > 800100
261 class freebsd_atacam_device
: public freebsd_ata_device
264 freebsd_atacam_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
)
265 : smart_device(intf
, dev_name
, "atacam", req_type
), freebsd_ata_device(intf
, dev_name
, req_type
)
269 virtual bool close();
273 struct cam_device
*m_camdev
;
275 virtual int do_cmd( struct ata_ioc_request
* request
);
278 bool freebsd_atacam_device::open(){
279 const char *dev
= get_dev_name();
281 if ((m_camdev
= cam_open_device(dev
, O_RDWR
)) == NULL
) {
285 set_fd(m_camdev
->fd
);
289 bool freebsd_atacam_device::close(){
290 cam_close_device(m_camdev
);
295 int freebsd_atacam_device::do_cmd( struct ata_ioc_request
* request
)
300 memset(&ccb
, 0, sizeof(ccb
));
302 if (request
->count
== 0)
303 camflags
= CAM_DIR_NONE
;
304 else if (request
->flags
== ATA_CMD_READ
)
305 camflags
= CAM_DIR_IN
;
307 camflags
= CAM_DIR_OUT
;
309 cam_fill_ataio(&ccb
.ataio
,
314 (u_int8_t
*)request
->data
,
316 request
->timeout
* 1000); // timeout in seconds
319 ccb
.ataio
.cmd
.flags
= 0;
320 ccb
.ataio
.cmd
.command
= request
->u
.ata
.command
;
321 ccb
.ataio
.cmd
.features
= request
->u
.ata
.feature
;
322 ccb
.ataio
.cmd
.lba_low
= request
->u
.ata
.lba
;
323 ccb
.ataio
.cmd
.lba_mid
= request
->u
.ata
.lba
>> 8;
324 ccb
.ataio
.cmd
.lba_high
= request
->u
.ata
.lba
>> 16;
325 ccb
.ataio
.cmd
.device
= 0x40 | ((request
->u
.ata
.lba
>> 24) & 0x0f);
326 ccb
.ataio
.cmd
.sector_count
= request
->u
.ata
.count
;
328 ccb
.ccb_h
.flags
|= CAM_DEV_QFRZDIS
;
330 if (cam_send_ccb(m_camdev
, &ccb
) < 0) {
331 err(1, "cam_send_ccb");
335 if ((ccb
.ccb_h
.status
& CAM_STATUS_MASK
) == CAM_REQ_CMP
)
338 cam_error_print(m_camdev
, &ccb
, CAM_ESF_ALL
, CAM_EPF_ALL
, stderr
);
344 int freebsd_ata_device::ata_command_interface(smart_command_set command
, int select
, char * data
)
346 int retval
, copydata
=0;
347 struct ata_ioc_request request
;
348 unsigned char buff
[512];
351 bzero(&request
,sizeof(struct ata_ioc_request
));
354 request
.u
.ata
.command
=ATA_SMART_CMD
;
355 request
.timeout
=SCSI_TIMEOUT_DEFAULT
;
358 request
.u
.ata
.feature
=ATA_SMART_READ_VALUES
;
359 request
.u
.ata
.lba
=0xc24f<<8;
360 request
.flags
=ATA_CMD_READ
;
361 request
.data
=(char *)buff
;
365 case READ_THRESHOLDS
:
366 request
.u
.ata
.feature
=ATA_SMART_READ_THRESHOLDS
;
367 request
.u
.ata
.count
=1;
368 request
.u
.ata
.lba
=1|(0xc24f<<8);
369 request
.flags
=ATA_CMD_READ
;
370 request
.data
=(char *)buff
;
375 request
.u
.ata
.feature
=ATA_SMART_READ_LOG_SECTOR
;
376 request
.u
.ata
.lba
=select
|(0xc24f<<8);
377 request
.u
.ata
.count
=1;
378 request
.flags
=ATA_CMD_READ
;
379 request
.data
=(char *)buff
;
384 request
.u
.ata
.command
=ATA_IDENTIFY_DEVICE
;
385 request
.flags
=ATA_CMD_READ
;
386 request
.data
=(char *)buff
;
391 request
.u
.ata
.command
=ATA_IDENTIFY_PACKET_DEVICE
;
392 request
.flags
=ATA_CMD_READ
;
393 request
.data
=(char *)buff
;
398 request
.u
.ata
.feature
=ATA_SMART_ENABLE
;
399 request
.u
.ata
.lba
=0xc24f<<8;
400 request
.flags
=ATA_CMD_CONTROL
;
403 request
.u
.ata
.feature
=ATA_SMART_DISABLE
;
404 request
.u
.ata
.lba
=0xc24f<<8;
405 request
.flags
=ATA_CMD_CONTROL
;
408 // NOTE: According to ATAPI 4 and UP, this command is obsolete
409 request
.u
.ata
.feature
=ATA_SMART_AUTO_OFFLINE
;
410 request
.u
.ata
.lba
=0xc24f<<8;
411 request
.u
.ata
.count
=select
;
412 request
.flags
=ATA_CMD_CONTROL
;
415 request
.u
.ata
.feature
=ATA_SMART_AUTOSAVE
;
416 request
.u
.ata
.lba
=0xc24f<<8;
417 request
.u
.ata
.count
=select
;
418 request
.flags
=ATA_CMD_CONTROL
;
420 case IMMEDIATE_OFFLINE
:
421 request
.u
.ata
.feature
=ATA_SMART_IMMEDIATE_OFFLINE
;
422 request
.u
.ata
.lba
= select
|(0xc24f<<8); // put test in sector
423 request
.flags
=ATA_CMD_CONTROL
;
425 case STATUS_CHECK
: // same command, no HDIO in FreeBSD
427 // this command only says if SMART is working. It could be
428 // replaced with STATUS_CHECK below.
429 request
.u
.ata
.feature
=ATA_SMART_STATUS
;
430 request
.u
.ata
.lba
=0xc24f<<8;
431 request
.flags
=ATA_CMD_CONTROL
;
433 case CHECK_POWER_MODE
:
434 request
.u
.ata
.command
=ATA_CHECK_POWER_MODE
;
435 request
.u
.ata
.feature
=0;
436 request
.flags
=ATA_CMD_CONTROL
;
439 memcpy(buff
, data
, 512);
440 request
.u
.ata
.feature
=ATA_SMART_WRITE_LOG_SECTOR
;
441 request
.u
.ata
.lba
=select
|(0xc24f<<8);
442 request
.u
.ata
.count
=1;
443 request
.flags
=ATA_CMD_WRITE
;
444 request
.data
=(char *)buff
;
448 pout("Unrecognized command %d in ata_command_interface()\n"
449 "Please contact " PACKAGE_BUGREPORT
"\n", command
);
454 if (command
==STATUS_CHECK
){
455 unsigned const char normal_lo
=0x4f, normal_hi
=0xc2;
456 unsigned const char failed_lo
=0xf4, failed_hi
=0x2c;
457 unsigned char low
,high
;
459 if ((retval
=do_cmd(&request
)) || request
.error
)
462 #if (FREEBSDVER < 502000)
463 printwarning(NO_RETURN
,NULL
);
466 high
= (request
.u
.ata
.lba
>> 16) & 0xff;
467 low
= (request
.u
.ata
.lba
>> 8) & 0xff;
469 // Cyl low and Cyl high unchanged means "Good SMART status"
470 if (low
==normal_lo
&& high
==normal_hi
)
473 // These values mean "Bad SMART status"
474 if (low
==failed_lo
&& high
==failed_hi
)
477 // We haven't gotten output that makes sense; print out some debugging info
479 sprintf(buf
,"CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
480 (int)request
.u
.ata
.command
,
481 (int)request
.u
.ata
.feature
,
482 (int)request
.u
.ata
.count
,
483 (int)((request
.u
.ata
.lba
) & 0xff),
484 (int)((request
.u
.ata
.lba
>>8) & 0xff),
485 (int)((request
.u
.ata
.lba
>>16) & 0xff),
487 printwarning(BAD_SMART
,buf
);
491 if ((retval
=do_cmd(&request
)) || request
.error
)
496 if (command
== CHECK_POWER_MODE
) {
497 data
[0] = request
.u
.ata
.count
& 0xff;
501 memcpy(data
, buff
, 512);
506 /////////////////////////////////////////////////////////////////////////////
507 /// Implement AMCC/3ware RAID support with old functions
509 class freebsd_escalade_device
510 : public /*implements*/ ata_device_with_command_set
,
511 public /*extends*/ freebsd_smart_device
514 freebsd_escalade_device(smart_interface
* intf
, const char * dev_name
,
515 int escalade_type
, int disknum
);
518 virtual int ata_command_interface(smart_command_set command
, int select
, char * data
);
522 int m_escalade_type
; ///< Type string for escalade_command_interface().
523 int m_disknum
; ///< Disk number.
526 freebsd_escalade_device::freebsd_escalade_device(smart_interface
* intf
, const char * dev_name
,
527 int escalade_type
, int disknum
)
528 : smart_device(intf
, dev_name
, "3ware", "3ware"),
529 freebsd_smart_device(
530 escalade_type
==CONTROLLER_3WARE_9000_CHAR
? "ATA_3WARE_9000" :
531 escalade_type
==CONTROLLER_3WARE_678K_CHAR
? "ATA_3WARE_678K" :
532 /* CONTROLLER_3WARE_678K */ "ATA" ),
533 m_escalade_type(escalade_type
), m_disknum(disknum
)
535 set_info().info_name
= strprintf("%s [3ware_disk_%02d]", dev_name
, disknum
);
538 bool freebsd_escalade_device::open()
540 const char *dev
= get_dev_name();
543 if ((fd
= ::open(dev
,O_RDWR
))<0) {
551 int freebsd_escalade_device::ata_command_interface(smart_command_set command
, int select
, char * data
)
553 // to hold true file descriptor
556 // return value and buffer for ioctl()
557 int ioctlreturn
, readdata
=0;
558 struct twe_usercommand
* cmd_twe
= NULL
;
559 TW_OSLI_IOCTL_NO_DATA_BUF
* cmd_twa
= NULL
;
560 TWE_Command_ATA
* ata
= NULL
;
562 // Used by both the SCSI and char interfaces
563 char ioctl_buffer
[TW_IOCTL_BUFFER_SIZE
];
566 printwarning(NO_DISK_3WARE
,NULL
);
570 memset(ioctl_buffer
, 0, TW_IOCTL_BUFFER_SIZE
);
572 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
573 cmd_twa
= (TW_OSLI_IOCTL_NO_DATA_BUF
*)ioctl_buffer
;
574 cmd_twa
->pdata
= ((TW_OSLI_IOCTL_WITH_PAYLOAD
*)cmd_twa
)->payload
.data_buf
;
575 cmd_twa
->driver_pkt
.buffer_length
= 512;
576 ata
= (TWE_Command_ATA
*)&cmd_twa
->cmd_pkt
.command
.cmd_pkt_7k
;
577 } else if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
578 cmd_twe
= (struct twe_usercommand
*)ioctl_buffer
;
579 ata
= &cmd_twe
->tu_command
.ata
;
581 pout("Unrecognized escalade_type %d in freebsd_3ware_command_interface(disk %d)\n"
582 "Please contact " PACKAGE_BUGREPORT
"\n", m_escalade_type
, m_disknum
);
587 ata
->opcode
= TWE_OP_ATA_PASSTHROUGH
;
589 // Same for (almost) all commands - but some reset below
590 ata
->request_id
= 0xFF;
591 ata
->unit
= m_disknum
;
594 ata
->drive_head
= 0x0;
597 // All SMART commands use this CL/CH signature. These are magic
598 // values from the ATA specifications.
599 ata
->cylinder_lo
= 0x4F;
600 ata
->cylinder_hi
= 0xC2;
602 // SMART ATA COMMAND REGISTER value
603 ata
->command
= ATA_SMART_CMD
;
605 // Is this a command that reads or returns 512 bytes?
606 // passthru->param values are:
607 // 0x0 - non data command without TFR write check,
608 // 0x8 - non data command with TFR write check,
609 // 0xD - data command that returns data to host from device
610 // 0xF - data command that writes data from host to device
611 // passthru->size values are 0x5 for non-data and 0x07 for data
612 if (command
== READ_VALUES
||
613 command
== READ_THRESHOLDS
||
614 command
== READ_LOG
||
615 command
== IDENTIFY
||
616 command
== WRITE_LOG
)
619 if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
620 cmd_twe
->tu_data
= data
;
621 cmd_twe
->tu_size
= 512;
623 ata
->sgl_offset
= 0x5;
626 ata
->sector_count
= 0x1;
627 // For 64-bit to work correctly, up the size of the command packet
628 // in dwords by 1 to account for the 64-bit single sgl 'address'
629 // field. Note that this doesn't agree with the typedefs but it's
630 // right (agree with kernel driver behavior/typedefs).
631 //if (sizeof(long)==8)
635 // Non data command -- but doesn't use large sector
636 // count register values.
637 ata
->sgl_offset
= 0x0;
640 ata
->sector_count
= 0x0;
643 // Now set ATA registers depending upon command
645 case CHECK_POWER_MODE
:
646 ata
->command
= ATA_CHECK_POWER_MODE
;
648 ata
->cylinder_lo
= 0;
649 ata
->cylinder_hi
= 0;
652 ata
->features
= ATA_SMART_READ_VALUES
;
654 case READ_THRESHOLDS
:
655 ata
->features
= ATA_SMART_READ_THRESHOLDS
;
658 ata
->features
= ATA_SMART_READ_LOG_SECTOR
;
659 // log number to return
660 ata
->sector_num
= select
;
664 ata
->features
= ATA_SMART_WRITE_LOG_SECTOR
;
665 ata
->sector_count
= 1;
666 ata
->sector_num
= select
;
667 ata
->param
= 0xF; // PIO data write
670 // ATA IDENTIFY DEVICE
671 ata
->command
= ATA_IDENTIFY_DEVICE
;
673 ata
->cylinder_lo
= 0;
674 ata
->cylinder_hi
= 0;
677 // 3WARE controller can NOT have packet device internally
678 pout("WARNING - NO DEVICE FOUND ON 3WARE CONTROLLER (disk %d)\n", m_disknum
);
682 ata
->features
= ATA_SMART_ENABLE
;
685 ata
->features
= ATA_SMART_DISABLE
;
688 ata
->features
= ATA_SMART_AUTO_OFFLINE
;
689 // Enable or disable?
690 ata
->sector_count
= select
;
693 ata
->features
= ATA_SMART_AUTOSAVE
;
694 // Enable or disable?
695 ata
->sector_count
= select
;
697 case IMMEDIATE_OFFLINE
:
698 ata
->features
= ATA_SMART_IMMEDIATE_OFFLINE
;
699 // What test type to run?
700 ata
->sector_num
= select
;
703 ata
->features
= ATA_SMART_STATUS
;
706 // This is JUST to see if SMART is enabled, by giving SMART status
707 // command. But it doesn't say if status was good, or failing.
708 // See below for the difference.
709 ata
->features
= ATA_SMART_STATUS
;
712 pout("Unrecognized command %d in freebsd_3ware_command_interface(disk %d)\n"
713 "Please contact " PACKAGE_BUGREPORT
"\n", command
, m_disknum
);
718 // Now send the command down through an ioctl()
719 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
720 ioctlreturn
=ioctl(fd
,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH
,cmd_twa
);
722 ioctlreturn
=ioctl(fd
,TWEIO_COMMAND
,cmd_twe
);
725 // Deal with the different error cases
732 // See if the ATA command failed. Now that we have returned from
733 // the ioctl() call, if passthru is valid, then:
734 // - ata->status contains the 3ware controller STATUS
735 // - ata->command contains the ATA STATUS register
736 // - ata->features contains the ATA ERROR register
738 // Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS
739 // If bit 0 (error bit) is set, then ATA ERROR register is valid.
740 // While we *might* decode the ATA ERROR register, at the moment it
741 // doesn't make much sense: we don't care in detail why the error
744 if (ata
->status
|| (ata
->command
& 0x21)) {
745 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
);
750 // If this is a read data command, copy data to output buffer
752 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
)
753 memcpy(data
, cmd_twa
->pdata
, 512);
756 // For STATUS_CHECK, we need to check register values
757 if (command
==STATUS_CHECK
) {
759 // To find out if the SMART RETURN STATUS is good or failing, we
760 // need to examine the values of the Cylinder Low and Cylinder
763 unsigned short cyl_lo
=ata
->cylinder_lo
;
764 unsigned short cyl_hi
=ata
->cylinder_hi
;
766 // If values in Cyl-LO and Cyl-HI are unchanged, SMART status is good.
767 if (cyl_lo
==0x4F && cyl_hi
==0xC2)
770 // If values in Cyl-LO and Cyl-HI are as follows, SMART status is FAIL
771 if (cyl_lo
==0xF4 && cyl_hi
==0x2C)
778 // copy sector count register (one byte!) to return data
779 if (command
==CHECK_POWER_MODE
)
780 *data
=*(char *)&(ata
->sector_count
);
782 // look for nonexistent devices/ports
783 if (command
==IDENTIFY
&& !nonempty((unsigned char *)data
, 512)) {
792 /////////////////////////////////////////////////////////////////////////////
793 /// Implement Highpoint RAID support with old functions
795 class freebsd_highpoint_device
796 : public /*implements*/ ata_device_with_command_set
,
797 public /*extends*/ freebsd_smart_device
800 freebsd_highpoint_device(smart_interface
* intf
, const char * dev_name
,
801 unsigned char controller
, unsigned char channel
, unsigned char port
);
804 virtual int ata_command_interface(smart_command_set command
, int select
, char * data
);
808 unsigned char m_hpt_data
[3]; ///< controller/channel/port
812 freebsd_highpoint_device::freebsd_highpoint_device(smart_interface
* intf
, const char * dev_name
,
813 unsigned char controller
, unsigned char channel
, unsigned char port
)
814 : smart_device(intf
, dev_name
, "hpt", "hpt"),
815 freebsd_smart_device("ATA")
817 m_hpt_data
[0] = controller
; m_hpt_data
[1] = channel
; m_hpt_data
[2] = port
;
818 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]);
821 bool freebsd_highpoint_device::open()
823 const char *dev
= get_dev_name();
826 if ((fd
= ::open(dev
,O_RDWR
))<0) {
834 int freebsd_highpoint_device::ata_command_interface(smart_command_set command
, int select
, char * data
)
838 HPT_IOCTL_PARAM param
;
839 HPT_CHANNEL_INFO_V2 info
;
840 unsigned char* buff
[512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER
)];
841 PHPT_PASS_THROUGH_HEADER pide_pt_hdr
, pide_pt_hdr_out
;
843 // get internal deviceid
844 ids
[0] = m_hpt_data
[0] - 1;
845 ids
[1] = m_hpt_data
[1] - 1;
847 memset(¶m
, 0, sizeof(HPT_IOCTL_PARAM
));
849 param
.magic
= HPT_IOCTL_MAGIC
;
850 param
.ctrl_code
= HPT_IOCTL_GET_CHANNEL_INFO_V2
;
851 param
.in
= (unsigned char *)ids
;
852 param
.in_size
= sizeof(unsigned int) * 2;
853 param
.out
= (unsigned char *)&info
;
854 param
.out_size
= sizeof(HPT_CHANNEL_INFO_V2
);
856 if (m_hpt_data
[2]==1) {
857 param
.ctrl_code
= HPT_IOCTL_GET_CHANNEL_INFO
;
858 param
.out_size
= sizeof(HPT_CHANNEL_INFO
);
860 if (ioctl(fd
, HPT_DO_IOCONTROL
, ¶m
)!=0 ||
861 info
.devices
[m_hpt_data
[2]-1]==0) {
865 // perform smart action
866 memset(buff
, 0, 512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER
));
867 pide_pt_hdr
= (PHPT_PASS_THROUGH_HEADER
)buff
;
869 pide_pt_hdr
->lbamid
= 0x4f;
870 pide_pt_hdr
->lbahigh
= 0xc2;
871 pide_pt_hdr
->command
= ATA_SMART_CMD
;
872 pide_pt_hdr
->id
= info
.devices
[m_hpt_data
[2] - 1];
876 pide_pt_hdr
->feature
=ATA_SMART_READ_VALUES
;
877 pide_pt_hdr
->protocol
=HPT_READ
;
879 case READ_THRESHOLDS
:
880 pide_pt_hdr
->feature
=ATA_SMART_READ_THRESHOLDS
;
881 pide_pt_hdr
->protocol
=HPT_READ
;
884 pide_pt_hdr
->feature
=ATA_SMART_READ_LOG_SECTOR
;
885 pide_pt_hdr
->lbalow
=select
;
886 pide_pt_hdr
->protocol
=HPT_READ
;
889 pide_pt_hdr
->command
=ATA_IDENTIFY_DEVICE
;
890 pide_pt_hdr
->protocol
=HPT_READ
;
893 pide_pt_hdr
->feature
=ATA_SMART_ENABLE
;
896 pide_pt_hdr
->feature
=ATA_SMART_DISABLE
;
899 pide_pt_hdr
->feature
=ATA_SMART_AUTO_OFFLINE
;
900 pide_pt_hdr
->sectorcount
=select
;
903 pide_pt_hdr
->feature
=ATA_SMART_AUTOSAVE
;
904 pide_pt_hdr
->sectorcount
=select
;
906 case IMMEDIATE_OFFLINE
:
907 pide_pt_hdr
->feature
=ATA_SMART_IMMEDIATE_OFFLINE
;
908 pide_pt_hdr
->lbalow
=select
;
912 pide_pt_hdr
->feature
=ATA_SMART_STATUS
;
914 case CHECK_POWER_MODE
:
915 pide_pt_hdr
->command
=ATA_CHECK_POWER_MODE
;
918 memcpy(buff
+sizeof(HPT_PASS_THROUGH_HEADER
), data
, 512);
919 pide_pt_hdr
->feature
=ATA_SMART_WRITE_LOG_SECTOR
;
920 pide_pt_hdr
->lbalow
=select
;
921 pide_pt_hdr
->protocol
=HPT_WRITE
;
924 pout("Unrecognized command %d in highpoint_command_interface()\n"
925 "Please contact " PACKAGE_BUGREPORT
"\n", command
);
929 if (pide_pt_hdr
->protocol
!=0) {
930 pide_pt_hdr
->sectors
= 1;
931 pide_pt_hdr
->sectorcount
= 1;
934 memset(¶m
, 0, sizeof(HPT_IOCTL_PARAM
));
936 param
.magic
= HPT_IOCTL_MAGIC
;
937 param
.ctrl_code
= HPT_IOCTL_IDE_PASS_THROUGH
;
938 param
.in
= (unsigned char *)buff
;
939 param
.in_size
= sizeof(HPT_PASS_THROUGH_HEADER
) + (pide_pt_hdr
->protocol
==HPT_READ
? 0 : pide_pt_hdr
->sectors
* 512);
940 param
.out
= (unsigned char *)buff
+param
.in_size
;
941 param
.out_size
= sizeof(HPT_PASS_THROUGH_HEADER
) + (pide_pt_hdr
->protocol
==HPT_READ
? pide_pt_hdr
->sectors
* 512 : 0);
943 pide_pt_hdr_out
= (PHPT_PASS_THROUGH_HEADER
)param
.out
;
945 if ((ioctl(fd
, HPT_DO_IOCONTROL
, ¶m
)!=0) ||
946 (pide_pt_hdr_out
->command
& 1)) {
950 if (command
==STATUS_CHECK
)
952 unsigned const char normal_lo
=0x4f, normal_hi
=0xc2;
953 unsigned const char failed_lo
=0xf4, failed_hi
=0x2c;
954 unsigned char low
,high
;
956 high
= pide_pt_hdr_out
->lbahigh
;
957 low
= pide_pt_hdr_out
->lbamid
;
959 // Cyl low and Cyl high unchanged means "Good SMART status"
960 if (low
==normal_lo
&& high
==normal_hi
)
963 // These values mean "Bad SMART status"
964 if (low
==failed_lo
&& high
==failed_hi
)
967 // We haven't gotten output that makes sense; print out some debugging info
969 sprintf(buf
,"CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
970 (int)pide_pt_hdr_out
->command
,
971 (int)pide_pt_hdr_out
->feature
,
972 (int)pide_pt_hdr_out
->sectorcount
,
973 (int)pide_pt_hdr_out
->lbalow
,
974 (int)pide_pt_hdr_out
->lbamid
,
975 (int)pide_pt_hdr_out
->lbahigh
,
976 (int)pide_pt_hdr_out
->sectors
);
977 printwarning(BAD_SMART
,buf
);
979 else if (command
==CHECK_POWER_MODE
)
980 data
[0] = pide_pt_hdr_out
->sectorcount
& 0xff;
981 else if (pide_pt_hdr
->protocol
==HPT_READ
)
982 memcpy(data
, (unsigned char *)buff
+ 2 * sizeof(HPT_PASS_THROUGH_HEADER
),
983 pide_pt_hdr
->sectors
* 512);
988 /////////////////////////////////////////////////////////////////////////////
989 /// Implement standard SCSI support with old functions
991 class freebsd_scsi_device
992 : public /*implements*/ scsi_device
,
993 public /*extends*/ freebsd_smart_device
996 freebsd_scsi_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
);
998 virtual smart_device
* autodetect_open();
1000 virtual bool scsi_pass_through(scsi_cmnd_io
* iop
);
1002 virtual bool open();
1004 virtual bool close();
1008 struct cam_device
*m_camdev
;
1011 bool freebsd_scsi_device::open(){
1012 const char *dev
= get_dev_name();
1014 if ((m_camdev
= cam_open_device(dev
, O_RDWR
)) == NULL
) {
1018 set_fd(m_camdev
->fd
);
1022 bool freebsd_scsi_device::close(){
1023 cam_close_device(m_camdev
);
1028 freebsd_scsi_device::freebsd_scsi_device(smart_interface
* intf
,
1029 const char * dev_name
, const char * req_type
)
1030 : smart_device(intf
, dev_name
, "scsi", req_type
),
1031 freebsd_smart_device("SCSI")
1036 bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io
* iop
)
1038 int report
=con
->reportscsiioctl
;
1043 const unsigned char * ucp
= iop
->cmnd
;
1046 np
= scsi_get_opcode_name(ucp
[0]);
1047 pout(" [%s: ", np
? np
: "<unknown opcode>");
1048 for (k
= 0; k
< iop
->cmnd_len
; ++k
)
1049 pout("%02x ", ucp
[k
]);
1051 (DXFER_TO_DEVICE
== iop
->dxfer_dir
) && (iop
->dxferp
)) {
1052 int trunc
= (iop
->dxfer_len
> 256) ? 1 : 0;
1054 pout("]\n Outgoing data, len=%d%s:\n", (int)iop
->dxfer_len
,
1055 (trunc
? " [only first 256 bytes shown]" : ""));
1056 dStrHex(iop
->dxferp
, (trunc
? 256 : iop
->dxfer_len
) , 1);
1062 if(m_camdev
==NULL
) {
1063 warnx("error: camdev=0!");
1067 if (!(ccb
= cam_getccb(m_camdev
))) {
1068 warnx("error allocating ccb");
1072 // clear out structure, except for header that was filled in for us
1073 bzero(&(&ccb
->ccb_h
)[1],
1074 sizeof(struct ccb_scsiio
) - sizeof(struct ccb_hdr
));
1076 cam_fill_csio(&ccb
->csio
,
1079 /* flags */ (iop
->dxfer_dir
== DXFER_NONE
? CAM_DIR_NONE
:(iop
->dxfer_dir
== DXFER_FROM_DEVICE
? CAM_DIR_IN
: CAM_DIR_OUT
)),
1080 /* tagaction */ MSG_SIMPLE_Q_TAG
,
1081 /* dataptr */ iop
->dxferp
,
1082 /* datalen */ iop
->dxfer_len
,
1083 /* senselen */ iop
->max_sense_len
,
1084 /* cdblen */ iop
->cmnd_len
,
1085 /* timout (converted to seconds) */ iop
->timeout
*1000);
1086 memcpy(ccb
->csio
.cdb_io
.cdb_bytes
,iop
->cmnd
,iop
->cmnd_len
);
1088 if (cam_send_ccb(m_camdev
,ccb
) < 0) {
1089 warn("error sending SCSI ccb");
1090 #if (FREEBSDVER > 500000)
1091 cam_error_print(m_camdev
,ccb
,CAM_ESF_ALL
,CAM_EPF_ALL
,stderr
);
1097 if (((ccb
->ccb_h
.status
& CAM_STATUS_MASK
) != CAM_REQ_CMP
) && ((ccb
->ccb_h
.status
& CAM_STATUS_MASK
) != CAM_SCSI_STATUS_ERROR
)) {
1098 #if (FREEBSDVER > 500000)
1099 cam_error_print(m_camdev
,ccb
,CAM_ESF_ALL
,CAM_EPF_ALL
,stderr
);
1106 memcpy(iop
->sensep
,&(ccb
->csio
.sense_data
),sizeof(struct scsi_sense_data
));
1107 iop
->resp_sense_len
= sizeof(struct scsi_sense_data
);
1110 iop
->scsi_status
= ccb
->csio
.scsi_status
;
1117 pout(" status=0\n");
1118 trunc
= (iop
->dxfer_len
> 256) ? 1 : 0;
1120 pout(" Incoming data, len=%d%s:\n", (int)iop
->dxfer_len
,
1121 (trunc
? " [only first 256 bytes shown]" : ""));
1122 dStrHex(iop
->dxferp
, (trunc
? 256 : iop
->dxfer_len
) , 1);
1129 /////////////////////////////////////////////////////////////////////////////
1130 /// Implement CCISS RAID support with old functions
1132 class freebsd_cciss_device
1133 : public /*implements*/ scsi_device
,
1134 public /*extends*/ freebsd_smart_device
1137 freebsd_cciss_device(smart_interface
* intf
, const char * name
, unsigned char disknum
);
1139 virtual bool scsi_pass_through(scsi_cmnd_io
* iop
);
1140 virtual bool open();
1143 unsigned char m_disknum
; ///< Disk number.
1146 bool freebsd_cciss_device::open()
1148 const char *dev
= get_dev_name();
1150 #ifndef HAVE_DEV_CISS_CISSIO_H
1151 pout("CCISS support is not available in this build of smartmontools,\n"
1152 "/usr/src/sys/dev/ciss/cissio.h was not available at build time.\n\n");
1155 if ((fd
= ::open(dev
,O_RDWR
))<0) {
1163 freebsd_cciss_device::freebsd_cciss_device(smart_interface
* intf
,
1164 const char * dev_name
, unsigned char disknum
)
1165 : smart_device(intf
, dev_name
, "cciss", "cciss"),
1166 freebsd_smart_device("SCSI"),
1169 set_info().info_name
= strprintf("%s [cciss_disk_%02d]", dev_name
, disknum
);
1172 bool freebsd_cciss_device::scsi_pass_through(scsi_cmnd_io
* iop
)
1174 #ifdef HAVE_DEV_CISS_CISSIO_H
1175 int status
= cciss_io_interface(get_fd(), m_disknum
, iop
, con
->reportscsiioctl
);
1177 return set_err(-status
);
1185 /////////////////////////////////////////////////////////////////////////////
1186 /// SCSI open with autodetection support
1188 smart_device
* freebsd_scsi_device::autodetect_open()
1194 // No Autodetection if device type was specified by user
1195 if (*get_req_type())
1198 // The code below is based on smartd.cpp:SCSIFilterKnown()
1201 unsigned char req_buff
[64] = {0, };
1203 if (scsiStdInquiry(this, req_buff
, req_len
)) {
1204 // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices
1205 // watch this spot ... other devices could lock up here
1207 if (scsiStdInquiry(this, req_buff
, req_len
)) {
1208 // device doesn't like INQUIRY commands
1210 set_err(EIO
, "INQUIRY failed");
1215 int avail_len
= req_buff
[4] + 5;
1216 int len
= (avail_len
< req_len
? avail_len
: req_len
);
1220 // Use INQUIRY to detect type
1223 if (!memcmp(req_buff
+ 8, "3ware", 5) || !memcmp(req_buff
+ 8, "AMCC", 4)) {
1225 set_err(EINVAL
, "AMCC/3ware controller, please try adding '-d 3ware,N',\n"
1226 "you may need to replace %s with /dev/twaN or /dev/tweN", get_dev_name());
1232 smart_device
* newdev
= smi()->autodetect_sat_device(this, req_buff
, len
);
1234 // NOTE: 'this' is now owned by '*newdev'
1238 // Nothing special found
1243 /////////////////////////////////////////////////////////////////////////////
1244 /// Implement platform interface with old functions.
1246 class freebsd_smart_interface
1247 : public /*implements*/ smart_interface
1250 virtual std::string
get_os_version_str();
1252 virtual std::string
get_app_examples(const char * appname
);
1254 virtual bool scan_smart_devices(smart_device_list
& devlist
, const char * type
,
1255 const char * pattern
= 0);
1258 virtual ata_device
* get_ata_device(const char * name
, const char * type
);
1260 #if FREEBSDVER > 800100
1261 virtual ata_device
* get_atacam_device(const char * name
, const char * type
);
1264 virtual scsi_device
* get_scsi_device(const char * name
, const char * type
);
1266 virtual smart_device
* autodetect_smart_device(const char * name
);
1268 virtual smart_device
* get_custom_smart_device(const char * name
, const char * type
);
1270 virtual std::string
get_valid_custom_dev_types_str();
1274 //////////////////////////////////////////////////////////////////////
1276 std::string
freebsd_smart_interface::get_os_version_str()
1278 struct utsname osname
;
1280 return strprintf("%s %s %s", osname
.sysname
, osname
.release
, osname
.machine
);
1283 std::string
freebsd_smart_interface::get_app_examples(const char * appname
)
1285 if (!strcmp(appname
, "smartctl"))
1286 return smartctl_examples
;
1290 ata_device
* freebsd_smart_interface::get_ata_device(const char * name
, const char * type
)
1292 return new freebsd_ata_device(this, name
, type
);
1295 #if FREEBSDVER > 800100
1296 ata_device
* freebsd_smart_interface::get_atacam_device(const char * name
, const char * type
)
1298 return new freebsd_atacam_device(this, name
, type
);
1302 scsi_device
* freebsd_smart_interface::get_scsi_device(const char * name
, const char * type
)
1304 return new freebsd_scsi_device(this, name
, type
);
1307 // we are using CAM subsystem XPT enumerator to found all CAM (scsi/usb/ada/...)
1308 // devices on system despite of it's names
1310 // If any errors occur, leave errno set as it was returned by the
1311 // system call, and return <0.
1314 // names: resulting array
1315 // show_all - export duplicate device name or not
1319 // >=0: number of discovered devices
1321 int get_dev_names_cam(char*** names
, bool show_all
) {
1326 int bufsize
, fd
= -1;
1327 int skip_device
= 0, skip_bus
= 0, changed
= 0;
1328 char *devname
= NULL
;
1331 // in case of non-clean exit
1333 ccb
.cdm
.matches
= NULL
;
1335 if ((fd
= open(XPT_DEVICE
, O_RDWR
)) == -1) {
1336 if (errno
== ENOENT
) /* There are no CAM device on this computer */
1339 pout("%s control device couldn't opened: %s\n", XPT_DEVICE
, strerror(errno
));
1344 // allocate space for up to MAX_NUM_DEV number of ATA devices
1345 mp
= (char **)calloc(MAX_NUM_DEV
, sizeof(char*));
1348 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__
);
1353 bzero(&ccb
, sizeof(union ccb
));
1355 ccb
.ccb_h
.path_id
= CAM_XPT_PATH_ID
;
1356 ccb
.ccb_h
.target_id
= CAM_TARGET_WILDCARD
;
1357 ccb
.ccb_h
.target_lun
= CAM_LUN_WILDCARD
;
1359 ccb
.ccb_h
.func_code
= XPT_DEV_MATCH
;
1360 bufsize
= sizeof(struct dev_match_result
) * MAX_NUM_DEV
;
1361 ccb
.cdm
.match_buf_len
= bufsize
;
1362 ccb
.cdm
.matches
= (struct dev_match_result
*)malloc(bufsize
);
1363 if (ccb
.cdm
.matches
== NULL
) {
1365 pout("can't malloc memory for matches on line %d\n", __LINE__
);
1369 ccb
.cdm
.num_matches
= 0;
1370 ccb
.cdm
.num_patterns
= 0;
1371 ccb
.cdm
.pattern_buf_len
= 0;
1374 * We do the ioctl multiple times if necessary, in case there are
1375 * more than MAX_NUM_DEV nodes in the EDT.
1378 if (ioctl(fd
, CAMIOCOMMAND
, &ccb
) == -1) {
1380 pout("error sending CAMIOCOMMAND ioctl: %s\n", strerror(errno
));
1385 if ((ccb
.ccb_h
.status
!= CAM_REQ_CMP
)
1386 || ((ccb
.cdm
.status
!= CAM_DEV_MATCH_LAST
)
1387 && (ccb
.cdm
.status
!= CAM_DEV_MATCH_MORE
))) {
1388 pout("got CAM error %#x, CDM error %d\n", ccb
.ccb_h
.status
, ccb
.cdm
.status
);
1394 for (i
= 0; i
< ccb
.cdm
.num_matches
&& n
< MAX_NUM_DEV
; i
++) {
1395 struct bus_match_result
*bus_result
;
1396 struct device_match_result
*dev_result
;
1397 struct periph_match_result
*periph_result
;
1399 if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_BUS
) {
1400 bus_result
= &ccb
.cdm
.matches
[i
].result
.bus_result
;
1402 if (strcmp(bus_result
->dev_name
,"ata") == 0 /* ATAPICAM devices will be probed as ATA devices, skip'em there */
1403 || strcmp(bus_result
->dev_name
,"xpt") == 0) /* skip XPT bus at all */
1408 } else if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_DEVICE
) {
1409 dev_result
= &ccb
.cdm
.matches
[i
].result
.device_result
;
1411 if (dev_result
->flags
& DEV_RESULT_UNCONFIGURED
|| skip_bus
== 1)
1416 // /* Shall we skip non T_DIRECT devices ? */
1417 // if (dev_result->inq_data.device != T_DIRECT)
1420 } else if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_PERIPH
&&
1421 (skip_device
== 0 || show_all
)) {
1422 /* One device may be populated as many peripherals (pass0 & da0 for example).
1423 * We are searching for latest name
1425 periph_result
= &ccb
.cdm
.matches
[i
].result
.periph_result
;
1427 asprintf(&devname
, "%s%s%d", _PATH_DEV
, periph_result
->periph_name
, periph_result
->unit_number
);
1428 if (devname
== NULL
) {
1430 pout("Out of memory constructing scan SCSI device list (on line %d)\n", __LINE__
);
1436 if ((changed
== 1 || show_all
) && devname
!= NULL
) {
1439 bytes
+=1+strlen(mp
[n
]);
1445 } while ((ccb
.ccb_h
.status
== CAM_REQ_CMP
) && (ccb
.cdm
.status
== CAM_DEV_MATCH_MORE
) && n
< MAX_NUM_DEV
);
1447 if (devname
!= NULL
) {
1450 bytes
+=1+strlen(mp
[n
]);
1454 mp
= (char **)reallocf(mp
,n
*(sizeof (char*))); // shrink to correct size
1455 bytes
+= (n
)*(sizeof(char*)); // and set allocated byte count
1458 free(ccb
.cdm
.matches
);
1473 // we are using ATA subsystem enumerator to found all ATA devices on system
1474 // despite of it's names
1476 // If any errors occur, leave errno set as it was returned by the
1477 // system call, and return <0.
1481 // >=0: number of discovered devices
1482 int get_dev_names_ata(char*** names
) {
1483 struct ata_ioc_devices devices
;
1484 int fd
=-1,maxchannel
,serrno
=-1,n
=0;
1489 if ((fd
= open(ATA_DEVICE
, O_RDWR
)) < 0) {
1490 if (errno
== ENOENT
) /* There are no ATA device on this computer */
1493 pout("%s control device can't be opened: %s\n", ATA_DEVICE
, strerror(errno
));
1498 if (ioctl(fd
, IOCATAGMAXCHANNEL
, &maxchannel
) < 0) {
1500 pout("ioctl(IOCATAGMAXCHANNEL) on /dev/ata failed: %s\n", strerror(errno
));
1505 // allocate space for up to MAX_NUM_DEV number of ATA devices
1506 mp
= (char **)calloc(MAX_NUM_DEV
, sizeof(char*));
1509 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__
);
1514 for (devices
.channel
= 0; devices
.channel
< maxchannel
&& n
< MAX_NUM_DEV
; devices
.channel
++) {
1517 if (ioctl(fd
, IOCATADEVICES
, &devices
) < 0) {
1519 continue; /* such channel not exist */
1520 pout("ioctl(IOCATADEVICES) on %s channel %d failed: %s\n", ATA_DEVICE
, devices
.channel
, strerror(errno
));
1524 for (j
=0;j
<=1 && n
<MAX_NUM_DEV
;j
++) {
1525 if (devices
.name
[j
][0] != '\0') {
1526 asprintf(mp
+n
, "%s%s", _PATH_DEV
, devices
.name
[j
]);
1527 if (mp
[n
] == NULL
) {
1528 pout("Out of memory constructing scan ATA device list (on line %d)\n", __LINE__
);
1532 bytes
+=1+strlen(mp
[n
]);
1537 mp
= (char **)reallocf(mp
,n
*(sizeof (char*))); // shrink to correct size
1538 bytes
+= (n
)*(sizeof(char*)); // and set allocated byte count
1557 bool freebsd_smart_interface::scan_smart_devices(smart_device_list
& devlist
,
1558 const char * type
, const char * pattern
/*= 0*/)
1561 set_err(EINVAL
, "DEVICESCAN with pattern not implemented yet");
1566 char * * atanames
= 0; int numata
= 0;
1567 if (!type
|| !strcmp(type
, "ata")) {
1568 numata
= get_dev_names_ata(&atanames
);
1575 char * * scsinames
= 0; int numscsi
= 0;
1576 if (!type
|| !strcmp(type
, "scsi")) { // do not export duplicated names
1577 numscsi
= get_dev_names_cam(&scsinames
,0);
1588 for (i
= 0; i
< numata
; i
++) {
1589 ata_device
* atadev
= get_ata_device(atanames
[i
], type
);
1591 devlist
.push_back(atadev
);
1594 for (i
= 0; i
< numscsi
; i
++) {
1595 if(!*type
) { // try USB autodetection if no type specified
1596 smart_device
* smartdev
= autodetect_smart_device(scsinames
[i
]);
1598 devlist
.push_back(smartdev
);
1601 scsi_device
* scsidev
= get_scsi_device(scsinames
[i
], type
);
1603 devlist
.push_back(scsidev
);
1610 #if (FREEBSDVER < 800000) // without this build fail on FreeBSD 8
1611 static char done
[USB_MAX_DEVICES
];
1613 static int usbdevinfo(int f
, int a
, int rec
, int busno
, unsigned short & vendor_id
,
1614 unsigned short & product_id
, unsigned short & version
)
1617 struct usb_device_info di
;
1621 snprintf(devname
, sizeof(devname
),"umass%d",busno
);
1624 e
= ioctl(f
, USB_DEVICEINFO
, &di
);
1627 printf("addr %d: I/O error\n", a
);
1633 for (i
= 0; i
< USB_MAX_DEVNAMES
; i
++) {
1634 if (di
.udi_devnames
[i
][0]) {
1635 if(strcmp(di
.udi_devnames
[i
],devname
)==0) {
1637 vendor_id
= di
.udi_vendorNo
;
1638 product_id
= di
.udi_productNo
;
1639 version
= di
.udi_releaseNo
;
1647 for (p
= 0; p
< di
.udi_nports
; p
++) {
1648 int s
= di
.udi_ports
[p
];
1649 if (s
>= USB_MAX_DEVICES
) {
1653 printf("addr 0 should never happen!\n");
1655 if(usbdevinfo(f
, s
, 1, busno
, vendor_id
, product_id
, version
)) return 1;
1663 static int usbdevlist(int busno
,unsigned short & vendor_id
,
1664 unsigned short & product_id
, unsigned short & version
)
1666 #if (FREEBSDVER >= 800000) // libusb2 interface
1667 struct libusb20_device
*pdev
= NULL
;
1668 struct libusb20_backend
*pbe
;
1669 uint32_t matches
= 0;
1670 char buf
[128]; // do not change!
1673 struct LIBUSB20_DEVICE_DESC_DECODED
*pdesc
;
1675 pbe
= libusb20_be_alloc_default();
1677 while ((pdev
= libusb20_be_device_foreach(pbe
, pdev
))) {
1680 if (libusb20_dev_open(pdev
, 0)) {
1681 warnx("libusb20_dev_open: could not open device");
1685 pdesc
=libusb20_dev_get_device_desc(pdev
);
1687 snprintf(devname
, sizeof(devname
),"umass%d:",busno
);
1688 for (n
= 0; n
!= 255; n
++) {
1689 if (libusb20_dev_get_iface_desc(pdev
, n
, buf
, sizeof(buf
)))
1693 if(strncmp(buf
,devname
,strlen(devname
))==0){
1695 vendor_id
= pdesc
->idVendor
;
1696 product_id
= pdesc
->idProduct
;
1697 version
= pdesc
->bcdDevice
;
1698 libusb20_dev_close(pdev
);
1699 libusb20_be_free(pbe
);
1704 libusb20_dev_close(pdev
);
1708 printf("No device match or lack of permissions.\n");
1711 libusb20_be_free(pbe
);
1714 #else // freebsd < 8.0 USB stack, ioctl interface
1720 for (ncont
= 0, i
= 0; i
< 10; i
++) {
1721 snprintf(buf
, sizeof(buf
), "%s%d", USBDEV
, i
);
1722 f
= open(buf
, O_RDONLY
);
1724 memset(done
, 0, sizeof done
);
1725 for (a
= 1; a
< USB_MAX_DEVICES
; a
++) {
1727 rc
= usbdevinfo(f
, a
, 1, busno
,vendor_id
, product_id
, version
);
1734 if (errno
== ENOENT
|| errno
== ENXIO
)
1744 smart_device
* freebsd_smart_interface::autodetect_smart_device(const char * name
)
1746 unsigned short vendor_id
= 0, product_id
= 0, version
= 0;
1747 struct cam_device
*cam_dev
;
1753 // if dev_name null, or string length zero
1754 if (!name
|| !(len
= strlen(name
)))
1758 char * * atanames
= 0; int numata
= 0;
1759 numata
= get_dev_names_ata(&atanames
);
1761 // check ATA/ATAPI devices
1762 for (i
= 0; i
< numata
; i
++) {
1763 if(!strcmp(atanames
[i
],name
)) {
1764 return new freebsd_ata_device(this, name
, "");
1770 pout("Unable to get ATA device list\n");
1774 char * * scsinames
= 0; int numscsi
= 0;
1775 numscsi
= get_dev_names_cam(&scsinames
, 1);
1777 // check all devices on CAM bus
1778 for (i
= 0; i
< numscsi
; i
++) {
1779 if(strcmp(scsinames
[i
],name
)==0)
1780 { // our disk device is CAM
1781 if ((cam_dev
= cam_open_device(name
, O_RDWR
)) == NULL
) {
1788 bzero(&(&ccb
.ccb_h
)[1], PATHINQ_SETTINGS_SIZE
);
1789 ccb
.ccb_h
.func_code
= XPT_PATH_INQ
; // send PATH_INQ to the device
1790 if (ioctl(cam_dev
->fd
, CAMIOCOMMAND
, &ccb
) == -1) {
1791 warn("Get Transfer Settings CCB failed\n"
1792 "%s", strerror(errno
));
1793 cam_close_device(cam_dev
);
1796 // now check if we are working with USB device, see umass.c
1797 if(strcmp(ccb
.cpi
.dev_name
,"umass-sim") == 0) { // USB device found
1798 usbdevlist(bus
,vendor_id
, product_id
, version
);
1799 int bus
=ccb
.cpi
.unit_number
; // unit_number will match umass number
1800 cam_close_device(cam_dev
);
1801 if(usbdevlist(bus
,vendor_id
, product_id
, version
)){
1802 const char * usbtype
= get_usb_dev_type_by_id(vendor_id
, product_id
, version
);
1805 return get_sat_device(usbtype
, new freebsd_scsi_device(this, name
, ""));
1808 #if FREEBSDVER > 800100
1809 // check if we have ATA device connected to CAM (ada)
1810 if(ccb
.cpi
.protocol
== PROTO_ATA
){
1811 cam_close_device(cam_dev
);
1812 return new freebsd_atacam_device(this, name
, "");
1815 // close cam device, we don`t need it anymore
1816 cam_close_device(cam_dev
);
1817 // handle as usual scsi
1818 return new freebsd_scsi_device(this, name
, "");
1823 if(numscsi
<0) pout("Unable to get CAM device list\n");
1825 // device type unknown
1830 smart_device
* freebsd_smart_interface::get_custom_smart_device(const char * name
, const char * type
)
1833 static const char * fbsd_dev_twe_ctrl
= "/dev/twe";
1834 static const char * fbsd_dev_twa_ctrl
= "/dev/twa";
1835 int disknum
= -1, n1
= -1, n2
= -1, contr
= -1;
1837 if (sscanf(type
, "3ware,%n%d%n", &n1
, &disknum
, &n2
) == 1 || n1
== 6) {
1838 if (n2
!= (int)strlen(type
)) {
1839 set_err(EINVAL
, "Option -d 3ware,N requires N to be a non-negative integer");
1842 if (!(0 <= disknum
&& disknum
<= 127)) {
1843 set_err(EINVAL
, "Option -d 3ware,N (N=%d) must have 0 <= N <= 127", disknum
);
1847 // guess 3ware device type based on device name
1848 if (!strncmp(fbsd_dev_twa_ctrl
, name
, strlen(fbsd_dev_twa_ctrl
))){
1849 contr
=CONTROLLER_3WARE_9000_CHAR
;
1851 if (!strncmp(fbsd_dev_twe_ctrl
, name
, strlen(fbsd_dev_twe_ctrl
))){
1852 contr
=CONTROLLER_3WARE_678K_CHAR
;
1856 set_err(EINVAL
, "3ware controller type unknown, use %sX or %sX devices",
1857 fbsd_dev_twe_ctrl
, fbsd_dev_twa_ctrl
);
1860 return new freebsd_escalade_device(this, name
, contr
, disknum
);
1864 int controller
= -1, channel
= -1; disknum
= 1;
1865 n1
= n2
= -1; int n3
= -1;
1866 if (sscanf(type
, "hpt,%n%d/%d%n/%d%n", &n1
, &controller
, &channel
, &n2
, &disknum
, &n3
) >= 2 || n1
== 4) {
1867 int len
= strlen(type
);
1868 if (!(n2
== len
|| n3
== len
)) {
1869 set_err(EINVAL
, "Option '-d hpt,L/M/N' supports 2-3 items");
1872 if (!(1 <= controller
&& controller
<= 8)) {
1873 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid controller id L supplied");
1876 if (!(1 <= channel
&& channel
<= 8)) {
1877 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid channel number M supplied");
1880 if (!(1 <= disknum
&& disknum
<= 15)) {
1881 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid pmport number N supplied");
1884 return new freebsd_highpoint_device(this, name
, controller
, channel
, disknum
);
1888 disknum
= n1
= n2
= -1;
1889 if (sscanf(type
, "cciss,%n%d%n", &n1
, &disknum
, &n2
) == 1 || n1
== 6) {
1890 if (n2
!= (int)strlen(type
)) {
1891 set_err(EINVAL
, "Option -d cciss,N requires N to be a non-negative integer");
1894 if (!(0 <= disknum
&& disknum
<= 15)) {
1895 set_err(EINVAL
, "Option -d cciss,N (N=%d) must have 0 <= N <= 15", disknum
);
1898 return new freebsd_cciss_device(this, name
, disknum
);
1900 #if FREEBSDVER > 800100
1902 if(!strcmp(type
,"atacam"))
1903 return new freebsd_atacam_device(this, name
, "");
1909 std::string
freebsd_smart_interface::get_valid_custom_dev_types_str()
1911 return "3ware,N, hpt,L/M/N, cciss,N"
1912 #if FREEBSDVER > 800100
1920 /////////////////////////////////////////////////////////////////////////////
1921 /// Initialize platform interface and register with smi()
1923 void smart_interface::init()
1925 static os_freebsd::freebsd_smart_interface the_interface
;
1926 smart_interface::set(&the_interface
);