Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 47922d06 authored by Mike Miller's avatar Mike Miller Committed by Linus Torvalds
Browse files

[PATCH] cciss: One Button Disaster Recovery support



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: default avatarStephen M. Cameron <steve.cameron@hp.com>
Signed-off-by: default avatarMike Miller <mike.miller@hp.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent bb2a37bf
Loading
Loading
Loading
Loading
+29 −12
Original line number Original line Diff line number Diff line
@@ -878,7 +878,7 @@ cciss_scsi_interpret_error(CommandList_struct *cp)


static int
static int
cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, 
cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, 
		 InquiryData_struct *buf)
		 unsigned char *buf, unsigned char bufsize)
{
{
	int rc;
	int rc;
	CommandList_struct *cp;
	CommandList_struct *cp;
@@ -901,11 +901,10 @@ cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
	cdb[1] = 0;
	cdb[1] = 0;
	cdb[2] = 0;
	cdb[2] = 0;
	cdb[3] = 0;
	cdb[3] = 0;
	cdb[4] = sizeof(*buf) & 0xff;
	cdb[4] = bufsize;
	cdb[5] = 0;
	cdb[5] = 0;
	rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, cdb, 
	rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, cdb, 
				6, (unsigned char *) buf, 
				6, buf, bufsize, XFER_READ);
				sizeof(*buf), XFER_READ);


	if (rc != 0) return rc; /* something went wrong */
	if (rc != 0) return rc; /* something went wrong */


@@ -1001,9 +1000,10 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
	   that though.  
	   that though.  


	 */
	 */

#define OBDR_TAPE_INQ_SIZE 49
#define OBDR_TAPE_SIG "$DR-10"
	ReportLunData_struct *ld_buff;
	ReportLunData_struct *ld_buff;
	InquiryData_struct *inq_buff;
	unsigned char *inq_buff;
	unsigned char scsi3addr[8];
	unsigned char scsi3addr[8];
	ctlr_info_t *c;
	ctlr_info_t *c;
	__u32 num_luns=0;
	__u32 num_luns=0;
@@ -1021,7 +1021,7 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
		return;
		return;
	}
	}
	memset(ld_buff, 0, reportlunsize);
	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) {
        if (inq_buff == NULL) {
                printk(KERN_ERR "cciss: out of memory\n");
                printk(KERN_ERR "cciss: out of memory\n");
                kfree(ld_buff);
                kfree(ld_buff);
@@ -1052,19 +1052,36 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)


		/* for each physical lun, do an inquiry */
		/* for each physical lun, do an inquiry */
		if (ld_buff->LUN[i][3] & 0xC0) continue;
		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);
		memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8);


		if (cciss_scsi_do_inquiry(hba[cntl_num], 
		if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, inq_buff,
			scsi3addr, inq_buff) != 0)
			(unsigned char) OBDR_TAPE_INQ_SIZE) != 0) {
		{
			/* Inquiry failed (msg printed already) */
			/* Inquiry failed (msg printed already) */
			devtype = 0; /* so we will skip this device. */
			devtype = 0; /* so we will skip this device. */
		} else /* what kind of device is this? */
		} else /* what kind of device is this? */
			devtype = (inq_buff->data_byte[0] & 0x1f);
			devtype = (inq_buff[0] & 0x1f);


		switch (devtype)
		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 0x01: /* sequential access, (tape) */
		  case 0x08: /* medium changer */
		  case 0x08: /* medium changer */
			if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
			if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {