diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/53c700.c | 86 | ||||
-rw-r--r-- | drivers/scsi/53c700.h | 2 |
2 files changed, 49 insertions, 39 deletions
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 4958c3b93c30..3c683dc23541 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c | |||
@@ -183,6 +183,10 @@ STATIC struct device_attribute *NCR_700_dev_attrs[]; | |||
183 | 183 | ||
184 | STATIC struct scsi_transport_template *NCR_700_transport_template = NULL; | 184 | STATIC struct scsi_transport_template *NCR_700_transport_template = NULL; |
185 | 185 | ||
186 | struct NCR_700_sense { | ||
187 | unsigned char cmnd[MAX_COMMAND_SIZE]; | ||
188 | }; | ||
189 | |||
186 | static char *NCR_700_phase[] = { | 190 | static char *NCR_700_phase[] = { |
187 | "", | 191 | "", |
188 | "after selection", | 192 | "after selection", |
@@ -537,6 +541,7 @@ find_empty_slot(struct NCR_700_Host_Parameters *hostdata) | |||
537 | * finish routine. If we cannot queue the command when it | 541 | * finish routine. If we cannot queue the command when it |
538 | * is properly build, we then change to NCR_700_SLOT_QUEUED */ | 542 | * is properly build, we then change to NCR_700_SLOT_QUEUED */ |
539 | slot->state = NCR_700_SLOT_BUSY; | 543 | slot->state = NCR_700_SLOT_BUSY; |
544 | slot->flags = 0; | ||
540 | hostdata->command_slot_count++; | 545 | hostdata->command_slot_count++; |
541 | 546 | ||
542 | return slot; | 547 | return slot; |
@@ -586,7 +591,7 @@ NCR_700_unmap(struct NCR_700_Host_Parameters *hostdata, struct scsi_cmnd *SCp, | |||
586 | if(SCp->sc_data_direction != DMA_NONE && | 591 | if(SCp->sc_data_direction != DMA_NONE && |
587 | SCp->sc_data_direction != DMA_BIDIRECTIONAL) { | 592 | SCp->sc_data_direction != DMA_BIDIRECTIONAL) { |
588 | if(SCp->use_sg) { | 593 | if(SCp->use_sg) { |
589 | dma_unmap_sg(hostdata->dev, SCp->buffer, | 594 | dma_unmap_sg(hostdata->dev, SCp->request_buffer, |
590 | SCp->use_sg, SCp->sc_data_direction); | 595 | SCp->use_sg, SCp->sc_data_direction); |
591 | } else { | 596 | } else { |
592 | dma_unmap_single(hostdata->dev, slot->dma_handle, | 597 | dma_unmap_single(hostdata->dev, slot->dma_handle, |
@@ -608,30 +613,23 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata, | |||
608 | (struct NCR_700_command_slot *)SCp->host_scribble; | 613 | (struct NCR_700_command_slot *)SCp->host_scribble; |
609 | 614 | ||
610 | NCR_700_unmap(hostdata, SCp, slot); | 615 | NCR_700_unmap(hostdata, SCp, slot); |
611 | dma_unmap_single(hostdata->dev, slot->pCmd, | 616 | if (slot->flags == NCR_700_FLAG_AUTOSENSE) { |
612 | sizeof(SCp->cmnd), DMA_TO_DEVICE); | 617 | struct NCR_700_sense *sense = SCp->device->hostdata; |
613 | if(SCp->cmnd[0] == REQUEST_SENSE && SCp->cmnd[6] == NCR_700_INTERNAL_SENSE_MAGIC) { | ||
614 | #ifdef NCR_700_DEBUG | 618 | #ifdef NCR_700_DEBUG |
615 | printk(" ORIGINAL CMD %p RETURNED %d, new return is %d sense is\n", | 619 | printk(" ORIGINAL CMD %p RETURNED %d, new return is %d sense is\n", |
616 | SCp, SCp->cmnd[7], result); | 620 | SCp, SCp->cmnd[7], result); |
617 | scsi_print_sense("53c700", SCp); | 621 | scsi_print_sense("53c700", SCp); |
618 | 622 | ||
619 | #endif | 623 | #endif |
624 | dma_unmap_single(hostdata->dev, slot->dma_handle, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); | ||
620 | /* restore the old result if the request sense was | 625 | /* restore the old result if the request sense was |
621 | * successful */ | 626 | * successful */ |
622 | if(result == 0) | 627 | if(result == 0) |
623 | result = SCp->cmnd[7]; | 628 | result = sense->cmnd[7]; |
624 | /* now restore the original command */ | 629 | } else |
625 | memcpy((void *) SCp->cmnd, (void *) SCp->data_cmnd, | 630 | dma_unmap_single(hostdata->dev, slot->pCmd, |
626 | sizeof(SCp->data_cmnd)); | 631 | sizeof(SCp->cmnd), DMA_TO_DEVICE); |
627 | SCp->request_buffer = SCp->buffer; | 632 | |
628 | SCp->request_bufflen = SCp->bufflen; | ||
629 | SCp->use_sg = SCp->old_use_sg; | ||
630 | SCp->cmd_len = SCp->old_cmd_len; | ||
631 | SCp->sc_data_direction = SCp->sc_old_data_direction; | ||
632 | SCp->underflow = SCp->old_underflow; | ||
633 | |||
634 | } | ||
635 | free_slot(slot, hostdata); | 633 | free_slot(slot, hostdata); |
636 | #ifdef NCR_700_DEBUG | 634 | #ifdef NCR_700_DEBUG |
637 | if(NCR_700_get_depth(SCp->device) == 0 || | 635 | if(NCR_700_get_depth(SCp->device) == 0 || |
@@ -979,6 +977,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, | |||
979 | "broken device is looping in contingent allegiance: ignoring\n"); | 977 | "broken device is looping in contingent allegiance: ignoring\n"); |
980 | NCR_700_scsi_done(hostdata, SCp, hostdata->status[0]); | 978 | NCR_700_scsi_done(hostdata, SCp, hostdata->status[0]); |
981 | } else { | 979 | } else { |
980 | struct NCR_700_sense *sense = SCp->device->hostdata; | ||
982 | #ifdef NCR_DEBUG | 981 | #ifdef NCR_DEBUG |
983 | scsi_print_command(SCp); | 982 | scsi_print_command(SCp); |
984 | printk(" cmd %p has status %d, requesting sense\n", | 983 | printk(" cmd %p has status %d, requesting sense\n", |
@@ -992,27 +991,25 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, | |||
992 | * data associated with the command | 991 | * data associated with the command |
993 | * here */ | 992 | * here */ |
994 | NCR_700_unmap(hostdata, SCp, slot); | 993 | NCR_700_unmap(hostdata, SCp, slot); |
995 | 994 | dma_unmap_single(hostdata->dev, slot->pCmd, | |
996 | SCp->cmnd[0] = REQUEST_SENSE; | 995 | sizeof(SCp->cmnd), |
997 | SCp->cmnd[1] = (SCp->device->lun & 0x7) << 5; | 996 | DMA_TO_DEVICE); |
998 | SCp->cmnd[2] = 0; | 997 | |
999 | SCp->cmnd[3] = 0; | 998 | sense->cmnd[0] = REQUEST_SENSE; |
1000 | SCp->cmnd[4] = sizeof(SCp->sense_buffer); | 999 | sense->cmnd[1] = (SCp->device->lun & 0x7) << 5; |
1001 | SCp->cmnd[5] = 0; | 1000 | sense->cmnd[2] = 0; |
1002 | SCp->cmd_len = 6; | 1001 | sense->cmnd[3] = 0; |
1002 | sense->cmnd[4] = sizeof(SCp->sense_buffer); | ||
1003 | sense->cmnd[5] = 0; | ||
1003 | /* Here's a quiet hack: the | 1004 | /* Here's a quiet hack: the |
1004 | * REQUEST_SENSE command is six bytes, | 1005 | * REQUEST_SENSE command is six bytes, |
1005 | * so store a flag indicating that | 1006 | * so store a flag indicating that |
1006 | * this was an internal sense request | 1007 | * this was an internal sense request |
1007 | * and the original status at the end | 1008 | * and the original status at the end |
1008 | * of the command */ | 1009 | * of the command */ |
1009 | SCp->cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; | 1010 | sense->cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; |
1010 | SCp->cmnd[7] = hostdata->status[0]; | 1011 | sense->cmnd[7] = hostdata->status[0]; |
1011 | SCp->use_sg = 0; | 1012 | slot->pCmd = dma_map_single(hostdata->dev, sense->cmnd, sizeof(sense->cmnd), DMA_TO_DEVICE); |
1012 | SCp->sc_data_direction = DMA_FROM_DEVICE; | ||
1013 | dma_sync_single_for_device(hostdata->dev, slot->pCmd, | ||
1014 | SCp->cmd_len, DMA_TO_DEVICE); | ||
1015 | SCp->request_bufflen = sizeof(SCp->sense_buffer); | ||
1016 | slot->dma_handle = dma_map_single(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); | 1013 | slot->dma_handle = dma_map_single(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); |
1017 | slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer)); | 1014 | slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer)); |
1018 | slot->SG[0].pAddr = bS_to_host(slot->dma_handle); | 1015 | slot->SG[0].pAddr = bS_to_host(slot->dma_handle); |
@@ -1024,6 +1021,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, | |||
1024 | 1021 | ||
1025 | /* queue the command for reissue */ | 1022 | /* queue the command for reissue */ |
1026 | slot->state = NCR_700_SLOT_QUEUED; | 1023 | slot->state = NCR_700_SLOT_QUEUED; |
1024 | slot->flags = NCR_700_FLAG_AUTOSENSE; | ||
1027 | hostdata->state = NCR_700_HOST_FREE; | 1025 | hostdata->state = NCR_700_HOST_FREE; |
1028 | hostdata->cmd = NULL; | 1026 | hostdata->cmd = NULL; |
1029 | } | 1027 | } |
@@ -1244,7 +1242,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, | |||
1244 | 1242 | ||
1245 | if(SCp->use_sg) { | 1243 | if(SCp->use_sg) { |
1246 | for(i = 0; i < SCp->use_sg + 1; i++) { | 1244 | for(i = 0; i < SCp->use_sg + 1; i++) { |
1247 | printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, ((struct scatterlist *)SCp->buffer)[i].length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr); | 1245 | printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, ((struct scatterlist *)SCp->request_buffer)[i].length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr); |
1248 | } | 1246 | } |
1249 | } | 1247 | } |
1250 | } | 1248 | } |
@@ -1403,12 +1401,14 @@ NCR_700_start_command(struct scsi_cmnd *SCp) | |||
1403 | /* keep interrupts disabled until we have the command correctly | 1401 | /* keep interrupts disabled until we have the command correctly |
1404 | * set up so we cannot take a selection interrupt */ | 1402 | * set up so we cannot take a selection interrupt */ |
1405 | 1403 | ||
1406 | hostdata->msgout[0] = NCR_700_identify(SCp->cmnd[0] != REQUEST_SENSE, | 1404 | hostdata->msgout[0] = NCR_700_identify((SCp->cmnd[0] != REQUEST_SENSE && |
1405 | slot->flags != NCR_700_FLAG_AUTOSENSE), | ||
1407 | SCp->device->lun); | 1406 | SCp->device->lun); |
1408 | /* for INQUIRY or REQUEST_SENSE commands, we cannot be sure | 1407 | /* for INQUIRY or REQUEST_SENSE commands, we cannot be sure |
1409 | * if the negotiated transfer parameters still hold, so | 1408 | * if the negotiated transfer parameters still hold, so |
1410 | * always renegotiate them */ | 1409 | * always renegotiate them */ |
1411 | if(SCp->cmnd[0] == INQUIRY || SCp->cmnd[0] == REQUEST_SENSE) { | 1410 | if(SCp->cmnd[0] == INQUIRY || SCp->cmnd[0] == REQUEST_SENSE || |
1411 | slot->flags == NCR_700_FLAG_AUTOSENSE) { | ||
1412 | NCR_700_clear_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); | 1412 | NCR_700_clear_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); |
1413 | } | 1413 | } |
1414 | 1414 | ||
@@ -1417,7 +1417,8 @@ NCR_700_start_command(struct scsi_cmnd *SCp) | |||
1417 | * will refuse all tags, so send the request sense as untagged | 1417 | * will refuse all tags, so send the request sense as untagged |
1418 | * */ | 1418 | * */ |
1419 | if((hostdata->tag_negotiated & (1<<scmd_id(SCp))) | 1419 | if((hostdata->tag_negotiated & (1<<scmd_id(SCp))) |
1420 | && (slot->tag != SCSI_NO_TAG && SCp->cmnd[0] != REQUEST_SENSE)) { | 1420 | && (slot->tag != SCSI_NO_TAG && SCp->cmnd[0] != REQUEST_SENSE && |
1421 | slot->flags != NCR_700_FLAG_AUTOSENSE)) { | ||
1421 | count += scsi_populate_tag_msg(SCp, &hostdata->msgout[count]); | 1422 | count += scsi_populate_tag_msg(SCp, &hostdata->msgout[count]); |
1422 | } | 1423 | } |
1423 | 1424 | ||
@@ -1863,8 +1864,9 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)) | |||
1863 | __u32 count = 0; | 1864 | __u32 count = 0; |
1864 | 1865 | ||
1865 | if(SCp->use_sg) { | 1866 | if(SCp->use_sg) { |
1866 | sg_count = dma_map_sg(hostdata->dev, SCp->buffer, | 1867 | sg_count = dma_map_sg(hostdata->dev, |
1867 | SCp->use_sg, direction); | 1868 | SCp->request_buffer, SCp->use_sg, |
1869 | direction); | ||
1868 | } else { | 1870 | } else { |
1869 | vPtr = dma_map_single(hostdata->dev, | 1871 | vPtr = dma_map_single(hostdata->dev, |
1870 | SCp->request_buffer, | 1872 | SCp->request_buffer, |
@@ -1879,7 +1881,7 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)) | |||
1879 | for(i = 0; i < sg_count; i++) { | 1881 | for(i = 0; i < sg_count; i++) { |
1880 | 1882 | ||
1881 | if(SCp->use_sg) { | 1883 | if(SCp->use_sg) { |
1882 | struct scatterlist *sg = SCp->buffer; | 1884 | struct scatterlist *sg = SCp->request_buffer; |
1883 | 1885 | ||
1884 | vPtr = sg_dma_address(&sg[i]); | 1886 | vPtr = sg_dma_address(&sg[i]); |
1885 | count = sg_dma_len(&sg[i]); | 1887 | count = sg_dma_len(&sg[i]); |
@@ -2042,6 +2044,11 @@ NCR_700_slave_configure(struct scsi_device *SDp) | |||
2042 | struct NCR_700_Host_Parameters *hostdata = | 2044 | struct NCR_700_Host_Parameters *hostdata = |
2043 | (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; | 2045 | (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; |
2044 | 2046 | ||
2047 | SDp->hostdata = kmalloc(GFP_KERNEL, sizeof(struct NCR_700_sense)); | ||
2048 | |||
2049 | if (!SDp->hostdata) | ||
2050 | return -ENOMEM; | ||
2051 | |||
2045 | /* to do here: allocate memory; build a queue_full list */ | 2052 | /* to do here: allocate memory; build a queue_full list */ |
2046 | if(SDp->tagged_supported) { | 2053 | if(SDp->tagged_supported) { |
2047 | scsi_set_tag_type(SDp, MSG_ORDERED_TAG); | 2054 | scsi_set_tag_type(SDp, MSG_ORDERED_TAG); |
@@ -2065,7 +2072,8 @@ NCR_700_slave_configure(struct scsi_device *SDp) | |||
2065 | STATIC void | 2072 | STATIC void |
2066 | NCR_700_slave_destroy(struct scsi_device *SDp) | 2073 | NCR_700_slave_destroy(struct scsi_device *SDp) |
2067 | { | 2074 | { |
2068 | /* to do here: deallocate memory */ | 2075 | kfree(SDp->hostdata); |
2076 | SDp->hostdata = NULL; | ||
2069 | } | 2077 | } |
2070 | 2078 | ||
2071 | static int | 2079 | static int |
diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h index a8c83bb03630..d8041952b1b5 100644 --- a/drivers/scsi/53c700.h +++ b/drivers/scsi/53c700.h | |||
@@ -163,6 +163,8 @@ struct NCR_700_command_slot { | |||
163 | #define NCR_700_SLOT_BUSY (1|NCR_700_SLOT_MAGIC) /* slot has command active on HA */ | 163 | #define NCR_700_SLOT_BUSY (1|NCR_700_SLOT_MAGIC) /* slot has command active on HA */ |
164 | #define NCR_700_SLOT_QUEUED (2|NCR_700_SLOT_MAGIC) /* slot has command to be made active on HA */ | 164 | #define NCR_700_SLOT_QUEUED (2|NCR_700_SLOT_MAGIC) /* slot has command to be made active on HA */ |
165 | __u8 state; | 165 | __u8 state; |
166 | #define NCR_700_FLAG_AUTOSENSE 0x01 | ||
167 | __u8 flags; | ||
166 | int tag; | 168 | int tag; |
167 | __u32 resume_offset; | 169 | __u32 resume_offset; |
168 | struct scsi_cmnd *cmnd; | 170 | struct scsi_cmnd *cmnd; |