X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2F53c700.c;h=4ce7438608ecb68a374146276eff3308da099589;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=15ce40a7053a6dfae5ccfcc20fc69b507483106b;hpb=3944158a6d33f94668dbd6bdc32ff5c67bb53ec2;p=linux-2.6.git diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 15ce40a70..4ce743860 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -114,6 +114,7 @@ * */ #define NCR_700_VERSION "2.8" +#include #include #include #include @@ -173,7 +174,6 @@ STATIC int NCR_700_bus_reset(struct scsi_cmnd * SCpnt); STATIC int NCR_700_host_reset(struct scsi_cmnd * SCpnt); STATIC void NCR_700_chip_setup(struct Scsi_Host *host); STATIC void NCR_700_chip_reset(struct Scsi_Host *host); -STATIC int NCR_700_slave_alloc(struct scsi_device *SDpnt); STATIC int NCR_700_slave_configure(struct scsi_device *SDpnt); STATIC void NCR_700_slave_destroy(struct scsi_device *SDpnt); static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth); @@ -238,6 +238,14 @@ static char *NCR_700_SBCL_to_phase[] = { "MSG IN", }; +static __u8 NCR_700_SDTR_msg[] = { + 0x01, /* Extended message */ + 0x03, /* Extended message Length */ + 0x01, /* SDTR Extended message */ + NCR_700_MIN_PERIOD, + NCR_700_MAX_OFFSET +}; + /* This translates the SDTR message offset and period to a value * which can be loaded into the SXFER_REG. * @@ -258,7 +266,7 @@ NCR_700_offset_period_to_sxfer(struct NCR_700_Host_Parameters *hostdata, return 0; if(period < hostdata->min_period) { - printk(KERN_WARNING "53c700: Period %dns is less than this chip's minimum, setting to %d\n", period*4, NCR_700_MIN_PERIOD*4); + printk(KERN_WARNING "53c700: Period %dns is less than this chip's minimum, setting to %d\n", period*4, NCR_700_SDTR_msg[3]*4); period = hostdata->min_period; } XFERP = (period*4 * hostdata->sync_clock)/1000 - 4; @@ -316,7 +324,7 @@ NCR_700_detect(struct scsi_host_template *tpnt, BUG_ON(!dma_is_consistent(pScript) && L1_CACHE_BYTES < dma_get_cache_alignment()); hostdata->slots = (struct NCR_700_command_slot *)(memory + SLOTS_OFFSET); hostdata->dev = dev; - + pSlots = pScript + SLOTS_OFFSET; /* Fill in the missing routines from the host template */ @@ -330,21 +338,21 @@ NCR_700_detect(struct scsi_host_template *tpnt, tpnt->use_clustering = ENABLE_CLUSTERING; tpnt->slave_configure = NCR_700_slave_configure; tpnt->slave_destroy = NCR_700_slave_destroy; - tpnt->slave_alloc = NCR_700_slave_alloc; tpnt->change_queue_depth = NCR_700_change_queue_depth; tpnt->change_queue_type = NCR_700_change_queue_type; - + if(tpnt->name == NULL) tpnt->name = "53c700"; if(tpnt->proc_name == NULL) tpnt->proc_name = "53c700"; + host = scsi_host_alloc(tpnt, 4); if (!host) return NULL; memset(hostdata->slots, 0, sizeof(struct NCR_700_command_slot) * NCR_700_COMMAND_SLOTS_PER_HOST); - for (j = 0; j < NCR_700_COMMAND_SLOTS_PER_HOST; j++) { + for(j = 0; j < NCR_700_COMMAND_SLOTS_PER_HOST; j++) { dma_addr_t offset = (dma_addr_t)((unsigned long)&hostdata->slots[j].SG[0] - (unsigned long)&hostdata->slots[0].SG[0]); hostdata->slots[j].pSG = (struct NCR_700_SG_List *)((unsigned long)(pSlots + offset)); @@ -355,12 +363,14 @@ NCR_700_detect(struct scsi_host_template *tpnt, hostdata->slots[j].state = NCR_700_SLOT_FREE; } - for (j = 0; j < ARRAY_SIZE(SCRIPT); j++) + for(j = 0; j < sizeof(SCRIPT)/sizeof(SCRIPT[0]); j++) { script[j] = bS_to_host(SCRIPT[j]); + } /* adjust all labels to be bus physical */ - for (j = 0; j < PATCHES; j++) + for(j = 0; j < PATCHES; j++) { script[LABELPATCHES[j]] = bS_to_host(pScript + SCRIPT[LABELPATCHES[j]]); + } /* now patch up fixed addresses. */ script_patch_32(script, MessageLocation, pScript + MSGOUT_OFFSET); @@ -374,7 +384,7 @@ NCR_700_detect(struct scsi_host_template *tpnt, dma_sync_single_for_device(hostdata->dev, pScript, sizeof(SCRIPT), DMA_TO_DEVICE); hostdata->state = NCR_700_HOST_FREE; hostdata->cmd = NULL; - host->max_id = 8; + host->max_id = 7; host->max_lun = NCR_700_MAX_LUNS; BUG_ON(NCR_700_transport_template == NULL); host->transportt = NCR_700_transport_template; @@ -383,17 +393,17 @@ NCR_700_detect(struct scsi_host_template *tpnt, host->hostdata[0] = (unsigned long)hostdata; /* kick the chip */ NCR_700_writeb(0xff, host, CTEST9_REG); - if (hostdata->chip710) + if(hostdata->chip710) hostdata->rev = (NCR_700_readb(host, CTEST8_REG)>>4) & 0x0f; else hostdata->rev = (NCR_700_readb(host, CTEST7_REG)>>4) & 0x0f; hostdata->fast = (NCR_700_readb(host, CTEST9_REG) == 0); - if (banner == 0) { + if(banner == 0) { printk(KERN_NOTICE "53c700: Version " NCR_700_VERSION " By James.Bottomley@HansenPartnership.com\n"); banner = 1; } printk(KERN_NOTICE "scsi%d: %s rev %d %s\n", host->host_no, - hostdata->chip710 ? "53c710" : + hostdata->chip710 ? "53c710" : (hostdata->fast ? "53c700-66" : "53c700"), hostdata->rev, hostdata->differential ? "(Differential)" : ""); @@ -538,7 +548,6 @@ find_empty_slot(struct NCR_700_Host_Parameters *hostdata) * finish routine. If we cannot queue the command when it * is properly build, we then change to NCR_700_SLOT_QUEUED */ slot->state = NCR_700_SLOT_BUSY; - slot->flags = 0; hostdata->command_slot_count++; return slot; @@ -588,7 +597,7 @@ NCR_700_unmap(struct NCR_700_Host_Parameters *hostdata, struct scsi_cmnd *SCp, if(SCp->sc_data_direction != DMA_NONE && SCp->sc_data_direction != DMA_BIDIRECTIONAL) { if(SCp->use_sg) { - dma_unmap_sg(hostdata->dev, SCp->request_buffer, + dma_unmap_sg(hostdata->dev, SCp->buffer, SCp->use_sg, SCp->sc_data_direction); } else { dma_unmap_single(hostdata->dev, slot->dma_handle, @@ -609,24 +618,31 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata, struct NCR_700_command_slot *slot = (struct NCR_700_command_slot *)SCp->host_scribble; + NCR_700_unmap(hostdata, SCp, slot); dma_unmap_single(hostdata->dev, slot->pCmd, sizeof(SCp->cmnd), DMA_TO_DEVICE); - if (slot->flags == NCR_700_FLAG_AUTOSENSE) { - char *cmnd = NCR_700_get_sense_cmnd(SCp->device); + if(SCp->cmnd[0] == REQUEST_SENSE && SCp->cmnd[6] == NCR_700_INTERNAL_SENSE_MAGIC) { #ifdef NCR_700_DEBUG printk(" ORIGINAL CMD %p RETURNED %d, new return is %d sense is\n", SCp, SCp->cmnd[7], result); scsi_print_sense("53c700", SCp); #endif - dma_unmap_single(hostdata->dev, slot->dma_handle, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); /* restore the old result if the request sense was * successful */ if(result == 0) - result = cmnd[7]; - } else - NCR_700_unmap(hostdata, SCp, slot); - + result = SCp->cmnd[7]; + /* now restore the original command */ + memcpy((void *) SCp->cmnd, (void *) SCp->data_cmnd, + sizeof(SCp->data_cmnd)); + SCp->request_buffer = SCp->buffer; + SCp->request_bufflen = SCp->bufflen; + SCp->use_sg = SCp->old_use_sg; + SCp->cmd_len = SCp->old_cmd_len; + SCp->sc_data_direction = SCp->sc_old_data_direction; + SCp->underflow = SCp->old_underflow; + + } free_slot(slot, hostdata); #ifdef NCR_700_DEBUG if(NCR_700_get_depth(SCp->device) == 0 || @@ -967,15 +983,13 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, status_byte(hostdata->status[0]) == COMMAND_TERMINATED) { struct NCR_700_command_slot *slot = (struct NCR_700_command_slot *)SCp->host_scribble; - if(slot->flags == NCR_700_FLAG_AUTOSENSE) { + if(SCp->cmnd[0] == REQUEST_SENSE) { /* OOPS: bad device, returning another * contingent allegiance condition */ scmd_printk(KERN_ERR, SCp, "broken device is looping in contingent allegiance: ignoring\n"); NCR_700_scsi_done(hostdata, SCp, hostdata->status[0]); } else { - char *cmnd = - NCR_700_get_sense_cmnd(SCp->device); #ifdef NCR_DEBUG scsi_print_command(SCp); printk(" cmd %p has status %d, requesting sense\n", @@ -989,25 +1003,27 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, * data associated with the command * here */ NCR_700_unmap(hostdata, SCp, slot); - dma_unmap_single(hostdata->dev, slot->pCmd, - sizeof(SCp->cmnd), - DMA_TO_DEVICE); - - cmnd[0] = REQUEST_SENSE; - cmnd[1] = (SCp->device->lun & 0x7) << 5; - cmnd[2] = 0; - cmnd[3] = 0; - cmnd[4] = sizeof(SCp->sense_buffer); - cmnd[5] = 0; + + SCp->cmnd[0] = REQUEST_SENSE; + SCp->cmnd[1] = (SCp->device->lun & 0x7) << 5; + SCp->cmnd[2] = 0; + SCp->cmnd[3] = 0; + SCp->cmnd[4] = sizeof(SCp->sense_buffer); + SCp->cmnd[5] = 0; + SCp->cmd_len = 6; /* Here's a quiet hack: the * REQUEST_SENSE command is six bytes, * so store a flag indicating that * this was an internal sense request * and the original status at the end * of the command */ - cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; - cmnd[7] = hostdata->status[0]; - slot->pCmd = dma_map_single(hostdata->dev, cmnd, MAX_COMMAND_SIZE, DMA_TO_DEVICE); + SCp->cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; + SCp->cmnd[7] = hostdata->status[0]; + SCp->use_sg = 0; + SCp->sc_data_direction = DMA_FROM_DEVICE; + dma_sync_single_for_device(hostdata->dev, slot->pCmd, + SCp->cmd_len, DMA_TO_DEVICE); + SCp->request_bufflen = sizeof(SCp->sense_buffer); slot->dma_handle = dma_map_single(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer)); slot->SG[0].pAddr = bS_to_host(slot->dma_handle); @@ -1019,7 +1035,6 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, /* queue the command for reissue */ slot->state = NCR_700_SLOT_QUEUED; - slot->flags = NCR_700_FLAG_AUTOSENSE; hostdata->state = NCR_700_HOST_FREE; hostdata->cmd = NULL; } @@ -1240,7 +1255,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, if(SCp->use_sg) { for(i = 0; i < SCp->use_sg + 1; i++) { - 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); + 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); } } } @@ -1399,14 +1414,12 @@ NCR_700_start_command(struct scsi_cmnd *SCp) /* keep interrupts disabled until we have the command correctly * set up so we cannot take a selection interrupt */ - hostdata->msgout[0] = NCR_700_identify((SCp->cmnd[0] != REQUEST_SENSE && - slot->flags != NCR_700_FLAG_AUTOSENSE), + hostdata->msgout[0] = NCR_700_identify(SCp->cmnd[0] != REQUEST_SENSE, SCp->device->lun); /* for INQUIRY or REQUEST_SENSE commands, we cannot be sure * if the negotiated transfer parameters still hold, so * always renegotiate them */ - if(SCp->cmnd[0] == INQUIRY || SCp->cmnd[0] == REQUEST_SENSE || - slot->flags == NCR_700_FLAG_AUTOSENSE) { + if(SCp->cmnd[0] == INQUIRY || SCp->cmnd[0] == REQUEST_SENSE) { NCR_700_clear_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); } @@ -1415,16 +1428,17 @@ NCR_700_start_command(struct scsi_cmnd *SCp) * will refuse all tags, so send the request sense as untagged * */ if((hostdata->tag_negotiated & (1<tag != SCSI_NO_TAG && SCp->cmnd[0] != REQUEST_SENSE && - slot->flags != NCR_700_FLAG_AUTOSENSE)) { + && (slot->tag != SCSI_NO_TAG && SCp->cmnd[0] != REQUEST_SENSE)) { count += scsi_populate_tag_msg(SCp, &hostdata->msgout[count]); } if(hostdata->fast && NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC)) { - count += spi_populate_sync_msg(&hostdata->msgout[count], - spi_period(SCp->device->sdev_target), - spi_offset(SCp->device->sdev_target)); + memcpy(&hostdata->msgout[count], NCR_700_SDTR_msg, + sizeof(NCR_700_SDTR_msg)); + hostdata->msgout[count+3] = spi_period(SCp->device->sdev_target); + hostdata->msgout[count+4] = spi_offset(SCp->device->sdev_target); + count += sizeof(NCR_700_SDTR_msg); NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); } @@ -1529,7 +1543,7 @@ NCR_700_intr(int irq, void *dev_id, struct pt_regs *regs) /* clear all the negotiated parameters */ __shost_for_each_device(SDp, host) - NCR_700_clear_flag(SDp, ~0); + SDp->hostdata = NULL; /* clear all the slots and their pending commands */ for(i = 0; i < NCR_700_COMMAND_SLOTS_PER_HOST; i++) { @@ -1862,9 +1876,8 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)) __u32 count = 0; if(SCp->use_sg) { - sg_count = dma_map_sg(hostdata->dev, - SCp->request_buffer, SCp->use_sg, - direction); + sg_count = dma_map_sg(hostdata->dev, SCp->buffer, + SCp->use_sg, direction); } else { vPtr = dma_map_single(hostdata->dev, SCp->request_buffer, @@ -1879,7 +1892,7 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)) for(i = 0; i < sg_count; i++) { if(SCp->use_sg) { - struct scatterlist *sg = SCp->request_buffer; + struct scatterlist *sg = SCp->buffer; vPtr = sg_dma_address(&sg[i]); count = sg_dma_len(&sg[i]); @@ -1939,7 +1952,7 @@ NCR_700_abort(struct scsi_cmnd * SCp) STATIC int NCR_700_bus_reset(struct scsi_cmnd * SCp) { - DECLARE_COMPLETION_ONSTACK(complete); + DECLARE_COMPLETION(complete); struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)SCp->device->host->hostdata[0]; @@ -2034,17 +2047,7 @@ NCR_700_set_offset(struct scsi_target *STp, int offset) spi_flags(STp) |= NCR_700_DEV_PRINT_SYNC_NEGOTIATION; } -STATIC int -NCR_700_slave_alloc(struct scsi_device *SDp) -{ - SDp->hostdata = kzalloc(sizeof(struct NCR_700_Device_Parameters), - GFP_KERNEL); - - if (!SDp->hostdata) - return -ENOMEM; - return 0; -} STATIC int NCR_700_slave_configure(struct scsi_device *SDp) @@ -2075,8 +2078,7 @@ NCR_700_slave_configure(struct scsi_device *SDp) STATIC void NCR_700_slave_destroy(struct scsi_device *SDp) { - kfree(SDp->hostdata); - SDp->hostdata = NULL; + /* to do here: deallocate memory */ } static int