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, write to the Free
15 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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"
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>
62 #elif defined(__DragonFly__)
63 #include <bus/usb/usb.h>
64 #include <bus/usb/usbhid.h>
66 #include <dev/usb/usb.h>
67 #include <dev/usb/usbhid.h>
70 #define CONTROLLER_3WARE_9000_CHAR 0x01
71 #define CONTROLLER_3WARE_678K_CHAR 0x02
73 #ifndef PATHINQ_SETTINGS_SIZE
74 #define PATHINQ_SETTINGS_SIZE 128
77 const char *os_XXXX_c_cvsid
="$Id: os_freebsd.cpp 3542 2012-05-18 18:18:45Z samm2 $" \
78 ATACMDS_H_CVSID CCISS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID
;
82 #define NO_DISK_3WARE 2
86 // Utility function for printing warnings
87 void printwarning(int msgNo
, const char* extra
) {
88 static int printed
[] = {0,0,0,0};
89 static const char* message
[]={
90 "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",
92 "Error SMART Status command failed\nPlease get assistance from \n" PACKAGE_HOMEPAGE
"\nRegister values returned from SMART Status command are:\n",
94 "You must specify a DISK # for 3ware drives with -d 3ware,<n> where <n> begins with 1 for first disk drive\n",
96 "ATA support is not provided for this kernel version. Please ugrade to a recent 5-CURRENT kernel (post 09/01/2003 or so)\n"
99 if (msgNo
>= 0 && msgNo
<= MAX_MSG
) {
100 if (!printed
[msgNo
]) {
102 pout("%s", message
[msgNo
]);
110 // Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c
112 #define BUFFER_LEN_678K_CHAR ( sizeof(struct twe_usercommand) ) // 520
113 #define BUFFER_LEN_9000_CHAR ( sizeof(TW_OSLI_IOCTL_NO_DATA_BUF) + sizeof(TWE_Command) ) // 2048
114 #define TW_IOCTL_BUFFER_SIZE ( MAX(BUFFER_LEN_678K_CHAR, BUFFER_LEN_9000_CHAR) )
117 #define ATA_DEVICE "/dev/ata"
120 #define ARGUSED(x) ((void)(x))
122 // global variable holding byte count of allocated memory
125 /////////////////////////////////////////////////////////////////////////////
127 namespace os_freebsd
{ // No need to publish anything, name provided for Doxygen
129 /////////////////////////////////////////////////////////////////////////////
130 /// Implement shared open/close routines with old functions.
132 class freebsd_smart_device
133 : virtual public /*implements*/ smart_device
136 explicit freebsd_smart_device(const char * mode
)
137 : smart_device(never_called
),
138 m_fd(-1), m_mode(mode
) { }
140 virtual ~freebsd_smart_device() throw();
142 virtual bool is_open() const;
146 virtual bool close();
149 /// Return filedesc for derived classes.
157 int m_fd
; ///< filedesc, -1 if not open.
158 const char * m_mode
; ///< Mode string for deviceopen().
162 static inline void * reallocf(void *ptr
, size_t size
) {
163 void *rv
= realloc(ptr
, size
);
164 if((rv
== NULL
) && (size
!= 0))
170 freebsd_smart_device::~freebsd_smart_device() throw()
173 os_freebsd::freebsd_smart_device::close();
176 // migration from the old_style
177 unsigned char m_controller_type
;
178 unsigned char m_controller_port
;
180 // examples for smartctl
181 static const char smartctl_examples
[] =
182 "=================================================== SMARTCTL EXAMPLES =====\n\n"
183 " smartctl -a /dev/ad0 (Prints all SMART information)\n\n"
184 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/ad0\n"
185 " (Enables SMART on first disk)\n\n"
186 " smartctl -t long /dev/ad0 (Executes extended disk self-test)\n\n"
187 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/ad0\n"
188 " (Prints Self-Test & Attribute errors)\n"
189 " (Prints Self-Test & Attribute errors)\n\n"
190 " smartctl -a --device=3ware,2 /dev/twa0\n"
191 " smartctl -a --device=3ware,2 /dev/twe0\n"
192 " (Prints all SMART information for ATA disk on\n"
193 " third port of first 3ware RAID controller)\n"
194 " smartctl -a --device=cciss,0 /dev/ciss0\n"
195 " (Prints all SMART information for first disk \n"
196 " on Common Interface for SCSI-3 Support driver)\n"
197 " smartctl -a --device=areca,3/1 /dev/arcmsr0\n"
198 " (Prints all SMART information for 3rd disk in the 1st enclosure \n"
199 " on first ARECA RAID controller)\n"
203 bool freebsd_smart_device::is_open() const
209 bool freebsd_smart_device::open()
211 const char *dev
= get_dev_name();
212 if ((m_fd
= ::open(dev
,O_RDONLY
))<0) {
219 bool freebsd_smart_device::close()
222 // close device, if open
224 failed
=::close(get_fd());
228 if(failed
) return false;
232 /////////////////////////////////////////////////////////////////////////////
233 /// Implement standard ATA support
235 class freebsd_ata_device
236 : public /*implements*/ ata_device
,
237 public /*extends*/ freebsd_smart_device
240 freebsd_ata_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
);
241 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
244 virtual int do_cmd(struct ata_ioc_request
* request
, bool is_48bit_cmd
);
247 freebsd_ata_device::freebsd_ata_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
)
248 : smart_device(intf
, dev_name
, "ata", req_type
),
249 freebsd_smart_device("ATA")
253 int freebsd_ata_device::do_cmd( struct ata_ioc_request
* request
, bool is_48bit_cmd
)
256 ARGUSED(is_48bit_cmd
); // no support for 48 bit commands in the IOCATAREQUEST
257 return ioctl(fd
, IOCATAREQUEST
, request
);
262 bool freebsd_ata_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
264 bool ata_48bit
= false; // no ata_48bit_support via IOCATAREQUEST
265 if(!strcmp("atacam",get_dev_type())) // enable for atacam interface
268 if (!ata_cmd_is_ok(in
,
269 true, // data_out_support
270 true, // multi_sector_support
275 struct ata_ioc_request request
;
276 bzero(&request
,sizeof(struct ata_ioc_request
));
278 request
.timeout
=SCSI_TIMEOUT_DEFAULT
;
279 request
.u
.ata
.command
=in
.in_regs
.command
;
280 request
.u
.ata
.feature
=in
.in_regs
.features
;
282 request
.u
.ata
.count
= in
.in_regs
.sector_count_16
;
283 request
.u
.ata
.lba
= in
.in_regs
.lba_48
;
285 switch (in
.direction
) {
286 case ata_cmd_in::no_data
:
287 request
.flags
=ATA_CMD_CONTROL
;
289 case ata_cmd_in::data_in
:
290 request
.flags
=ATA_CMD_READ
| ATA_CMD_CONTROL
;
291 request
.data
=(char *)in
.buffer
;
292 request
.count
=in
.size
;
294 case ata_cmd_in::data_out
:
295 request
.flags
=ATA_CMD_WRITE
| ATA_CMD_CONTROL
;
296 request
.data
=(char *)in
.buffer
;
297 request
.count
=in
.size
;
300 return set_err(ENOSYS
);
305 if (do_cmd(&request
, in
.in_regs
.is_48bit_cmd()))
306 return set_err(errno
);
308 return set_err(EIO
, "request failed, error code 0x%02x", request
.error
);
310 out
.out_regs
.error
= request
.error
;
311 out
.out_regs
.sector_count_16
= request
.u
.ata
.count
;
312 out
.out_regs
.lba_48
= request
.u
.ata
.lba
;
315 // Command specific processing
316 if (in
.in_regs
.command
== ATA_SMART_CMD
317 && in
.in_regs
.features
== ATA_SMART_STATUS
318 && in
.out_needed
.lba_high
)
320 unsigned const char normal_lo
=0x4f, normal_hi
=0xc2;
321 unsigned const char failed_lo
=0xf4, failed_hi
=0x2c;
323 // Cyl low and Cyl high unchanged means "Good SMART status"
324 if (!(out
.out_regs
.lba_mid
==normal_lo
&& out
.out_regs
.lba_high
==normal_hi
)
325 // These values mean "Bad SMART status"
326 && !(out
.out_regs
.lba_mid
==failed_lo
&& out
.out_regs
.lba_high
==failed_hi
))
329 // We haven't gotten output that makes sense; print out some debugging info
331 sprintf(buf
,"CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
332 (int)request
.u
.ata
.command
,
333 (int)request
.u
.ata
.feature
,
334 (int)request
.u
.ata
.count
,
335 (int)((request
.u
.ata
.lba
) & 0xff),
336 (int)((request
.u
.ata
.lba
>>8) & 0xff),
337 (int)((request
.u
.ata
.lba
>>16) & 0xff),
339 printwarning(BAD_SMART
,buf
);
340 out
.out_regs
.lba_high
= failed_hi
;
341 out
.out_regs
.lba_mid
= failed_lo
;
348 #if FREEBSDVER > 800100
349 class freebsd_atacam_device
: public freebsd_ata_device
352 freebsd_atacam_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
)
353 : smart_device(intf
, dev_name
, "atacam", req_type
), freebsd_ata_device(intf
, dev_name
, req_type
)
357 virtual bool close();
361 struct cam_device
*m_camdev
;
363 virtual int do_cmd( struct ata_ioc_request
* request
, bool is_48bit_cmd
);
366 bool freebsd_atacam_device::open(){
367 const char *dev
= get_dev_name();
369 if ((m_camdev
= cam_open_device(dev
, O_RDWR
)) == NULL
) {
373 set_fd(m_camdev
->fd
);
377 bool freebsd_atacam_device::close(){
378 cam_close_device(m_camdev
);
383 int freebsd_atacam_device::do_cmd( struct ata_ioc_request
* request
, bool is_48bit_cmd
)
388 memset(&ccb
, 0, sizeof(ccb
));
390 if (request
->count
== 0)
391 camflags
= CAM_DIR_NONE
;
392 else if (request
->flags
& ATA_CMD_READ
)
393 camflags
= CAM_DIR_IN
;
395 camflags
= CAM_DIR_OUT
;
397 camflags
|= CAM_ATAIO_48BIT
;
399 cam_fill_ataio(&ccb
.ataio
,
404 (u_int8_t
*)request
->data
,
406 request
->timeout
* 1000); // timeout in seconds
408 ccb
.ataio
.cmd
.flags
= CAM_ATAIO_NEEDRESULT
;
410 ccb
.ataio
.cmd
.command
= request
->u
.ata
.command
;
411 ccb
.ataio
.cmd
.features
= request
->u
.ata
.feature
;
412 ccb
.ataio
.cmd
.lba_low
= request
->u
.ata
.lba
;
413 ccb
.ataio
.cmd
.lba_mid
= request
->u
.ata
.lba
>> 8;
414 ccb
.ataio
.cmd
.lba_high
= request
->u
.ata
.lba
>> 16;
416 ccb
.ataio
.cmd
.lba_low_exp
= request
->u
.ata
.lba
>> 24;
417 ccb
.ataio
.cmd
.lba_mid_exp
= request
->u
.ata
.lba
>> 32;
418 ccb
.ataio
.cmd
.lba_high_exp
= request
->u
.ata
.lba
>> 40;
419 ccb
.ataio
.cmd
.device
= 0x40 | ((request
->u
.ata
.lba
>> 24) & 0x0f);
420 ccb
.ataio
.cmd
.sector_count
= request
->u
.ata
.count
;
421 ccb
.ataio
.cmd
.sector_count_exp
= request
->u
.ata
.count
>> 8;;
423 ccb
.ccb_h
.flags
|= CAM_DEV_QFRZDIS
;
425 if (cam_send_ccb(m_camdev
, &ccb
) < 0) {
426 err(1, "cam_send_ccb");
430 if ((ccb
.ccb_h
.status
& CAM_STATUS_MASK
) != CAM_REQ_CMP
) {
431 cam_error_print(m_camdev
, &ccb
, CAM_ESF_ALL
, CAM_EPF_ALL
, stderr
);
436 ((u_int64_t
)(ccb
.ataio
.res
.lba_low
)) |
437 ((u_int64_t
)(ccb
.ataio
.res
.lba_mid
) << 8) |
438 ((u_int64_t
)(ccb
.ataio
.res
.lba_high
) << 16) |
439 ((u_int64_t
)(ccb
.ataio
.res
.lba_low_exp
) << 24) |
440 ((u_int64_t
)(ccb
.ataio
.res
.lba_mid_exp
) << 32) |
441 ((u_int64_t
)(ccb
.ataio
.res
.lba_high_exp
) << 40);
443 request
->u
.ata
.count
= ccb
.ataio
.res
.sector_count
| (ccb
.ataio
.res
.sector_count_exp
<< 8);
444 request
->error
= ccb
.ataio
.res
.error
;
451 /////////////////////////////////////////////////////////////////////////////
452 /// Implement AMCC/3ware RAID support with old functions
454 class freebsd_escalade_device
455 : public /*implements*/ ata_device_with_command_set
,
456 public /*extends*/ freebsd_smart_device
459 freebsd_escalade_device(smart_interface
* intf
, const char * dev_name
,
460 int escalade_type
, int disknum
);
463 virtual int ata_command_interface(smart_command_set command
, int select
, char * data
);
467 int m_escalade_type
; ///< Type string for escalade_command_interface().
468 int m_disknum
; ///< Disk number.
471 freebsd_escalade_device::freebsd_escalade_device(smart_interface
* intf
, const char * dev_name
,
472 int escalade_type
, int disknum
)
473 : smart_device(intf
, dev_name
, "3ware", "3ware"),
474 freebsd_smart_device(
475 escalade_type
==CONTROLLER_3WARE_9000_CHAR
? "ATA_3WARE_9000" :
476 escalade_type
==CONTROLLER_3WARE_678K_CHAR
? "ATA_3WARE_678K" :
477 /* CONTROLLER_3WARE_678K */ "ATA" ),
478 m_escalade_type(escalade_type
), m_disknum(disknum
)
480 set_info().info_name
= strprintf("%s [3ware_disk_%02d]", dev_name
, disknum
);
483 bool freebsd_escalade_device::open()
485 const char *dev
= get_dev_name();
488 if ((fd
= ::open(dev
,O_RDWR
))<0) {
496 int freebsd_escalade_device::ata_command_interface(smart_command_set command
, int select
, char * data
)
498 // to hold true file descriptor
501 // return value and buffer for ioctl()
502 int ioctlreturn
, readdata
=0;
503 struct twe_usercommand
* cmd_twe
= NULL
;
504 TW_OSLI_IOCTL_NO_DATA_BUF
* cmd_twa
= NULL
;
505 TWE_Command_ATA
* ata
= NULL
;
507 // Used by both the SCSI and char interfaces
508 char ioctl_buffer
[TW_IOCTL_BUFFER_SIZE
];
511 printwarning(NO_DISK_3WARE
,NULL
);
515 memset(ioctl_buffer
, 0, TW_IOCTL_BUFFER_SIZE
);
517 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
518 cmd_twa
= (TW_OSLI_IOCTL_NO_DATA_BUF
*)ioctl_buffer
;
519 cmd_twa
->pdata
= ((TW_OSLI_IOCTL_WITH_PAYLOAD
*)cmd_twa
)->payload
.data_buf
;
520 cmd_twa
->driver_pkt
.buffer_length
= 512;
521 ata
= (TWE_Command_ATA
*)&cmd_twa
->cmd_pkt
.command
.cmd_pkt_7k
;
522 } else if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
523 cmd_twe
= (struct twe_usercommand
*)ioctl_buffer
;
524 ata
= &cmd_twe
->tu_command
.ata
;
526 pout("Unrecognized escalade_type %d in freebsd_3ware_command_interface(disk %d)\n"
527 "Please contact " PACKAGE_BUGREPORT
"\n", m_escalade_type
, m_disknum
);
532 ata
->opcode
= TWE_OP_ATA_PASSTHROUGH
;
534 // Same for (almost) all commands - but some reset below
535 ata
->request_id
= 0xFF;
536 ata
->unit
= m_disknum
;
539 ata
->drive_head
= 0x0;
542 // All SMART commands use this CL/CH signature. These are magic
543 // values from the ATA specifications.
544 ata
->cylinder_lo
= 0x4F;
545 ata
->cylinder_hi
= 0xC2;
547 // SMART ATA COMMAND REGISTER value
548 ata
->command
= ATA_SMART_CMD
;
550 // Is this a command that reads or returns 512 bytes?
551 // passthru->param values are:
552 // 0x0 - non data command without TFR write check,
553 // 0x8 - non data command with TFR write check,
554 // 0xD - data command that returns data to host from device
555 // 0xF - data command that writes data from host to device
556 // passthru->size values are 0x5 for non-data and 0x07 for data
557 if (command
== READ_VALUES
||
558 command
== READ_THRESHOLDS
||
559 command
== READ_LOG
||
560 command
== IDENTIFY
||
561 command
== WRITE_LOG
)
564 if (m_escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
565 cmd_twe
->tu_data
= data
;
566 cmd_twe
->tu_size
= 512;
568 ata
->sgl_offset
= 0x5;
571 ata
->sector_count
= 0x1;
572 // For 64-bit to work correctly, up the size of the command packet
573 // in dwords by 1 to account for the 64-bit single sgl 'address'
574 // field. Note that this doesn't agree with the typedefs but it's
575 // right (agree with kernel driver behavior/typedefs).
576 //if (sizeof(long)==8)
580 // Non data command -- but doesn't use large sector
581 // count register values.
582 ata
->sgl_offset
= 0x0;
585 ata
->sector_count
= 0x0;
588 // Now set ATA registers depending upon command
590 case CHECK_POWER_MODE
:
591 ata
->command
= ATA_CHECK_POWER_MODE
;
593 ata
->cylinder_lo
= 0;
594 ata
->cylinder_hi
= 0;
597 ata
->features
= ATA_SMART_READ_VALUES
;
599 case READ_THRESHOLDS
:
600 ata
->features
= ATA_SMART_READ_THRESHOLDS
;
603 ata
->features
= ATA_SMART_READ_LOG_SECTOR
;
604 // log number to return
605 ata
->sector_num
= select
;
609 ata
->features
= ATA_SMART_WRITE_LOG_SECTOR
;
610 ata
->sector_count
= 1;
611 ata
->sector_num
= select
;
612 ata
->param
= 0xF; // PIO data write
615 // ATA IDENTIFY DEVICE
616 ata
->command
= ATA_IDENTIFY_DEVICE
;
618 ata
->cylinder_lo
= 0;
619 ata
->cylinder_hi
= 0;
622 // 3WARE controller can NOT have packet device internally
623 pout("WARNING - NO DEVICE FOUND ON 3WARE CONTROLLER (disk %d)\n", m_disknum
);
627 ata
->features
= ATA_SMART_ENABLE
;
630 ata
->features
= ATA_SMART_DISABLE
;
633 ata
->features
= ATA_SMART_AUTO_OFFLINE
;
634 // Enable or disable?
635 ata
->sector_count
= select
;
638 ata
->features
= ATA_SMART_AUTOSAVE
;
639 // Enable or disable?
640 ata
->sector_count
= select
;
642 case IMMEDIATE_OFFLINE
:
643 ata
->features
= ATA_SMART_IMMEDIATE_OFFLINE
;
644 // What test type to run?
645 ata
->sector_num
= select
;
648 ata
->features
= ATA_SMART_STATUS
;
651 // This is JUST to see if SMART is enabled, by giving SMART status
652 // command. But it doesn't say if status was good, or failing.
653 // See below for the difference.
654 ata
->features
= ATA_SMART_STATUS
;
657 pout("Unrecognized command %d in freebsd_3ware_command_interface(disk %d)\n"
658 "Please contact " PACKAGE_BUGREPORT
"\n", command
, m_disknum
);
663 // Now send the command down through an ioctl()
664 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
665 ioctlreturn
=ioctl(fd
,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH
,cmd_twa
);
667 ioctlreturn
=ioctl(fd
,TWEIO_COMMAND
,cmd_twe
);
670 // Deal with the different error cases
677 // See if the ATA command failed. Now that we have returned from
678 // the ioctl() call, if passthru is valid, then:
679 // - ata->status contains the 3ware controller STATUS
680 // - ata->command contains the ATA STATUS register
681 // - ata->features contains the ATA ERROR register
683 // Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS
684 // If bit 0 (error bit) is set, then ATA ERROR register is valid.
685 // While we *might* decode the ATA ERROR register, at the moment it
686 // doesn't make much sense: we don't care in detail why the error
689 if (ata
->status
|| (ata
->command
& 0x21)) {
690 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
);
695 // If this is a read data command, copy data to output buffer
697 if (m_escalade_type
==CONTROLLER_3WARE_9000_CHAR
)
698 memcpy(data
, cmd_twa
->pdata
, 512);
701 // For STATUS_CHECK, we need to check register values
702 if (command
==STATUS_CHECK
) {
704 // To find out if the SMART RETURN STATUS is good or failing, we
705 // need to examine the values of the Cylinder Low and Cylinder
708 unsigned short cyl_lo
=ata
->cylinder_lo
;
709 unsigned short cyl_hi
=ata
->cylinder_hi
;
711 // If values in Cyl-LO and Cyl-HI are unchanged, SMART status is good.
712 if (cyl_lo
==0x4F && cyl_hi
==0xC2)
715 // If values in Cyl-LO and Cyl-HI are as follows, SMART status is FAIL
716 if (cyl_lo
==0xF4 && cyl_hi
==0x2C)
723 // copy sector count register (one byte!) to return data
724 if (command
==CHECK_POWER_MODE
)
725 *data
=*(char *)&(ata
->sector_count
);
727 // look for nonexistent devices/ports
728 if (command
==IDENTIFY
&& !nonempty(data
, 512)) {
737 /////////////////////////////////////////////////////////////////////////////
738 /// Implement Highpoint RAID support with old functions
740 class freebsd_highpoint_device
741 : public /*implements*/ ata_device_with_command_set
,
742 public /*extends*/ freebsd_smart_device
745 freebsd_highpoint_device(smart_interface
* intf
, const char * dev_name
,
746 unsigned char controller
, unsigned char channel
, unsigned char port
);
749 virtual int ata_command_interface(smart_command_set command
, int select
, char * data
);
753 unsigned char m_hpt_data
[3]; ///< controller/channel/port
757 freebsd_highpoint_device::freebsd_highpoint_device(smart_interface
* intf
, const char * dev_name
,
758 unsigned char controller
, unsigned char channel
, unsigned char port
)
759 : smart_device(intf
, dev_name
, "hpt", "hpt"),
760 freebsd_smart_device("ATA")
762 m_hpt_data
[0] = controller
; m_hpt_data
[1] = channel
; m_hpt_data
[2] = port
;
763 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]);
766 bool freebsd_highpoint_device::open()
768 const char *dev
= get_dev_name();
771 if ((fd
= ::open(dev
,O_RDWR
))<0) {
779 int freebsd_highpoint_device::ata_command_interface(smart_command_set command
, int select
, char * data
)
783 HPT_IOCTL_PARAM param
;
784 HPT_CHANNEL_INFO_V2 info
;
785 unsigned char* buff
[512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER
)];
786 PHPT_PASS_THROUGH_HEADER pide_pt_hdr
, pide_pt_hdr_out
;
788 // get internal deviceid
789 ids
[0] = m_hpt_data
[0] - 1;
790 ids
[1] = m_hpt_data
[1] - 1;
792 memset(¶m
, 0, sizeof(HPT_IOCTL_PARAM
));
794 param
.magic
= HPT_IOCTL_MAGIC
;
795 param
.ctrl_code
= HPT_IOCTL_GET_CHANNEL_INFO_V2
;
796 param
.in
= (unsigned char *)ids
;
797 param
.in_size
= sizeof(unsigned int) * 2;
798 param
.out
= (unsigned char *)&info
;
799 param
.out_size
= sizeof(HPT_CHANNEL_INFO_V2
);
801 if (m_hpt_data
[2]==1) {
802 param
.ctrl_code
= HPT_IOCTL_GET_CHANNEL_INFO
;
803 param
.out_size
= sizeof(HPT_CHANNEL_INFO
);
805 if (ioctl(fd
, HPT_DO_IOCONTROL
, ¶m
)!=0 ||
806 info
.devices
[m_hpt_data
[2]-1]==0) {
810 // perform smart action
811 memset(buff
, 0, 512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER
));
812 pide_pt_hdr
= (PHPT_PASS_THROUGH_HEADER
)buff
;
814 pide_pt_hdr
->lbamid
= 0x4f;
815 pide_pt_hdr
->lbahigh
= 0xc2;
816 pide_pt_hdr
->command
= ATA_SMART_CMD
;
817 pide_pt_hdr
->id
= info
.devices
[m_hpt_data
[2] - 1];
821 pide_pt_hdr
->feature
=ATA_SMART_READ_VALUES
;
822 pide_pt_hdr
->protocol
=HPT_READ
;
824 case READ_THRESHOLDS
:
825 pide_pt_hdr
->feature
=ATA_SMART_READ_THRESHOLDS
;
826 pide_pt_hdr
->protocol
=HPT_READ
;
829 pide_pt_hdr
->feature
=ATA_SMART_READ_LOG_SECTOR
;
830 pide_pt_hdr
->lbalow
=select
;
831 pide_pt_hdr
->protocol
=HPT_READ
;
834 pide_pt_hdr
->command
=ATA_IDENTIFY_DEVICE
;
835 pide_pt_hdr
->protocol
=HPT_READ
;
838 pide_pt_hdr
->feature
=ATA_SMART_ENABLE
;
841 pide_pt_hdr
->feature
=ATA_SMART_DISABLE
;
844 pide_pt_hdr
->feature
=ATA_SMART_AUTO_OFFLINE
;
845 pide_pt_hdr
->sectorcount
=select
;
848 pide_pt_hdr
->feature
=ATA_SMART_AUTOSAVE
;
849 pide_pt_hdr
->sectorcount
=select
;
851 case IMMEDIATE_OFFLINE
:
852 pide_pt_hdr
->feature
=ATA_SMART_IMMEDIATE_OFFLINE
;
853 pide_pt_hdr
->lbalow
=select
;
857 pide_pt_hdr
->feature
=ATA_SMART_STATUS
;
859 case CHECK_POWER_MODE
:
860 pide_pt_hdr
->command
=ATA_CHECK_POWER_MODE
;
863 memcpy(buff
+sizeof(HPT_PASS_THROUGH_HEADER
), data
, 512);
864 pide_pt_hdr
->feature
=ATA_SMART_WRITE_LOG_SECTOR
;
865 pide_pt_hdr
->lbalow
=select
;
866 pide_pt_hdr
->protocol
=HPT_WRITE
;
869 pout("Unrecognized command %d in highpoint_command_interface()\n"
870 "Please contact " PACKAGE_BUGREPORT
"\n", command
);
874 if (pide_pt_hdr
->protocol
!=0) {
875 pide_pt_hdr
->sectors
= 1;
876 pide_pt_hdr
->sectorcount
= 1;
879 memset(¶m
, 0, sizeof(HPT_IOCTL_PARAM
));
881 param
.magic
= HPT_IOCTL_MAGIC
;
882 param
.ctrl_code
= HPT_IOCTL_IDE_PASS_THROUGH
;
883 param
.in
= (unsigned char *)buff
;
884 param
.in_size
= sizeof(HPT_PASS_THROUGH_HEADER
) + (pide_pt_hdr
->protocol
==HPT_READ
? 0 : pide_pt_hdr
->sectors
* 512);
885 param
.out
= (unsigned char *)buff
+param
.in_size
;
886 param
.out_size
= sizeof(HPT_PASS_THROUGH_HEADER
) + (pide_pt_hdr
->protocol
==HPT_READ
? pide_pt_hdr
->sectors
* 512 : 0);
888 pide_pt_hdr_out
= (PHPT_PASS_THROUGH_HEADER
)param
.out
;
890 if ((ioctl(fd
, HPT_DO_IOCONTROL
, ¶m
)!=0) ||
891 (pide_pt_hdr_out
->command
& 1)) {
895 if (command
==STATUS_CHECK
)
897 unsigned const char normal_lo
=0x4f, normal_hi
=0xc2;
898 unsigned const char failed_lo
=0xf4, failed_hi
=0x2c;
899 unsigned char low
,high
;
901 high
= pide_pt_hdr_out
->lbahigh
;
902 low
= pide_pt_hdr_out
->lbamid
;
904 // Cyl low and Cyl high unchanged means "Good SMART status"
905 if (low
==normal_lo
&& high
==normal_hi
)
908 // These values mean "Bad SMART status"
909 if (low
==failed_lo
&& high
==failed_hi
)
912 // We haven't gotten output that makes sense; print out some debugging info
914 sprintf(buf
,"CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
915 (int)pide_pt_hdr_out
->command
,
916 (int)pide_pt_hdr_out
->feature
,
917 (int)pide_pt_hdr_out
->sectorcount
,
918 (int)pide_pt_hdr_out
->lbalow
,
919 (int)pide_pt_hdr_out
->lbamid
,
920 (int)pide_pt_hdr_out
->lbahigh
,
921 (int)pide_pt_hdr_out
->sectors
);
922 printwarning(BAD_SMART
,buf
);
924 else if (command
==CHECK_POWER_MODE
)
925 data
[0] = pide_pt_hdr_out
->sectorcount
& 0xff;
926 else if (pide_pt_hdr
->protocol
==HPT_READ
)
927 memcpy(data
, (unsigned char *)buff
+ 2 * sizeof(HPT_PASS_THROUGH_HEADER
),
928 pide_pt_hdr
->sectors
* 512);
933 /////////////////////////////////////////////////////////////////////////////
934 /// Standard SCSI support
936 class freebsd_scsi_device
937 : public /*implements*/ scsi_device
,
938 public /*extends*/ freebsd_smart_device
941 freebsd_scsi_device(smart_interface
* intf
, const char * dev_name
, const char * req_type
);
943 virtual smart_device
* autodetect_open();
945 virtual bool scsi_pass_through(scsi_cmnd_io
* iop
);
949 virtual bool close();
953 struct cam_device
*m_camdev
;
956 bool freebsd_scsi_device::open(){
957 const char *dev
= get_dev_name();
959 if ((m_camdev
= cam_open_device(dev
, O_RDWR
)) == NULL
) {
963 set_fd(m_camdev
->fd
);
967 bool freebsd_scsi_device::close(){
968 cam_close_device(m_camdev
);
973 freebsd_scsi_device::freebsd_scsi_device(smart_interface
* intf
,
974 const char * dev_name
, const char * req_type
)
975 : smart_device(intf
, dev_name
, "scsi", req_type
),
976 freebsd_smart_device("SCSI")
981 bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io
* iop
)
983 int report
=scsi_debugmode
;
988 const unsigned char * ucp
= iop
->cmnd
;
991 np
= scsi_get_opcode_name(ucp
[0]);
992 pout(" [%s: ", np
? np
: "<unknown opcode>");
993 for (k
= 0; k
< iop
->cmnd_len
; ++k
)
994 pout("%02x ", ucp
[k
]);
996 (DXFER_TO_DEVICE
== iop
->dxfer_dir
) && (iop
->dxferp
)) {
997 int trunc
= (iop
->dxfer_len
> 256) ? 1 : 0;
999 pout("]\n Outgoing data, len=%d%s:\n", (int)iop
->dxfer_len
,
1000 (trunc
? " [only first 256 bytes shown]" : ""));
1001 dStrHex(iop
->dxferp
, (trunc
? 256 : iop
->dxfer_len
) , 1);
1007 if(m_camdev
==NULL
) {
1008 warnx("error: camdev=0!");
1012 if (!(ccb
= cam_getccb(m_camdev
))) {
1013 warnx("error allocating ccb");
1016 // mfi SAT layer is known to be buggy
1017 if(!strcmp("mfi",m_camdev
->sim_name
)) {
1018 if (iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_12
|| iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_16
) {
1019 // Controller does not return ATA output registers in SAT sense data
1020 if (iop
->cmnd
[2] & (1 << 5)) // chk_cond
1021 return set_err(ENOSYS
, "ATA return descriptor not supported by controller firmware");
1023 // SMART WRITE LOG SECTOR causing media errors
1024 if ((iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_16
&& iop
->cmnd
[14] == ATA_SMART_CMD
1025 && iop
->cmnd
[3]==0 && iop
->cmnd
[4] == ATA_SMART_WRITE_LOG_SECTOR
) ||
1026 (iop
->cmnd
[0] == SAT_ATA_PASSTHROUGH_12
&& iop
->cmnd
[9] == ATA_SMART_CMD
&&
1027 iop
->cmnd
[3] == ATA_SMART_WRITE_LOG_SECTOR
))
1028 return set_err(ENOSYS
, "SMART WRITE LOG SECTOR command is not supported by controller firmware");
1031 // clear out structure, except for header that was filled in for us
1032 bzero(&(&ccb
->ccb_h
)[1],
1033 sizeof(struct ccb_scsiio
) - sizeof(struct ccb_hdr
));
1035 cam_fill_csio(&ccb
->csio
,
1038 /* flags */ (iop
->dxfer_dir
== DXFER_NONE
? CAM_DIR_NONE
:(iop
->dxfer_dir
== DXFER_FROM_DEVICE
? CAM_DIR_IN
: CAM_DIR_OUT
)),
1039 /* tagaction */ MSG_SIMPLE_Q_TAG
,
1040 /* dataptr */ iop
->dxferp
,
1041 /* datalen */ iop
->dxfer_len
,
1042 /* senselen */ iop
->max_sense_len
,
1043 /* cdblen */ iop
->cmnd_len
,
1044 /* timout (converted to seconds) */ iop
->timeout
*1000);
1045 memcpy(ccb
->csio
.cdb_io
.cdb_bytes
,iop
->cmnd
,iop
->cmnd_len
);
1047 if (cam_send_ccb(m_camdev
,ccb
) < 0) {
1048 warn("error sending SCSI ccb");
1049 cam_error_print(m_camdev
,ccb
,CAM_ESF_ALL
,CAM_EPF_ALL
,stderr
);
1054 if (((ccb
->ccb_h
.status
& CAM_STATUS_MASK
) != CAM_REQ_CMP
) && ((ccb
->ccb_h
.status
& CAM_STATUS_MASK
) != CAM_SCSI_STATUS_ERROR
)) {
1055 cam_error_print(m_camdev
,ccb
,CAM_ESF_ALL
,CAM_EPF_ALL
,stderr
);
1061 iop
->resp_sense_len
= ccb
->csio
.sense_len
- ccb
->csio
.sense_resid
;
1062 memcpy(iop
->sensep
,&(ccb
->csio
.sense_data
),iop
->resp_sense_len
);
1065 iop
->scsi_status
= ccb
->csio
.scsi_status
;
1072 pout(" status=0\n");
1073 trunc
= (iop
->dxfer_len
> 256) ? 1 : 0;
1075 pout(" Incoming data, len=%d%s:\n", (int)iop
->dxfer_len
,
1076 (trunc
? " [only first 256 bytes shown]" : ""));
1077 dStrHex(iop
->dxferp
, (trunc
? 256 : iop
->dxfer_len
) , 1);
1084 /////////////////////////////////////////////////////////////////////////////
1085 /// Areca RAID support
1087 class freebsd_areca_device
1088 : public /*implements*/ ata_device
,
1089 public /*extends*/ freebsd_smart_device
1092 freebsd_areca_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
= 1);
1095 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
);
1098 int m_disknum
; ///< Disk number.
1103 // This is an interface routine meant to isolate the OS dependent
1104 // parts of the code, and to provide a debugging interface. Each
1105 // different port and OS needs to provide it's own interface. This
1106 // is the linux interface to the Areca "arcmsr" driver. It allows ATA
1107 // commands to be passed through the SCSI driver.
1108 // DETAILED DESCRIPTION OF ARGUMENTS
1109 // fd: is the file descriptor provided by open()
1110 // disknum is the disk number (0 to 15) in the RAID array
1111 // command: defines the different operations.
1112 // select: additional input data if needed (which log, which type of
1114 // data: location to write output data, if needed (512 bytes).
1115 // Note: not all commands use all arguments.
1117 // -1 if the command failed
1118 // 0 if the command succeeded,
1119 // STATUS_CHECK routine:
1120 // -1 if the command failed
1121 // 0 if the command succeeded and disk SMART status is "OK"
1122 // 1 if the command succeeded and disk SMART status is "FAILING"
1126 #define FUNCTION_READ_RQBUFFER 0x0801
1127 #define FUNCTION_WRITE_WQBUFFER 0x0802
1128 #define FUNCTION_CLEAR_RQBUFFER 0x0803
1129 #define FUNCTION_CLEAR_WQBUFFER 0x0804
1131 /* ARECA IO CONTROL CODE*/
1132 #define ARCMSR_IOCTL_READ_RQBUFFER _IOWR('F', FUNCTION_READ_RQBUFFER, sSRB_BUFFER)
1133 #define ARCMSR_IOCTL_WRITE_WQBUFFER _IOWR('F', FUNCTION_WRITE_WQBUFFER, sSRB_BUFFER)
1134 #define ARCMSR_IOCTL_CLEAR_RQBUFFER _IOWR('F', FUNCTION_CLEAR_RQBUFFER, sSRB_BUFFER)
1135 #define ARCMSR_IOCTL_CLEAR_WQBUFFER _IOWR('F', FUNCTION_CLEAR_WQBUFFER, sSRB_BUFFER)
1136 #define ARECA_SIG_STR "ARCMSR"
1140 // The SRB_IO_CONTROL & SRB_BUFFER structures are used to communicate(to/from) to areca driver
1141 typedef struct _SRB_IO_CONTROL
1143 unsigned int HeaderLength
;
1144 unsigned char Signature
[8];
1145 unsigned int Timeout
;
1146 unsigned int ControlCode
;
1147 unsigned int ReturnCode
;
1148 unsigned int Length
;
1151 typedef struct _SRB_BUFFER
1153 sSRB_IO_CONTROL srbioctl
;
1154 unsigned char ioctldatabuffer
[1032]; // the buffer to put the command data to/from firmware
1158 // For debugging areca code
1160 static void areca_dumpdata(unsigned char *block
, int len
)
1162 int ln
= (len
/ 16) + 1; // total line#
1166 printf(" Address = %p, Length = (0x%x)%d\n", block
, len
, len
);
1167 printf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F ASCII \n");
1168 printf("=====================================================================\n");
1170 for ( int l
= 0; l
< ln
&& len
; l
++ )
1172 // printf the line# and the HEX data
1173 // if a line data length < 16 then append the space to the tail of line to reach 16 chars
1174 printf("%02X | ", l
);
1175 for ( pos
= 0; pos
< 16 && len
; pos
++, len
-- )
1177 c
= block
[l
*16+pos
];
1183 for ( int loop
= pos
; loop
< 16; loop
++ )
1190 for ( int loop
= 0; loop
< pos
; loop
++ )
1192 c
= block
[l
*16+loop
];
1193 if ( c
>= 0x20 && c
<= 0x7F )
1204 printf("=====================================================================\n");
1208 static int arcmsr_command_handler(int fd
, unsigned long arcmsr_cmd
, unsigned char *data
, int data_len
, void *ext_data
/* reserved for further use */)
1212 int ioctlreturn
= 0;
1215 unsigned char *areca_return_packet
;
1218 unsigned char return_buff
[2048];
1219 unsigned char *ptr
= &return_buff
[0];
1220 memset(return_buff
, 0, sizeof(return_buff
));
1222 memset((unsigned char *)&sBuf
, 0, sizeof(sBuf
));
1225 sBuf
.srbioctl
.HeaderLength
= sizeof(sSRB_IO_CONTROL
);
1226 memcpy(sBuf
.srbioctl
.Signature
, ARECA_SIG_STR
, strlen(ARECA_SIG_STR
));
1227 sBuf
.srbioctl
.Timeout
= 10000;
1228 sBuf
.srbioctl
.ControlCode
= ARCMSR_IOCTL_READ_RQBUFFER
;
1230 switch ( arcmsr_cmd
)
1232 // command for writing data to driver
1233 case ARCMSR_IOCTL_WRITE_WQBUFFER
:
1234 if ( data
&& data_len
)
1236 sBuf
.srbioctl
.Length
= data_len
;
1237 memcpy((unsigned char *)sBuf
.ioctldatabuffer
, (unsigned char *)data
, data_len
);
1239 // commands for clearing related buffer of driver
1240 case ARCMSR_IOCTL_CLEAR_RQBUFFER
:
1241 case ARCMSR_IOCTL_CLEAR_WQBUFFER
:
1243 // command for reading data from driver
1244 case ARCMSR_IOCTL_READ_RQBUFFER
:
1247 // unknown arcmsr commands
1254 ioctlreturn
= ioctl(fd
,arcmsr_cmd
,&sBuf
);
1261 if ( arcmsr_cmd
!= ARCMSR_IOCTL_READ_RQBUFFER
)
1263 // if succeeded, just returns the length of outgoing data
1267 if ( sBuf
.srbioctl
.Length
)
1270 areca_dumpdata(&sBuf
.ioctldatabuffer
[0], sBuf
.srbioctl
.Length
);
1271 memcpy(ptr
, &sBuf
.ioctldatabuffer
[0], sBuf
.srbioctl
.Length
);
1272 ptr
+= sBuf
.srbioctl
.Length
;
1273 total
+= sBuf
.srbioctl
.Length
;
1274 // the returned bytes enough to compute payload length ?
1275 if ( expected
< 0 && total
>= 5 )
1277 areca_return_packet
= (unsigned char *)&return_buff
[0];
1278 if ( areca_return_packet
[0] == 0x5E &&
1279 areca_return_packet
[1] == 0x01 &&
1280 areca_return_packet
[2] == 0x61 )
1282 // valid header, let's compute the returned payload length,
1283 // we expected the total length is
1284 // payload + 3 bytes header + 2 bytes length + 1 byte checksum
1285 expected
= areca_return_packet
[4] * 256 + areca_return_packet
[3] + 6;
1289 if ( total
>= 7 && total
>= expected
)
1291 //printf("total bytes received = %d, expected length = %d\n", total, expected);
1293 // ------ Okay! we received enough --------
1299 // Deal with the different error cases
1302 pout("ioctl write buffer failed code = %x\n", ioctlreturn
);
1309 memcpy(data
, return_buff
, total
);
1316 freebsd_areca_device::freebsd_areca_device(smart_interface
* intf
, const char * dev_name
, int disknum
, int encnum
)
1317 : smart_device(intf
, dev_name
, "areca", "areca"),
1318 freebsd_smart_device("ATA"),
1322 set_info().info_name
= strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name
, disknum
, encnum
);
1325 // Areca RAID Controller
1326 // int freebsd_areca_device::ata_command_interface(smart_command_set command, int select, char * data)
1327 bool freebsd_areca_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
1329 if (!ata_cmd_is_ok(in
,
1330 true, // data_out_support
1331 false, // TODO: multi_sector_support
1332 true) // ata_48bit_support
1336 // ATA input registers
1337 typedef struct _ATA_INPUT_REGISTERS
1339 unsigned char features
;
1340 unsigned char sector_count
;
1341 unsigned char sector_number
;
1342 unsigned char cylinder_low
;
1343 unsigned char cylinder_high
;
1344 unsigned char device_head
;
1345 unsigned char command
;
1346 unsigned char reserved
[8];
1347 unsigned char data
[512]; // [in/out] buffer for outgoing/incoming data
1348 } sATA_INPUT_REGISTERS
;
1350 // ATA output registers
1351 // Note: The output registers is re-sorted for areca internal use only
1352 typedef struct _ATA_OUTPUT_REGISTERS
1354 unsigned char error
;
1355 unsigned char status
;
1356 unsigned char sector_count
;
1357 unsigned char sector_number
;
1358 unsigned char cylinder_low
;
1359 unsigned char cylinder_high
;
1360 }sATA_OUTPUT_REGISTERS
;
1362 // Areca packet format for outgoing:
1363 // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
1364 // B[3~4] : 2 bytes command length + variant data length, little endian
1365 // B[5] : 1 bytes areca defined command code, ATA passthrough command code is 0x1c
1366 // B[6~last-1] : variant bytes payload data
1367 // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
1370 // header 3 bytes length 2 bytes cmd 1 byte payload data x bytes cs 1 byte
1371 // +--------------------------------------------------------------------------------+
1372 // + 0x5E 0x01 0x61 | 0x00 0x00 | 0x1c | .................... | 0x00 |
1373 // +--------------------------------------------------------------------------------+
1376 //Areca packet format for incoming:
1377 // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
1378 // B[3~4] : 2 bytes payload length, little endian
1379 // B[5~last-1] : variant bytes returned payload data
1380 // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
1383 // header 3 bytes length 2 bytes payload data x bytes cs 1 byte
1384 // +-------------------------------------------------------------------+
1385 // + 0x5E 0x01 0x61 | 0x00 0x00 | .................... | 0x00 |
1386 // +-------------------------------------------------------------------+
1387 unsigned char areca_packet
[640];
1388 int areca_packet_len
= sizeof(areca_packet
);
1389 unsigned char cs
= 0;
1391 sATA_INPUT_REGISTERS
*ata_cmd
;
1394 memset(areca_packet
, 0, areca_packet_len
);
1396 // ----- BEGIN TO SETUP HEADERS -------
1397 areca_packet
[0] = 0x5E;
1398 areca_packet
[1] = 0x01;
1399 areca_packet
[2] = 0x61;
1400 areca_packet
[3] = (unsigned char)((areca_packet_len
- 6) & 0xff);
1401 areca_packet
[4] = (unsigned char)(((areca_packet_len
- 6) >> 8) & 0xff);
1402 areca_packet
[5] = 0x1c; // areca defined code for ATA passthrough command
1404 // ----- BEGIN TO SETUP PAYLOAD DATA -----
1405 memcpy(&areca_packet
[7], "SmrT", 4); // areca defined password
1406 ata_cmd
= (sATA_INPUT_REGISTERS
*)&areca_packet
[12];
1410 const ata_in_regs_48bit
& r
= in
.in_regs
;
1411 ata_cmd
->features
= r
.features_16
;
1412 ata_cmd
->sector_count
= r
.sector_count_16
;
1413 ata_cmd
->sector_number
= r
.lba_low_16
;
1414 ata_cmd
->cylinder_low
= r
.lba_mid_16
;
1415 ata_cmd
->cylinder_high
= r
.lba_high_16
;
1416 ata_cmd
->device_head
= r
.device
;
1417 ata_cmd
->command
= r
.command
;
1419 bool readdata
= false;
1420 if (in
.direction
== ata_cmd_in::data_in
) {
1422 // the command will read data
1423 areca_packet
[6] = 0x13;
1425 else if ( in
.direction
== ata_cmd_in::no_data
)
1427 // the commands will return no data
1428 areca_packet
[6] = 0x15;
1430 else if (in
.direction
== ata_cmd_in::data_out
)
1432 // the commands will write data
1433 memcpy(ata_cmd
->data
, in
.buffer
, in
.size
);
1434 areca_packet
[6] = 0x14;
1437 // COMMAND NOT SUPPORTED VIA ARECA IOCTL INTERFACE
1438 return set_err(ENOTSUP
, "DATA OUT not supported for this Areca controller type");
1441 areca_packet
[11] = m_disknum
- 1; // disk #
1442 areca_packet
[19] = m_encnum
- 1; // enc#
1444 // ----- BEGIN TO SETUP CHECKSUM -----
1445 for ( int loop
= 3; loop
< areca_packet_len
- 1; loop
++ )
1447 cs
+= areca_packet
[loop
];
1449 areca_packet
[areca_packet_len
-1] = cs
;
1451 // ----- BEGIN TO SEND TO ARECA DRIVER ------
1453 unsigned char return_buff
[2048];
1454 memset(return_buff
, 0, sizeof(return_buff
));
1456 expected
= arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_CLEAR_RQBUFFER
, NULL
, 0, NULL
);
1458 return set_err(EIO
);
1461 expected
= arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_CLEAR_WQBUFFER
, NULL
, 0, NULL
);
1462 expected
= arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_WRITE_WQBUFFER
, areca_packet
, areca_packet_len
, NULL
);
1465 expected
= arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_READ_RQBUFFER
, return_buff
, sizeof(return_buff
), NULL
);
1472 // ----- VERIFY THE CHECKSUM -----
1474 for ( int loop
= 3; loop
< expected
- 1; loop
++ )
1476 cs
+= return_buff
[loop
];
1479 if ( return_buff
[expected
- 1] != cs
)
1481 return set_err(EIO
);
1484 sATA_OUTPUT_REGISTERS
*ata_out
= (sATA_OUTPUT_REGISTERS
*)&return_buff
[5] ;
1485 if ( ata_out
->status
)
1487 if ( in
.in_regs
.command
== ATA_IDENTIFY_DEVICE
1488 && !nonempty((unsigned char *)in
.buffer
, in
.size
))
1490 return set_err(ENODEV
, "No drive on port %d", m_disknum
);
1494 // returns with data
1497 memcpy(in
.buffer
, &return_buff
[7], in
.size
);
1500 // Return register values
1502 ata_out_regs_48bit
& r
= out
.out_regs
;
1503 r
.error
= ata_out
->error
;
1504 r
.sector_count_16
= ata_out
->sector_count
;
1505 r
.lba_low_16
= ata_out
->sector_number
;
1506 r
.lba_mid_16
= ata_out
->cylinder_low
;
1507 r
.lba_high_16
= ata_out
->cylinder_high
;
1508 r
.status
= ata_out
->status
;
1515 /////////////////////////////////////////////////////////////////////////////
1516 /// Implement CCISS RAID support with old functions
1518 class freebsd_cciss_device
1519 : public /*implements*/ scsi_device
,
1520 public /*extends*/ freebsd_smart_device
1523 freebsd_cciss_device(smart_interface
* intf
, const char * name
, unsigned char disknum
);
1525 virtual bool scsi_pass_through(scsi_cmnd_io
* iop
);
1526 virtual bool open();
1529 unsigned char m_disknum
; ///< Disk number.
1532 bool freebsd_cciss_device::open()
1534 const char *dev
= get_dev_name();
1536 if ((fd
= ::open(dev
,O_RDWR
))<0) {
1544 freebsd_cciss_device::freebsd_cciss_device(smart_interface
* intf
,
1545 const char * dev_name
, unsigned char disknum
)
1546 : smart_device(intf
, dev_name
, "cciss", "cciss"),
1547 freebsd_smart_device("SCSI"),
1550 set_info().info_name
= strprintf("%s [cciss_disk_%02d]", dev_name
, disknum
);
1553 bool freebsd_cciss_device::scsi_pass_through(scsi_cmnd_io
* iop
)
1555 int status
= cciss_io_interface(get_fd(), m_disknum
, iop
, scsi_debugmode
);
1557 return set_err(-status
);
1564 /////////////////////////////////////////////////////////////////////////////
1565 /// SCSI open with autodetection support
1567 smart_device
* freebsd_scsi_device::autodetect_open()
1573 // No Autodetection if device type was specified by user
1574 if (*get_req_type())
1577 // The code below is based on smartd.cpp:SCSIFilterKnown()
1580 unsigned char req_buff
[64] = {0, };
1582 if (scsiStdInquiry(this, req_buff
, req_len
)) {
1583 // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices
1584 // watch this spot ... other devices could lock up here
1586 if (scsiStdInquiry(this, req_buff
, req_len
)) {
1587 // device doesn't like INQUIRY commands
1589 set_err(EIO
, "INQUIRY failed");
1594 int avail_len
= req_buff
[4] + 5;
1595 int len
= (avail_len
< req_len
? avail_len
: req_len
);
1599 // Use INQUIRY to detect type
1602 if (!memcmp(req_buff
+ 8, "3ware", 5) || !memcmp(req_buff
+ 8, "AMCC", 4)) {
1604 set_err(EINVAL
, "AMCC/3ware controller, please try adding '-d 3ware,N',\n"
1605 "you may need to replace %s with /dev/twaN or /dev/tweN", get_dev_name());
1609 // SAT or USB, skip MFI controllers because of bugs
1611 smart_device
* newdev
= smi()->autodetect_sat_device(this, req_buff
, len
);
1613 // NOTE: 'this' is now owned by '*newdev'
1614 if(!strcmp("mfi",m_camdev
->sim_name
)) {
1616 newdev
->set_err(ENOSYS
, "SATA device detected,\n"
1617 "MegaRAID SAT layer is reportedly buggy, use '-d sat' to try anyhow");
1623 // Nothing special found
1628 /////////////////////////////////////////////////////////////////////////////
1629 /// Implement platform interface with old functions.
1631 class freebsd_smart_interface
1632 : public /*implements*/ smart_interface
1635 virtual std::string
get_os_version_str();
1637 virtual std::string
get_app_examples(const char * appname
);
1639 virtual bool scan_smart_devices(smart_device_list
& devlist
, const char * type
,
1640 const char * pattern
= 0);
1643 virtual ata_device
* get_ata_device(const char * name
, const char * type
);
1645 #if FREEBSDVER > 800100
1646 virtual ata_device
* get_atacam_device(const char * name
, const char * type
);
1649 virtual scsi_device
* get_scsi_device(const char * name
, const char * type
);
1651 virtual smart_device
* autodetect_smart_device(const char * name
);
1653 virtual smart_device
* get_custom_smart_device(const char * name
, const char * type
);
1655 virtual std::string
get_valid_custom_dev_types_str();
1659 //////////////////////////////////////////////////////////////////////
1661 std::string
freebsd_smart_interface::get_os_version_str()
1663 struct utsname osname
;
1665 return strprintf("%s %s %s", osname
.sysname
, osname
.release
, osname
.machine
);
1668 std::string
freebsd_smart_interface::get_app_examples(const char * appname
)
1670 if (!strcmp(appname
, "smartctl"))
1671 return smartctl_examples
;
1675 ata_device
* freebsd_smart_interface::get_ata_device(const char * name
, const char * type
)
1677 return new freebsd_ata_device(this, name
, type
);
1680 #if FREEBSDVER > 800100
1681 ata_device
* freebsd_smart_interface::get_atacam_device(const char * name
, const char * type
)
1683 return new freebsd_atacam_device(this, name
, type
);
1687 scsi_device
* freebsd_smart_interface::get_scsi_device(const char * name
, const char * type
)
1689 return new freebsd_scsi_device(this, name
, type
);
1692 // we are using CAM subsystem XPT enumerator to found all CAM (scsi/usb/ada/...)
1693 // devices on system despite of it's names
1695 // If any errors occur, leave errno set as it was returned by the
1696 // system call, and return <0.
1699 // names: resulting array
1700 // show_all - export duplicate device name or not
1704 // >=0: number of discovered devices
1706 bool get_dev_names_cam(std::vector
<std::string
> & names
, bool show_all
)
1709 if ((fd
= open(XPT_DEVICE
, O_RDWR
)) == -1) {
1710 if (errno
== ENOENT
) /* There are no CAM device on this computer */
1713 pout("%s control device couldn't opened: %s\n", XPT_DEVICE
, strerror(errno
));
1719 bzero(&ccb
, sizeof(union ccb
));
1721 ccb
.ccb_h
.path_id
= CAM_XPT_PATH_ID
;
1722 ccb
.ccb_h
.target_id
= CAM_TARGET_WILDCARD
;
1723 ccb
.ccb_h
.target_lun
= CAM_LUN_WILDCARD
;
1725 ccb
.ccb_h
.func_code
= XPT_DEV_MATCH
;
1726 int bufsize
= sizeof(struct dev_match_result
) * MAX_NUM_DEV
;
1727 ccb
.cdm
.match_buf_len
= bufsize
;
1728 // TODO: Use local buffer instead of malloc() if possible
1729 ccb
.cdm
.matches
= (struct dev_match_result
*)malloc(bufsize
);
1730 bzero(ccb
.cdm
.matches
,bufsize
); // clear ccb.cdm.matches structure
1732 if (ccb
.cdm
.matches
== NULL
) {
1734 throw std::bad_alloc();
1736 ccb
.cdm
.num_matches
= 0;
1737 ccb
.cdm
.num_patterns
= 0;
1738 ccb
.cdm
.pattern_buf_len
= 0;
1741 * We do the ioctl multiple times if necessary, in case there are
1742 * more than MAX_NUM_DEV nodes in the EDT.
1744 int skip_device
= 0, skip_bus
= 0, changed
= 0; // TODO: bool
1745 std::string devname
;
1747 if (ioctl(fd
, CAMIOCOMMAND
, &ccb
) == -1) {
1749 pout("error sending CAMIOCOMMAND ioctl: %s\n", strerror(errno
));
1750 free(ccb
.cdm
.matches
);
1756 if ((ccb
.ccb_h
.status
!= CAM_REQ_CMP
)
1757 || ((ccb
.cdm
.status
!= CAM_DEV_MATCH_LAST
)
1758 && (ccb
.cdm
.status
!= CAM_DEV_MATCH_MORE
))) {
1759 pout("got CAM error %#x, CDM error %d\n", ccb
.ccb_h
.status
, ccb
.cdm
.status
);
1760 free(ccb
.cdm
.matches
);
1766 for (unsigned i
= 0; i
< ccb
.cdm
.num_matches
; i
++) {
1767 struct bus_match_result
*bus_result
;
1768 struct device_match_result
*dev_result
;
1769 struct periph_match_result
*periph_result
;
1771 if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_BUS
) {
1772 bus_result
= &ccb
.cdm
.matches
[i
].result
.bus_result
;
1774 if (strcmp(bus_result
->dev_name
,"xpt") == 0) /* skip XPT bus at all */
1779 } else if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_DEVICE
) {
1780 dev_result
= &ccb
.cdm
.matches
[i
].result
.device_result
;
1782 if (dev_result
->flags
& DEV_RESULT_UNCONFIGURED
|| skip_bus
== 1)
1787 // /* Shall we skip non T_DIRECT devices ? */
1788 // if (dev_result->inq_data.device != T_DIRECT)
1791 } else if (ccb
.cdm
.matches
[i
].type
== DEV_MATCH_PERIPH
&&
1792 (skip_device
== 0 || show_all
)) {
1793 /* One device may be populated as many peripherals (pass0 & da0 for example).
1794 * We are searching for latest name
1796 periph_result
= &ccb
.cdm
.matches
[i
].result
.periph_result
;
1797 devname
= strprintf("%s%s%d", _PATH_DEV
, periph_result
->periph_name
, periph_result
->unit_number
);
1800 if ((changed
== 1 || show_all
) && !devname
.empty()) {
1801 names
.push_back(devname
);
1807 } while ((ccb
.ccb_h
.status
== CAM_REQ_CMP
) && (ccb
.cdm
.status
== CAM_DEV_MATCH_MORE
));
1809 if (!devname
.empty())
1810 names
.push_back(devname
);
1812 free(ccb
.cdm
.matches
);
1817 // we are using ATA subsystem enumerator to found all ATA devices on system
1818 // despite of it's names
1820 // If any errors occur, leave errno set as it was returned by the
1821 // system call, and return <0.
1825 // >=0: number of discovered devices
1826 int get_dev_names_ata(char*** names
) {
1827 struct ata_ioc_devices devices
;
1828 int fd
=-1,maxchannel
,serrno
=-1,n
=0;
1833 if ((fd
= open(ATA_DEVICE
, O_RDWR
)) < 0) {
1834 if (errno
== ENOENT
) /* There are no ATA device on this computer */
1837 pout("%s control device can't be opened: %s\n", ATA_DEVICE
, strerror(errno
));
1842 if (ioctl(fd
, IOCATAGMAXCHANNEL
, &maxchannel
) < 0) {
1844 pout("ioctl(IOCATAGMAXCHANNEL) on /dev/ata failed: %s\n", strerror(errno
));
1849 // allocate space for up to MAX_NUM_DEV number of ATA devices
1850 mp
= (char **)calloc(MAX_NUM_DEV
, sizeof(char*));
1853 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__
);
1858 for (devices
.channel
= 0; devices
.channel
< maxchannel
&& n
< MAX_NUM_DEV
; devices
.channel
++) {
1861 if (ioctl(fd
, IOCATADEVICES
, &devices
) < 0) {
1863 continue; /* such channel not exist */
1864 pout("ioctl(IOCATADEVICES) on %s channel %d failed: %s\n", ATA_DEVICE
, devices
.channel
, strerror(errno
));
1868 for (j
=0;j
<=1 && n
<MAX_NUM_DEV
;j
++) {
1869 if (devices
.name
[j
][0] != '\0') {
1870 asprintf(mp
+n
, "%s%s", _PATH_DEV
, devices
.name
[j
]);
1871 if (mp
[n
] == NULL
) {
1872 pout("Out of memory constructing scan ATA device list (on line %d)\n", __LINE__
);
1876 bytes
+=1+strlen(mp
[n
]);
1881 mp
= (char **)reallocf(mp
,n
*(sizeof (char*))); // shrink to correct size
1882 if (mp
== NULL
&& n
> 0 ) { // reallocf never fail for size=0, but may return NULL
1884 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__
);
1888 bytes
+= (n
)*(sizeof(char*)); // and set allocated byte count
1907 bool freebsd_smart_interface::scan_smart_devices(smart_device_list
& devlist
,
1908 const char * type
, const char * pattern
/*= 0*/)
1911 set_err(EINVAL
, "DEVICESCAN with pattern not implemented yet");
1916 char * * atanames
= 0; int numata
= 0;
1917 if (!type
|| !strcmp(type
, "ata")) {
1918 numata
= get_dev_names_ata(&atanames
);
1925 std::vector
<std::string
> scsinames
;
1926 if (!type
|| !strcmp(type
, "scsi")) { // do not export duplicated names
1927 if (!get_dev_names_cam(scsinames
, false)) {
1937 for (i
= 0; i
< numata
; i
++) {
1938 ata_device
* atadev
= get_ata_device(atanames
[i
], type
);
1940 devlist
.push_back(atadev
);
1943 if(numata
) free(atanames
);
1945 for (i
= 0; i
< (int)scsinames
.size(); i
++) {
1946 if(!*type
) { // try USB autodetection if no type specified
1947 smart_device
* smartdev
= autodetect_smart_device(scsinames
[i
].c_str());
1949 devlist
.push_back(smartdev
);
1952 scsi_device
* scsidev
= get_scsi_device(scsinames
[i
].c_str(), type
);
1954 devlist
.push_back(scsidev
);
1961 #if (FREEBSDVER < 800000) // without this build fail on FreeBSD 8
1962 static char done
[USB_MAX_DEVICES
];
1964 static int usbdevinfo(int f
, int a
, int rec
, int busno
, unsigned short & vendor_id
,
1965 unsigned short & product_id
, unsigned short & version
)
1968 struct usb_device_info di
;
1972 snprintf(devname
, sizeof(devname
),"umass%d",busno
);
1975 e
= ioctl(f
, USB_DEVICEINFO
, &di
);
1978 printf("addr %d: I/O error\n", a
);
1984 for (i
= 0; i
< USB_MAX_DEVNAMES
; i
++) {
1985 if (di
.udi_devnames
[i
][0]) {
1986 if(strcmp(di
.udi_devnames
[i
],devname
)==0) {
1988 vendor_id
= di
.udi_vendorNo
;
1989 product_id
= di
.udi_productNo
;
1990 version
= di
.udi_releaseNo
;
1998 for (p
= 0; p
< di
.udi_nports
; p
++) {
1999 int s
= di
.udi_ports
[p
];
2000 if (s
>= USB_MAX_DEVICES
) {
2004 printf("addr 0 should never happen!\n");
2006 if(usbdevinfo(f
, s
, 1, busno
, vendor_id
, product_id
, version
)) return 1;
2014 static int usbdevlist(int busno
,unsigned short & vendor_id
,
2015 unsigned short & product_id
, unsigned short & version
)
2017 #if (FREEBSDVER >= 800000) // libusb2 interface
2018 struct libusb20_device
*pdev
= NULL
;
2019 struct libusb20_backend
*pbe
;
2020 uint32_t matches
= 0;
2021 char buf
[128]; // do not change!
2024 struct LIBUSB20_DEVICE_DESC_DECODED
*pdesc
;
2026 pbe
= libusb20_be_alloc_default();
2028 while ((pdev
= libusb20_be_device_foreach(pbe
, pdev
))) {
2031 if (libusb20_dev_open(pdev
, 0)) {
2032 warnx("libusb20_dev_open: could not open device");
2036 pdesc
=libusb20_dev_get_device_desc(pdev
);
2038 snprintf(devname
, sizeof(devname
),"umass%d:",busno
);
2039 for (n
= 0; n
!= 255; n
++) {
2040 if (libusb20_dev_get_iface_desc(pdev
, n
, buf
, sizeof(buf
)))
2044 if(strncmp(buf
,devname
,strlen(devname
))==0){
2046 vendor_id
= pdesc
->idVendor
;
2047 product_id
= pdesc
->idProduct
;
2048 version
= pdesc
->bcdDevice
;
2049 libusb20_dev_close(pdev
);
2050 libusb20_be_free(pbe
);
2055 libusb20_dev_close(pdev
);
2059 printf("No device match or lack of permissions.\n");
2062 libusb20_be_free(pbe
);
2065 #else // freebsd < 8.0 USB stack, ioctl interface
2071 for (ncont
= 0, i
= 0; i
< 10; i
++) {
2072 snprintf(buf
, sizeof(buf
), "%s%d", USBDEV
, i
);
2073 f
= open(buf
, O_RDONLY
);
2075 memset(done
, 0, sizeof done
);
2076 for (a
= 1; a
< USB_MAX_DEVICES
; a
++) {
2078 rc
= usbdevinfo(f
, a
, 1, busno
,vendor_id
, product_id
, version
);
2085 if (errno
== ENOENT
|| errno
== ENXIO
)
2095 smart_device
* freebsd_smart_interface::autodetect_smart_device(const char * name
)
2097 unsigned short vendor_id
= 0, product_id
= 0, version
= 0;
2098 struct cam_device
*cam_dev
;
2103 const char * test_name
= name
;
2105 // if dev_name null, or string length zero
2106 if (!name
|| !(len
= strlen(name
)))
2109 // Dereference symlinks
2111 std::string pathbuf
;
2112 if (!lstat(name
, &st
) && S_ISLNK(st
.st_mode
)) {
2113 char * p
= realpath(name
, (char *)0);
2117 test_name
= pathbuf
.c_str();
2122 char * * atanames
= 0; int numata
= 0;
2123 numata
= get_dev_names_ata(&atanames
);
2125 // check ATA/ATAPI devices
2126 for (i
= 0; i
< numata
; i
++) {
2127 if(!strcmp(atanames
[i
],test_name
)) {
2128 for (c
= i
; c
< numata
; c
++) free(atanames
[c
]);
2130 return new freebsd_ata_device(this, test_name
, "");
2132 else free(atanames
[i
]);
2134 if(numata
) free(atanames
);
2138 pout("Unable to get ATA device list\n");
2142 std::vector
<std::string
> scsinames
;
2143 if (!get_dev_names_cam(scsinames
, true))
2144 pout("Unable to get CAM device list\n");
2145 else if (!scsinames
.empty()) {
2146 // check all devices on CAM bus
2147 for (i
= 0; i
< (int)scsinames
.size(); i
++) {
2148 if(strcmp(scsinames
[i
].c_str(), test_name
)==0)
2149 { // our disk device is CAM
2150 if ((cam_dev
= cam_open_device(test_name
, O_RDWR
)) == NULL
) {
2156 bzero(&(&ccb
.ccb_h
)[1], PATHINQ_SETTINGS_SIZE
);
2157 ccb
.ccb_h
.func_code
= XPT_PATH_INQ
; // send PATH_INQ to the device
2158 if (ioctl(cam_dev
->fd
, CAMIOCOMMAND
, &ccb
) == -1) {
2159 warn("Get Transfer Settings CCB failed\n"
2160 "%s", strerror(errno
));
2161 cam_close_device(cam_dev
);
2164 // now check if we are working with USB device, see umass.c
2165 if(strcmp(ccb
.cpi
.dev_name
,"umass-sim") == 0) { // USB device found
2166 usbdevlist(bus
,vendor_id
, product_id
, version
);
2167 int bus
=ccb
.cpi
.unit_number
; // unit_number will match umass number
2168 cam_close_device(cam_dev
);
2169 if(usbdevlist(bus
,vendor_id
, product_id
, version
)){
2170 const char * usbtype
= get_usb_dev_type_by_id(vendor_id
, product_id
, version
);
2172 return get_sat_device(usbtype
, new freebsd_scsi_device(this, test_name
, ""));
2176 #if FREEBSDVER > 800100
2177 // check if we have ATA device connected to CAM (ada)
2178 if(ccb
.cpi
.protocol
== PROTO_ATA
){
2179 cam_close_device(cam_dev
);
2180 return new freebsd_atacam_device(this, test_name
, "");
2183 // close cam device, we don`t need it anymore
2184 cam_close_device(cam_dev
);
2185 // handle as usual scsi
2186 return new freebsd_scsi_device(this, test_name
, "");
2190 // device is LSI raid supported by mfi driver
2191 if(!strncmp("/dev/mfid", test_name
, strlen("/dev/mfid")))
2192 set_err(EINVAL
, "To monitor disks on LSI RAID load mfip.ko module and run 'smartctl -a /dev/passX' to show SMART information");
2193 // device type unknown
2198 smart_device
* freebsd_smart_interface::get_custom_smart_device(const char * name
, const char * type
)
2201 static const char * fbsd_dev_twe_ctrl
= "/dev/twe";
2202 static const char * fbsd_dev_twa_ctrl
= "/dev/twa";
2203 int disknum
= -1, n1
= -1, n2
= -1, contr
= -1;
2205 if (sscanf(type
, "3ware,%n%d%n", &n1
, &disknum
, &n2
) == 1 || n1
== 6) {
2206 if (n2
!= (int)strlen(type
)) {
2207 set_err(EINVAL
, "Option -d 3ware,N requires N to be a non-negative integer");
2210 if (!(0 <= disknum
&& disknum
<= 127)) {
2211 set_err(EINVAL
, "Option -d 3ware,N (N=%d) must have 0 <= N <= 127", disknum
);
2215 // guess 3ware device type based on device name
2216 if (!strncmp(fbsd_dev_twa_ctrl
, name
, strlen(fbsd_dev_twa_ctrl
))){
2217 contr
=CONTROLLER_3WARE_9000_CHAR
;
2219 if (!strncmp(fbsd_dev_twe_ctrl
, name
, strlen(fbsd_dev_twe_ctrl
))){
2220 contr
=CONTROLLER_3WARE_678K_CHAR
;
2224 set_err(EINVAL
, "3ware controller type unknown, use %sX or %sX devices",
2225 fbsd_dev_twe_ctrl
, fbsd_dev_twa_ctrl
);
2228 return new freebsd_escalade_device(this, name
, contr
, disknum
);
2232 int controller
= -1, channel
= -1; disknum
= 1;
2233 n1
= n2
= -1; int n3
= -1;
2234 if (sscanf(type
, "hpt,%n%d/%d%n/%d%n", &n1
, &controller
, &channel
, &n2
, &disknum
, &n3
) >= 2 || n1
== 4) {
2235 int len
= strlen(type
);
2236 if (!(n2
== len
|| n3
== len
)) {
2237 set_err(EINVAL
, "Option '-d hpt,L/M/N' supports 2-3 items");
2240 if (!(1 <= controller
&& controller
<= 8)) {
2241 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid controller id L supplied");
2244 if (!(1 <= channel
&& channel
<= 16)) {
2245 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid channel number M supplied");
2248 if (!(1 <= disknum
&& disknum
<= 15)) {
2249 set_err(EINVAL
, "Option '-d hpt,L/M/N' invalid pmport number N supplied");
2252 return new freebsd_highpoint_device(this, name
, controller
, channel
, disknum
);
2256 disknum
= n1
= n2
= -1;
2257 if (sscanf(type
, "cciss,%n%d%n", &n1
, &disknum
, &n2
) == 1 || n1
== 6) {
2258 if (n2
!= (int)strlen(type
)) {
2259 set_err(EINVAL
, "Option -d cciss,N requires N to be a non-negative integer");
2262 if (!(0 <= disknum
&& disknum
<= 127)) {
2263 set_err(EINVAL
, "Option -d cciss,N (N=%d) must have 0 <= N <= 127", disknum
);
2266 return new freebsd_cciss_device(this, name
, disknum
);
2268 #if FREEBSDVER > 800100
2270 if(!strcmp(type
,"atacam"))
2271 return new freebsd_atacam_device(this, name
, "");
2274 disknum
= n1
= n2
= -1;
2276 if (sscanf(type
, "areca,%n%d/%d%n", &n1
, &disknum
, &encnum
, &n2
) >= 1 || n1
== 6) {
2277 if (!(1 <= disknum
&& disknum
<= 128)) {
2278 set_err(EINVAL
, "Option -d areca,N/E (N=%d) must have 1 <= N <= 128", disknum
);
2281 if (!(1 <= encnum
&& encnum
<= 8)) {
2282 set_err(EINVAL
, "Option -d areca,N/E (E=%d) must have 1 <= E <= 8", encnum
);
2285 return new freebsd_areca_device(this, name
, disknum
);
2291 std::string
freebsd_smart_interface::get_valid_custom_dev_types_str()
2293 return "3ware,N, hpt,L/M/N, cciss,N, areca,N/E"
2294 #if FREEBSDVER > 800100
2302 /////////////////////////////////////////////////////////////////////////////
2303 /// Initialize platform interface and register with smi()
2305 void smart_interface::init()
2307 static os_freebsd::freebsd_smart_interface the_interface
;
2308 smart_interface::set(&the_interface
);