diff options
Diffstat (limited to 'drivers/block/cciss_scsi.c')
-rw-r--r-- | drivers/block/cciss_scsi.c | 69 |
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 | ||
878 | static int | 879 | static int |
879 | cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, | 880 | cciss_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; |