[PATCH] cciss: One Button Disaster Recovery support
authorMike Miller <mike.miller@hp.com>
Tue, 13 Sep 2005 08:25:25 +0000 (01:25 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Tue, 13 Sep 2005 15:22:30 +0000 (08:22 -0700)
This patch adds support for "One Button Disaster Recovery" devices to the
cciss driver.  (OBDR devices are tape drives which can pretend to be cd-rom
devices temporarily.  Once booted the device can be reverted to a tape drive
and data recovery operations can be automatically begun.)

This is an enhancement request by a vendor/partner working on One Button
Disaster Recovery.

Signed-off-by: Stephen M. Cameron <steve.cameron@hp.com>
Signed-off-by: Mike Miller <mike.miller@hp.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/block/cciss_scsi.c

index df4afacc75d79b99e9defab474b8659b1ba0c51e..efc0bea7693fba420c793b8fe4ff207f16256277 100644 (file)
@@ -878,7 +878,7 @@ cciss_scsi_interpret_error(CommandList_struct *cp)
 
 static int
 cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, 
-                InquiryData_struct *buf)
+                unsigned char *buf, unsigned char bufsize)
 {
        int rc;
        CommandList_struct *cp;
@@ -901,11 +901,10 @@ cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
        cdb[1] = 0;
        cdb[2] = 0;
        cdb[3] = 0;
-       cdb[4] = sizeof(*buf) & 0xff;
+       cdb[4] = bufsize;
        cdb[5] = 0;
        rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, cdb, 
-                               6, (unsigned char *) buf, 
-                               sizeof(*buf), XFER_READ);
+                               6, buf, bufsize, XFER_READ);
 
        if (rc != 0) return rc; /* something went wrong */
 
@@ -1001,9 +1000,10 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
           that though.  
 
         */
-
+#define OBDR_TAPE_INQ_SIZE 49
+#define OBDR_TAPE_SIG "$DR-10"
        ReportLunData_struct *ld_buff;
-       InquiryData_struct *inq_buff;
+       unsigned char *inq_buff;
        unsigned char scsi3addr[8];
        ctlr_info_t *c;
        __u32 num_luns=0;
@@ -1021,7 +1021,7 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
                return;
        }
        memset(ld_buff, 0, reportlunsize);
-       inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
+       inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
         if (inq_buff == NULL) {
                 printk(KERN_ERR "cciss: out of memory\n");
                 kfree(ld_buff);
@@ -1052,19 +1052,36 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
 
                /* for each physical lun, do an inquiry */
                if (ld_buff->LUN[i][3] & 0xC0) continue;
-               memset(inq_buff, 0, sizeof(InquiryData_struct));
+               memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE);
                memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8);
 
-               if (cciss_scsi_do_inquiry(hba[cntl_num], 
-                       scsi3addr, inq_buff) != 0)
-               {
+               if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, inq_buff,
+                       (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) {
                        /* Inquiry failed (msg printed already) */
                        devtype = 0; /* so we will skip this device. */
                } else /* what kind of device is this? */
-                       devtype = (inq_buff->data_byte[0] & 0x1f);
+                       devtype = (inq_buff[0] & 0x1f);
 
                switch (devtype)
                {
+                 case 0x05: /* CD-ROM */ {
+
+                       /* We don't *really* support actual CD-ROM devices,
+                        * just this "One Button Disaster Recovery" tape drive
+                        * which temporarily pretends to be a CD-ROM drive.
+                        * So we check that the device is really an OBDR tape
+                        * device by checking for "$DR-10" in bytes 43-48 of
+                        * the inquiry data.
+                        */
+                               char obdr_sig[7];
+
+                               strncpy(obdr_sig, &inq_buff[43], 6);
+                               obdr_sig[6] = '\0';
+                               if (strncmp(obdr_sig, OBDR_TAPE_SIG, 6) != 0)
+                                       /* Not OBDR device, ignore it. */
+                                       break;
+                       }
+                       /* fall through . . . */
                  case 0x01: /* sequential access, (tape) */
                  case 0x08: /* medium changer */
                        if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {