#! /bin/sh /usr/share/dpatch/dpatch-run ## 60_cciss.dpatch.dpatch by ## Praveen Chidambaram ## Douglas Gilbert ## Guido Guenther ## Frédéric BOITEUX ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: add support for Compaq/HP CCISS controllers @DPATCH@ diff -urNad smartmontools-cvs~/os_linux.cpp smartmontools-cvs/os_linux.cpp --- smartmontools-cvs~/os_linux.cpp 2006-10-02 17:34:50.000000000 +0200 +++ smartmontools-cvs/os_linux.cpp 2006-10-02 17:38:35.000000000 +0200 @@ -66,12 +66,17 @@ #include "os_linux.h" #include "scsicmds.h" #include "utility.h" +#include "extern.h" + +#include + #ifndef ENOTSUP #define ENOTSUP ENOSYS #endif typedef unsigned long long u8; + #define ARGUSED(x) ((void)(x)) static const char *filenameandversion="$Id: os_linux.cpp,v 1.86 2006/09/12 01:16:54 sxzzsf Exp $"; @@ -85,6 +90,23 @@ // global variable holding byte count of allocated memory extern long long bytes; +/* for passing global control variables */ +extern smartmonctrl *con; + +static int cciss_io_interface(int device, int target, + struct scsi_cmnd_io * iop, int report); + +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 /* This function will setup and fix device nodes for a 3ware controller. */ @@ -193,8 +215,13 @@ } return open(pathname, O_RDONLY | O_NONBLOCK); } + else if(!strcmp(type, "CCISS")) { + // the device is a cciss smart array device. + return open(pathname, O_RDWR | O_NONBLOCK); + } else return -1; + } // equivalent to close(file descriptor) @@ -618,6 +645,94 @@ return 0; } +// 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))) + { + fprintf(stderr, "CCISS ioctl error %d\n", err); + } + 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; iLUN[i][6] == target) + { + memcpy(physlun, luns->LUN[i], 8); + free(luns); + return 0; + } + } + + free(luns); + return ret; +} +// end CCISS Smart Array Controller + // >>>>>> Start of general SCSI specific linux code /* Linux specific code. @@ -926,7 +1041,8 @@ * (e.g. CHECK CONDITION). If the SCSI command could not be issued * (e.g. device not present or timeout) or some other problem * (e.g. timeout) then returns a negative errno value */ -int do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report) +static int do_normal_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, + int report) { int res; @@ -956,8 +1072,94 @@ } } +/* Check and call the right interface. Maybe when the do_generic_scsi_cmd_io interface is better + we can take off this crude way of calling the right interface */ + 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; + } + } + // >>>>>> End of general SCSI specific linux code +/* 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 */ + } + } + // prototype void printwarning(smart_command_set command); @@ -1657,6 +1859,7 @@ static const char * lin_dev_scsi_tape3 = "nos"; static const char * lin_dev_3ware_9000_char = "twa"; static const char * lin_dev_3ware_678k_char = "twe"; +static const char * lin_dev_cciss_dir = "cciss/"; int guess_device_type(const char * dev_name) { int len; @@ -1719,6 +1922,10 @@ if (!strncmp(lin_dev_3ware_678k_char, dev_name, strlen(lin_dev_3ware_678k_char))) return CONTROLLER_3WARE_678K_CHAR; + // form /dev/cciss* + if (!strncmp(lin_dev_cciss_dir, dev_name, + strlen(lin_dev_cciss_dir))) + return CONTROLLER_CCISS; // we failed to recognize any of the forms return CONTROLLER_UNKNOWN; diff -urNad smartmontools-cvs~/smartctl.8.in smartmontools-cvs/smartctl.8.in --- smartmontools-cvs~/smartctl.8.in 2006-10-02 17:34:50.000000000 +0200 +++ smartmontools-cvs/smartctl.8.in 2006-10-02 17:35:17.000000000 +0200 @@ -185,9 +185,9 @@ .TP .B \-d TYPE, \-\-device=TYPE Specifies the type of the device. The valid arguments to this option -are \fIata\fP, \fIscsi\fP, \fIsat\fP, \fImarvell\fP, \fI3ware,N\fP, and \fIhpt,L/M\fP -or \fIhpt,L/M/N\fP. If this option is not used then \fBsmartctl\fP will attempt to -guess the device type from the device name. +are \fIata\fP, \fIscsi\fP, \fIsat\fP, \fImarvell\fP, \fI3ware,N\fP, and \fIhpt,L/M\fP, +\fIcciss,N\fP or \fIhpt,L/M/N\fP. If this option is not used then +\fBsmartctl\fP will attempt to guess the device type from the device name. The \'sat\' device type is for ATA disks that have a SCSI to ATA Translation (SAT) Layer (SATL) between the disk and the operating system. @@ -291,6 +291,8 @@ .B HighPoint RocketRAID controllers are currently ONLY supported under Linux. +.B cciss controllers are currently ONLY supported under Linux. + .TP .B \-T TYPE, \-\-tolerance=TYPE Specifies how tolerant \fBsmartctl\fP should be of ATA and SMART command @@ -1242,6 +1244,12 @@ power\-cycled during the read\-scan, resume the scan 45 minutes after power to the device is restored. .PP +.nf +.B smartctl \-a \-d cciss,0 /dev/cciss/c0d0 +.fi +Examine all SMART data for the first SCSI disk connected to a cciss +RAID controller card. +.PP .SH RETURN VALUES The return values of \fBsmartctl\fP are defined by a bitmask. If all is well with the disk, the return value (exit status) of diff -urNad smartmontools-cvs~/smartctl.cpp smartmontools-cvs/smartctl.cpp --- smartmontools-cvs~/smartctl.cpp 2006-10-02 17:34:50.000000000 +0200 +++ smartmontools-cvs/smartctl.cpp 2006-10-02 17:35:17.000000000 +0200 @@ -239,7 +239,7 @@ case 'q': return "errorsonly, silent"; case 'd': - return "ata, scsi, marvell, sat, 3ware,N, hpt,L/M/N"; + return "ata, scsi, marvell, sat, 3ware,N, hpt,L/M/N cciss,N"; case 'T': return "normal, conservative, permissive, verypermissive"; case 'b': @@ -459,21 +459,35 @@ con->dont_print = FALSE; pout("No memory for argument of -d. Exiting...\n"); exit(FAILCMD); - } else if (strncmp(s,"3ware,",6)) { - badarg = TRUE; - } else if (split_report_arg2(s, &i)) { - sprintf(extraerror, "Option -d 3ware,N requires N to be a non-negative integer\n"); - badarg = TRUE; - } else if (i<0 || i>15) { - sprintf(extraerror, "Option -d 3ware,N (N=%d) must have 0 <= N <= 15\n", i); - badarg = TRUE; - } else { - // NOTE: controller_port == disk number + 1 - con->controller_type = CONTROLLER_3WARE; - con->controller_port = i+1; - } - free(s); - } + } else if (!strncmp(s,"3ware,",6)) { + if (split_report_arg2(s, &i)) { + sprintf(extraerror, "Option -d 3ware,N requires N to be a non-negative integer\n"); + badarg = TRUE; + } else if (i<0 || i>15) { + sprintf(extraerror, "Option -d 3ware,N (N=%d) must have 0 <= N <= 15\n", i); + badarg = TRUE; + } else { + // NOTE: controller_port == disk number + 1 + con->controller_type = CONTROLLER_3WARE; + con->controller_port = i+1; + } + free(s); + } else if (!strncmp(s,"cciss,",6)) { + if (split_report_arg2(s, &i)) { + sprintf(extraerror, "Option -d cciss,N requires N to be a non-negative integer\n"); + badarg = TRUE; + } else if (i<0 || i>15) { + sprintf(extraerror, "Option -d cciss,N (N=%d) must have 0 <= N <= 15\n", i); + badarg = TRUE; + } else { + // NOTE: controller_port == drive number + con->controller_type = CONTROLLER_CCISS; + con->controller_port = i+1; + } + free(s); + } else + badarg=TRUE; + } break; case 'T': if (!strcmp(optarg,"normal")) { @@ -948,6 +962,9 @@ case CONTROLLER_3WARE_678K_CHAR: mode="ATA_3WARE_678K"; break; + case CONTROLLER_CCISS: + mode="CCISS"; + break; default: mode="ATA"; break; @@ -981,6 +998,11 @@ if ((0 == retval) && (CONTROLLER_SAT == con->controller_type)) retval = ataPrintMain(fd); break; + case CONTROLLER_CCISS: + // route the cciss command through scsiPrintMain. + // cciss pass-throughs will separeate from the SCSI data-path. + retval = scsiPrintMain(fd); + break; default: retval = ataPrintMain(fd); break; diff -urNad smartmontools-cvs~/smartd.8.in smartmontools-cvs/smartd.8.in --- smartmontools-cvs~/smartd.8.in 2006-10-02 17:35:16.000000000 +0200 +++ smartmontools-cvs/smartd.8.in 2006-10-02 17:35:17.000000000 +0200 @@ -610,8 +610,8 @@ .B \-d TYPE Specifies the type of the device. This Directive may be used multiple times for one device, but the arguments \fIata\fP, \fIscsi\fP, \fIsat\fP, -\fImarvell\fP, and \fI3ware,N\fP are mutually-exclusive. If more than -one is given then \fBsmartd\fP will use the last one which appears. +\fImarvell\fP, \fIcciss\fP and \fI3ware,N\fP are mutually-exclusive. If more +than one is given then \fBsmartd\fP will use the last one which appears. If none of these three arguments is given, then \fBsmartd\fP will first attempt to guess the device type by looking at whether the sixth @@ -690,8 +690,14 @@ 6/7/8000 series controllers) or /dev/twa0-15 (3ware 9000 series controllers). +.I cciss,N +\- the device consists of one or more SCSI disks connected to a cciss +RAID controller. The non-negative integer N (in the range from 0 to 15 +inclusive) denotes which disk on the controller is monitored. In log +files and email messages this disk will be identified as cciss_disk_XX +with XX in the range from 00 to 15 inclusive. -.B 3ware controllers are currently ONLY supported under Linux. +.B 3ware and cciss controllers are currently ONLY supported under Linux. .I hpt,L/M/N \- the device consists of one or more ATA disks connected to a HighPoint diff -urNad smartmontools-cvs~/smartd.conf.5.in smartmontools-cvs/smartd.conf.5.in --- smartmontools-cvs~/smartd.conf.5.in 2006-10-02 17:34:50.000000000 +0200 +++ smartmontools-cvs/smartd.conf.5.in 2006-10-02 17:35:17.000000000 +0200 @@ -254,8 +254,8 @@ .B \-d TYPE Specifies the type of the device. This Directive may be used multiple times for one device, but the arguments \fIata\fP, \fIscsi\fP, \fIsat\fP, -\fImarvell\fP, and \fI3ware,N\fP are mutually-exclusive. If more than -one is given then \fBsmartd\fP will use the last one which appears. +\fImarvell\fP, \fIcciss,N\fP and \fI3ware,N\fP are mutually-exclusive. If more +than one is given then \fBsmartd\fP will use the last one which appears. If none of these three arguments is given, then \fBsmartd\fP will first attempt to guess the device type by looking at whether the sixth @@ -334,8 +334,14 @@ 6/7/8000 series controllers) or /dev/twa0-15 (3ware 9000 series controllers). +.I cciss,N +\- the device consists of one or more SCSI disks connected to a cciss +RAID controller. The non-negative integer N (in the range from 0 to 15 +inclusive) denotes which disk on the controller is monitored. In log +files and email messages this disk will be identified as cciss_disk_XX +with XX in the range from 00 to 15 inclusive. -.B 3ware controllers are currently ONLY supported under Linux. +.B 3ware and cciss controllers are currently ONLY supported under Linux. .I hpt,L/M/N \- the device consists of one or more ATA disks connected to a HighPoint diff -urNad smartmontools-cvs~/smartd.cpp smartmontools-cvs/smartd.cpp --- smartmontools-cvs~/smartd.cpp 2006-10-02 17:34:50.000000000 +0200 +++ smartmontools-cvs/smartd.cpp 2006-10-02 17:35:17.000000000 +0200 @@ -712,6 +712,18 @@ *s=' '; } break; + case CONTROLLER_CCISS: + { + char *s,devicetype[16]; + sprintf(devicetype, "cciss,%d", cfg->controller_port-1); + exportenv(environ_strings[8], "SMARTD_DEVICETYPE", devicetype); + if ((s=strchr(cfg->name, ' '))) + *s='\0'; + exportenv(environ_strings[9], "SMARTD_DEVICE", cfg->name); + if (s) + *s=' '; + } + break; case CONTROLLER_ATA: exportenv(environ_strings[8], "SMARTD_DEVICETYPE", "ata"); exportenv(environ_strings[9], "SMARTD_DEVICE", cfg->name); @@ -723,9 +735,11 @@ case CONTROLLER_SCSI: exportenv(environ_strings[8], "SMARTD_DEVICETYPE", "scsi"); exportenv(environ_strings[9], "SMARTD_DEVICE", cfg->name); + break; case CONTROLLER_SAT: exportenv(environ_strings[8], "SMARTD_DEVICETYPE", "sat"); exportenv(environ_strings[9], "SMARTD_DEVICE", cfg->name); + break; case CONTROLLER_HPT: { char *s,devicetype[16]; @@ -738,6 +752,7 @@ if (s) *s=' '; } + break; } snprintf(fullmessage, 1024, @@ -1090,7 +1105,7 @@ void Directives() { PrintOut(LOG_INFO, "Configuration file (%s) Directives (after device name):\n" - " -d TYPE Set the device type: ata, scsi, marvell, removable, sat, 3ware,N, hpt,L/M/N\n" + " -d TYPE Set the device type: ata, scsi, marvell, removable, sat, 3ware,N, hpt,L/M/N, cciss,N\n" " -T TYPE Set the tolerance to one of: normal, permissive\n" " -o VAL Enable/disable automatic offline tests (on/off)\n" " -S VAL Enable/disable attribute autosave (on/off)\n" @@ -1638,18 +1653,26 @@ char *device = cfg->name; struct scsi_iec_mode_page iec; UINT8 tBuf[64]; + char *mode=NULL; // should we try to register this as a SCSI device? switch (cfg->controller_type) { case CONTROLLER_SCSI: case CONTROLLER_UNKNOWN: + mode="SCSI"; + break; + case CONTROLLER_CCISS: + mode="CCISS"; break; default: return 1; } + // pass user settings on to low-level SCSI commands + con->controller_port=cfg->controller_port; + con->controller_type=cfg->controller_type; // open the device - if ((fd = OpenDevice(device, "SCSI", scanning)) < 0) + if ((fd = OpenDevice(device, mode, scanning)) < 0) return 1; PrintOut(LOG_INFO,"Device: %s, opened\n", device); @@ -1725,7 +1748,8 @@ } // record type of device - cfg->controller_type = CONTROLLER_SCSI; + if (cfg->controller_type == CONTROLLER_UNKNOWN) + cfg->controller_type = CONTROLLER_SCSI; // get rid of allocated memory only needed for ATA devices. These // might have been allocated if the user specified Ignore options or @@ -2525,6 +2549,24 @@ int fd; char *name=cfg->name; const char *cp; + char *mode=NULL; + + // should we try to register this as a SCSI device? + switch (cfg->controller_type) { + case CONTROLLER_CCISS: + mode="CCISS"; + break; + case CONTROLLER_SCSI: + case CONTROLLER_UNKNOWN: + mode="SCSI"; + break; + default: + return 1; + } + + // pass user settings on to low-level SCSI commands + con->controller_port=cfg->controller_port; + con->controller_type=cfg->controller_type; // If the user has asked for it, test the email warning system if (cfg->mailwarn && cfg->mailwarn->emailtest) @@ -2532,7 +2574,7 @@ // if we can't open device, fail gracefully rather than hard -- // perhaps the next time around we'll be able to open it - if ((fd=OpenDevice(name, "SCSI", 0))<0) { + if ((fd=OpenDevice(name, mode, 0))<0) { // Lack of PrintOut() here is intentional! MailWarning(cfg, 9, "Device: %s, unable to open device", name); return 1; @@ -2993,26 +3035,42 @@ PrintOut(LOG_CRIT, "No memory to copy argument to -d option - exiting\n"); EXIT(EXIT_NOMEM); - } else if (strncmp(s,"3ware,",6)) { - badarg=1; - } else if (split_report_arg2(s, &i)){ - PrintOut(LOG_CRIT, "File %s line %d (drive %s): Directive -d 3ware,N requires N integer\n", - configfile, lineno, name); - badarg=1; - } else if ( i<0 || i>15) { - PrintOut(LOG_CRIT, "File %s line %d (drive %s): Directive -d 3ware,N (N=%d) must have 0 <= N <= 15\n", - configfile, lineno, name, i); - badarg=1; - } else { - // determine type of escalade device from name of device - cfg->controller_type = guess_device_type(name); - if (cfg->controller_type!=CONTROLLER_3WARE_9000_CHAR && cfg->controller_type!=CONTROLLER_3WARE_678K_CHAR) - cfg->controller_type=CONTROLLER_3WARE_678K; + } else if (!strncmp(s,"3ware,",6)) { + if (split_report_arg2(s, &i)){ + PrintOut(LOG_CRIT, "File %s line %d (drive %s): Directive -d 3ware,N requires N integer\n", + configfile, lineno, name); + badarg=1; + } else if ( i<0 || i>15) { + PrintOut(LOG_CRIT, "File %s line %d (drive %s): Directive -d 3ware,N (N=%d) must have 0 <= N <= 15\n", + configfile, lineno, name, i); + badarg=1; + } else { + // determine type of escalade device from name of device + cfg->controller_type = guess_device_type(name); + if (cfg->controller_type!=CONTROLLER_3WARE_9000_CHAR && cfg->controller_type!=CONTROLLER_3WARE_678K_CHAR) + cfg->controller_type=CONTROLLER_3WARE_678K; - // NOTE: controller_port == disk number + 1 - cfg->controller_port = i+1; + // NOTE: controller_port == disk number + 1 + cfg->controller_port = i+1; + } + } else if (!strncmp(s,"cciss,",6)) { + if (split_report_arg2(s, &i)){ + PrintOut(LOG_CRIT, "File %s line %d (drive %s): Directive -d cciss,N requires N integer\n", + configfile, lineno, name); + badarg=1; + } else if ( i<0 || i>15) { + PrintOut(LOG_CRIT, "File %s line %d (drive %s): Directive -d cciss,N (N=%d) must have 0 <= N <= 15\n", + configfile, lineno, name, i); + badarg=1; + } else { + // NOTE: controller_port == disk number + 1 + cfg->controller_type = CONTROLLER_CCISS; + cfg->controller_port = i+1; + } + } else { + badarg=1; } - s=CheckFree(s, __LINE__,filenameandversion); + s=CheckFree(s, __LINE__,filenameandversion); } break; case 'F': @@ -3429,13 +3487,13 @@ } } - // If we found 3ware controller, then modify device name by adding a SPACE - if (cfg->controller_port){ + // If we found 3ware/cciss controller, then modify device name by adding a SPACE + if (cfg->controller_port) { int len=17+strlen(cfg->name); char *newname; if (devscan){ - PrintOut(LOG_CRIT, "smartd: can not scan for 3ware devices (line %d of file %s)\n", + PrintOut(LOG_CRIT, "smartd: can not scan for 3ware/cciss devices (line %d of file %s)\n", lineno, configfile); return -2; } @@ -3446,7 +3504,8 @@ } // Make new device name by adding a space then RAID disk number - snprintf(newname, len, "%s [3ware_disk_%02d]", cfg->name, cfg->controller_port-1); + snprintf(newname, len, "%s [%s_disk_%02d]", cfg->name, (cfg->controller_type == CONTROLLER_CCISS) ? "cciss" : "3ware", + cfg->controller_port-1); cfg->name=CheckFree(cfg->name, __LINE__,filenameandversion); cfg->name=newname; bytes+=16; @@ -4116,7 +4175,7 @@ continue; // register ATA devices - if (ent->controller_type!=CONTROLLER_SCSI){ + if (ent->controller_type!=CONTROLLER_SCSI && ent->controller_type!=CONTROLLER_CCISS){ if (ATADeviceScan(ent, scanning)) CanNotRegister(ent->name, "ATA", ent->lineno, scanning); else { @@ -4129,7 +4188,8 @@ } // then register SCSI devices - if (ent->controller_type==CONTROLLER_SCSI || ent->controller_type==CONTROLLER_UNKNOWN){ + if (ent->controller_type==CONTROLLER_SCSI || ent->controller_type==CONTROLLER_CCISS || + ent->controller_type==CONTROLLER_UNKNOWN){ int retscsi=0; #if SCSITIMEOUT diff -urNad smartmontools-cvs~/utility.h smartmontools-cvs/utility.h --- smartmontools-cvs~/utility.h 2006-10-02 17:34:50.000000000 +0200 +++ smartmontools-cvs/utility.h 2006-10-02 17:35:17.000000000 +0200 @@ -186,5 +186,6 @@ #define CONTROLLER_MARVELL_SATA 0x07 // SATA drives behind Marvell controllers #define CONTROLLER_SAT 0x08 // SATA device behind a SCSI ATA Translation (SAT) layer #define CONTROLLER_HPT 0x09 // SATA drives behind HighPoint Raid controllers +#define CONTROLLER_CCISS 0x10 // CCISS controller #endif