aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/cciss_scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/cciss_scsi.c')
-rw-r--r--drivers/block/cciss_scsi.c69
1 files changed, 54 insertions, 15 deletions
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index f16e3caed58a..e183a3ef7839 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -93,6 +93,7 @@ struct cciss_scsi_cmd_stack_elem_t {
93 CommandList_struct cmd; 93 CommandList_struct cmd;
94 ErrorInfo_struct Err; 94 ErrorInfo_struct Err;
95 __u32 busaddr; 95 __u32 busaddr;
96 __u32 pad;
96}; 97};
97 98
98#pragma pack() 99#pragma pack()
@@ -877,7 +878,7 @@ cciss_scsi_interpret_error(CommandList_struct *cp)
877 878
878static int 879static int
879cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, 880cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
880 InquiryData_struct *buf) 881 unsigned char *buf, unsigned char bufsize)
881{ 882{
882 int rc; 883 int rc;
883 CommandList_struct *cp; 884 CommandList_struct *cp;
@@ -900,11 +901,10 @@ cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
900 cdb[1] = 0; 901 cdb[1] = 0;
901 cdb[2] = 0; 902 cdb[2] = 0;
902 cdb[3] = 0; 903 cdb[3] = 0;
903 cdb[4] = sizeof(*buf) & 0xff; 904 cdb[4] = bufsize;
904 cdb[5] = 0; 905 cdb[5] = 0;
905 rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, cdb, 906 rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, cdb,
906 6, (unsigned char *) buf, 907 6, buf, bufsize, XFER_READ);
907 sizeof(*buf), XFER_READ);
908 908
909 if (rc != 0) return rc; /* something went wrong */ 909 if (rc != 0) return rc; /* something went wrong */
910 910
@@ -1000,9 +1000,10 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
1000 that though. 1000 that though.
1001 1001
1002 */ 1002 */
1003 1003#define OBDR_TAPE_INQ_SIZE 49
1004#define OBDR_TAPE_SIG "$DR-10"
1004 ReportLunData_struct *ld_buff; 1005 ReportLunData_struct *ld_buff;
1005 InquiryData_struct *inq_buff; 1006 unsigned char *inq_buff;
1006 unsigned char scsi3addr[8]; 1007 unsigned char scsi3addr[8];
1007 ctlr_info_t *c; 1008 ctlr_info_t *c;
1008 __u32 num_luns=0; 1009 __u32 num_luns=0;
@@ -1020,7 +1021,7 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
1020 return; 1021 return;
1021 } 1022 }
1022 memset(ld_buff, 0, reportlunsize); 1023 memset(ld_buff, 0, reportlunsize);
1023 inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); 1024 inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
1024 if (inq_buff == NULL) { 1025 if (inq_buff == NULL) {
1025 printk(KERN_ERR "cciss: out of memory\n"); 1026 printk(KERN_ERR "cciss: out of memory\n");
1026 kfree(ld_buff); 1027 kfree(ld_buff);
@@ -1051,19 +1052,36 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
1051 1052
1052 /* for each physical lun, do an inquiry */ 1053 /* for each physical lun, do an inquiry */
1053 if (ld_buff->LUN[i][3] & 0xC0) continue; 1054 if (ld_buff->LUN[i][3] & 0xC0) continue;
1054 memset(inq_buff, 0, sizeof(InquiryData_struct)); 1055 memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE);
1055 memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8); 1056 memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8);
1056 1057
1057 if (cciss_scsi_do_inquiry(hba[cntl_num], 1058 if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, inq_buff,
1058 scsi3addr, inq_buff) != 0) 1059 (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) {
1059 {
1060 /* Inquiry failed (msg printed already) */ 1060 /* Inquiry failed (msg printed already) */
1061 devtype = 0; /* so we will skip this device. */ 1061 devtype = 0; /* so we will skip this device. */
1062 } else /* what kind of device is this? */ 1062 } else /* what kind of device is this? */
1063 devtype = (inq_buff->data_byte[0] & 0x1f); 1063 devtype = (inq_buff[0] & 0x1f);
1064 1064
1065 switch (devtype) 1065 switch (devtype)
1066 { 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 . . . */
1067 case 0x01: /* sequential access, (tape) */ 1085 case 0x01: /* sequential access, (tape) */
1068 case 0x08: /* medium changer */ 1086 case 0x08: /* medium changer */
1069 if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) { 1087 if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
@@ -1126,6 +1144,7 @@ cciss_scsi_proc_info(struct Scsi_Host *sh,
1126 1144
1127 int buflen, datalen; 1145 int buflen, datalen;
1128 ctlr_info_t *ci; 1146 ctlr_info_t *ci;
1147 int i;
1129 int cntl_num; 1148 int cntl_num;
1130 1149
1131 1150
@@ -1136,8 +1155,28 @@ cciss_scsi_proc_info(struct Scsi_Host *sh,
1136 cntl_num = ci->ctlr; /* Get our index into the hba[] array */ 1155 cntl_num = ci->ctlr; /* Get our index into the hba[] array */
1137 1156
1138 if (func == 0) { /* User is reading from /proc/scsi/ciss*?/?* */ 1157 if (func == 0) { /* User is reading from /proc/scsi/ciss*?/?* */
1139 buflen = sprintf(buffer, "hostnum=%d\n", sh->host_no); 1158 buflen = sprintf(buffer, "cciss%d: SCSI host: %d\n",
1140 1159 cntl_num, sh->host_no);
1160
1161 /* this information is needed by apps to know which cciss
1162 device corresponds to which scsi host number without
1163 having to open a scsi target device node. The device
1164 information is not a duplicate of /proc/scsi/scsi because
1165 the two may be out of sync due to scsi hotplug, rather
1166 this info is for an app to be able to use to know how to
1167 get them back in sync. */
1168
1169 for (i=0;i<ccissscsi[cntl_num].ndevices;i++) {
1170 struct cciss_scsi_dev_t *sd = &ccissscsi[cntl_num].dev[i];
1171 buflen += sprintf(&buffer[buflen], "c%db%dt%dl%d %02d "
1172 "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
1173 sh->host_no, sd->bus, sd->target, sd->lun,
1174 sd->devtype,
1175 sd->scsi3addr[0], sd->scsi3addr[1],
1176 sd->scsi3addr[2], sd->scsi3addr[3],
1177 sd->scsi3addr[4], sd->scsi3addr[5],
1178 sd->scsi3addr[6], sd->scsi3addr[7]);
1179 }
1141 datalen = buflen - offset; 1180 datalen = buflen - offset;
1142 if (datalen < 0) { /* they're reading past EOF. */ 1181 if (datalen < 0) { /* they're reading past EOF. */
1143 datalen = 0; 1182 datalen = 0;
@@ -1399,7 +1438,7 @@ cciss_proc_tape_report(int ctlr, unsigned char *buffer, off_t *pos, off_t *len)
1399 1438
1400 CPQ_TAPE_LOCK(ctlr, flags); 1439 CPQ_TAPE_LOCK(ctlr, flags);
1401 size = sprintf(buffer + *len, 1440 size = sprintf(buffer + *len,
1402 " Sequential access devices: %d\n\n", 1441 "Sequential access devices: %d\n\n",
1403 ccissscsi[ctlr].ndevices); 1442 ccissscsi[ctlr].ndevices);
1404 CPQ_TAPE_UNLOCK(ctlr, flags); 1443 CPQ_TAPE_UNLOCK(ctlr, flags);
1405 *pos += size; *len += size; 1444 *pos += size; *len += size;