diff options
Diffstat (limited to 'drivers/scsi/stex.c')
-rw-r--r-- | drivers/scsi/stex.c | 107 |
1 files changed, 35 insertions, 72 deletions
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index a3a18ad73125..47b614e8580c 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * SuperTrak EX Series Storage Controller driver for Linux | 2 | * SuperTrak EX Series Storage Controller driver for Linux |
3 | * | 3 | * |
4 | * Copyright (C) 2005, 2006 Promise Technology Inc. | 4 | * Copyright (C) 2005-2009 Promise Technology Inc. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License | 7 | * modify it under the terms of the GNU General Public License |
@@ -36,8 +36,8 @@ | |||
36 | #include <scsi/scsi_eh.h> | 36 | #include <scsi/scsi_eh.h> |
37 | 37 | ||
38 | #define DRV_NAME "stex" | 38 | #define DRV_NAME "stex" |
39 | #define ST_DRIVER_VERSION "3.6.0000.1" | 39 | #define ST_DRIVER_VERSION "4.6.0000.1" |
40 | #define ST_VER_MAJOR 3 | 40 | #define ST_VER_MAJOR 4 |
41 | #define ST_VER_MINOR 6 | 41 | #define ST_VER_MINOR 6 |
42 | #define ST_OEM 0 | 42 | #define ST_OEM 0 |
43 | #define ST_BUILD_VER 1 | 43 | #define ST_BUILD_VER 1 |
@@ -103,7 +103,7 @@ enum { | |||
103 | MU_REQ_COUNT = (MU_MAX_REQUEST + 1), | 103 | MU_REQ_COUNT = (MU_MAX_REQUEST + 1), |
104 | MU_STATUS_COUNT = (MU_MAX_REQUEST + 1), | 104 | MU_STATUS_COUNT = (MU_MAX_REQUEST + 1), |
105 | 105 | ||
106 | STEX_CDB_LENGTH = MAX_COMMAND_SIZE, | 106 | STEX_CDB_LENGTH = 16, |
107 | REQ_VARIABLE_LEN = 1024, | 107 | REQ_VARIABLE_LEN = 1024, |
108 | STATUS_VAR_LEN = 128, | 108 | STATUS_VAR_LEN = 128, |
109 | ST_CAN_QUEUE = MU_MAX_REQUEST, | 109 | ST_CAN_QUEUE = MU_MAX_REQUEST, |
@@ -114,15 +114,19 @@ enum { | |||
114 | SG_CF_EOT = 0x80, /* end of table */ | 114 | SG_CF_EOT = 0x80, /* end of table */ |
115 | SG_CF_64B = 0x40, /* 64 bit item */ | 115 | SG_CF_64B = 0x40, /* 64 bit item */ |
116 | SG_CF_HOST = 0x20, /* sg in host memory */ | 116 | SG_CF_HOST = 0x20, /* sg in host memory */ |
117 | MSG_DATA_DIR_ND = 0, | ||
118 | MSG_DATA_DIR_IN = 1, | ||
119 | MSG_DATA_DIR_OUT = 2, | ||
117 | 120 | ||
118 | st_shasta = 0, | 121 | st_shasta = 0, |
119 | st_vsc = 1, | 122 | st_vsc = 1, |
120 | st_vsc1 = 2, | 123 | st_vsc1 = 2, |
121 | st_yosemite = 3, | 124 | st_yosemite = 3, |
125 | st_seq = 4, | ||
122 | 126 | ||
123 | PASSTHRU_REQ_TYPE = 0x00000001, | 127 | PASSTHRU_REQ_TYPE = 0x00000001, |
124 | PASSTHRU_REQ_NO_WAKEUP = 0x00000100, | 128 | PASSTHRU_REQ_NO_WAKEUP = 0x00000100, |
125 | ST_INTERNAL_TIMEOUT = 30, | 129 | ST_INTERNAL_TIMEOUT = 180, |
126 | 130 | ||
127 | ST_TO_CMD = 0, | 131 | ST_TO_CMD = 0, |
128 | ST_FROM_CMD = 1, | 132 | ST_FROM_CMD = 1, |
@@ -152,35 +156,6 @@ enum { | |||
152 | ST_ADDITIONAL_MEM = 0x200000, | 156 | ST_ADDITIONAL_MEM = 0x200000, |
153 | }; | 157 | }; |
154 | 158 | ||
155 | /* SCSI inquiry data */ | ||
156 | typedef struct st_inq { | ||
157 | u8 DeviceType :5; | ||
158 | u8 DeviceTypeQualifier :3; | ||
159 | u8 DeviceTypeModifier :7; | ||
160 | u8 RemovableMedia :1; | ||
161 | u8 Versions; | ||
162 | u8 ResponseDataFormat :4; | ||
163 | u8 HiSupport :1; | ||
164 | u8 NormACA :1; | ||
165 | u8 ReservedBit :1; | ||
166 | u8 AERC :1; | ||
167 | u8 AdditionalLength; | ||
168 | u8 Reserved[2]; | ||
169 | u8 SoftReset :1; | ||
170 | u8 CommandQueue :1; | ||
171 | u8 Reserved2 :1; | ||
172 | u8 LinkedCommands :1; | ||
173 | u8 Synchronous :1; | ||
174 | u8 Wide16Bit :1; | ||
175 | u8 Wide32Bit :1; | ||
176 | u8 RelativeAddressing :1; | ||
177 | u8 VendorId[8]; | ||
178 | u8 ProductId[16]; | ||
179 | u8 ProductRevisionLevel[4]; | ||
180 | u8 VendorSpecific[20]; | ||
181 | u8 Reserved3[40]; | ||
182 | } ST_INQ; | ||
183 | |||
184 | struct st_sgitem { | 159 | struct st_sgitem { |
185 | u8 ctrl; /* SG_CF_xxx */ | 160 | u8 ctrl; /* SG_CF_xxx */ |
186 | u8 reserved[3]; | 161 | u8 reserved[3]; |
@@ -222,7 +197,7 @@ struct req_msg { | |||
222 | u8 target; | 197 | u8 target; |
223 | u8 task_attr; | 198 | u8 task_attr; |
224 | u8 task_manage; | 199 | u8 task_manage; |
225 | u8 prd_entry; | 200 | u8 data_dir; |
226 | u8 payload_sz; /* payload size in 4-byte, not used */ | 201 | u8 payload_sz; /* payload size in 4-byte, not used */ |
227 | u8 cdb[STEX_CDB_LENGTH]; | 202 | u8 cdb[STEX_CDB_LENGTH]; |
228 | u8 variable[REQ_VARIABLE_LEN]; | 203 | u8 variable[REQ_VARIABLE_LEN]; |
@@ -284,7 +259,7 @@ struct st_drvver { | |||
284 | #define MU_REQ_BUFFER_SIZE (MU_REQ_COUNT * sizeof(struct req_msg)) | 259 | #define MU_REQ_BUFFER_SIZE (MU_REQ_COUNT * sizeof(struct req_msg)) |
285 | #define MU_STATUS_BUFFER_SIZE (MU_STATUS_COUNT * sizeof(struct status_msg)) | 260 | #define MU_STATUS_BUFFER_SIZE (MU_STATUS_COUNT * sizeof(struct status_msg)) |
286 | #define MU_BUFFER_SIZE (MU_REQ_BUFFER_SIZE + MU_STATUS_BUFFER_SIZE) | 261 | #define MU_BUFFER_SIZE (MU_REQ_BUFFER_SIZE + MU_STATUS_BUFFER_SIZE) |
287 | #define STEX_EXTRA_SIZE max(sizeof(struct st_frame), sizeof(ST_INQ)) | 262 | #define STEX_EXTRA_SIZE sizeof(struct st_frame) |
288 | #define STEX_BUFFER_SIZE (MU_BUFFER_SIZE + STEX_EXTRA_SIZE) | 263 | #define STEX_BUFFER_SIZE (MU_BUFFER_SIZE + STEX_EXTRA_SIZE) |
289 | 264 | ||
290 | struct st_ccb { | 265 | struct st_ccb { |
@@ -346,8 +321,8 @@ MODULE_VERSION(ST_DRIVER_VERSION); | |||
346 | static void stex_gettime(__le32 *time) | 321 | static void stex_gettime(__le32 *time) |
347 | { | 322 | { |
348 | struct timeval tv; | 323 | struct timeval tv; |
349 | do_gettimeofday(&tv); | ||
350 | 324 | ||
325 | do_gettimeofday(&tv); | ||
351 | *time = cpu_to_le32(tv.tv_sec & 0xffffffff); | 326 | *time = cpu_to_le32(tv.tv_sec & 0xffffffff); |
352 | *(time + 1) = cpu_to_le32((tv.tv_sec >> 16) >> 16); | 327 | *(time + 1) = cpu_to_le32((tv.tv_sec >> 16) >> 16); |
353 | } | 328 | } |
@@ -368,7 +343,7 @@ static void stex_invalid_field(struct scsi_cmnd *cmd, | |||
368 | { | 343 | { |
369 | cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; | 344 | cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; |
370 | 345 | ||
371 | /* "Invalid field in cbd" */ | 346 | /* "Invalid field in cdb" */ |
372 | scsi_build_sense_buffer(0, cmd->sense_buffer, ILLEGAL_REQUEST, 0x24, | 347 | scsi_build_sense_buffer(0, cmd->sense_buffer, ILLEGAL_REQUEST, 0x24, |
373 | 0x0); | 348 | 0x0); |
374 | done(cmd); | 349 | done(cmd); |
@@ -497,6 +472,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) | |||
497 | unsigned int id,lun; | 472 | unsigned int id,lun; |
498 | struct req_msg *req; | 473 | struct req_msg *req; |
499 | u16 tag; | 474 | u16 tag; |
475 | |||
500 | host = cmd->device->host; | 476 | host = cmd->device->host; |
501 | id = cmd->device->id; | 477 | id = cmd->device->id; |
502 | lun = cmd->device->lun; | 478 | lun = cmd->device->lun; |
@@ -508,6 +484,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) | |||
508 | static char ms10_caching_page[12] = | 484 | static char ms10_caching_page[12] = |
509 | { 0, 0x12, 0, 0, 0, 0, 0, 0, 0x8, 0xa, 0x4, 0 }; | 485 | { 0, 0x12, 0, 0, 0, 0, 0, 0, 0x8, 0xa, 0x4, 0 }; |
510 | unsigned char page; | 486 | unsigned char page; |
487 | |||
511 | page = cmd->cmnd[2] & 0x3f; | 488 | page = cmd->cmnd[2] & 0x3f; |
512 | if (page == 0x8 || page == 0x3f) { | 489 | if (page == 0x8 || page == 0x3f) { |
513 | scsi_sg_copy_from_buffer(cmd, ms10_caching_page, | 490 | scsi_sg_copy_from_buffer(cmd, ms10_caching_page, |
@@ -551,6 +528,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) | |||
551 | if (cmd->cmnd[1] == PASSTHRU_GET_DRVVER) { | 528 | if (cmd->cmnd[1] == PASSTHRU_GET_DRVVER) { |
552 | struct st_drvver ver; | 529 | struct st_drvver ver; |
553 | size_t cp_len = sizeof(ver); | 530 | size_t cp_len = sizeof(ver); |
531 | |||
554 | ver.major = ST_VER_MAJOR; | 532 | ver.major = ST_VER_MAJOR; |
555 | ver.minor = ST_VER_MINOR; | 533 | ver.minor = ST_VER_MINOR; |
556 | ver.oem = ST_OEM; | 534 | ver.oem = ST_OEM; |
@@ -584,6 +562,13 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) | |||
584 | /* cdb */ | 562 | /* cdb */ |
585 | memcpy(req->cdb, cmd->cmnd, STEX_CDB_LENGTH); | 563 | memcpy(req->cdb, cmd->cmnd, STEX_CDB_LENGTH); |
586 | 564 | ||
565 | if (cmd->sc_data_direction == DMA_FROM_DEVICE) | ||
566 | req->data_dir = MSG_DATA_DIR_IN; | ||
567 | else if (cmd->sc_data_direction == DMA_TO_DEVICE) | ||
568 | req->data_dir = MSG_DATA_DIR_OUT; | ||
569 | else | ||
570 | req->data_dir = MSG_DATA_DIR_ND; | ||
571 | |||
587 | hba->ccb[tag].cmd = cmd; | 572 | hba->ccb[tag].cmd = cmd; |
588 | hba->ccb[tag].sense_bufflen = SCSI_SENSE_BUFFERSIZE; | 573 | hba->ccb[tag].sense_bufflen = SCSI_SENSE_BUFFERSIZE; |
589 | hba->ccb[tag].sense_buffer = cmd->sense_buffer; | 574 | hba->ccb[tag].sense_buffer = cmd->sense_buffer; |
@@ -642,6 +627,7 @@ static void stex_copy_data(struct st_ccb *ccb, | |||
642 | struct status_msg *resp, unsigned int variable) | 627 | struct status_msg *resp, unsigned int variable) |
643 | { | 628 | { |
644 | size_t count = variable; | 629 | size_t count = variable; |
630 | |||
645 | if (resp->scsi_status != SAM_STAT_GOOD) { | 631 | if (resp->scsi_status != SAM_STAT_GOOD) { |
646 | if (ccb->sense_buffer != NULL) | 632 | if (ccb->sense_buffer != NULL) |
647 | memcpy(ccb->sense_buffer, resp->variable, | 633 | memcpy(ccb->sense_buffer, resp->variable, |
@@ -661,24 +647,6 @@ static void stex_ys_commands(struct st_hba *hba, | |||
661 | resp->scsi_status != SAM_STAT_CHECK_CONDITION) { | 647 | resp->scsi_status != SAM_STAT_CHECK_CONDITION) { |
662 | scsi_set_resid(ccb->cmd, scsi_bufflen(ccb->cmd) - | 648 | scsi_set_resid(ccb->cmd, scsi_bufflen(ccb->cmd) - |
663 | le32_to_cpu(*(__le32 *)&resp->variable[0])); | 649 | le32_to_cpu(*(__le32 *)&resp->variable[0])); |
664 | return; | ||
665 | } | ||
666 | |||
667 | if (resp->srb_status != 0) | ||
668 | return; | ||
669 | |||
670 | /* determine inquiry command status by DeviceTypeQualifier */ | ||
671 | if (ccb->cmd->cmnd[0] == INQUIRY && | ||
672 | resp->scsi_status == SAM_STAT_GOOD) { | ||
673 | ST_INQ *inq_data; | ||
674 | |||
675 | scsi_sg_copy_to_buffer(ccb->cmd, hba->copy_buffer, | ||
676 | STEX_EXTRA_SIZE); | ||
677 | inq_data = (ST_INQ *)hba->copy_buffer; | ||
678 | if (inq_data->DeviceTypeQualifier != 0) | ||
679 | ccb->srb_status = SRB_STATUS_SELECTION_TIMEOUT; | ||
680 | else | ||
681 | ccb->srb_status = SRB_STATUS_SUCCESS; | ||
682 | } | 650 | } |
683 | } | 651 | } |
684 | 652 | ||
@@ -746,6 +714,7 @@ static void stex_mu_intr(struct st_hba *hba, u32 doorbell) | |||
746 | stex_copy_data(ccb, resp, size); | 714 | stex_copy_data(ccb, resp, size); |
747 | } | 715 | } |
748 | 716 | ||
717 | ccb->req = NULL; | ||
749 | ccb->srb_status = resp->srb_status; | 718 | ccb->srb_status = resp->srb_status; |
750 | ccb->scsi_status = resp->scsi_status; | 719 | ccb->scsi_status = resp->scsi_status; |
751 | 720 | ||
@@ -983,6 +952,7 @@ static int stex_reset(struct scsi_cmnd *cmd) | |||
983 | struct st_hba *hba; | 952 | struct st_hba *hba; |
984 | unsigned long flags; | 953 | unsigned long flags; |
985 | unsigned long before; | 954 | unsigned long before; |
955 | |||
986 | hba = (struct st_hba *) &cmd->device->host->hostdata[0]; | 956 | hba = (struct st_hba *) &cmd->device->host->hostdata[0]; |
987 | 957 | ||
988 | printk(KERN_INFO DRV_NAME | 958 | printk(KERN_INFO DRV_NAME |
@@ -1067,6 +1037,7 @@ static struct scsi_host_template driver_template = { | |||
1067 | static int stex_set_dma_mask(struct pci_dev * pdev) | 1037 | static int stex_set_dma_mask(struct pci_dev * pdev) |
1068 | { | 1038 | { |
1069 | int ret; | 1039 | int ret; |
1040 | |||
1070 | if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK) | 1041 | if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK) |
1071 | && !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) | 1042 | && !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) |
1072 | return 0; | 1043 | return 0; |
@@ -1124,9 +1095,9 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1124 | } | 1095 | } |
1125 | 1096 | ||
1126 | hba->cardtype = (unsigned int) id->driver_data; | 1097 | hba->cardtype = (unsigned int) id->driver_data; |
1127 | if (hba->cardtype == st_vsc && (pdev->subsystem_device & 0xf) == 0x1) | 1098 | if (hba->cardtype == st_vsc && (pdev->subsystem_device & 1)) |
1128 | hba->cardtype = st_vsc1; | 1099 | hba->cardtype = st_vsc1; |
1129 | hba->dma_size = (hba->cardtype == st_vsc1) ? | 1100 | hba->dma_size = (hba->cardtype == st_vsc1 || hba->cardtype == st_seq) ? |
1130 | (STEX_BUFFER_SIZE + ST_ADDITIONAL_MEM) : (STEX_BUFFER_SIZE); | 1101 | (STEX_BUFFER_SIZE + ST_ADDITIONAL_MEM) : (STEX_BUFFER_SIZE); |
1131 | hba->dma_mem = dma_alloc_coherent(&pdev->dev, | 1102 | hba->dma_mem = dma_alloc_coherent(&pdev->dev, |
1132 | hba->dma_size, &hba->dma_handle, GFP_KERNEL); | 1103 | hba->dma_size, &hba->dma_handle, GFP_KERNEL); |
@@ -1146,10 +1117,10 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1146 | host->max_lun = 8; | 1117 | host->max_lun = 8; |
1147 | host->max_id = 16 + 1; | 1118 | host->max_id = 16 + 1; |
1148 | } else if (hba->cardtype == st_yosemite) { | 1119 | } else if (hba->cardtype == st_yosemite) { |
1149 | host->max_lun = 128; | 1120 | host->max_lun = 256; |
1150 | host->max_id = 1 + 1; | 1121 | host->max_id = 1 + 1; |
1151 | } else { | 1122 | } else { |
1152 | /* st_vsc and st_vsc1 */ | 1123 | /* st_vsc , st_vsc1 and st_seq */ |
1153 | host->max_lun = 1; | 1124 | host->max_lun = 1; |
1154 | host->max_id = 128 + 1; | 1125 | host->max_id = 128 + 1; |
1155 | } | 1126 | } |
@@ -1299,18 +1270,10 @@ static struct pci_device_id stex_pci_tbl[] = { | |||
1299 | { 0x105a, 0x7250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_vsc }, | 1270 | { 0x105a, 0x7250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_vsc }, |
1300 | 1271 | ||
1301 | /* st_yosemite */ | 1272 | /* st_yosemite */ |
1302 | { 0x105a, 0x8650, PCI_ANY_ID, 0x4600, 0, 0, | 1273 | { 0x105a, 0x8650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_yosemite }, |
1303 | st_yosemite }, /* SuperTrak EX4650 */ | 1274 | |
1304 | { 0x105a, 0x8650, PCI_ANY_ID, 0x4610, 0, 0, | 1275 | /* st_seq */ |
1305 | st_yosemite }, /* SuperTrak EX4650o */ | 1276 | { 0x105a, 0x3360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_seq }, |
1306 | { 0x105a, 0x8650, PCI_ANY_ID, 0x8600, 0, 0, | ||
1307 | st_yosemite }, /* SuperTrak EX8650EL */ | ||
1308 | { 0x105a, 0x8650, PCI_ANY_ID, 0x8601, 0, 0, | ||
1309 | st_yosemite }, /* SuperTrak EX8650 */ | ||
1310 | { 0x105a, 0x8650, PCI_ANY_ID, 0x8602, 0, 0, | ||
1311 | st_yosemite }, /* SuperTrak EX8654 */ | ||
1312 | { 0x105a, 0x8650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
1313 | st_yosemite }, /* generic st_yosemite */ | ||
1314 | { } /* terminate list */ | 1277 | { } /* terminate list */ |
1315 | }; | 1278 | }; |
1316 | MODULE_DEVICE_TABLE(pci, stex_pci_tbl); | 1279 | MODULE_DEVICE_TABLE(pci, stex_pci_tbl); |