4 * Home page of code is: http://smartmontools.sourceforge.net
6 * Copyright (C) 2003-6 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 #if defined(__DragonFly__)
45 #include "os_freebsd.h"
47 static const char *filenameandversion
="$Id: os_freebsd.cpp,v 1.56 2008/02/23 06:41:59 ballen4705 Exp $";
49 const char *os_XXXX_c_cvsid
="$Id: os_freebsd.cpp,v 1.56 2008/02/23 06:41:59 ballen4705 Exp $" \
50 ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID
;
52 // to hold onto exit code for atexit routine
53 extern int exitstatus
;
55 extern smartmonctrl
* con
;
57 // Private table of open devices: guaranteed zero on startup since
58 // part of static data.
59 struct freebsd_dev_channel
*devicetable
[FREEBSD_MAXDEV
];
61 // forward declaration
62 static int parse_ata_chan_dev(const char * dev_name
, struct freebsd_dev_channel
*ch
);
64 // print examples for smartctl
65 void print_smartctl_examples(){
66 printf("=================================================== SMARTCTL EXAMPLES =====\n\n");
67 #ifdef HAVE_GETOPT_LONG
69 " smartctl -a /dev/ad0 (Prints all SMART information)\n\n"
70 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/ad0\n"
71 " (Enables SMART on first disk)\n\n"
72 " smartctl -t long /dev/ad0 (Executes extended disk self-test)\n\n"
73 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/ad0\n"
74 " (Prints Self-Test & Attribute errors)\n"
75 " (Prints Self-Test & Attribute errors)\n\n"
76 " smartctl -a --device=3ware,2 /dev/twa0\n"
77 " smartctl -a --device=3ware,2 /dev/twe0\n"
78 " (Prints all SMART information for ATA disk on\n"
79 " third port of first 3ware RAID controller)\n"
83 " smartctl -a /dev/ad0 (Prints all SMART information)\n"
84 " smartctl -s on -o on -S on /dev/ad0 (Enables SMART on first disk)\n"
85 " smartctl -t long /dev/ad0 (Executes extended disk self-test)\n"
86 " smartctl -A -l selftest -q errorsonly /dev/ad0\n"
87 " (Prints Self-Test & Attribute errors)\n"
88 " smartctl -a -d 3ware,2 /dev/twa0\n"
89 " smartctl -a -d 3ware,2 /dev/twe0\n"
95 // Like open(). Return positive integer handle, used by functions below only. mode=="ATA" or "SCSI".
96 int deviceopen (const char* dev
, __unused
char* mode
) {
97 struct freebsd_dev_channel
*fdchan
;
100 // Search table for a free entry
101 for (i
=0; i
<FREEBSD_MAXDEV
; i
++)
105 // If no free entry found, return error. We have max allowed number
106 // of "file descriptors" already allocated.
107 if (i
==FREEBSD_MAXDEV
) {
112 fdchan
= (struct freebsd_dev_channel
*)calloc(1,sizeof(struct freebsd_dev_channel
));
113 if (fdchan
== NULL
) {
114 // errno already set by call to malloc()
118 parse_ok
= parse_ata_chan_dev (dev
,fdchan
);
119 if (parse_ok
== CONTROLLER_UNKNOWN
) {
122 return -1; // can't handle what we don't know
125 if (parse_ok
== CONTROLLER_ATA
) {
127 if ((fdchan
->device
= open(dev
,O_RDONLY
))<0) {
129 if ((fdchan
->atacommand
= open("/dev/ata",O_RDWR
))<0) {
131 int myerror
= errno
; //preserve across free call
138 if (parse_ok
== CONTROLLER_3WARE_678K_CHAR
) {
140 sprintf(buf
,"/dev/twe%d",fdchan
->device
);
142 if ((fdchan
->device
= open(buf
,O_RDWR
))<0) {
144 if ((fdchan
->atacommand
= open(buf
,O_RDWR
))<0) {
146 int myerror
= errno
; // preserver across free call
153 if (parse_ok
== CONTROLLER_3WARE_9000_CHAR
) {
155 sprintf(buf
,"/dev/twa%d",fdchan
->device
);
157 if ((fdchan
->device
= open(buf
,O_RDWR
))<0) {
159 if ((fdchan
->atacommand
= open(buf
,O_RDWR
))<0) {
161 int myerror
= errno
; // preserver across free call
168 if (parse_ok
== CONTROLLER_CCISS
) {
169 if ((fdchan
->device
= open(dev
,O_RDWR
))<0) {
170 int myerror
= errno
; // preserver across free call
177 if (parse_ok
== CONTROLLER_SCSI
) {
178 // this is really a NO-OP, as the parse takes care
179 // of filling in correct details
182 // return pointer to "file descriptor" table entry, properly offset.
183 devicetable
[i
]=fdchan
;
184 return i
+FREEBSD_FDOFFSET
;
187 // Returns 1 if device not available/open/found else 0. Also shifts fd into valid range.
188 static int isnotopen(int *fd
, struct freebsd_dev_channel
** fdchan
) {
189 // put valid "file descriptor" into range 0...FREEBSD_MAXDEV-1
190 *fd
-= FREEBSD_FDOFFSET
;
192 // check for validity of "file descriptor".
193 if (*fd
<0 || *fd
>=FREEBSD_MAXDEV
|| !((*fdchan
)=devicetable
[*fd
])) {
201 // Like close(). Acts on handles returned by above function.
202 int deviceclose (int fd
) {
203 struct freebsd_dev_channel
*fdchan
;
206 // check for valid file descriptor
207 if (isnotopen(&fd
, &fdchan
))
211 // did we allocate a SCSI device name?
213 free(fdchan
->devname
);
215 // close device, if open
218 failed
=close(fdchan
->device
);
220 if (fdchan
->atacommand
)
221 failed
=close(fdchan
->atacommand
);
224 if (fdchan
->scsicontrol
)
225 failed
=close(fdchan
->scsicontrol
);
227 // if close succeeded, then remove from device list
228 // Eduard, should we also remove it from list if close() fails? I'm
229 // not sure. Here I only remove it from list if close() worked.
232 devicetable
[fd
]=NULL
;
240 #define NO_DISK_3WARE 2
244 // Utility function for printing warnings
245 void printwarning(int msgNo
, const char* extra
) {
246 static int printed
[] = {0,0,0,0};
247 static const char* message
[]={
248 "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",
250 "Error SMART Status command failed\nPlease get assistance from \n" PACKAGE_HOMEPAGE
"\nRegister values returned from SMART Status command are:\n",
252 "You must specify a DISK # for 3ware drives with -d 3ware,<n> where <n> begins with 1 for first disk drive\n",
254 "ATA support is not provided for this kernel version. Please ugrade to a recent 5-CURRENT kernel (post 09/01/2003 or so)\n"
257 if (msgNo
>= 0 && msgNo
<= MAX_MSG
) {
258 if (!printed
[msgNo
]) {
260 pout("%s", message
[msgNo
]);
268 // Interface to ATA devices. See os_linux.c
270 int marvell_command_interface(__unused
int fd
, __unused smart_command_set command
, __unused
int select
, __unused
char *data
) {
274 int highpoint_command_interface(__unused
int fd
, __unused smart_command_set command
, __unused
int select
, __unused
char *data
) {
279 int ata_command_interface(int fd
, smart_command_set command
, int select
, char *data
) {
280 #if !defined(ATAREQUEST) && !defined(IOCATAREQUEST)
281 // sorry, but without ATAng, we can't do anything here
282 printwarning(BAD_KERNEL
,NULL
);
286 struct freebsd_dev_channel
* con
;
287 int retval
, copydata
=0;
289 struct ata_ioc_request request
;
291 struct ata_cmd iocmd
;
293 unsigned char buff
[512];
295 // check that "file descriptor" is valid
296 if (isnotopen(&fd
,&con
))
302 bzero(&request
,sizeof(struct ata_ioc_request
));
304 bzero(&iocmd
,sizeof(struct ata_cmd
));
308 #ifndef IOCATAREQUEST
309 iocmd
.cmd
=ATAREQUEST
;
310 iocmd
.channel
=con
->channel
;
311 iocmd
.device
=con
->device
;
312 #define request iocmd.u.request
315 request
.u
.ata
.command
=ATA_SMART_CMD
;
319 request
.u
.ata
.feature
=ATA_SMART_READ_VALUES
;
320 request
.u
.ata
.lba
=0xc24f<<8;
321 request
.flags
=ATA_CMD_READ
;
322 request
.data
=(char *)buff
;
326 case READ_THRESHOLDS
:
327 request
.u
.ata
.feature
=ATA_SMART_READ_THRESHOLDS
;
328 request
.u
.ata
.count
=1;
329 request
.u
.ata
.lba
=1|(0xc24f<<8);
330 request
.flags
=ATA_CMD_READ
;
331 request
.data
=(char *)buff
;
336 request
.u
.ata
.feature
=ATA_SMART_READ_LOG_SECTOR
;
337 request
.u
.ata
.lba
=select
|(0xc24f<<8);
338 request
.u
.ata
.count
=1;
339 request
.flags
=ATA_CMD_READ
;
340 request
.data
=(char *)buff
;
345 request
.u
.ata
.command
=ATA_IDENTIFY_DEVICE
;
346 request
.flags
=ATA_CMD_READ
;
347 request
.data
=(char *)buff
;
352 request
.u
.ata
.command
=ATA_IDENTIFY_PACKET_DEVICE
;
353 request
.flags
=ATA_CMD_READ
;
354 request
.data
=(char *)buff
;
359 request
.u
.ata
.feature
=ATA_SMART_ENABLE
;
360 request
.u
.ata
.lba
=0xc24f<<8;
361 request
.flags
=ATA_CMD_CONTROL
;
364 request
.u
.ata
.feature
=ATA_SMART_DISABLE
;
365 request
.u
.ata
.lba
=0xc24f<<8;
366 request
.flags
=ATA_CMD_CONTROL
;
369 // NOTE: According to ATAPI 4 and UP, this command is obsolete
370 request
.u
.ata
.feature
=ATA_SMART_AUTO_OFFLINE
;
371 request
.u
.ata
.lba
=0xc24f<<8;
372 request
.u
.ata
.count
=select
;
373 request
.flags
=ATA_CMD_CONTROL
;
376 request
.u
.ata
.feature
=ATA_SMART_AUTOSAVE
;
377 request
.u
.ata
.count
=0xf1; // to enable autosave
378 request
.u
.ata
.lba
=0xc24f<<8;
379 request
.flags
=ATA_CMD_CONTROL
;
381 case IMMEDIATE_OFFLINE
:
382 request
.u
.ata
.feature
=ATA_SMART_IMMEDIATE_OFFLINE
;
383 request
.u
.ata
.lba
= select
|(0xc24f<<8); // put test in sector
384 request
.flags
=ATA_CMD_CONTROL
;
386 case STATUS_CHECK
: // same command, no HDIO in FreeBSD
388 // this command only says if SMART is working. It could be
389 // replaced with STATUS_CHECK below.
390 request
.u
.ata
.feature
=ATA_SMART_STATUS
;
391 request
.u
.ata
.lba
=0xc24f<<8;
392 request
.flags
=ATA_CMD_CONTROL
;
395 pout("Unrecognized command %d in ata_command_interface()\n"
396 "Please contact " PACKAGE_BUGREPORT
"\n", command
);
401 if (command
==STATUS_CHECK
){
402 unsigned const char normal_lo
=0x4f, normal_hi
=0xc2;
403 unsigned const char failed_lo
=0xf4, failed_hi
=0x2c;
404 unsigned char low
,high
;
407 if ((retval
=ioctl(con
->device
, IOCATAREQUEST
, &request
)) || request
.error
)
409 if ((retval
=ioctl(con
->atacommand
, IOCATA
, &iocmd
)) || request
.error
)
413 #if __FreeBSD_version < 502000
414 printwarning(NO_RETURN
,NULL
);
417 high
= (request
.u
.ata
.lba
>> 16) & 0xff;
418 low
= (request
.u
.ata
.lba
>> 8) & 0xff;
420 // Cyl low and Cyl high unchanged means "Good SMART status"
421 if (low
==normal_lo
&& high
==normal_hi
)
424 // These values mean "Bad SMART status"
425 if (low
==failed_lo
&& high
==failed_hi
)
428 // We haven't gotten output that makes sense; print out some debugging info
430 sprintf(buf
,"CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
431 (int)request
.u
.ata
.command
,
432 (int)request
.u
.ata
.feature
,
433 (int)request
.u
.ata
.count
,
434 (int)((request
.u
.ata
.lba
) & 0xff),
435 (int)((request
.u
.ata
.lba
>>8) & 0xff),
436 (int)((request
.u
.ata
.lba
>>16) & 0xff),
438 printwarning(BAD_SMART
,buf
);
443 if ((retval
=ioctl(con
->device
, IOCATAREQUEST
, &request
)) || request
.error
)
445 if ((retval
=ioctl(con
->atacommand
, IOCATA
, &iocmd
)) || request
.error
)
452 memcpy(data
, buff
, 512);
459 // Interface to SCSI devices. See os_linux.c
460 int do_normal_scsi_cmnd_io(int fd
, struct scsi_cmnd_io
* iop
, int report
)
462 struct freebsd_dev_channel
* con
= NULL
;
463 struct cam_device
* cam_dev
= NULL
;
469 const unsigned char * ucp
= iop
->cmnd
;
472 np
= scsi_get_opcode_name(ucp
[0]);
473 pout(" [%s: ", np
? np
: "<unknown opcode>");
474 for (k
= 0; k
< iop
->cmnd_len
; ++k
)
475 pout("%02x ", ucp
[k
]);
477 (DXFER_TO_DEVICE
== iop
->dxfer_dir
) && (iop
->dxferp
)) {
478 int trunc
= (iop
->dxfer_len
> 256) ? 1 : 0;
480 pout("]\n Outgoing data, len=%d%s:\n", (int)iop
->dxfer_len
,
481 (trunc
? " [only first 256 bytes shown]" : ""));
482 dStrHex(iop
->dxferp
, (trunc
? 256 : iop
->dxfer_len
) , 1);
488 // check that "file descriptor" is valid
489 if (isnotopen(&fd
,&con
))
493 if (!(cam_dev
= cam_open_spec_device(con
->devname
,con
->unitnum
,O_RDWR
,NULL
))) {
494 warnx("%s",cam_errbuf
);
498 if (!(ccb
= cam_getccb(cam_dev
))) {
499 warnx("error allocating ccb");
503 // clear out structure, except for header that was filled in for us
504 bzero(&(&ccb
->ccb_h
)[1],
505 sizeof(struct ccb_scsiio
) - sizeof(struct ccb_hdr
));
507 cam_fill_csio(&ccb
->csio
,
510 /* flags */ (iop
->dxfer_dir
== DXFER_NONE
? CAM_DIR_NONE
:(iop
->dxfer_dir
== DXFER_FROM_DEVICE
? CAM_DIR_IN
: CAM_DIR_OUT
)),
511 /* tagaction */ MSG_SIMPLE_Q_TAG
,
512 /* dataptr */ iop
->dxferp
,
513 /* datalen */ iop
->dxfer_len
,
514 /* senselen */ iop
->max_sense_len
,
515 /* cdblen */ iop
->cmnd_len
,
516 /* timout (converted to seconds) */ iop
->timeout
*1000);
517 memcpy(ccb
->csio
.cdb_io
.cdb_bytes
,iop
->cmnd
,iop
->cmnd_len
);
519 if (cam_send_ccb(cam_dev
,ccb
) < 0) {
520 warn("error sending SCSI ccb");
521 #if __FreeBSD_version > 500000
522 cam_error_print(cam_dev
,ccb
,CAM_ESF_ALL
,CAM_EPF_ALL
,stderr
);
528 if ((ccb
->ccb_h
.status
& CAM_STATUS_MASK
) != CAM_REQ_CMP
) {
529 #if __FreeBSD_version > 500000
530 cam_error_print(cam_dev
,ccb
,CAM_ESF_ALL
,CAM_EPF_ALL
,stderr
);
537 memcpy(iop
->sensep
,&(ccb
->csio
.sense_data
),sizeof(struct scsi_sense_data
));
538 iop
->resp_sense_len
= sizeof(struct scsi_sense_data
);
541 iop
->scsi_status
= ccb
->csio
.scsi_status
;
546 cam_close_device(cam_dev
);
552 trunc
= (iop
->dxfer_len
> 256) ? 1 : 0;
554 pout(" Incoming data, len=%d%s:\n", (int)iop
->dxfer_len
,
555 (trunc
? " [only first 256 bytes shown]" : ""));
556 dStrHex(iop
->dxferp
, (trunc
? 256 : iop
->dxfer_len
) , 1);
561 /* Check and call the right interface. Maybe when the do_generic_scsi_cmd_io interface is better
562 we can take off this crude way of calling the right interface */
563 int do_scsi_cmnd_io(int dev_fd
, struct scsi_cmnd_io
* iop
, int report
)
565 struct freebsd_dev_channel
*fdchan
;
566 switch(con
->controller_type
)
568 case CONTROLLER_CCISS
:
569 // check that "file descriptor" is valid
570 if (isnotopen(&dev_fd
,&fdchan
))
572 #ifdef HAVE_DEV_CISS_CISSIO_H
573 return cciss_io_interface(fdchan
->device
, con
->controller_port
-1, iop
, report
);
576 static int warned
= 0;
578 pout("CCISS support is not available in this build of smartmontools,\n"
579 "/usr/src/sys/dev/ciss/cissio.h was not available at build time.\n\n");
589 return do_normal_scsi_cmnd_io(dev_fd
, iop
, report
);
595 // Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c
597 #define BUFFER_LEN_678K_CHAR ( sizeof(struct twe_usercommand) ) // 520
598 #define BUFFER_LEN_9000_CHAR ( sizeof(TW_OSLI_IOCTL_NO_DATA_BUF) + sizeof(TWE_Command) ) // 2048
599 #define TW_IOCTL_BUFFER_SIZE ( MAX(BUFFER_LEN_678K_CHAR, BUFFER_LEN_9000_CHAR) )
601 int escalade_command_interface(int fd
, int disknum
, int escalade_type
, smart_command_set command
, int select
, char *data
) {
602 // to hold true file descriptor
603 struct freebsd_dev_channel
* con
;
605 // return value and buffer for ioctl()
606 int ioctlreturn
, readdata
=0;
607 struct twe_usercommand
* cmd_twe
= NULL
;
608 TW_OSLI_IOCTL_NO_DATA_BUF
* cmd_twa
= NULL
;
609 TWE_Command_ATA
* ata
= NULL
;
611 // Used by both the SCSI and char interfaces
612 char ioctl_buffer
[TW_IOCTL_BUFFER_SIZE
];
615 printwarning(NO_DISK_3WARE
,NULL
);
619 // check that "file descriptor" is valid
620 if (isnotopen(&fd
,&con
))
623 memset(ioctl_buffer
, 0, TW_IOCTL_BUFFER_SIZE
);
625 if (escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
626 cmd_twa
= (TW_OSLI_IOCTL_NO_DATA_BUF
*)ioctl_buffer
;
627 cmd_twa
->pdata
= ((TW_OSLI_IOCTL_WITH_PAYLOAD
*)cmd_twa
)->payload
.data_buf
;
628 cmd_twa
->driver_pkt
.buffer_length
= 512;
629 ata
= (TWE_Command_ATA
*)&cmd_twa
->cmd_pkt
.command
.cmd_pkt_7k
;
630 } else if (escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
631 cmd_twe
= (struct twe_usercommand
*)ioctl_buffer
;
632 ata
= &cmd_twe
->tu_command
.ata
;
634 pout("Unrecognized escalade_type %d in freebsd_3ware_command_interface(disk %d)\n"
635 "Please contact " PACKAGE_BUGREPORT
"\n", escalade_type
, disknum
);
640 ata
->opcode
= TWE_OP_ATA_PASSTHROUGH
;
642 // Same for (almost) all commands - but some reset below
643 ata
->request_id
= 0xFF;
647 ata
->drive_head
= 0x0;
650 // All SMART commands use this CL/CH signature. These are magic
651 // values from the ATA specifications.
652 ata
->cylinder_lo
= 0x4F;
653 ata
->cylinder_hi
= 0xC2;
655 // SMART ATA COMMAND REGISTER value
656 ata
->command
= ATA_SMART_CMD
;
658 // Is this a command that reads or returns 512 bytes?
659 // passthru->param values are:
660 // 0x0 - non data command without TFR write check,
661 // 0x8 - non data command with TFR write check,
662 // 0xD - data command that returns data to host from device
663 // 0xF - data command that writes data from host to device
664 // passthru->size values are 0x5 for non-data and 0x07 for data
665 if (command
== READ_VALUES
||
666 command
== READ_THRESHOLDS
||
667 command
== READ_LOG
||
668 command
== IDENTIFY
||
669 command
== WRITE_LOG
) {
671 if (escalade_type
==CONTROLLER_3WARE_678K_CHAR
) {
672 cmd_twe
->tu_data
= data
;
673 cmd_twe
->tu_size
= 512;
675 ata
->sgl_offset
= 0x5;
678 ata
->sector_count
= 0x1;
679 // For 64-bit to work correctly, up the size of the command packet
680 // in dwords by 1 to account for the 64-bit single sgl 'address'
681 // field. Note that this doesn't agree with the typedefs but it's
682 // right (agree with kernel driver behavior/typedefs).
683 //if (sizeof(long)==8)
687 // Non data command -- but doesn't use large sector
688 // count register values.
689 ata
->sgl_offset
= 0x0;
692 ata
->sector_count
= 0x0;
695 // Now set ATA registers depending upon command
697 case CHECK_POWER_MODE
:
698 ata
->command
= ATA_CHECK_POWER_MODE
;
700 ata
->cylinder_lo
= 0;
701 ata
->cylinder_hi
= 0;
704 ata
->features
= ATA_SMART_READ_VALUES
;
706 case READ_THRESHOLDS
:
707 ata
->features
= ATA_SMART_READ_THRESHOLDS
;
710 ata
->features
= ATA_SMART_READ_LOG_SECTOR
;
711 // log number to return
712 ata
->sector_num
= select
;
716 ata
->features
= ATA_SMART_WRITE_LOG_SECTOR
;
717 ata
->sector_count
= 1;
718 ata
->sector_num
= select
;
719 ata
->param
= 0xF; // PIO data write
722 // ATA IDENTIFY DEVICE
723 ata
->command
= ATA_IDENTIFY_DEVICE
;
725 ata
->cylinder_lo
= 0;
726 ata
->cylinder_hi
= 0;
729 // 3WARE controller can NOT have packet device internally
730 pout("WARNING - NO DEVICE FOUND ON 3WARE CONTROLLER (disk %d)\n", disknum
);
734 ata
->features
= ATA_SMART_ENABLE
;
737 ata
->features
= ATA_SMART_DISABLE
;
740 ata
->features
= ATA_SMART_AUTO_OFFLINE
;
741 // Enable or disable?
742 ata
->sector_count
= select
;
745 ata
->features
= ATA_SMART_AUTOSAVE
;
746 // Enable or disable?
747 ata
->sector_count
= select
;
749 case IMMEDIATE_OFFLINE
:
750 ata
->features
= ATA_SMART_IMMEDIATE_OFFLINE
;
751 // What test type to run?
752 ata
->sector_num
= select
;
755 ata
->features
= ATA_SMART_STATUS
;
758 // This is JUST to see if SMART is enabled, by giving SMART status
759 // command. But it doesn't say if status was good, or failing.
760 // See below for the difference.
761 ata
->features
= ATA_SMART_STATUS
;
764 pout("Unrecognized command %d in freebsd_3ware_command_interface(disk %d)\n"
765 "Please contact " PACKAGE_BUGREPORT
"\n", command
, disknum
);
770 // Now send the command down through an ioctl()
771 if (escalade_type
==CONTROLLER_3WARE_9000_CHAR
) {
773 ioctlreturn
=ioctl(con
->device
,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH
,cmd_twa
);
775 ioctlreturn
=ioctl(con
->atacommand
,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH
,cmd_twa
);
779 ioctlreturn
=ioctl(con
->device
,TWEIO_COMMAND
,cmd_twe
);
781 ioctlreturn
=ioctl(con
->atacommand
,TWEIO_COMMAND
,cmd_twe
);
785 // Deal with the different error cases
792 // See if the ATA command failed. Now that we have returned from
793 // the ioctl() call, if passthru is valid, then:
794 // - ata->status contains the 3ware controller STATUS
795 // - ata->command contains the ATA STATUS register
796 // - ata->features contains the ATA ERROR register
798 // Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS
799 // If bit 0 (error bit) is set, then ATA ERROR register is valid.
800 // While we *might* decode the ATA ERROR register, at the moment it
801 // doesn't make much sense: we don't care in detail why the error
804 if (ata
->status
|| (ata
->command
& 0x21)) {
805 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
);
810 // If this is a read data command, copy data to output buffer
812 if (escalade_type
==CONTROLLER_3WARE_9000_CHAR
)
813 memcpy(data
, cmd_twa
->pdata
, 512);
816 // For STATUS_CHECK, we need to check register values
817 if (command
==STATUS_CHECK
) {
819 // To find out if the SMART RETURN STATUS is good or failing, we
820 // need to examine the values of the Cylinder Low and Cylinder
823 unsigned short cyl_lo
=ata
->cylinder_lo
;
824 unsigned short cyl_hi
=ata
->cylinder_hi
;
826 // If values in Cyl-LO and Cyl-HI are unchanged, SMART status is good.
827 if (cyl_lo
==0x4F && cyl_hi
==0xC2)
830 // If values in Cyl-LO and Cyl-HI are as follows, SMART status is FAIL
831 if (cyl_lo
==0xF4 && cyl_hi
==0x2C)
838 // copy sector count register (one byte!) to return data
839 if (command
==CHECK_POWER_MODE
)
840 *data
=*(char *)&(ata
->sector_count
);
842 // look for nonexistent devices/ports
843 if (command
==IDENTIFY
&& !nonempty((unsigned char *)data
, 512)) {
851 static int get_tw_channel_unit (const char* name
, int* unit
, int* dev
) {
854 /* device node sanity check */
855 for (p
= name
+ 3; *p
; p
++)
856 if (*p
< '0' || *p
> '9')
858 if (strlen(name
) > 4 && *(name
+ 3) == '0')
864 /* no need for unit number */
871 #ifndef IOCATAREQUEST
872 static int get_ata_channel_unit ( const char* name
, int* unit
, int* dev
) {
878 // there is no direct correlation between name 'ad0, ad1, ...' and
879 // channel/unit number. So we need to iterate through the possible
880 // channels and check each unit to see if we match names
881 struct ata_cmd iocmd
;
884 bzero(&iocmd
, sizeof(struct ata_cmd
));
886 if ((fd
= open("/dev/ata", O_RDWR
)) < 0)
889 iocmd
.cmd
= ATAGMAXCHANNEL
;
890 if (ioctl(fd
, IOCATA
, &iocmd
) < 0) {
894 maxunit
= iocmd
.u
.maxchan
;
895 for (*unit
= 0; *unit
< maxunit
; (*unit
)++) {
896 iocmd
.channel
= *unit
;
898 iocmd
.cmd
= ATAGPARM
;
899 if (ioctl(fd
, IOCATA
, &iocmd
) < 0) {
903 if (iocmd
.u
.param
.type
[0] && !strcmp(name
,iocmd
.u
.param
.name
[0])) {
907 if (iocmd
.u
.param
.type
[1] && !strcmp(name
,iocmd
.u
.param
.name
[1])) {
913 if (*unit
== maxunit
)
921 // Guess device type (ata or scsi) based on device name (FreeBSD
922 // specific) SCSI device name in FreeBSD can be sd, sr, scd, st, nst,
923 // osst, nosst and sg.
924 static const char * fbsd_dev_prefix
= "/dev/";
925 static const char * fbsd_dev_ata_disk_prefix
= "ad";
926 static const char * fbsd_dev_scsi_disk_plus
= "da";
927 static const char * fbsd_dev_scsi_tape1
= "sa";
928 static const char * fbsd_dev_scsi_tape2
= "nsa";
929 static const char * fbsd_dev_scsi_tape3
= "esa";
930 static const char * fbsd_dev_twe_ctrl
= "twe";
931 static const char * fbsd_dev_twa_ctrl
= "twa";
932 static const char * fbsd_dev_cciss
= "ciss";
934 static int parse_ata_chan_dev(const char * dev_name
, struct freebsd_dev_channel
*chan
) {
936 int dev_prefix_len
= strlen(fbsd_dev_prefix
);
938 // if dev_name null, or string length zero
939 if (!dev_name
|| !(len
= strlen(dev_name
)))
940 return CONTROLLER_UNKNOWN
;
942 // Remove the leading /dev/... if it's there
943 if (!strncmp(fbsd_dev_prefix
, dev_name
, dev_prefix_len
)) {
944 if (len
<= dev_prefix_len
)
945 // if nothing else in the string, unrecognized
946 return CONTROLLER_UNKNOWN
;
947 // else advance pointer to following characters
948 dev_name
+= dev_prefix_len
;
950 // form /dev/ad* or ad*
951 if (!strncmp(fbsd_dev_ata_disk_prefix
, dev_name
,
952 strlen(fbsd_dev_ata_disk_prefix
))) {
953 #ifndef IOCATAREQUEST
955 if (get_ata_channel_unit(dev_name
,&(chan
->channel
),&(chan
->device
))<0) {
956 return CONTROLLER_UNKNOWN
;
960 return CONTROLLER_ATA
;
963 // form /dev/da* or da*
964 if (!strncmp(fbsd_dev_scsi_disk_plus
, dev_name
,
965 strlen(fbsd_dev_scsi_disk_plus
)))
968 // form /dev/sa* or sa*
969 if (!strncmp(fbsd_dev_scsi_tape1
, dev_name
,
970 strlen(fbsd_dev_scsi_tape1
)))
973 // form /dev/nsa* or nsa*
974 if (!strncmp(fbsd_dev_scsi_tape2
, dev_name
,
975 strlen(fbsd_dev_scsi_tape2
)))
978 // form /dev/esa* or esa*
979 if (!strncmp(fbsd_dev_scsi_tape3
, dev_name
,
980 strlen(fbsd_dev_scsi_tape3
)))
983 if (!strncmp(fbsd_dev_twa_ctrl
,dev_name
,
984 strlen(fbsd_dev_twa_ctrl
))) {
986 if (get_tw_channel_unit(dev_name
,&(chan
->channel
),&(chan
->device
))<0) {
987 return CONTROLLER_UNKNOWN
;
990 else if (get_tw_channel_unit(dev_name
,NULL
,NULL
)<0) {
991 return CONTROLLER_UNKNOWN
;
993 return CONTROLLER_3WARE_9000_CHAR
;
996 if (!strncmp(fbsd_dev_twe_ctrl
,dev_name
,
997 strlen(fbsd_dev_twe_ctrl
))) {
999 if (get_tw_channel_unit(dev_name
,&(chan
->channel
),&(chan
->device
))<0) {
1000 return CONTROLLER_UNKNOWN
;
1003 else if (get_tw_channel_unit(dev_name
,NULL
,NULL
)<0) {
1004 return CONTROLLER_UNKNOWN
;
1006 return CONTROLLER_3WARE_678K_CHAR
;
1009 if (!strncmp(fbsd_dev_cciss
, dev_name
,
1010 strlen(fbsd_dev_cciss
)))
1011 return CONTROLLER_CCISS
;
1013 // we failed to recognize any of the forms
1014 return CONTROLLER_UNKNOWN
;
1018 if (!(chan
->devname
= (char *)calloc(1,DEV_IDLEN
+1)))
1019 return CONTROLLER_UNKNOWN
;
1021 if (cam_get_device(dev_name
,chan
->devname
,DEV_IDLEN
,&(chan
->unitnum
)) == -1)
1022 return CONTROLLER_UNKNOWN
;
1024 return CONTROLLER_SCSI
;
1028 int guess_device_type (const char* dev_name
) {
1029 return parse_ata_chan_dev(dev_name
,NULL
);
1032 // global variable holding byte count of allocated memory
1033 extern long long bytes
;
1035 // we are going to take advantage of the fact that FreeBSD's devfs will only
1036 // have device entries for devices that exist. So if we get the equivilent of
1037 // ls /dev/ad?, we have all the ATA devices on the system
1039 // If any errors occur, leave errno set as it was returned by the
1040 // system call, and return <0.
1044 // -2 to -5 errors in glob
1046 int get_dev_names(char*** names
, const char* prefix
) {
1052 char pattern1
[128],pattern2
[128];
1054 bzero(&globbuf
,sizeof(globbuf
));
1055 // in case of non-clean exit
1058 // handle 0-99 possible devices, will still be limited by MAX_NUM_DEV
1059 sprintf(pattern1
,"/dev/%s[0-9]",prefix
);
1060 sprintf(pattern2
,"/dev/%s[0-9][0-9]",prefix
);
1062 // Use glob to look for any directory entries matching the patterns
1063 // first call inits with first pattern match, second call appends
1064 // to first list. GLOB_NOCHECK results in no error if no more matches
1065 // found, however it does append the actual pattern to the list of
1067 if ((retglob
=glob(pattern1
, GLOB_ERR
|GLOB_NOCHECK
, NULL
, &globbuf
)) ||
1068 (retglob
=glob(pattern2
, GLOB_ERR
|GLOB_APPEND
|GLOB_NOCHECK
,NULL
,&globbuf
))) {
1071 if (retglob
==GLOB_NOSPACE
)
1072 pout("glob(3) ran out of memory matching patterns (%s),(%s)\n",
1073 pattern1
, pattern2
);
1074 else if (retglob
==GLOB_ABORTED
)
1075 pout("glob(3) aborted matching patterns (%s),(%s)\n",
1076 pattern1
, pattern2
);
1077 else if (retglob
==GLOB_NOMATCH
) {
1078 pout("glob(3) found no matches for patterns (%s),(%s)\n",
1079 pattern1
, pattern2
);
1083 pout("Unexplained error in glob(3) of patterns (%s),(%s)\n",
1084 pattern1
, pattern2
);
1086 // Free memory and return
1092 // did we find too many paths?
1093 lim
= globbuf
.gl_pathc
< MAX_NUM_DEV
? globbuf
.gl_pathc
: MAX_NUM_DEV
;
1094 if (lim
< globbuf
.gl_pathc
)
1095 pout("glob(3) found %d > MAX=%d devices matching patterns (%s),(%s): ignoring %d paths\n",
1096 globbuf
.gl_pathc
, MAX_NUM_DEV
, pattern1
,pattern2
,
1097 globbuf
.gl_pathc
-MAX_NUM_DEV
);
1099 // allocate space for up to lim number of ATA devices
1100 if (!(mp
= (char **)calloc(lim
, sizeof(char*)))){
1101 pout("Out of memory constructing scan device list\n");
1105 // now step through the list returned by glob. No link checking needed
1107 for (i
=0; i
<globbuf
.gl_pathc
; i
++){
1108 // because of the NO_CHECK in calls to glob,
1109 // the pattern itself will be added to path list..
1110 // so ignore any paths that have the ']' from pattern
1111 if (strchr(globbuf
.gl_pathv
[i
],']') == NULL
)
1112 mp
[n
++] = CustomStrDup(globbuf
.gl_pathv
[i
], 1, __LINE__
, filenameandversion
);
1116 mp
= (char **)realloc(mp
,n
*(sizeof(char*))); // shrink to correct size
1117 bytes
+= (n
)*(sizeof(char*)); // and set allocated byte count
1122 int make_device_names (char*** devlist
, const char* name
) {
1123 if (!strcmp(name
,"SCSI"))
1124 return get_dev_names(devlist
,"da");
1125 else if (!strcmp(name
,"ATA"))
1126 return get_dev_names(devlist
,"ad");