]> git.proxmox.com Git - mirror_smartmontools-debian.git/blob - debian/patches/60_cciss.dpatch
New upstream CVS release candidate
[mirror_smartmontools-debian.git] / debian / patches / 60_cciss.dpatch
1 #! /bin/sh /usr/share/dpatch/dpatch-run
2 ## 60_cciss.dpatch.dpatch by
3 ## Praveen Chidambaram <bunchofmails@gmail.com>
4 ## Douglas Gilbert <dougg@torque.net>
5 ## Guido Guenther <agx@sigxcpu.org>
6 ## Frédéric BOITEUX <fboiteux@calistel.com>
7 ##
8 ## All lines beginning with `## DP:' are a description of the patch.
9 ## DP: add support for Compaq/HP CCISS controllers
10
11 @DPATCH@
12 diff -urNad smartmontools-cvs~/os_linux.cpp smartmontools-cvs/os_linux.cpp
13 --- smartmontools-cvs~/os_linux.cpp 2006-10-02 17:34:50.000000000 +0200
14 +++ smartmontools-cvs/os_linux.cpp 2006-10-02 17:38:35.000000000 +0200
15 @@ -66,12 +66,17 @@
16 #include "os_linux.h"
17 #include "scsicmds.h"
18 #include "utility.h"
19 +#include "extern.h"
20 +
21 +#include <linux/cciss_ioctl.h>
22 +
23
24 #ifndef ENOTSUP
25 #define ENOTSUP ENOSYS
26 #endif
27 typedef unsigned long long u8;
28
29 +
30 #define ARGUSED(x) ((void)(x))
31
32 static const char *filenameandversion="$Id: os_linux.cpp,v 1.86 2006/09/12 01:16:54 sxzzsf Exp $";
33 @@ -85,6 +90,23 @@
34 // global variable holding byte count of allocated memory
35 extern long long bytes;
36
37 +/* for passing global control variables */
38 +extern smartmonctrl *con;
39 +
40 +static int cciss_io_interface(int device, int target,
41 + struct scsi_cmnd_io * iop, int report);
42 +
43 +typedef struct _ReportLUNdata_struct
44 +{
45 + BYTE LUNListLength[4];
46 + DWORD reserved;
47 + BYTE LUN[CISS_MAX_LUN][8];
48 +} ReportLunData_struct;
49 +
50 +/* Structure/defines of Report Physical LUNS of drive */
51 +#define CISS_MAX_LUN 16
52 +#define CISS_MAX_PHYS_LUN 1024
53 +#define CISS_REPORT_PHYS 0xc3
54
55
56 /* This function will setup and fix device nodes for a 3ware controller. */
57 @@ -193,8 +215,13 @@
58 }
59 return open(pathname, O_RDONLY | O_NONBLOCK);
60 }
61 + else if(!strcmp(type, "CCISS")) {
62 + // the device is a cciss smart array device.
63 + return open(pathname, O_RDWR | O_NONBLOCK);
64 + }
65 else
66 return -1;
67 +
68 }
69
70 // equivalent to close(file descriptor)
71 @@ -618,6 +645,94 @@
72 return 0;
73 }
74
75 +// CCISS Smart Array Controller
76 +static int cciss_sendpassthru(unsigned int cmdtype, unsigned char *CDB,
77 + unsigned int CDBlen, char *buff,
78 + unsigned int size, unsigned int LunID,
79 + unsigned char *scsi3addr, int fd)
80 +{
81 + int err ;
82 + IOCTL_Command_struct iocommand;
83 +
84 + memset(&iocommand, 0, sizeof(iocommand));
85 +
86 + if (cmdtype == 0)
87 + {
88 + // To controller; nothing to do
89 + }
90 + else if (cmdtype == 1)
91 + {
92 + iocommand.LUN_info.LogDev.VolId = LunID;
93 + iocommand.LUN_info.LogDev.Mode = 1;
94 + }
95 + else if (cmdtype == 2)
96 + {
97 + memcpy(&iocommand.LUN_info.LunAddrBytes,scsi3addr,8);
98 + iocommand.LUN_info.LogDev.Mode = 0;
99 + }
100 + else
101 + {
102 + fprintf(stderr, "cciss_sendpassthru: bad cmdtype\n");
103 + return 1;
104 + }
105 +
106 + memcpy(&iocommand.Request.CDB[0], CDB, CDBlen);
107 + iocommand.Request.CDBLen = CDBlen;
108 + iocommand.Request.Type.Type = TYPE_CMD;
109 + iocommand.Request.Type.Attribute = ATTR_SIMPLE;
110 + iocommand.Request.Type.Direction = XFER_READ;
111 + iocommand.Request.Timeout = 0;
112 +
113 + iocommand.buf_size = size;
114 + iocommand.buf = (unsigned char *)buff;
115 +
116 + if ((err = ioctl(fd, CCISS_PASSTHRU, &iocommand)))
117 + {
118 + fprintf(stderr, "CCISS ioctl error %d\n", err);
119 + }
120 + return err;
121 +}
122 +
123 +static int cciss_getlun(int device, int target, unsigned char *physlun)
124 +{
125 + unsigned char CDB[16]= {0};
126 + ReportLunData_struct *luns;
127 + int reportlunsize = sizeof(*luns) + CISS_MAX_PHYS_LUN * 8;
128 + int i;
129 + int ret;
130 +
131 + luns = (ReportLunData_struct *)malloc(reportlunsize);
132 +
133 + memset(luns, 0, reportlunsize);
134 +
135 + /* Get Physical LUN Info (for physical device) */
136 + CDB[0] = CISS_REPORT_PHYS;
137 + CDB[6] = (reportlunsize >> 24) & 0xFF; /* MSB */
138 + CDB[7] = (reportlunsize >> 16) & 0xFF;
139 + CDB[8] = (reportlunsize >> 8) & 0xFF;
140 + CDB[9] = reportlunsize & 0xFF;
141 +
142 + if ((ret = cciss_sendpassthru(0, CDB, 12, (char *)luns, reportlunsize, 0, NULL, device)))
143 + {
144 + free(luns);
145 + return ret;
146 + }
147 +
148 + for (i=0; i<CISS_MAX_LUN+1; i++)
149 + {
150 + if (luns->LUN[i][6] == target)
151 + {
152 + memcpy(physlun, luns->LUN[i], 8);
153 + free(luns);
154 + return 0;
155 + }
156 + }
157 +
158 + free(luns);
159 + return ret;
160 +}
161 +// end CCISS Smart Array Controller
162 +
163 // >>>>>> Start of general SCSI specific linux code
164
165 /* Linux specific code.
166 @@ -926,7 +1041,8 @@
167 * (e.g. CHECK CONDITION). If the SCSI command could not be issued
168 * (e.g. device not present or timeout) or some other problem
169 * (e.g. timeout) then returns a negative errno value */
170 -int do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report)
171 +static int do_normal_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop,
172 + int report)
173 {
174 int res;
175
176 @@ -956,8 +1072,94 @@
177 }
178 }
179
180 +/* Check and call the right interface. Maybe when the do_generic_scsi_cmd_io interface is better
181 + we can take off this crude way of calling the right interface */
182 + int do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report)
183 + {
184 + switch(con->controller_type)
185 + {
186 + case CONTROLLER_CCISS:
187 + return cciss_io_interface(dev_fd, con->controller_port-1, iop, report);
188 + // not reached
189 + break;
190 + default:
191 + return do_normal_scsi_cmnd_io(dev_fd, iop, report);
192 + // not reached
193 + break;
194 + }
195 + }
196 +
197 // >>>>>> End of general SCSI specific linux code
198
199 +/* cciss >> CCSISS I/O passthrough
200 + This is an interface that uses the cciss passthrough to talk to the SMART controller on
201 + the HP system. The cciss driver provides a way to send SCSI cmds through the CCISS passthrough
202 + essentially the methods above and below pertain to SCSI, except for the SG driver which is not
203 + involved. The CCISS driver does not engage the scsi subsystem. */
204 + static int cciss_io_interface(int device, int target, struct scsi_cmnd_io * iop, int report)
205 + {
206 + unsigned char pBuf[512] = {0};
207 + unsigned char phylun[1024] = {0};
208 + int iBufLen = 512;
209 + int status = -1;
210 + int len = 0; // used later in the code.
211 + report = 0;
212 +
213 + cciss_getlun(device, target, phylun);
214 + status = cciss_sendpassthru( 2, iop->cmnd, iop->cmnd_len, (char*) pBuf, iBufLen, 1, phylun, device);
215 +
216 + if (0 == status)
217 + {
218 + if (report > 0)
219 + printf(" status=0\n");
220 + if (DXFER_FROM_DEVICE == iop->dxfer_dir)
221 + {
222 + memcpy(iop->dxferp, pBuf, iop->dxfer_len);
223 + if (report > 1)
224 + {
225 + int trunc = (iop->dxfer_len > 256) ? 1 : 0;
226 + printf(" Incoming data, len=%d%s:\n", (int)iop->dxfer_len,
227 + (trunc ? " [only first 256 bytes shown]" : ""));
228 + dStrHex((const char*)iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
229 + }
230 + }
231 + return 0;
232 + }
233 + iop->scsi_status = status & 0x7e; /* bits 0 and 7 used to be for vendors */
234 + if (LSCSI_DRIVER_SENSE == ((status >> 24) & 0xf))
235 + iop->scsi_status = SCSI_STATUS_CHECK_CONDITION;
236 + len = (SEND_IOCTL_RESP_SENSE_LEN < iop->max_sense_len) ?
237 + SEND_IOCTL_RESP_SENSE_LEN : iop->max_sense_len;
238 + if ((SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) &&
239 + iop->sensep && (len > 0))
240 + {
241 + memcpy(iop->sensep, pBuf, len);
242 + iop->resp_sense_len = iBufLen;
243 + if (report > 1)
244 + {
245 + printf(" >>> Sense buffer, len=%d:\n", (int)len);
246 + dStrHex((const char *)pBuf, len , 1);
247 + }
248 + }
249 + if (report)
250 + {
251 + if (SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) {
252 + printf(" status=%x: sense_key=%x asc=%x ascq=%x\n", status & 0xff,
253 + pBuf[2] & 0xf, pBuf[12], pBuf[13]);
254 + }
255 + else
256 + printf(" status=0x%x\n", status);
257 + }
258 + if (iop->scsi_status > 0)
259 + return 0;
260 + else
261 + {
262 + if (report > 0)
263 + printf(" ioctl status=0x%x but scsi status=0, fail with EIO\n", status);
264 + return -EIO; /* give up, assume no device there */
265 + }
266 + }
267 +
268
269 // prototype
270 void printwarning(smart_command_set command);
271 @@ -1657,6 +1859,7 @@
272 static const char * lin_dev_scsi_tape3 = "nos";
273 static const char * lin_dev_3ware_9000_char = "twa";
274 static const char * lin_dev_3ware_678k_char = "twe";
275 +static const char * lin_dev_cciss_dir = "cciss/";
276
277 int guess_device_type(const char * dev_name) {
278 int len;
279 @@ -1719,6 +1922,10 @@
280 if (!strncmp(lin_dev_3ware_678k_char, dev_name,
281 strlen(lin_dev_3ware_678k_char)))
282 return CONTROLLER_3WARE_678K_CHAR;
283 + // form /dev/cciss*
284 + if (!strncmp(lin_dev_cciss_dir, dev_name,
285 + strlen(lin_dev_cciss_dir)))
286 + return CONTROLLER_CCISS;
287
288 // we failed to recognize any of the forms
289 return CONTROLLER_UNKNOWN;
290 diff -urNad smartmontools-cvs~/smartctl.8.in smartmontools-cvs/smartctl.8.in
291 --- smartmontools-cvs~/smartctl.8.in 2006-10-02 17:34:50.000000000 +0200
292 +++ smartmontools-cvs/smartctl.8.in 2006-10-02 17:35:17.000000000 +0200
293 @@ -185,9 +185,9 @@
294 .TP
295 .B \-d TYPE, \-\-device=TYPE
296 Specifies the type of the device. The valid arguments to this option
297 -are \fIata\fP, \fIscsi\fP, \fIsat\fP, \fImarvell\fP, \fI3ware,N\fP, and \fIhpt,L/M\fP
298 -or \fIhpt,L/M/N\fP. If this option is not used then \fBsmartctl\fP will attempt to
299 -guess the device type from the device name.
300 +are \fIata\fP, \fIscsi\fP, \fIsat\fP, \fImarvell\fP, \fI3ware,N\fP, and \fIhpt,L/M\fP,
301 +\fIcciss,N\fP or \fIhpt,L/M/N\fP. If this option is not used then
302 +\fBsmartctl\fP will attempt to guess the device type from the device name.
303
304 The \'sat\' device type is for ATA disks that have a SCSI to ATA
305 Translation (SAT) Layer (SATL) between the disk and the operating system.
306 @@ -291,6 +291,8 @@
307
308 .B HighPoint RocketRAID controllers are currently ONLY supported under Linux.
309
310 +.B cciss controllers are currently ONLY supported under Linux.
311 +
312 .TP
313 .B \-T TYPE, \-\-tolerance=TYPE
314 Specifies how tolerant \fBsmartctl\fP should be of ATA and SMART command
315 @@ -1242,6 +1244,12 @@
316 power\-cycled during the read\-scan, resume the scan 45 minutes after power to the
317 device is restored.
318 .PP
319 +.nf
320 +.B smartctl \-a \-d cciss,0 /dev/cciss/c0d0
321 +.fi
322 +Examine all SMART data for the first SCSI disk connected to a cciss
323 +RAID controller card.
324 +.PP
325 .SH RETURN VALUES
326 The return values of \fBsmartctl\fP are defined by a bitmask. If all
327 is well with the disk, the return value (exit status) of
328 diff -urNad smartmontools-cvs~/smartctl.cpp smartmontools-cvs/smartctl.cpp
329 --- smartmontools-cvs~/smartctl.cpp 2006-10-02 17:34:50.000000000 +0200
330 +++ smartmontools-cvs/smartctl.cpp 2006-10-02 17:35:17.000000000 +0200
331 @@ -239,7 +239,7 @@
332 case 'q':
333 return "errorsonly, silent";
334 case 'd':
335 - return "ata, scsi, marvell, sat, 3ware,N, hpt,L/M/N";
336 + return "ata, scsi, marvell, sat, 3ware,N, hpt,L/M/N cciss,N";
337 case 'T':
338 return "normal, conservative, permissive, verypermissive";
339 case 'b':
340 @@ -459,21 +459,35 @@
341 con->dont_print = FALSE;
342 pout("No memory for argument of -d. Exiting...\n");
343 exit(FAILCMD);
344 - } else if (strncmp(s,"3ware,",6)) {
345 - badarg = TRUE;
346 - } else if (split_report_arg2(s, &i)) {
347 - sprintf(extraerror, "Option -d 3ware,N requires N to be a non-negative integer\n");
348 - badarg = TRUE;
349 - } else if (i<0 || i>15) {
350 - sprintf(extraerror, "Option -d 3ware,N (N=%d) must have 0 <= N <= 15\n", i);
351 - badarg = TRUE;
352 - } else {
353 - // NOTE: controller_port == disk number + 1
354 - con->controller_type = CONTROLLER_3WARE;
355 - con->controller_port = i+1;
356 - }
357 - free(s);
358 - }
359 + } else if (!strncmp(s,"3ware,",6)) {
360 + if (split_report_arg2(s, &i)) {
361 + sprintf(extraerror, "Option -d 3ware,N requires N to be a non-negative integer\n");
362 + badarg = TRUE;
363 + } else if (i<0 || i>15) {
364 + sprintf(extraerror, "Option -d 3ware,N (N=%d) must have 0 <= N <= 15\n", i);
365 + badarg = TRUE;
366 + } else {
367 + // NOTE: controller_port == disk number + 1
368 + con->controller_type = CONTROLLER_3WARE;
369 + con->controller_port = i+1;
370 + }
371 + free(s);
372 + } else if (!strncmp(s,"cciss,",6)) {
373 + if (split_report_arg2(s, &i)) {
374 + sprintf(extraerror, "Option -d cciss,N requires N to be a non-negative integer\n");
375 + badarg = TRUE;
376 + } else if (i<0 || i>15) {
377 + sprintf(extraerror, "Option -d cciss,N (N=%d) must have 0 <= N <= 15\n", i);
378 + badarg = TRUE;
379 + } else {
380 + // NOTE: controller_port == drive number
381 + con->controller_type = CONTROLLER_CCISS;
382 + con->controller_port = i+1;
383 + }
384 + free(s);
385 + } else
386 + badarg=TRUE;
387 + }
388 break;
389 case 'T':
390 if (!strcmp(optarg,"normal")) {
391 @@ -948,6 +962,9 @@
392 case CONTROLLER_3WARE_678K_CHAR:
393 mode="ATA_3WARE_678K";
394 break;
395 + case CONTROLLER_CCISS:
396 + mode="CCISS";
397 + break;
398 default:
399 mode="ATA";
400 break;
401 @@ -981,6 +998,11 @@
402 if ((0 == retval) && (CONTROLLER_SAT == con->controller_type))
403 retval = ataPrintMain(fd);
404 break;
405 + case CONTROLLER_CCISS:
406 + // route the cciss command through scsiPrintMain.
407 + // cciss pass-throughs will separeate from the SCSI data-path.
408 + retval = scsiPrintMain(fd);
409 + break;
410 default:
411 retval = ataPrintMain(fd);
412 break;
413 diff -urNad smartmontools-cvs~/smartd.8.in smartmontools-cvs/smartd.8.in
414 --- smartmontools-cvs~/smartd.8.in 2006-10-02 17:35:16.000000000 +0200
415 +++ smartmontools-cvs/smartd.8.in 2006-10-02 17:35:17.000000000 +0200
416 @@ -610,8 +610,8 @@
417 .B \-d TYPE
418 Specifies the type of the device. This Directive may be used multiple
419 times for one device, but the arguments \fIata\fP, \fIscsi\fP, \fIsat\fP,
420 -\fImarvell\fP, and \fI3ware,N\fP are mutually-exclusive. If more than
421 -one is given then \fBsmartd\fP will use the last one which appears.
422 +\fImarvell\fP, \fIcciss\fP and \fI3ware,N\fP are mutually-exclusive. If more
423 +than one is given then \fBsmartd\fP will use the last one which appears.
424
425 If none of these three arguments is given, then \fBsmartd\fP will
426 first attempt to guess the device type by looking at whether the sixth
427 @@ -690,8 +690,14 @@
428 6/7/8000 series controllers) or /dev/twa0-15 (3ware 9000 series
429 controllers).
430
431 +.I cciss,N
432 +\- the device consists of one or more SCSI disks connected to a cciss
433 +RAID controller. The non-negative integer N (in the range from 0 to 15
434 +inclusive) denotes which disk on the controller is monitored. In log
435 +files and email messages this disk will be identified as cciss_disk_XX
436 +with XX in the range from 00 to 15 inclusive.
437
438 -.B 3ware controllers are currently ONLY supported under Linux.
439 +.B 3ware and cciss controllers are currently ONLY supported under Linux.
440
441 .I hpt,L/M/N
442 \- the device consists of one or more ATA disks connected to a HighPoint
443 diff -urNad smartmontools-cvs~/smartd.conf.5.in smartmontools-cvs/smartd.conf.5.in
444 --- smartmontools-cvs~/smartd.conf.5.in 2006-10-02 17:34:50.000000000 +0200
445 +++ smartmontools-cvs/smartd.conf.5.in 2006-10-02 17:35:17.000000000 +0200
446 @@ -254,8 +254,8 @@
447 .B \-d TYPE
448 Specifies the type of the device. This Directive may be used multiple
449 times for one device, but the arguments \fIata\fP, \fIscsi\fP, \fIsat\fP,
450 -\fImarvell\fP, and \fI3ware,N\fP are mutually-exclusive. If more than
451 -one is given then \fBsmartd\fP will use the last one which appears.
452 +\fImarvell\fP, \fIcciss,N\fP and \fI3ware,N\fP are mutually-exclusive. If more
453 +than one is given then \fBsmartd\fP will use the last one which appears.
454
455 If none of these three arguments is given, then \fBsmartd\fP will
456 first attempt to guess the device type by looking at whether the sixth
457 @@ -334,8 +334,14 @@
458 6/7/8000 series controllers) or /dev/twa0-15 (3ware 9000 series
459 controllers).
460
461 +.I cciss,N
462 +\- the device consists of one or more SCSI disks connected to a cciss
463 +RAID controller. The non-negative integer N (in the range from 0 to 15
464 +inclusive) denotes which disk on the controller is monitored. In log
465 +files and email messages this disk will be identified as cciss_disk_XX
466 +with XX in the range from 00 to 15 inclusive.
467
468 -.B 3ware controllers are currently ONLY supported under Linux.
469 +.B 3ware and cciss controllers are currently ONLY supported under Linux.
470
471 .I hpt,L/M/N
472 \- the device consists of one or more ATA disks connected to a HighPoint
473 diff -urNad smartmontools-cvs~/smartd.cpp smartmontools-cvs/smartd.cpp
474 --- smartmontools-cvs~/smartd.cpp 2006-10-02 17:34:50.000000000 +0200
475 +++ smartmontools-cvs/smartd.cpp 2006-10-02 17:35:17.000000000 +0200
476 @@ -712,6 +712,18 @@
477 *s=' ';
478 }
479 break;
480 + case CONTROLLER_CCISS:
481 + {
482 + char *s,devicetype[16];
483 + sprintf(devicetype, "cciss,%d", cfg->controller_port-1);
484 + exportenv(environ_strings[8], "SMARTD_DEVICETYPE", devicetype);
485 + if ((s=strchr(cfg->name, ' ')))
486 + *s='\0';
487 + exportenv(environ_strings[9], "SMARTD_DEVICE", cfg->name);
488 + if (s)
489 + *s=' ';
490 + }
491 + break;
492 case CONTROLLER_ATA:
493 exportenv(environ_strings[8], "SMARTD_DEVICETYPE", "ata");
494 exportenv(environ_strings[9], "SMARTD_DEVICE", cfg->name);
495 @@ -723,9 +735,11 @@
496 case CONTROLLER_SCSI:
497 exportenv(environ_strings[8], "SMARTD_DEVICETYPE", "scsi");
498 exportenv(environ_strings[9], "SMARTD_DEVICE", cfg->name);
499 + break;
500 case CONTROLLER_SAT:
501 exportenv(environ_strings[8], "SMARTD_DEVICETYPE", "sat");
502 exportenv(environ_strings[9], "SMARTD_DEVICE", cfg->name);
503 + break;
504 case CONTROLLER_HPT:
505 {
506 char *s,devicetype[16];
507 @@ -738,6 +752,7 @@
508 if (s)
509 *s=' ';
510 }
511 + break;
512 }
513
514 snprintf(fullmessage, 1024,
515 @@ -1090,7 +1105,7 @@
516 void Directives() {
517 PrintOut(LOG_INFO,
518 "Configuration file (%s) Directives (after device name):\n"
519 - " -d TYPE Set the device type: ata, scsi, marvell, removable, sat, 3ware,N, hpt,L/M/N\n"
520 + " -d TYPE Set the device type: ata, scsi, marvell, removable, sat, 3ware,N, hpt,L/M/N, cciss,N\n"
521 " -T TYPE Set the tolerance to one of: normal, permissive\n"
522 " -o VAL Enable/disable automatic offline tests (on/off)\n"
523 " -S VAL Enable/disable attribute autosave (on/off)\n"
524 @@ -1638,18 +1653,26 @@
525 char *device = cfg->name;
526 struct scsi_iec_mode_page iec;
527 UINT8 tBuf[64];
528 + char *mode=NULL;
529
530 // should we try to register this as a SCSI device?
531 switch (cfg->controller_type) {
532 case CONTROLLER_SCSI:
533 case CONTROLLER_UNKNOWN:
534 + mode="SCSI";
535 + break;
536 + case CONTROLLER_CCISS:
537 + mode="CCISS";
538 break;
539 default:
540 return 1;
541 }
542 + // pass user settings on to low-level SCSI commands
543 + con->controller_port=cfg->controller_port;
544 + con->controller_type=cfg->controller_type;
545
546 // open the device
547 - if ((fd = OpenDevice(device, "SCSI", scanning)) < 0)
548 + if ((fd = OpenDevice(device, mode, scanning)) < 0)
549 return 1;
550 PrintOut(LOG_INFO,"Device: %s, opened\n", device);
551
552 @@ -1725,7 +1748,8 @@
553 }
554
555 // record type of device
556 - cfg->controller_type = CONTROLLER_SCSI;
557 + if (cfg->controller_type == CONTROLLER_UNKNOWN)
558 + cfg->controller_type = CONTROLLER_SCSI;
559
560 // get rid of allocated memory only needed for ATA devices. These
561 // might have been allocated if the user specified Ignore options or
562 @@ -2525,6 +2549,24 @@
563 int fd;
564 char *name=cfg->name;
565 const char *cp;
566 + char *mode=NULL;
567 +
568 + // should we try to register this as a SCSI device?
569 + switch (cfg->controller_type) {
570 + case CONTROLLER_CCISS:
571 + mode="CCISS";
572 + break;
573 + case CONTROLLER_SCSI:
574 + case CONTROLLER_UNKNOWN:
575 + mode="SCSI";
576 + break;
577 + default:
578 + return 1;
579 + }
580 +
581 + // pass user settings on to low-level SCSI commands
582 + con->controller_port=cfg->controller_port;
583 + con->controller_type=cfg->controller_type;
584
585 // If the user has asked for it, test the email warning system
586 if (cfg->mailwarn && cfg->mailwarn->emailtest)
587 @@ -2532,7 +2574,7 @@
588
589 // if we can't open device, fail gracefully rather than hard --
590 // perhaps the next time around we'll be able to open it
591 - if ((fd=OpenDevice(name, "SCSI", 0))<0) {
592 + if ((fd=OpenDevice(name, mode, 0))<0) {
593 // Lack of PrintOut() here is intentional!
594 MailWarning(cfg, 9, "Device: %s, unable to open device", name);
595 return 1;
596 @@ -2993,26 +3035,42 @@
597 PrintOut(LOG_CRIT,
598 "No memory to copy argument to -d option - exiting\n");
599 EXIT(EXIT_NOMEM);
600 - } else if (strncmp(s,"3ware,",6)) {
601 - badarg=1;
602 - } else if (split_report_arg2(s, &i)){
603 - PrintOut(LOG_CRIT, "File %s line %d (drive %s): Directive -d 3ware,N requires N integer\n",
604 - configfile, lineno, name);
605 - badarg=1;
606 - } else if ( i<0 || i>15) {
607 - PrintOut(LOG_CRIT, "File %s line %d (drive %s): Directive -d 3ware,N (N=%d) must have 0 <= N <= 15\n",
608 - configfile, lineno, name, i);
609 - badarg=1;
610 - } else {
611 - // determine type of escalade device from name of device
612 - cfg->controller_type = guess_device_type(name);
613 - if (cfg->controller_type!=CONTROLLER_3WARE_9000_CHAR && cfg->controller_type!=CONTROLLER_3WARE_678K_CHAR)
614 - cfg->controller_type=CONTROLLER_3WARE_678K;
615 + } else if (!strncmp(s,"3ware,",6)) {
616 + if (split_report_arg2(s, &i)){
617 + PrintOut(LOG_CRIT, "File %s line %d (drive %s): Directive -d 3ware,N requires N integer\n",
618 + configfile, lineno, name);
619 + badarg=1;
620 + } else if ( i<0 || i>15) {
621 + PrintOut(LOG_CRIT, "File %s line %d (drive %s): Directive -d 3ware,N (N=%d) must have 0 <= N <= 15\n",
622 + configfile, lineno, name, i);
623 + badarg=1;
624 + } else {
625 + // determine type of escalade device from name of device
626 + cfg->controller_type = guess_device_type(name);
627 + if (cfg->controller_type!=CONTROLLER_3WARE_9000_CHAR && cfg->controller_type!=CONTROLLER_3WARE_678K_CHAR)
628 + cfg->controller_type=CONTROLLER_3WARE_678K;
629
630 - // NOTE: controller_port == disk number + 1
631 - cfg->controller_port = i+1;
632 + // NOTE: controller_port == disk number + 1
633 + cfg->controller_port = i+1;
634 + }
635 + } else if (!strncmp(s,"cciss,",6)) {
636 + if (split_report_arg2(s, &i)){
637 + PrintOut(LOG_CRIT, "File %s line %d (drive %s): Directive -d cciss,N requires N integer\n",
638 + configfile, lineno, name);
639 + badarg=1;
640 + } else if ( i<0 || i>15) {
641 + PrintOut(LOG_CRIT, "File %s line %d (drive %s): Directive -d cciss,N (N=%d) must have 0 <= N <= 15\n",
642 + configfile, lineno, name, i);
643 + badarg=1;
644 + } else {
645 + // NOTE: controller_port == disk number + 1
646 + cfg->controller_type = CONTROLLER_CCISS;
647 + cfg->controller_port = i+1;
648 + }
649 + } else {
650 + badarg=1;
651 }
652 - s=CheckFree(s, __LINE__,filenameandversion);
653 + s=CheckFree(s, __LINE__,filenameandversion);
654 }
655 break;
656 case 'F':
657 @@ -3429,13 +3487,13 @@
658 }
659 }
660
661 - // If we found 3ware controller, then modify device name by adding a SPACE
662 - if (cfg->controller_port){
663 + // If we found 3ware/cciss controller, then modify device name by adding a SPACE
664 + if (cfg->controller_port) {
665 int len=17+strlen(cfg->name);
666 char *newname;
667
668 if (devscan){
669 - PrintOut(LOG_CRIT, "smartd: can not scan for 3ware devices (line %d of file %s)\n",
670 + PrintOut(LOG_CRIT, "smartd: can not scan for 3ware/cciss devices (line %d of file %s)\n",
671 lineno, configfile);
672 return -2;
673 }
674 @@ -3446,7 +3504,8 @@
675 }
676
677 // Make new device name by adding a space then RAID disk number
678 - snprintf(newname, len, "%s [3ware_disk_%02d]", cfg->name, cfg->controller_port-1);
679 + snprintf(newname, len, "%s [%s_disk_%02d]", cfg->name, (cfg->controller_type == CONTROLLER_CCISS) ? "cciss" : "3ware",
680 + cfg->controller_port-1);
681 cfg->name=CheckFree(cfg->name, __LINE__,filenameandversion);
682 cfg->name=newname;
683 bytes+=16;
684 @@ -4116,7 +4175,7 @@
685 continue;
686
687 // register ATA devices
688 - if (ent->controller_type!=CONTROLLER_SCSI){
689 + if (ent->controller_type!=CONTROLLER_SCSI && ent->controller_type!=CONTROLLER_CCISS){
690 if (ATADeviceScan(ent, scanning))
691 CanNotRegister(ent->name, "ATA", ent->lineno, scanning);
692 else {
693 @@ -4129,7 +4188,8 @@
694 }
695
696 // then register SCSI devices
697 - if (ent->controller_type==CONTROLLER_SCSI || ent->controller_type==CONTROLLER_UNKNOWN){
698 + if (ent->controller_type==CONTROLLER_SCSI || ent->controller_type==CONTROLLER_CCISS ||
699 + ent->controller_type==CONTROLLER_UNKNOWN){
700 int retscsi=0;
701
702 #if SCSITIMEOUT
703 diff -urNad smartmontools-cvs~/utility.h smartmontools-cvs/utility.h
704 --- smartmontools-cvs~/utility.h 2006-10-02 17:34:50.000000000 +0200
705 +++ smartmontools-cvs/utility.h 2006-10-02 17:35:17.000000000 +0200
706 @@ -186,5 +186,6 @@
707 #define CONTROLLER_MARVELL_SATA 0x07 // SATA drives behind Marvell controllers
708 #define CONTROLLER_SAT 0x08 // SATA device behind a SCSI ATA Translation (SAT) layer
709 #define CONTROLLER_HPT 0x09 // SATA drives behind HighPoint Raid controllers
710 +#define CONTROLLER_CCISS 0x10 // CCISS controller
711
712 #endif