diff options
author | Mike Miller <mike.miller@hp.com> | 2005-09-13 04:25:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-13 11:22:30 -0400 |
commit | 47922d068e90ed34c1336cdd39912d51e190f8a5 (patch) | |
tree | 7e19d44c078339428318054ebbadd00479d461cf /drivers/block/cciss_scsi.c | |
parent | bb2a37bf4131d64b76dcdb126e3ff5bf371b1842 (diff) |
[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: 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>
Diffstat (limited to 'drivers/block/cciss_scsi.c')
-rw-r--r-- | drivers/block/cciss_scsi.c | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index df4afacc75d7..efc0bea7693f 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c | |||
@@ -878,7 +878,7 @@ cciss_scsi_interpret_error(CommandList_struct *cp) | |||
878 | 878 | ||
879 | static int | 879 | static int |
880 | cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, | 880 | cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, |
881 | InquiryData_struct *buf) | 881 | unsigned char *buf, unsigned char bufsize) |
882 | { | 882 | { |
883 | int rc; | 883 | int rc; |
884 | CommandList_struct *cp; | 884 | CommandList_struct *cp; |
@@ -901,11 +901,10 @@ cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, | |||
901 | cdb[1] = 0; | 901 | cdb[1] = 0; |
902 | cdb[2] = 0; | 902 | cdb[2] = 0; |
903 | cdb[3] = 0; | 903 | cdb[3] = 0; |
904 | cdb[4] = sizeof(*buf) & 0xff; | 904 | cdb[4] = bufsize; |
905 | cdb[5] = 0; | 905 | cdb[5] = 0; |
906 | rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, cdb, | 906 | rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, cdb, |
907 | 6, (unsigned char *) buf, | 907 | 6, buf, bufsize, XFER_READ); |
908 | sizeof(*buf), XFER_READ); | ||
909 | 908 | ||
910 | if (rc != 0) return rc; /* something went wrong */ | 909 | if (rc != 0) return rc; /* something went wrong */ |
911 | 910 | ||
@@ -1001,9 +1000,10 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) | |||
1001 | that though. | 1000 | that though. |
1002 | 1001 | ||
1003 | */ | 1002 | */ |
1004 | 1003 | #define OBDR_TAPE_INQ_SIZE 49 | |
1004 | #define OBDR_TAPE_SIG "$DR-10" | ||
1005 | ReportLunData_struct *ld_buff; | 1005 | ReportLunData_struct *ld_buff; |
1006 | InquiryData_struct *inq_buff; | 1006 | unsigned char *inq_buff; |
1007 | unsigned char scsi3addr[8]; | 1007 | unsigned char scsi3addr[8]; |
1008 | ctlr_info_t *c; | 1008 | ctlr_info_t *c; |
1009 | __u32 num_luns=0; | 1009 | __u32 num_luns=0; |
@@ -1021,7 +1021,7 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) | |||
1021 | return; | 1021 | return; |
1022 | } | 1022 | } |
1023 | memset(ld_buff, 0, reportlunsize); | 1023 | memset(ld_buff, 0, reportlunsize); |
1024 | inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); | 1024 | inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL); |
1025 | if (inq_buff == NULL) { | 1025 | if (inq_buff == NULL) { |
1026 | printk(KERN_ERR "cciss: out of memory\n"); | 1026 | printk(KERN_ERR "cciss: out of memory\n"); |
1027 | kfree(ld_buff); | 1027 | kfree(ld_buff); |
@@ -1052,19 +1052,36 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) | |||
1052 | 1052 | ||
1053 | /* for each physical lun, do an inquiry */ | 1053 | /* for each physical lun, do an inquiry */ |
1054 | if (ld_buff->LUN[i][3] & 0xC0) continue; | 1054 | if (ld_buff->LUN[i][3] & 0xC0) continue; |
1055 | memset(inq_buff, 0, sizeof(InquiryData_struct)); | 1055 | memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE); |
1056 | memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8); | 1056 | memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8); |
1057 | 1057 | ||
1058 | if (cciss_scsi_do_inquiry(hba[cntl_num], | 1058 | if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, inq_buff, |
1059 | scsi3addr, inq_buff) != 0) | 1059 | (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) { |
1060 | { | ||
1061 | /* Inquiry failed (msg printed already) */ | 1060 | /* Inquiry failed (msg printed already) */ |
1062 | devtype = 0; /* so we will skip this device. */ | 1061 | devtype = 0; /* so we will skip this device. */ |
1063 | } else /* what kind of device is this? */ | 1062 | } else /* what kind of device is this? */ |
1064 | devtype = (inq_buff->data_byte[0] & 0x1f); | 1063 | devtype = (inq_buff[0] & 0x1f); |
1065 | 1064 | ||
1066 | switch (devtype) | 1065 | switch (devtype) |
1067 | { | 1066 | { |
1067 | case 0x05: /* CD-ROM */ { | ||
1068 | |||
1069 | /* We don't *really* support actual CD-ROM devices, | ||
1070 | * just this "One Button Disaster Recovery" tape drive | ||
1071 | * which temporarily pretends to be a CD-ROM drive. | ||
1072 | * So we check that the device is really an OBDR tape | ||
1073 | * device by checking for "$DR-10" in bytes 43-48 of | ||
1074 | * the inquiry data. | ||
1075 | */ | ||
1076 | char obdr_sig[7]; | ||
1077 | |||
1078 | strncpy(obdr_sig, &inq_buff[43], 6); | ||
1079 | obdr_sig[6] = '\0'; | ||
1080 | if (strncmp(obdr_sig, OBDR_TAPE_SIG, 6) != 0) | ||
1081 | /* Not OBDR device, ignore it. */ | ||
1082 | break; | ||
1083 | } | ||
1084 | /* fall through . . . */ | ||
1068 | case 0x01: /* sequential access, (tape) */ | 1085 | case 0x01: /* sequential access, (tape) */ |
1069 | case 0x08: /* medium changer */ | 1086 | case 0x08: /* medium changer */ |
1070 | if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) { | 1087 | if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) { |