diff options
author | pav <pav@FreeBSD.org> | 2007-03-03 21:05:41 +0800 |
---|---|---|
committer | pav <pav@FreeBSD.org> | 2007-03-03 21:05:41 +0800 |
commit | a219498843254bf5e492ae79d4bf6d595618e775 (patch) | |
tree | 25025478ed8c66164bad39e499fc1c5eb5cb2a5b /sysutils | |
parent | 2efd40e1a83bb8a06ac8c79055929e93f94161fb (diff) | |
download | freebsd-ports-gnome-a219498843254bf5e492ae79d4bf6d595618e775.tar.gz freebsd-ports-gnome-a219498843254bf5e492ae79d4bf6d595618e775.tar.zst freebsd-ports-gnome-a219498843254bf5e492ae79d4bf6d595618e775.zip |
- Add optional ciss(4) support, defaults to off
Submitted by: mi
Diffstat (limited to 'sysutils')
-rw-r--r-- | sysutils/smartmontools-devel/Makefile | 14 | ||||
-rw-r--r-- | sysutils/smartmontools-devel/files/ciss-patch | 172 | ||||
-rw-r--r-- | sysutils/smartmontools-devel/files/ciss_common.c | 197 | ||||
-rw-r--r-- | sysutils/smartmontools/Makefile | 14 | ||||
-rw-r--r-- | sysutils/smartmontools/files/ciss-patch | 172 | ||||
-rw-r--r-- | sysutils/smartmontools/files/ciss_common.c | 197 |
6 files changed, 764 insertions, 2 deletions
diff --git a/sysutils/smartmontools-devel/Makefile b/sysutils/smartmontools-devel/Makefile index 189dc559c37e..158c22081338 100644 --- a/sysutils/smartmontools-devel/Makefile +++ b/sysutils/smartmontools-devel/Makefile @@ -25,10 +25,22 @@ USE_RC_SUBR= smartd MAN5= smartd.conf.5 MAN8= smartd.8 smartctl.8 +OPTIONS= CISS "Support ciss(4) -- requires kernel source tree" off + +.include <bsd.port.pre.mk> + +.if defined(WITH_CISS) +. if !exists(/sys/dev/ciss/cissio.h) +IGNORE= built WITH_CISS requires /sys/dev/ciss/cissio.h +. endif +CFLAGS+= -I/sys/dev/ciss -I${FILESDIR} +EXTRA_PATCHES= ${FILESDIR}/ciss-patch +.endif + post-patch: @${REINPLACE_CMD} -e 's| install-initdDATA | |' ${WRKSRC}/Makefile.in post-install: @${CAT} ${PKGMESSAGE} -.include <bsd.port.mk> +.include <bsd.port.post.mk> diff --git a/sysutils/smartmontools-devel/files/ciss-patch b/sysutils/smartmontools-devel/files/ciss-patch new file mode 100644 index 000000000000..1c0e627d39fe --- /dev/null +++ b/sysutils/smartmontools-devel/files/ciss-patch @@ -0,0 +1,172 @@ +--- os_freebsd.cpp Sat Sep 16 23:17:53 2006 ++++ os_freebsd.cpp Sat Mar 3 05:00:36 2007 +@@ -38,4 +39,5 @@ + #include "utility.h" + #include "os_freebsd.h" ++#include "extern.h" + + static const char *filenameandversion="$Id: os_freebsd.cpp,v 1.51 2006/09/17 03:17:53 dpgilbert Exp $"; +@@ -47,4 +49,7 @@ + extern int exitstatus; + ++/* for passing global control variables */ ++extern smartmonctrl *con; ++ + // Private table of open devices: guaranteed zero on startup since + // part of static data. +@@ -86,8 +91,11 @@ + + // Like open(). Return positive integer handle, used by functions below only. mode=="ATA" or "SCSI". +-int deviceopen (const char* dev, char* mode __unused) { ++int deviceopen (const char* dev, char* mode) { + struct freebsd_dev_channel *fdchan; + int parse_ok, i; + ++ if (strcasecmp(mode, "CCISS") == 0) ++ return open(dev, O_RDONLY); ++ + // Search table for a free entry + for (i=0; i<FREEBSD_MAXDEV; i++) +@@ -440,5 +453,6 @@ + + // Interface to SCSI devices. See os_linux.c +-int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report) ++static int ++do_normal_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report) + { + struct freebsd_dev_channel* con = NULL; +@@ -541,4 +555,21 @@ + } + ++#include "ciss_common.c" ++ ++int do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report) ++{ ++ switch(con->controller_type) ++ { ++ case CONTROLLER_CCISS: ++ return cciss_io_interface(dev_fd, con->controller_port-1, iop, report); ++ // not reached ++ break; ++ default: ++ return do_normal_scsi_cmnd_io(dev_fd, iop, report); ++ // not reached ++ break; ++ } ++} ++ + // Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c + +@@ -871,16 +902,17 @@ + // specific) SCSI device name in FreeBSD can be sd, sr, scd, st, nst, + // osst, nosst and sg. +-static const char * fbsd_dev_prefix = "/dev/"; +-static const char * fbsd_dev_ata_disk_prefix = "ad"; +-static const char * fbsd_dev_scsi_disk_plus = "da"; +-static const char * fbsd_dev_scsi_tape1 = "sa"; +-static const char * fbsd_dev_scsi_tape2 = "nsa"; +-static const char * fbsd_dev_scsi_tape3 = "esa"; +-static const char * fbsd_dev_twe_ctrl = "twe"; +-static const char * fbsd_dev_twa_ctrl = "twa"; ++static const char fbsd_dev_prefix[] = "/dev/"; ++static const char fbsd_dev_ata_disk_prefix[] = "ad"; ++static const char fbsd_dev_scsi_disk_plus[] = "da"; ++static const char fbsd_dev_scsi_tape1[] = "sa"; ++static const char fbsd_dev_scsi_tape2[] = "nsa"; ++static const char fbsd_dev_scsi_tape3[] = "esa"; ++static const char fbsd_dev_twe_ctrl[] = "twe"; ++static const char fbsd_dev_twa_ctrl[] = "twa"; ++static const char fbsd_dev_ciss_ctrl[] = "ciss"; + + static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel *chan) { + int len; +- int dev_prefix_len = strlen(fbsd_dev_prefix); ++ int dev_prefix_len = sizeof fbsd_dev_prefix - 1; + + // if dev_name null, or string length zero +@@ -898,5 +930,5 @@ + // form /dev/ad* or ad* + if (!strncmp(fbsd_dev_ata_disk_prefix, dev_name, +- strlen(fbsd_dev_ata_disk_prefix))) { ++ sizeof fbsd_dev_ata_disk_prefix - 1)) { + #ifndef IOCATAREQUEST + if (chan != NULL) { +@@ -911,24 +943,24 @@ + // form /dev/da* or da* + if (!strncmp(fbsd_dev_scsi_disk_plus, dev_name, +- strlen(fbsd_dev_scsi_disk_plus))) ++ sizeof fbsd_dev_scsi_disk_plus - 1)) + goto handlescsi; + + // form /dev/sa* or sa* + if (!strncmp(fbsd_dev_scsi_tape1, dev_name, +- strlen(fbsd_dev_scsi_tape1))) ++ sizeof fbsd_dev_scsi_tape1 - 1)) + goto handlescsi; + + // form /dev/nsa* or nsa* + if (!strncmp(fbsd_dev_scsi_tape2, dev_name, +- strlen(fbsd_dev_scsi_tape2))) ++ sizeof fbsd_dev_scsi_tape2 - 1)) + goto handlescsi; + + // form /dev/esa* or esa* + if (!strncmp(fbsd_dev_scsi_tape3, dev_name, +- strlen(fbsd_dev_scsi_tape3))) ++ sizeof fbsd_dev_scsi_tape3 - 1)) + goto handlescsi; + + if (!strncmp(fbsd_dev_twa_ctrl,dev_name, +- strlen(fbsd_dev_twa_ctrl))) { ++ sizeof fbsd_dev_twa_ctrl - 1)) { + if (chan != NULL) { + if (get_tw_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) { +@@ -943,5 +975,5 @@ + + if (!strncmp(fbsd_dev_twe_ctrl,dev_name, +- strlen(fbsd_dev_twe_ctrl))) { ++ sizeof fbsd_dev_twe_ctrl - 1)) { + if (chan != NULL) { + if (get_tw_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) { +@@ -953,4 +985,13 @@ + } + return CONTROLLER_3WARE_678K_CHAR; ++ } ++ // form /dev/esa* or esa* ++ if (!strncmp(fbsd_dev_ciss_ctrl, dev_name, ++ sizeof fbsd_dev_ciss_ctrl - 1)) { ++ // This is of dubious value, as the desired disk's (unit's) number ++ // still must be specified explicitly with the `-d' option ++ warnx("Use the `-d' option to access drives behind %s. " ++ "See smartctl(8) manual page.", dev_name); ++ return CONTROLLER_CCISS; + } + +--- smartctl.8.in Wed Dec 20 02:30:43 2006 ++++ smartctl.8.in Sat Mar 3 05:22:28 2007 +@@ -303,5 +303,5 @@ + .B HighPoint RocketRAID controllers are currently ONLY supported under Linux. + +-.B cciss controllers are currently ONLY supported under Linux. ++.B cciss controllers are currently ONLY supported under Linux and FreeBSD. + + .TP +@@ -1257,7 +1257,7 @@ + .PP + .nf +-.B smartctl \-a \-d cciss,0 /dev/cciss/c0d0 ++.B smartctl \-a \-d cciss,0 /dev/ciss0 + .fi +-Examine all SMART data for the first SCSI disk connected to a cciss ++Examine all SMART data for the first SCSI disk connected to the first ciss + RAID controller card. + .PP +--- smartd.8.in Wed Dec 20 02:30:43 2006 ++++ smartd.8.in Sat Mar 3 05:24:51 2007 +@@ -717,5 +717,5 @@ + with XX in the range from 00 to 15 inclusive. + +-.B 3ware and cciss controllers are currently ONLY supported under Linux. ++.B 3ware and cciss controllers are currently ONLY supported under Linux and FreeBSD. + + .I hpt,L/M/N diff --git a/sysutils/smartmontools-devel/files/ciss_common.c b/sysutils/smartmontools-devel/files/ciss_common.c new file mode 100644 index 000000000000..80dfaf812cf0 --- /dev/null +++ b/sysutils/smartmontools-devel/files/ciss_common.c @@ -0,0 +1,197 @@ +/* + * This bits are ripped almost verbatim from os_linux.cpp to allow + * FreeBSD, which has the same ciss-ioctls as Linux, to access + * individual drives behind ciss(4) controllers. + * Authors of smartmontools may wish to make this code shared between + * *BSD and Linux, but * currently it remains a duplicate. + * + * Mikhail T. <mi@aldan.algebra.com> + */ + +/* + * This header is not currently installed under /usr/include. Thus + * having a kernel source tree is required to compile this file. Use: + * + * -I/sys/dev/ciss + * + * to build. Rather unfortunate... + */ +#include <cissio.h> + +#define SEND_IOCTL_RESP_SENSE_LEN 16 /* ioctl limitation */ +#define LSCSI_DRIVER_SENSE 0x8 /* alternate CHECK CONDITION indication */ + +static int cciss_io_interface(int device, int target, + struct scsi_cmnd_io * iop, int report); + +typedef int8_t BYTE; /* some kind of Linuxism? */ +typedef uint32_t DWORD; + +typedef struct _ReportLUNdata_struct +{ + BYTE LUNListLength[4]; + DWORD reserved; + BYTE LUN[CISS_MAX_LUN][8]; +} ReportLunData_struct; + +/* Structure/defines of Report Physical LUNS of drive */ +#define CISS_MAX_LUN 16 +#define CISS_MAX_PHYS_LUN 1024 +#define CISS_REPORT_PHYS 0xc3 + +// CCISS Smart Array Controller +static int cciss_sendpassthru(unsigned int cmdtype, unsigned char *CDB, + unsigned int CDBlen, char *buff, + unsigned int size, unsigned int LunID, + unsigned char *scsi3addr, int fd) +{ + int err ; + IOCTL_Command_struct iocommand; + + memset(&iocommand, 0, sizeof(iocommand)); + + if (cmdtype == 0) + { + // To controller; nothing to do + } + else if (cmdtype == 1) + { + iocommand.LUN_info.LogDev.VolId = LunID; + iocommand.LUN_info.LogDev.Mode = 1; + } + else if (cmdtype == 2) + { + memcpy(&iocommand.LUN_info.LunAddrBytes,scsi3addr,8); + iocommand.LUN_info.LogDev.Mode = 0; + } + else + { + fprintf(stderr, "cciss_sendpassthru: bad cmdtype\n"); + return 1; + } + + memcpy(&iocommand.Request.CDB[0], CDB, CDBlen); + iocommand.Request.CDBLen = CDBlen; + iocommand.Request.Type.Type = TYPE_CMD; + iocommand.Request.Type.Attribute = ATTR_SIMPLE; + iocommand.Request.Type.Direction = XFER_READ; + iocommand.Request.Timeout = 0; + + iocommand.buf_size = size; + iocommand.buf = (unsigned char *)buff; + + if ((err = ioctl(fd, CCISS_PASSTHRU, &iocommand))) + { + perror("CCISS ioctl error"); + } + return err; +} + +static int cciss_getlun(int device, int target, unsigned char *physlun) +{ + unsigned char CDB[16]= {0}; + ReportLunData_struct *luns; + int reportlunsize = sizeof(*luns) + CISS_MAX_PHYS_LUN * 8; + int i; + int ret; + + luns = (ReportLunData_struct *)malloc(reportlunsize); + + memset(luns, 0, reportlunsize); + + /* Get Physical LUN Info (for physical device) */ + CDB[0] = CISS_REPORT_PHYS; + CDB[6] = (reportlunsize >> 24) & 0xFF; /* MSB */ + CDB[7] = (reportlunsize >> 16) & 0xFF; + CDB[8] = (reportlunsize >> 8) & 0xFF; + CDB[9] = reportlunsize & 0xFF; + + if ((ret = cciss_sendpassthru(0, CDB, 12, (char *)luns, reportlunsize, 0, NULL, device))) + { + free(luns); + return ret; + } + + for (i=0; i<CISS_MAX_LUN+1; i++) + { + if (luns->LUN[i][6] == target) + { + memcpy(physlun, luns->LUN[i], 8); + free(luns); + return 0; + } + } + + free(luns); + return ret; +} +// end CCISS Smart Array Controller + +/* cciss >> CCSISS I/O passthrough + This is an interface that uses the cciss passthrough to talk to the SMART controller on + the HP system. The cciss driver provides a way to send SCSI cmds through the CCISS passthrough + essentially the methods above and below pertain to SCSI, except for the SG driver which is not + involved. The CCISS driver does not engage the scsi subsystem. */ + static int cciss_io_interface(int device, int target, struct scsi_cmnd_io * iop, int report) + { + unsigned char pBuf[512] = {0}; + unsigned char phylun[1024] = {0}; + int iBufLen = 512; + int status = -1; + int len = 0; // used later in the code. + report = 0; + + cciss_getlun(device, target, phylun); + status = cciss_sendpassthru( 2, iop->cmnd, iop->cmnd_len, (char*) pBuf, iBufLen, 1, phylun, device); + + if (0 == status) + { + if (report > 0) + printf(" status=0\n"); + if (DXFER_FROM_DEVICE == iop->dxfer_dir) + { + memcpy(iop->dxferp, pBuf, iop->dxfer_len); + if (report > 1) + { + int trunc = (iop->dxfer_len > 256) ? 1 : 0; + printf(" Incoming data, len=%d%s:\n", (int)iop->dxfer_len, + (trunc ? " [only first 256 bytes shown]" : "")); + dStrHex((const char*)iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1); + } + } + return 0; + } + iop->scsi_status = status & 0x7e; /* bits 0 and 7 used to be for vendors */ + if (LSCSI_DRIVER_SENSE == ((status >> 24) & 0xf)) + iop->scsi_status = SCSI_STATUS_CHECK_CONDITION; + len = (SEND_IOCTL_RESP_SENSE_LEN < iop->max_sense_len) ? + SEND_IOCTL_RESP_SENSE_LEN : iop->max_sense_len; + if ((SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) && + iop->sensep && (len > 0)) + { + memcpy(iop->sensep, pBuf, len); + iop->resp_sense_len = iBufLen; + if (report > 1) + { + printf(" >>> Sense buffer, len=%d:\n", (int)len); + dStrHex((const char *)pBuf, len , 1); + } + } + if (report) + { + if (SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) { + printf(" status=%x: sense_key=%x asc=%x ascq=%x\n", status & 0xff, + pBuf[2] & 0xf, pBuf[12], pBuf[13]); + } + else + printf(" status=0x%x\n", status); + } + if (iop->scsi_status > 0) + return 0; + else + { + if (report > 0) + printf(" ioctl status=0x%x but scsi status=0, fail with EIO\n", status); + return -EIO; /* give up, assume no device there */ + } + } diff --git a/sysutils/smartmontools/Makefile b/sysutils/smartmontools/Makefile index 189dc559c37e..158c22081338 100644 --- a/sysutils/smartmontools/Makefile +++ b/sysutils/smartmontools/Makefile @@ -25,10 +25,22 @@ USE_RC_SUBR= smartd MAN5= smartd.conf.5 MAN8= smartd.8 smartctl.8 +OPTIONS= CISS "Support ciss(4) -- requires kernel source tree" off + +.include <bsd.port.pre.mk> + +.if defined(WITH_CISS) +. if !exists(/sys/dev/ciss/cissio.h) +IGNORE= built WITH_CISS requires /sys/dev/ciss/cissio.h +. endif +CFLAGS+= -I/sys/dev/ciss -I${FILESDIR} +EXTRA_PATCHES= ${FILESDIR}/ciss-patch +.endif + post-patch: @${REINPLACE_CMD} -e 's| install-initdDATA | |' ${WRKSRC}/Makefile.in post-install: @${CAT} ${PKGMESSAGE} -.include <bsd.port.mk> +.include <bsd.port.post.mk> diff --git a/sysutils/smartmontools/files/ciss-patch b/sysutils/smartmontools/files/ciss-patch new file mode 100644 index 000000000000..1c0e627d39fe --- /dev/null +++ b/sysutils/smartmontools/files/ciss-patch @@ -0,0 +1,172 @@ +--- os_freebsd.cpp Sat Sep 16 23:17:53 2006 ++++ os_freebsd.cpp Sat Mar 3 05:00:36 2007 +@@ -38,4 +39,5 @@ + #include "utility.h" + #include "os_freebsd.h" ++#include "extern.h" + + static const char *filenameandversion="$Id: os_freebsd.cpp,v 1.51 2006/09/17 03:17:53 dpgilbert Exp $"; +@@ -47,4 +49,7 @@ + extern int exitstatus; + ++/* for passing global control variables */ ++extern smartmonctrl *con; ++ + // Private table of open devices: guaranteed zero on startup since + // part of static data. +@@ -86,8 +91,11 @@ + + // Like open(). Return positive integer handle, used by functions below only. mode=="ATA" or "SCSI". +-int deviceopen (const char* dev, char* mode __unused) { ++int deviceopen (const char* dev, char* mode) { + struct freebsd_dev_channel *fdchan; + int parse_ok, i; + ++ if (strcasecmp(mode, "CCISS") == 0) ++ return open(dev, O_RDONLY); ++ + // Search table for a free entry + for (i=0; i<FREEBSD_MAXDEV; i++) +@@ -440,5 +453,6 @@ + + // Interface to SCSI devices. See os_linux.c +-int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report) ++static int ++do_normal_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report) + { + struct freebsd_dev_channel* con = NULL; +@@ -541,4 +555,21 @@ + } + ++#include "ciss_common.c" ++ ++int do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report) ++{ ++ switch(con->controller_type) ++ { ++ case CONTROLLER_CCISS: ++ return cciss_io_interface(dev_fd, con->controller_port-1, iop, report); ++ // not reached ++ break; ++ default: ++ return do_normal_scsi_cmnd_io(dev_fd, iop, report); ++ // not reached ++ break; ++ } ++} ++ + // Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c + +@@ -871,16 +902,17 @@ + // specific) SCSI device name in FreeBSD can be sd, sr, scd, st, nst, + // osst, nosst and sg. +-static const char * fbsd_dev_prefix = "/dev/"; +-static const char * fbsd_dev_ata_disk_prefix = "ad"; +-static const char * fbsd_dev_scsi_disk_plus = "da"; +-static const char * fbsd_dev_scsi_tape1 = "sa"; +-static const char * fbsd_dev_scsi_tape2 = "nsa"; +-static const char * fbsd_dev_scsi_tape3 = "esa"; +-static const char * fbsd_dev_twe_ctrl = "twe"; +-static const char * fbsd_dev_twa_ctrl = "twa"; ++static const char fbsd_dev_prefix[] = "/dev/"; ++static const char fbsd_dev_ata_disk_prefix[] = "ad"; ++static const char fbsd_dev_scsi_disk_plus[] = "da"; ++static const char fbsd_dev_scsi_tape1[] = "sa"; ++static const char fbsd_dev_scsi_tape2[] = "nsa"; ++static const char fbsd_dev_scsi_tape3[] = "esa"; ++static const char fbsd_dev_twe_ctrl[] = "twe"; ++static const char fbsd_dev_twa_ctrl[] = "twa"; ++static const char fbsd_dev_ciss_ctrl[] = "ciss"; + + static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel *chan) { + int len; +- int dev_prefix_len = strlen(fbsd_dev_prefix); ++ int dev_prefix_len = sizeof fbsd_dev_prefix - 1; + + // if dev_name null, or string length zero +@@ -898,5 +930,5 @@ + // form /dev/ad* or ad* + if (!strncmp(fbsd_dev_ata_disk_prefix, dev_name, +- strlen(fbsd_dev_ata_disk_prefix))) { ++ sizeof fbsd_dev_ata_disk_prefix - 1)) { + #ifndef IOCATAREQUEST + if (chan != NULL) { +@@ -911,24 +943,24 @@ + // form /dev/da* or da* + if (!strncmp(fbsd_dev_scsi_disk_plus, dev_name, +- strlen(fbsd_dev_scsi_disk_plus))) ++ sizeof fbsd_dev_scsi_disk_plus - 1)) + goto handlescsi; + + // form /dev/sa* or sa* + if (!strncmp(fbsd_dev_scsi_tape1, dev_name, +- strlen(fbsd_dev_scsi_tape1))) ++ sizeof fbsd_dev_scsi_tape1 - 1)) + goto handlescsi; + + // form /dev/nsa* or nsa* + if (!strncmp(fbsd_dev_scsi_tape2, dev_name, +- strlen(fbsd_dev_scsi_tape2))) ++ sizeof fbsd_dev_scsi_tape2 - 1)) + goto handlescsi; + + // form /dev/esa* or esa* + if (!strncmp(fbsd_dev_scsi_tape3, dev_name, +- strlen(fbsd_dev_scsi_tape3))) ++ sizeof fbsd_dev_scsi_tape3 - 1)) + goto handlescsi; + + if (!strncmp(fbsd_dev_twa_ctrl,dev_name, +- strlen(fbsd_dev_twa_ctrl))) { ++ sizeof fbsd_dev_twa_ctrl - 1)) { + if (chan != NULL) { + if (get_tw_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) { +@@ -943,5 +975,5 @@ + + if (!strncmp(fbsd_dev_twe_ctrl,dev_name, +- strlen(fbsd_dev_twe_ctrl))) { ++ sizeof fbsd_dev_twe_ctrl - 1)) { + if (chan != NULL) { + if (get_tw_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) { +@@ -953,4 +985,13 @@ + } + return CONTROLLER_3WARE_678K_CHAR; ++ } ++ // form /dev/esa* or esa* ++ if (!strncmp(fbsd_dev_ciss_ctrl, dev_name, ++ sizeof fbsd_dev_ciss_ctrl - 1)) { ++ // This is of dubious value, as the desired disk's (unit's) number ++ // still must be specified explicitly with the `-d' option ++ warnx("Use the `-d' option to access drives behind %s. " ++ "See smartctl(8) manual page.", dev_name); ++ return CONTROLLER_CCISS; + } + +--- smartctl.8.in Wed Dec 20 02:30:43 2006 ++++ smartctl.8.in Sat Mar 3 05:22:28 2007 +@@ -303,5 +303,5 @@ + .B HighPoint RocketRAID controllers are currently ONLY supported under Linux. + +-.B cciss controllers are currently ONLY supported under Linux. ++.B cciss controllers are currently ONLY supported under Linux and FreeBSD. + + .TP +@@ -1257,7 +1257,7 @@ + .PP + .nf +-.B smartctl \-a \-d cciss,0 /dev/cciss/c0d0 ++.B smartctl \-a \-d cciss,0 /dev/ciss0 + .fi +-Examine all SMART data for the first SCSI disk connected to a cciss ++Examine all SMART data for the first SCSI disk connected to the first ciss + RAID controller card. + .PP +--- smartd.8.in Wed Dec 20 02:30:43 2006 ++++ smartd.8.in Sat Mar 3 05:24:51 2007 +@@ -717,5 +717,5 @@ + with XX in the range from 00 to 15 inclusive. + +-.B 3ware and cciss controllers are currently ONLY supported under Linux. ++.B 3ware and cciss controllers are currently ONLY supported under Linux and FreeBSD. + + .I hpt,L/M/N diff --git a/sysutils/smartmontools/files/ciss_common.c b/sysutils/smartmontools/files/ciss_common.c new file mode 100644 index 000000000000..80dfaf812cf0 --- /dev/null +++ b/sysutils/smartmontools/files/ciss_common.c @@ -0,0 +1,197 @@ +/* + * This bits are ripped almost verbatim from os_linux.cpp to allow + * FreeBSD, which has the same ciss-ioctls as Linux, to access + * individual drives behind ciss(4) controllers. + * Authors of smartmontools may wish to make this code shared between + * *BSD and Linux, but * currently it remains a duplicate. + * + * Mikhail T. <mi@aldan.algebra.com> + */ + +/* + * This header is not currently installed under /usr/include. Thus + * having a kernel source tree is required to compile this file. Use: + * + * -I/sys/dev/ciss + * + * to build. Rather unfortunate... + */ +#include <cissio.h> + +#define SEND_IOCTL_RESP_SENSE_LEN 16 /* ioctl limitation */ +#define LSCSI_DRIVER_SENSE 0x8 /* alternate CHECK CONDITION indication */ + +static int cciss_io_interface(int device, int target, + struct scsi_cmnd_io * iop, int report); + +typedef int8_t BYTE; /* some kind of Linuxism? */ +typedef uint32_t DWORD; + +typedef struct _ReportLUNdata_struct +{ + BYTE LUNListLength[4]; + DWORD reserved; + BYTE LUN[CISS_MAX_LUN][8]; +} ReportLunData_struct; + +/* Structure/defines of Report Physical LUNS of drive */ +#define CISS_MAX_LUN 16 +#define CISS_MAX_PHYS_LUN 1024 +#define CISS_REPORT_PHYS 0xc3 + +// CCISS Smart Array Controller +static int cciss_sendpassthru(unsigned int cmdtype, unsigned char *CDB, + unsigned int CDBlen, char *buff, + unsigned int size, unsigned int LunID, + unsigned char *scsi3addr, int fd) +{ + int err ; + IOCTL_Command_struct iocommand; + + memset(&iocommand, 0, sizeof(iocommand)); + + if (cmdtype == 0) + { + // To controller; nothing to do + } + else if (cmdtype == 1) + { + iocommand.LUN_info.LogDev.VolId = LunID; + iocommand.LUN_info.LogDev.Mode = 1; + } + else if (cmdtype == 2) + { + memcpy(&iocommand.LUN_info.LunAddrBytes,scsi3addr,8); + iocommand.LUN_info.LogDev.Mode = 0; + } + else + { + fprintf(stderr, "cciss_sendpassthru: bad cmdtype\n"); + return 1; + } + + memcpy(&iocommand.Request.CDB[0], CDB, CDBlen); + iocommand.Request.CDBLen = CDBlen; + iocommand.Request.Type.Type = TYPE_CMD; + iocommand.Request.Type.Attribute = ATTR_SIMPLE; + iocommand.Request.Type.Direction = XFER_READ; + iocommand.Request.Timeout = 0; + + iocommand.buf_size = size; + iocommand.buf = (unsigned char *)buff; + + if ((err = ioctl(fd, CCISS_PASSTHRU, &iocommand))) + { + perror("CCISS ioctl error"); + } + return err; +} + +static int cciss_getlun(int device, int target, unsigned char *physlun) +{ + unsigned char CDB[16]= {0}; + ReportLunData_struct *luns; + int reportlunsize = sizeof(*luns) + CISS_MAX_PHYS_LUN * 8; + int i; + int ret; + + luns = (ReportLunData_struct *)malloc(reportlunsize); + + memset(luns, 0, reportlunsize); + + /* Get Physical LUN Info (for physical device) */ + CDB[0] = CISS_REPORT_PHYS; + CDB[6] = (reportlunsize >> 24) & 0xFF; /* MSB */ + CDB[7] = (reportlunsize >> 16) & 0xFF; + CDB[8] = (reportlunsize >> 8) & 0xFF; + CDB[9] = reportlunsize & 0xFF; + + if ((ret = cciss_sendpassthru(0, CDB, 12, (char *)luns, reportlunsize, 0, NULL, device))) + { + free(luns); + return ret; + } + + for (i=0; i<CISS_MAX_LUN+1; i++) + { + if (luns->LUN[i][6] == target) + { + memcpy(physlun, luns->LUN[i], 8); + free(luns); + return 0; + } + } + + free(luns); + return ret; +} +// end CCISS Smart Array Controller + +/* cciss >> CCSISS I/O passthrough + This is an interface that uses the cciss passthrough to talk to the SMART controller on + the HP system. The cciss driver provides a way to send SCSI cmds through the CCISS passthrough + essentially the methods above and below pertain to SCSI, except for the SG driver which is not + involved. The CCISS driver does not engage the scsi subsystem. */ + static int cciss_io_interface(int device, int target, struct scsi_cmnd_io * iop, int report) + { + unsigned char pBuf[512] = {0}; + unsigned char phylun[1024] = {0}; + int iBufLen = 512; + int status = -1; + int len = 0; // used later in the code. + report = 0; + + cciss_getlun(device, target, phylun); + status = cciss_sendpassthru( 2, iop->cmnd, iop->cmnd_len, (char*) pBuf, iBufLen, 1, phylun, device); + + if (0 == status) + { + if (report > 0) + printf(" status=0\n"); + if (DXFER_FROM_DEVICE == iop->dxfer_dir) + { + memcpy(iop->dxferp, pBuf, iop->dxfer_len); + if (report > 1) + { + int trunc = (iop->dxfer_len > 256) ? 1 : 0; + printf(" Incoming data, len=%d%s:\n", (int)iop->dxfer_len, + (trunc ? " [only first 256 bytes shown]" : "")); + dStrHex((const char*)iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1); + } + } + return 0; + } + iop->scsi_status = status & 0x7e; /* bits 0 and 7 used to be for vendors */ + if (LSCSI_DRIVER_SENSE == ((status >> 24) & 0xf)) + iop->scsi_status = SCSI_STATUS_CHECK_CONDITION; + len = (SEND_IOCTL_RESP_SENSE_LEN < iop->max_sense_len) ? + SEND_IOCTL_RESP_SENSE_LEN : iop->max_sense_len; + if ((SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) && + iop->sensep && (len > 0)) + { + memcpy(iop->sensep, pBuf, len); + iop->resp_sense_len = iBufLen; + if (report > 1) + { + printf(" >>> Sense buffer, len=%d:\n", (int)len); + dStrHex((const char *)pBuf, len , 1); + } + } + if (report) + { + if (SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) { + printf(" status=%x: sense_key=%x asc=%x ascq=%x\n", status & 0xff, + pBuf[2] & 0xf, pBuf[12], pBuf[13]); + } + else + printf(" status=0x%x\n", status); + } + if (iop->scsi_status > 0) + return 0; + else + { + if (report > 0) + printf(" ioctl status=0x%x but scsi status=0, fail with EIO\n", status); + return -EIO; /* give up, assume no device there */ + } + } |