mirror of
https://git.freebsd.org/ports.git
synced 2025-07-18 17:59:20 -04:00
- Add optional ciss(4) support, defaults to off
Submitted by: mi
This commit is contained in:
parent
16c71ba0be
commit
d146de2fad
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=186402
6 changed files with 764 additions and 2 deletions
|
@ -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>
|
||||
|
|
172
sysutils/smartmontools-devel/files/ciss-patch
Normal file
172
sysutils/smartmontools-devel/files/ciss-patch
Normal file
|
@ -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
|
197
sysutils/smartmontools-devel/files/ciss_common.c
Normal file
197
sysutils/smartmontools-devel/files/ciss_common.c
Normal file
|
@ -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 */
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
172
sysutils/smartmontools/files/ciss-patch
Normal file
172
sysutils/smartmontools/files/ciss-patch
Normal file
|
@ -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
|
197
sysutils/smartmontools/files/ciss_common.c
Normal file
197
sysutils/smartmontools/files/ciss_common.c
Normal file
|
@ -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 */
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue