X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2F53c700.c;h=68103e508db7077455dd437db6eae86797d63c0c;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=f623d8c392e7c48ef42d36240cce802edd13f544;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index f623d8c39..68103e508 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -114,7 +114,6 @@ * */ #define NCR_700_VERSION "2.8" -#include #include #include #include @@ -125,18 +124,22 @@ #include #include #include +#include +#include +#include +#include #include #include #include #include #include -#include -#include -#include - -#include "scsi.h" -#include "hosts.h" +#include +#include +#include +#include +#include +#include #include #include @@ -164,15 +167,17 @@ MODULE_LICENSE("GPL"); #include "53c700_d.h" -STATIC int NCR_700_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -STATIC int NCR_700_abort(Scsi_Cmnd * SCpnt); -STATIC int NCR_700_bus_reset(Scsi_Cmnd * SCpnt); -STATIC int NCR_700_dev_reset(Scsi_Cmnd * SCpnt); -STATIC int NCR_700_host_reset(Scsi_Cmnd * SCpnt); +STATIC int NCR_700_queuecommand(struct scsi_cmnd *, void (*done)(struct scsi_cmnd *)); +STATIC int NCR_700_abort(struct scsi_cmnd * SCpnt); +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_configure(Scsi_Device *SDpnt); -STATIC void NCR_700_slave_destroy(Scsi_Device *SDpnt); +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); +static int NCR_700_change_queue_type(struct scsi_device *SDpnt, int depth); STATIC struct device_attribute *NCR_700_dev_attrs[]; @@ -233,14 +238,6 @@ 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. * @@ -261,7 +258,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_SDTR_msg[3]*4); + printk(KERN_WARNING "53c700: Period %dns is less than this chip's minimum, setting to %d\n", period*4, NCR_700_MIN_PERIOD*4); period = hostdata->min_period; } XFERP = (period*4 * hostdata->sync_clock)/1000 - 4; @@ -279,18 +276,19 @@ NCR_700_offset_period_to_sxfer(struct NCR_700_Host_Parameters *hostdata, } static inline __u8 -NCR_700_get_SXFER(Scsi_Device *SDp) +NCR_700_get_SXFER(struct scsi_device *SDp) { struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; - return NCR_700_offset_period_to_sxfer(hostdata, spi_offset(SDp), - spi_period(SDp)); + return NCR_700_offset_period_to_sxfer(hostdata, + spi_offset(SDp->sdev_target), + spi_period(SDp->sdev_target)); } struct Scsi_Host * -NCR_700_detect(Scsi_Host_Template *tpnt, - struct NCR_700_Host_Parameters *hostdata) +NCR_700_detect(struct scsi_host_template *tpnt, + struct NCR_700_Host_Parameters *hostdata, struct device *dev) { dma_addr_t pScript, pSlots; __u8 *memory; @@ -315,36 +313,38 @@ NCR_700_detect(Scsi_Host_Template *tpnt, hostdata->status = memory + STATUS_OFFSET; /* all of these offsets are L1_CACHE_BYTES separated. It is fatal * if this isn't sufficient separation to avoid dma flushing issues */ - BUG_ON(!dma_is_consistent(pScript) && L1_CACHE_BYTES < dma_get_cache_alignment()); + BUG_ON(!dma_is_consistent(hostdata->dev, 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 */ tpnt->queuecommand = NCR_700_queuecommand; tpnt->eh_abort_handler = NCR_700_abort; - tpnt->eh_device_reset_handler = NCR_700_dev_reset; tpnt->eh_bus_reset_handler = NCR_700_bus_reset; tpnt->eh_host_reset_handler = NCR_700_host_reset; tpnt->can_queue = NCR_700_COMMAND_SLOTS_PER_HOST; tpnt->sg_tablesize = NCR_700_SG_SEGMENTS; tpnt->cmd_per_lun = NCR_700_CMD_PER_LUN; - tpnt->use_clustering = DISABLE_CLUSTERING; + 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,20 +355,18 @@ NCR_700_detect(Scsi_Host_Template *tpnt, hostdata->slots[j].state = NCR_700_SLOT_FREE; } - for(j = 0; j < sizeof(SCRIPT)/sizeof(SCRIPT[0]); j++) { + for (j = 0; j < ARRAY_SIZE(SCRIPT); 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, + script_patch_32(hostdata->dev, script, MessageLocation, pScript + MSGOUT_OFFSET); - script_patch_32(script, StatusAddress, + script_patch_32(hostdata->dev, script, StatusAddress, pScript + STATUS_OFFSET); - script_patch_32(script, ReceiveMsgAddress, + script_patch_32(hostdata->dev, script, ReceiveMsgAddress, pScript + MSGIN_OFFSET); hostdata->script = script; @@ -376,33 +374,41 @@ NCR_700_detect(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 = 7; + host->max_id = 8; host->max_lun = NCR_700_MAX_LUNS; BUG_ON(NCR_700_transport_template == NULL); host->transportt = NCR_700_transport_template; - host->unique_id = hostdata->base; - host->base = hostdata->base; + host->unique_id = (unsigned long)hostdata->base; hostdata->eh_complete = NULL; 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)" : ""); /* reset the chip */ NCR_700_chip_reset(host); + if (scsi_add_host(host, dev)) { + dev_printk(KERN_ERR, dev, "53c700: scsi_add_host failed\n"); + scsi_host_put(host); + return NULL; + } + + spi_signalling(host) = hostdata->differential ? SPI_SIGNAL_HVD : + SPI_SIGNAL_SE; + return host; } @@ -532,6 +538,7 @@ 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; @@ -561,7 +568,7 @@ free_slot(struct NCR_700_command_slot *slot, the ITL and (if tagged) the ITLQ lists in _queuecommand */ STATIC void save_for_reselection(struct NCR_700_Host_Parameters *hostdata, - Scsi_Cmnd *SCp, __u32 dsp) + struct scsi_cmnd *SCp, __u32 dsp) { /* Its just possible that this gets executed twice */ if(SCp != NULL) { @@ -575,27 +582,25 @@ save_for_reselection(struct NCR_700_Host_Parameters *hostdata, } STATIC inline void -NCR_700_unmap(struct NCR_700_Host_Parameters *hostdata, Scsi_Cmnd *SCp, +NCR_700_unmap(struct NCR_700_Host_Parameters *hostdata, struct scsi_cmnd *SCp, struct NCR_700_command_slot *slot) { - if(SCp->sc_data_direction != SCSI_DATA_NONE && - SCp->sc_data_direction != SCSI_DATA_UNKNOWN) { - enum dma_data_direction direction = SCp->sc_data_direction; + if(SCp->sc_data_direction != DMA_NONE && + SCp->sc_data_direction != DMA_BIDIRECTIONAL) { if(SCp->use_sg) { - dma_unmap_sg(hostdata->dev, SCp->buffer, - SCp->use_sg, direction); + dma_unmap_sg(hostdata->dev, SCp->request_buffer, + SCp->use_sg, SCp->sc_data_direction); } else { - dma_unmap_single(hostdata->dev, - slot->dma_handle, + dma_unmap_single(hostdata->dev, slot->dma_handle, SCp->request_bufflen, - direction); + SCp->sc_data_direction); } } } STATIC inline void NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata, - Scsi_Cmnd *SCp, int result) + struct scsi_cmnd *SCp, int result) { hostdata->state = NCR_700_HOST_FREE; hostdata->cmd = NULL; @@ -604,31 +609,26 @@ 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(SCp->cmnd[0] == REQUEST_SENSE && SCp->cmnd[6] == NCR_700_INTERNAL_SENSE_MAGIC) { + if (slot->flags == NCR_700_FLAG_AUTOSENSE) { + char *cmnd = NCR_700_get_sense_cmnd(SCp->device); #ifdef NCR_700_DEBUG printk(" ORIGINAL CMD %p RETURNED %d, new return is %d sense is\n", SCp, SCp->cmnd[7], result); - print_sense("53c700", SCp); + 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 = 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; - - } + if (result == 0) + result = cmnd[7]; + /* restore the original length */ + SCp->cmd_len = cmnd[8]; + } else + NCR_700_unmap(hostdata, SCp, slot); + free_slot(slot, hostdata); #ifdef NCR_700_DEBUG if(NCR_700_get_depth(SCp->device) == 0 || @@ -780,7 +780,7 @@ NCR_700_chip_reset(struct Scsi_Host *host) STATIC __u32 process_extended_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata, - Scsi_Cmnd *SCp, __u32 dsp, __u32 dsps) + struct scsi_cmnd *SCp, __u32 dsp, __u32 dsps) { __u32 resume_offset = dsp, temp = dsp + 8; __u8 pun = 0xff, lun = 0xff; @@ -793,6 +793,7 @@ process_extended_message(struct Scsi_Host *host, switch(hostdata->msgin[2]) { case A_SDTR_MSG: if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION)) { + struct scsi_target *starget = SCp->device->sdev_target; __u8 period = hostdata->msgin[3]; __u8 offset = hostdata->msgin[4]; @@ -800,22 +801,15 @@ process_extended_message(struct Scsi_Host *host, offset = 0; period = 0; } + + spi_offset(starget) = offset; + spi_period(starget) = period; if(NCR_700_is_flag_set(SCp->device, NCR_700_DEV_PRINT_SYNC_NEGOTIATION)) { - if(spi_offset(SCp->device) != 0) - printk(KERN_INFO "scsi%d: (%d:%d) Synchronous at offset %d, period %dns\n", - host->host_no, pun, lun, - offset, period*4); - else - printk(KERN_INFO "scsi%d: (%d:%d) Asynchronous\n", - host->host_no, pun, lun); + spi_display_xfer_agreement(starget); NCR_700_clear_flag(SCp->device, NCR_700_DEV_PRINT_SYNC_NEGOTIATION); } - - spi_offset(SCp->device) = offset; - spi_period(SCp->device) = period; - NCR_700_set_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); @@ -824,11 +818,12 @@ process_extended_message(struct Scsi_Host *host, } else { /* SDTR message out of the blue, reject it */ - printk(KERN_WARNING "scsi%d Unexpected SDTR msg\n", - host->host_no); + shost_printk(KERN_WARNING, host, + "Unexpected SDTR msg\n"); hostdata->msgout[0] = A_REJECT_MSG; - dma_cache_sync(hostdata->msgout, 1, DMA_TO_DEVICE); - script_patch_16(hostdata->script, MessageCount, 1); + dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE); + script_patch_16(hostdata->dev, hostdata->script, + MessageCount, 1); /* SendMsgOut returns, so set up the return * address */ resume_offset = hostdata->pScript + Ent_SendMessageWithATN; @@ -839,8 +834,9 @@ process_extended_message(struct Scsi_Host *host, printk(KERN_INFO "scsi%d: (%d:%d), Unsolicited WDTR after CMD, Rejecting\n", host->host_no, pun, lun); hostdata->msgout[0] = A_REJECT_MSG; - dma_cache_sync(hostdata->msgout, 1, DMA_TO_DEVICE); - script_patch_16(hostdata->script, MessageCount, 1); + dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE); + script_patch_16(hostdata->dev, hostdata->script, MessageCount, + 1); resume_offset = hostdata->pScript + Ent_SendMessageWithATN; break; @@ -849,12 +845,13 @@ process_extended_message(struct Scsi_Host *host, printk(KERN_INFO "scsi%d (%d:%d): Unexpected message %s: ", host->host_no, pun, lun, NCR_700_phase[(dsps & 0xf00) >> 8]); - print_msg(hostdata->msgin); + spi_print_msg(hostdata->msgin); printk("\n"); /* just reject it */ hostdata->msgout[0] = A_REJECT_MSG; - dma_cache_sync(hostdata->msgout, 1, DMA_TO_DEVICE); - script_patch_16(hostdata->script, MessageCount, 1); + dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE); + script_patch_16(hostdata->dev, hostdata->script, MessageCount, + 1); /* SendMsgOut returns, so set up the return * address */ resume_offset = hostdata->pScript + Ent_SendMessageWithATN; @@ -865,7 +862,7 @@ process_extended_message(struct Scsi_Host *host, STATIC __u32 process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata, - Scsi_Cmnd *SCp, __u32 dsp, __u32 dsps) + struct scsi_cmnd *SCp, __u32 dsp, __u32 dsps) { /* work out where to return to */ __u32 temp = dsp + 8, resume_offset = dsp; @@ -879,7 +876,7 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata #ifdef NCR_700_DEBUG printk("scsi%d (%d:%d): message %s: ", host->host_no, pun, lun, NCR_700_phase[(dsps & 0xf00) >> 8]); - print_msg(hostdata->msgin); + spi_print_msg(hostdata->msgin); printk("\n"); #endif @@ -893,19 +890,23 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata case A_REJECT_MSG: if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION)) { /* Rejected our sync negotiation attempt */ - spi_period(SCp->device) = spi_offset(SCp->device) = 0; + spi_period(SCp->device->sdev_target) = + spi_offset(SCp->device->sdev_target) = 0; NCR_700_set_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); - } else if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING)) { + } else if(SCp != NULL && NCR_700_get_tag_neg_state(SCp->device) == NCR_700_DURING_TAG_NEGOTIATION) { /* rejected our first simple tag message */ - printk(KERN_WARNING "scsi%d (%d:%d) Rejected first tag queue attempt, turning off tag queueing\n", host->host_no, pun, lun); - NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING); - hostdata->tag_negotiated &= ~(1<device->id); + scmd_printk(KERN_WARNING, SCp, + "Rejected first tag queue attempt, turning off tag queueing\n"); + /* we're done negotiating */ + NCR_700_set_tag_neg_state(SCp->device, NCR_700_FINISHED_TAG_NEGOTIATION); + hostdata->tag_negotiated &= ~(1<device->tagged_supported = 0; scsi_deactivate_tcq(SCp->device, host->cmd_per_lun); } else { - printk(KERN_WARNING "scsi%d (%d:%d) Unexpected REJECT Message %s\n", - host->host_no, pun, lun, + shost_printk(KERN_WARNING, host, + "(%d:%d) Unexpected REJECT Message %s\n", + pun, lun, NCR_700_phase[(dsps & 0xf00) >> 8]); /* however, just ignore it */ } @@ -927,12 +928,13 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata host->host_no, pun, lun, NCR_700_phase[(dsps & 0xf00) >> 8]); - print_msg(hostdata->msgin); + spi_print_msg(hostdata->msgin); printk("\n"); /* just reject it */ hostdata->msgout[0] = A_REJECT_MSG; - dma_cache_sync(hostdata->msgout, 1, DMA_TO_DEVICE); - script_patch_16(hostdata->script, MessageCount, 1); + dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE); + script_patch_16(hostdata->dev, hostdata->script, MessageCount, + 1); /* SendMsgOut returns, so set up the return * address */ resume_offset = hostdata->pScript + Ent_SendMessageWithATN; @@ -941,12 +943,12 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata } NCR_700_writel(temp, host, TEMP_REG); /* set us up to receive another message */ - dma_cache_sync(hostdata->msgin, MSG_ARRAY_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE, DMA_FROM_DEVICE); return resume_offset; } STATIC __u32 -process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp, +process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata) { @@ -961,21 +963,27 @@ process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp, if(dsps == A_GOOD_STATUS_AFTER_STATUS) { DEBUG((" COMMAND COMPLETE, status=%02x\n", hostdata->status[0])); - /* OK, if TCQ still on, we know it works */ - NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING); + /* OK, if TCQ still under negotiation, we now know it works */ + if (NCR_700_get_tag_neg_state(SCp->device) == NCR_700_DURING_TAG_NEGOTIATION) + NCR_700_set_tag_neg_state(SCp->device, + NCR_700_FINISHED_TAG_NEGOTIATION); + /* check for contingent allegiance contitions */ if(status_byte(hostdata->status[0]) == CHECK_CONDITION || status_byte(hostdata->status[0]) == COMMAND_TERMINATED) { struct NCR_700_command_slot *slot = (struct NCR_700_command_slot *)SCp->host_scribble; - if(SCp->cmnd[0] == REQUEST_SENSE) { + if(slot->flags == NCR_700_FLAG_AUTOSENSE) { /* OOPS: bad device, returning another * contingent allegiance condition */ - printk(KERN_ERR "scsi%d (%d:%d) broken device is looping in contingent allegiance: ignoring\n", host->host_no, pun, lun); + 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 - print_command(SCp->cmnd); + scsi_print_command(SCp); printk(" cmd %p has status %d, requesting sense\n", SCp, hostdata->status[0]); #endif @@ -987,38 +995,40 @@ process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp, * data associated with the command * here */ NCR_700_unmap(hostdata, SCp, slot); - - 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; + 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; /* 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 */ - SCp->cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; - SCp->cmnd[7] = hostdata->status[0]; - SCp->use_sg = 0; - SCp->sc_data_direction = SCSI_DATA_READ; - dma_sync_single_for_device(hostdata->dev, slot->pCmd, - SCp->cmd_len, DMA_TO_DEVICE); - SCp->request_bufflen = sizeof(SCp->sense_buffer); + cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; + cmnd[7] = hostdata->status[0]; + cmnd[8] = SCp->cmd_len; + SCp->cmd_len = 6; /* command length for + * REQUEST_SENSE */ + slot->pCmd = dma_map_single(hostdata->dev, cmnd, MAX_COMMAND_SIZE, DMA_TO_DEVICE); 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); slot->SG[1].ins = bS_to_host(SCRIPT_RETURN); slot->SG[1].pAddr = 0; slot->resume_offset = hostdata->pScript; - dma_cache_sync(slot->SG, sizeof(slot->SG[0])*2, DMA_TO_DEVICE); - dma_cache_sync(SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); - + dma_cache_sync(hostdata->dev, slot->SG, sizeof(slot->SG[0])*2, DMA_TO_DEVICE); + dma_cache_sync(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); + /* 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; } @@ -1035,12 +1045,13 @@ process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp, // SCp->request_bufflen, // DMA_FROM_DEVICE); // if(((char *)SCp->request_buffer)[7] & 0x02) { - // printk(KERN_INFO "scsi%d: (%d:%d) Enabling Tag Command Queuing\n", host->host_no, pun, lun); - // hostdata->tag_negotiated |= (1<device->id); + // scmd_printk(KERN_INFO, SCp, + // "Enabling Tag Command Queuing\n"); + // hostdata->tag_negotiated |= (1<device, NCR_700_DEV_BEGIN_TAG_QUEUEING); // } else { // NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING); - // hostdata->tag_negotiated &= ~(1<device->id); + // hostdata->tag_negotiated &= ~(1<status[0]); @@ -1048,12 +1059,12 @@ process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp, } else if((dsps & 0xfffff0f0) == A_UNEXPECTED_PHASE) { __u8 i = (dsps & 0xf00) >> 8; - printk(KERN_ERR "scsi%d: (%d:%d), UNEXPECTED PHASE %s (%s)\n", - host->host_no, pun, lun, + scmd_printk(KERN_ERR, SCp, "UNEXPECTED PHASE %s (%s)\n", NCR_700_phase[i], sbcl_to_string(NCR_700_readb(host, SBCL_REG))); - printk(KERN_ERR " len = %d, cmd =", SCp->cmd_len); - print_command(SCp->cmnd); + scmd_printk(KERN_ERR, SCp, " len = %d, cmd =", + SCp->cmd_len); + scsi_print_command(SCp); NCR_700_internal_bus_reset(host); } else if((dsps & 0xfffff000) == A_FATAL) { @@ -1080,7 +1091,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp, __u8 lun; struct NCR_700_command_slot *slot; __u8 reselection_id = hostdata->reselection_id; - Scsi_Device *SDp; + struct scsi_device *SDp; lun = hostdata->msgin[0] & 0x1f; @@ -1095,7 +1106,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp, BUG(); } if(hostdata->msgin[1] == A_SIMPLE_TAG_MSG) { - Scsi_Cmnd *SCp = scsi_find_tag(SDp, hostdata->msgin[2]); + struct scsi_cmnd *SCp = scsi_find_tag(SDp, hostdata->msgin[2]); if(unlikely(SCp == NULL)) { printk(KERN_ERR "scsi%d: (%d:%d) no saved request for tag %d\n", host->host_no, reselection_id, lun, hostdata->msgin[2]); @@ -1103,14 +1114,14 @@ process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp, } slot = (struct NCR_700_command_slot *)SCp->host_scribble; - DEBUG(("53c700: %d:%d:%d, reselection is tag %d, slot %p(%d)\n", - host->host_no, SDp->id, SDp->lun, - hostdata->msgin[2], slot, slot->tag)); + DDEBUG(KERN_DEBUG, SDp, + "reselection is tag %d, slot %p(%d)\n", + hostdata->msgin[2], slot, slot->tag); } else { - Scsi_Cmnd *SCp = scsi_find_tag(SDp, SCSI_NO_TAG); + struct scsi_cmnd *SCp = scsi_find_tag(SDp, SCSI_NO_TAG); if(unlikely(SCp == NULL)) { - printk(KERN_ERR "scsi%d: (%d:%d) no saved request for untagged cmd\n", - host->host_no, reselection_id, lun); + sdev_printk(KERN_ERR, SDp, + "no saved request for untagged cmd\n"); BUG(); } slot = (struct NCR_700_command_slot *)SCp->host_scribble; @@ -1129,11 +1140,12 @@ process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp, hostdata->cmd = slot->cmnd; /* re-patch for this command */ - script_patch_32_abs(hostdata->script, CommandAddress, - slot->pCmd); - script_patch_16(hostdata->script, + script_patch_32_abs(hostdata->dev, hostdata->script, + CommandAddress, slot->pCmd); + script_patch_16(hostdata->dev, hostdata->script, CommandCount, slot->cmnd->cmd_len); - script_patch_32_abs(hostdata->script, SGScriptStartAddress, + script_patch_32_abs(hostdata->dev, hostdata->script, + SGScriptStartAddress, to32bit(&slot->pSG[0].ins)); /* Note: setting SXFER only works if we're @@ -1143,13 +1155,13 @@ process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp, * should therefore always clear ACK */ NCR_700_writeb(NCR_700_get_SXFER(hostdata->cmd->device), host, SXFER_REG); - dma_cache_sync(hostdata->msgin, + dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE, DMA_FROM_DEVICE); - dma_cache_sync(hostdata->msgout, + dma_cache_sync(hostdata->dev, hostdata->msgout, MSG_ARRAY_SIZE, DMA_TO_DEVICE); /* I'm just being paranoid here, the command should * already have been flushed from the cache */ - dma_cache_sync(slot->cmnd->cmnd, + dma_cache_sync(hostdata->dev, slot->cmnd->cmnd, slot->cmnd->cmd_len, DMA_TO_DEVICE); @@ -1213,7 +1225,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp, hostdata->reselection_id = reselection_id; /* just in case we have a stale simple tag message, clear it */ hostdata->msgin[1] = 0; - dma_cache_sync(hostdata->msgin, + dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE, DMA_BIDIRECTIONAL); if(hostdata->tag_negotiated & (1<pScript + Ent_GetReselectionWithTag; @@ -1234,11 +1246,11 @@ process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp, host->host_no, pun, lun, NCR_700_condition[i], NCR_700_phase[j], dsp - hostdata->pScript); if(SCp != NULL) { - print_command(SCp->cmnd); + scsi_print_command(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->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->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); } } } @@ -1270,7 +1282,7 @@ process_selection(struct Scsi_Host *host, __u32 dsp) __u32 resume_offset = 0; struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)host->hostdata[0]; - Scsi_Cmnd *SCp = hostdata->cmd; + struct scsi_cmnd *SCp = hostdata->cmd; __u8 sbcl; for(count = 0; count < 5; count++) { @@ -1329,7 +1341,7 @@ process_selection(struct Scsi_Host *host, __u32 dsp) hostdata->cmd = NULL; /* clear any stale simple tag message */ hostdata->msgin[1] = 0; - dma_cache_sync(hostdata->msgin, MSG_ARRAY_SIZE, + dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE, DMA_BIDIRECTIONAL); if(id == 0xff) { @@ -1373,7 +1385,7 @@ NCR_700_flush_fifo(struct Scsi_Host *host) { /* The queue lock with interrupts disabled must be held on entry to * this function */ STATIC int -NCR_700_start_command(Scsi_Cmnd *SCp) +NCR_700_start_command(struct scsi_cmnd *SCp) { struct NCR_700_command_slot *slot = (struct NCR_700_command_slot *)SCp->host_scribble; @@ -1397,12 +1409,14 @@ NCR_700_start_command(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, + hostdata->msgout[0] = NCR_700_identify((SCp->cmnd[0] != REQUEST_SENSE && + slot->flags != NCR_700_FLAG_AUTOSENSE), 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) { + if(SCp->cmnd[0] == INQUIRY || SCp->cmnd[0] == REQUEST_SENSE || + slot->flags == NCR_700_FLAG_AUTOSENSE) { NCR_700_clear_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC); } @@ -1410,44 +1424,44 @@ NCR_700_start_command(Scsi_Cmnd *SCp) * If a contingent allegiance condition exists, the device * will refuse all tags, so send the request sense as untagged * */ - if((hostdata->tag_negotiated & (1<device->id)) - && (slot->tag != SCSI_NO_TAG && SCp->cmnd[0] != REQUEST_SENSE)) { + if((hostdata->tag_negotiated & (1<tag != SCSI_NO_TAG && SCp->cmnd[0] != REQUEST_SENSE && + slot->flags != NCR_700_FLAG_AUTOSENSE)) { count += scsi_populate_tag_msg(SCp, &hostdata->msgout[count]); } if(hostdata->fast && NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC)) { - memcpy(&hostdata->msgout[count], NCR_700_SDTR_msg, - sizeof(NCR_700_SDTR_msg)); - hostdata->msgout[count+3] = spi_period(SCp->device); - hostdata->msgout[count+4] = spi_offset(SCp->device); - count += sizeof(NCR_700_SDTR_msg); + count += spi_populate_sync_msg(&hostdata->msgout[count], + spi_period(SCp->device->sdev_target), + spi_offset(SCp->device->sdev_target)); NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); } - script_patch_16(hostdata->script, MessageCount, count); + script_patch_16(hostdata->dev, hostdata->script, MessageCount, count); - script_patch_ID(hostdata->script, - Device_ID, 1<device->id); + script_patch_ID(hostdata->dev, hostdata->script, + Device_ID, 1<script, CommandAddress, + script_patch_32_abs(hostdata->dev, hostdata->script, CommandAddress, slot->pCmd); - script_patch_16(hostdata->script, CommandCount, SCp->cmd_len); + script_patch_16(hostdata->dev, hostdata->script, CommandCount, + SCp->cmd_len); /* finally plumb the beginning of the SG list into the script * */ - script_patch_32_abs(hostdata->script, SGScriptStartAddress, - to32bit(&slot->pSG[0].ins)); + script_patch_32_abs(hostdata->dev, hostdata->script, + SGScriptStartAddress, to32bit(&slot->pSG[0].ins)); NCR_700_clear_fifo(SCp->device->host); if(slot->resume_offset == 0) slot->resume_offset = hostdata->pScript; /* now perform all the writebacks and invalidates */ - dma_cache_sync(hostdata->msgout, count, DMA_TO_DEVICE); - dma_cache_sync(hostdata->msgin, MSG_ARRAY_SIZE, + dma_cache_sync(hostdata->dev, hostdata->msgout, count, DMA_TO_DEVICE); + dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE, DMA_FROM_DEVICE); - dma_cache_sync(SCp->cmnd, SCp->cmd_len, DMA_TO_DEVICE); - dma_cache_sync(hostdata->status, 1, DMA_FROM_DEVICE); + dma_cache_sync(hostdata->dev, SCp->cmnd, SCp->cmd_len, DMA_TO_DEVICE); + dma_cache_sync(hostdata->dev, hostdata->status, 1, DMA_FROM_DEVICE); /* set the synchronous period/offset */ NCR_700_writeb(NCR_700_get_SXFER(SCp->device), @@ -1459,7 +1473,7 @@ NCR_700_start_command(Scsi_Cmnd *SCp) } irqreturn_t -NCR_700_intr(int irq, void *dev_id, struct pt_regs *regs) +NCR_700_intr(int irq, void *dev_id) { struct Scsi_Host *host = (struct Scsi_Host *)dev_id; struct NCR_700_Host_Parameters *hostdata = @@ -1481,7 +1495,7 @@ NCR_700_intr(int irq, void *dev_id, struct pt_regs *regs) __u32 dsps; __u8 sstat0 = 0, dstat = 0; __u32 dsp; - Scsi_Cmnd *SCp = hostdata->cmd; + struct scsi_cmnd *SCp = hostdata->cmd; enum NCR_700_Host_State state; handled = 1; @@ -1514,7 +1528,7 @@ NCR_700_intr(int irq, void *dev_id, struct pt_regs *regs) } if(sstat0 & SCSI_RESET_DETECTED) { - Scsi_Device *SDp; + struct scsi_device *SDp; int i; hostdata->state = NCR_700_HOST_BUSY; @@ -1526,11 +1540,11 @@ NCR_700_intr(int irq, void *dev_id, struct pt_regs *regs) /* clear all the negotiated parameters */ __shost_for_each_device(SDp, host) - SDp->hostdata = 0; + NCR_700_clear_flag(SDp, ~0); /* clear all the slots and their pending commands */ for(i = 0; i < NCR_700_COMMAND_SLOTS_PER_HOST; i++) { - Scsi_Cmnd *SCp; + struct scsi_cmnd *SCp; struct NCR_700_command_slot *slot = &hostdata->slots[i]; @@ -1590,7 +1604,7 @@ NCR_700_intr(int irq, void *dev_id, struct pt_regs *regs) printk("scsi%d: (%d:%d) Expected phase mismatch in slot->SG[%d], transferred 0x%x\n", host->host_no, pun, lun, SGcount, data_transfer); - print_command(SCp->cmnd); + scsi_print_command(SCp); if(residual) { printk("scsi%d: (%d:%d) Expected phase mismatch in slot->SG[%d], transferred 0x%x, residual %d\n", host->host_no, pun, lun, @@ -1623,7 +1637,7 @@ NCR_700_intr(int irq, void *dev_id, struct pt_regs *regs) slot->SG[i].ins = bS_to_host(SCRIPT_NOP); slot->SG[i].pAddr = 0; } - dma_cache_sync(slot->SG, sizeof(slot->SG), DMA_TO_DEVICE); + dma_cache_sync(hostdata->dev, slot->SG, sizeof(slot->SG), DMA_TO_DEVICE); /* and pretend we disconnected after * the command phase */ resume_offset = hostdata->pScript + Ent_MsgInDuringData; @@ -1731,7 +1745,7 @@ NCR_700_intr(int irq, void *dev_id, struct pt_regs *regs) } STATIC int -NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *)) +NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)) { struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)SCp->device->host->hostdata[0]; @@ -1752,17 +1766,15 @@ NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *)) * - The blk layer sent and untagged command */ if(NCR_700_get_depth(SCp->device) != 0 - && (!(hostdata->tag_negotiated & (1<device->id)) + && (!(hostdata->tag_negotiated & (1<request))) { - DEBUG((KERN_ERR "scsi%d (%d:%d) has non zero depth %d\n", - SCp->device->host->host_no, SCp->device->id, SCp->device->lun, - NCR_700_get_depth(SCp->device))); + CDEBUG(KERN_ERR, SCp, "has non zero depth %d\n", + NCR_700_get_depth(SCp->device)); return SCSI_MLQUEUE_DEVICE_BUSY; } if(NCR_700_get_depth(SCp->device) >= SCp->device->queue_depth) { - DEBUG((KERN_ERR "scsi%d (%d:%d) has max tag depth %d\n", - SCp->device->host->host_no, SCp->device->id, SCp->device->lun, - NCR_700_get_depth(SCp->device))); + CDEBUG(KERN_ERR, SCp, "has max tag depth %d\n", + NCR_700_get_depth(SCp->device)); return SCSI_MLQUEUE_DEVICE_BUSY; } NCR_700_set_depth(SCp->device, NCR_700_get_depth(SCp->device) + 1); @@ -1781,25 +1793,14 @@ NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *)) #ifdef NCR_700_DEBUG printk("53c700: scsi%d, command ", SCp->device->host->host_no); - print_command(SCp->cmnd); + scsi_print_command(SCp); #endif - if(SCp->device->tagged_supported && !SCp->device->simple_tags - && (hostdata->tag_negotiated &(1<device->id)) == 0 - && NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING)) { - /* upper layer has indicated tags are supported. We don't - * necessarily believe it yet. - * - * NOTE: There is a danger here: the mid layer supports - * tag queuing per LUN. We only support it per PUN because - * of potential reselection issues */ - scsi_activate_tcq(SCp->device, NCR_700_DEFAULT_TAGS); - } - if(blk_rq_tagged(SCp->request) - && (hostdata->tag_negotiated &(1<device->id)) == 0) { - printk(KERN_INFO "scsi%d: (%d:%d) Enabling Tag Command Queuing\n", SCp->device->host->host_no, SCp->device->id, SCp->device->lun); - hostdata->tag_negotiated |= (1<device->id); - NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING); + && (hostdata->tag_negotiated &(1<device) == NCR_700_START_TAG_NEGOTIATION) { + scmd_printk(KERN_ERR, SCp, "Enabling Tag Command Queuing\n"); + hostdata->tag_negotiated |= (1<device, NCR_700_DURING_TAG_NEGOTIATION); } /* here we may have to process an untagged command. The gate @@ -1809,16 +1810,16 @@ NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *)) * FIXME: This will royally screw up on multiple LUN devices * */ if(!blk_rq_tagged(SCp->request) - && (hostdata->tag_negotiated &(1<device->id))) { - printk(KERN_INFO "scsi%d: (%d:%d) Disabling Tag Command Queuing\n", SCp->device->host->host_no, SCp->device->id, SCp->device->lun); - hostdata->tag_negotiated &= ~(1<device->id); + && (hostdata->tag_negotiated &(1<tag_negotiated &= ~(1<tag_negotiated &(1<device->id))) { + if((hostdata->tag_negotiated &(1<device)) { slot->tag = SCp->request->tag; - DEBUG(("53c700 %d:%d:%d, sending out tag %d, slot %p\n", - SCp->device->host->host_no, SCp->device->id, SCp->device->lun, slot->tag, - slot)); + CDEBUG(KERN_DEBUG, SCp, "sending out tag %d, slot %p\n", + slot->tag, slot); } else { slot->tag = SCSI_NO_TAG; /* must populate current_cmnd for scsi_find_tag to work */ @@ -1827,13 +1828,13 @@ NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *)) /* sanity check: some of the commands generated by the mid-layer * have an eccentric idea of their sc_data_direction */ if(!SCp->use_sg && !SCp->request_bufflen - && SCp->sc_data_direction != SCSI_DATA_NONE) { + && SCp->sc_data_direction != DMA_NONE) { #ifdef NCR_700_DEBUG printk("53c700: Command"); - print_command(SCp->cmnd); + scsi_print_command(SCp); printk("Has wrong data direction %d\n", SCp->sc_data_direction); #endif - SCp->sc_data_direction = SCSI_DATA_NONE; + SCp->sc_data_direction = DMA_NONE; } switch (SCp->cmnd[0]) { @@ -1844,20 +1845,20 @@ NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *)) default: /* OK, get it from the command */ switch(SCp->sc_data_direction) { - case SCSI_DATA_UNKNOWN: + case DMA_BIDIRECTIONAL: default: printk(KERN_ERR "53c700: Unknown command for data direction "); - print_command(SCp->cmnd); + scsi_print_command(SCp); move_ins = 0; break; - case SCSI_DATA_NONE: + case DMA_NONE: move_ins = 0; break; - case SCSI_DATA_READ: + case DMA_FROM_DEVICE: move_ins = SCRIPT_MOVE_DATA_IN; break; - case SCSI_DATA_WRITE: + case DMA_TO_DEVICE: move_ins = SCRIPT_MOVE_DATA_OUT; break; } @@ -1872,8 +1873,9 @@ NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *)) __u32 count = 0; if(SCp->use_sg) { - sg_count = dma_map_sg(hostdata->dev, SCp->buffer, - SCp->use_sg, direction); + sg_count = dma_map_sg(hostdata->dev, + SCp->request_buffer, SCp->use_sg, + direction); } else { vPtr = dma_map_single(hostdata->dev, SCp->request_buffer, @@ -1888,7 +1890,7 @@ NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *)) for(i = 0; i < sg_count; i++) { if(SCp->use_sg) { - struct scatterlist *sg = SCp->buffer; + struct scatterlist *sg = SCp->request_buffer; vPtr = sg_dma_address(&sg[i]); count = sg_dma_len(&sg[i]); @@ -1901,9 +1903,9 @@ NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *)) } slot->SG[i].ins = bS_to_host(SCRIPT_RETURN); slot->SG[i].pAddr = 0; - dma_cache_sync(slot->SG, sizeof(slot->SG), DMA_TO_DEVICE); + dma_cache_sync(hostdata->dev, slot->SG, sizeof(slot->SG), DMA_TO_DEVICE); DEBUG((" SETTING %08lx to %x\n", - (&slot->pSG[i].ins), + (&slot->pSG[i].ins), slot->SG[i].ins)); } slot->resume_offset = 0; @@ -1914,13 +1916,13 @@ NCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *)) } STATIC int -NCR_700_abort(Scsi_Cmnd * SCp) +NCR_700_abort(struct scsi_cmnd * SCp) { struct NCR_700_command_slot *slot; - printk(KERN_INFO "scsi%d (%d:%d) New error handler wants to abort command\n\t", - SCp->device->host->host_no, SCp->device->id, SCp->device->lun); - print_command(SCp->cmnd); + scmd_printk(KERN_INFO, SCp, + "New error handler wants to abort command\n\t"); + scsi_print_command(SCp); slot = (struct NCR_700_command_slot *)SCp->host_scribble; @@ -1946,62 +1948,64 @@ NCR_700_abort(Scsi_Cmnd * SCp) } STATIC int -NCR_700_bus_reset(Scsi_Cmnd * SCp) +NCR_700_bus_reset(struct scsi_cmnd * SCp) { - DECLARE_COMPLETION(complete); + DECLARE_COMPLETION_ONSTACK(complete); struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)SCp->device->host->hostdata[0]; - printk(KERN_INFO "scsi%d (%d:%d) New error handler wants BUS reset, cmd %p\n\t", - SCp->device->host->host_no, SCp->device->id, SCp->device->lun, SCp); - print_command(SCp->cmnd); + scmd_printk(KERN_INFO, SCp, + "New error handler wants BUS reset, cmd %p\n\t", SCp); + scsi_print_command(SCp); + /* In theory, eh_complete should always be null because the * eh is single threaded, but just in case we're handling a * reset via sg or something */ - while(hostdata->eh_complete != NULL) { + spin_lock_irq(SCp->device->host->host_lock); + while (hostdata->eh_complete != NULL) { spin_unlock_irq(SCp->device->host->host_lock); - schedule_timeout(HZ/10); + msleep_interruptible(100); spin_lock_irq(SCp->device->host->host_lock); } + hostdata->eh_complete = &complete; NCR_700_internal_bus_reset(SCp->device->host); + spin_unlock_irq(SCp->device->host->host_lock); wait_for_completion(&complete); spin_lock_irq(SCp->device->host->host_lock); + hostdata->eh_complete = NULL; /* Revalidate the transport parameters of the failing device */ if(hostdata->fast) spi_schedule_dv_device(SCp->device); + + spin_unlock_irq(SCp->device->host->host_lock); return SUCCESS; } STATIC int -NCR_700_dev_reset(Scsi_Cmnd * SCp) +NCR_700_host_reset(struct scsi_cmnd * SCp) { - printk(KERN_INFO "scsi%d (%d:%d) New error handler wants device reset\n\t", - SCp->device->host->host_no, SCp->device->id, SCp->device->lun); - print_command(SCp->cmnd); - - return FAILED; -} + scmd_printk(KERN_INFO, SCp, "New error handler wants HOST reset\n\t"); + scsi_print_command(SCp); -STATIC int -NCR_700_host_reset(Scsi_Cmnd * SCp) -{ - printk(KERN_INFO "scsi%d (%d:%d) New error handler wants HOST reset\n\t", - SCp->device->host->host_no, SCp->device->id, SCp->device->lun); - print_command(SCp->cmnd); + spin_lock_irq(SCp->device->host->host_lock); NCR_700_internal_bus_reset(SCp->device->host); NCR_700_chip_reset(SCp->device->host); + + spin_unlock_irq(SCp->device->host->host_lock); + return SUCCESS; } STATIC void -NCR_700_set_period(struct scsi_device *SDp, int period) +NCR_700_set_period(struct scsi_target *STp, int period) { + struct Scsi_Host *SHp = dev_to_shost(STp->dev.parent); struct NCR_700_Host_Parameters *hostdata = - (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; + (struct NCR_700_Host_Parameters *)SHp->hostdata[0]; if(!hostdata->fast) return; @@ -2009,17 +2013,18 @@ NCR_700_set_period(struct scsi_device *SDp, int period) if(period < hostdata->min_period) period = hostdata->min_period; - spi_period(SDp) = period; - NCR_700_clear_flag(SDp, NCR_700_DEV_NEGOTIATED_SYNC); - NCR_700_clear_flag(SDp, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); - NCR_700_set_flag(SDp, NCR_700_DEV_PRINT_SYNC_NEGOTIATION); + spi_period(STp) = period; + spi_flags(STp) &= ~(NCR_700_DEV_NEGOTIATED_SYNC | + NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); + spi_flags(STp) |= NCR_700_DEV_PRINT_SYNC_NEGOTIATION; } STATIC void -NCR_700_set_offset(struct scsi_device *SDp, int offset) +NCR_700_set_offset(struct scsi_target *STp, int offset) { + struct Scsi_Host *SHp = dev_to_shost(STp->dev.parent); struct NCR_700_Host_Parameters *hostdata = - (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; + (struct NCR_700_Host_Parameters *)SHp->hostdata[0]; int max_offset = hostdata->chip710 ? NCR_710_MAX_OFFSET : NCR_700_MAX_OFFSET; @@ -2030,77 +2035,113 @@ NCR_700_set_offset(struct scsi_device *SDp, int offset) offset = max_offset; /* if we're currently async, make sure the period is reasonable */ - if(spi_offset(SDp) == 0 && (spi_period(SDp) < hostdata->min_period || - spi_period(SDp) > 0xff)) - spi_period(SDp) = hostdata->min_period; - - spi_offset(SDp) = offset; - NCR_700_clear_flag(SDp, NCR_700_DEV_NEGOTIATED_SYNC); - NCR_700_clear_flag(SDp, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); - NCR_700_set_flag(SDp, NCR_700_DEV_PRINT_SYNC_NEGOTIATION); + if(spi_offset(STp) == 0 && (spi_period(STp) < hostdata->min_period || + spi_period(STp) > 0xff)) + spi_period(STp) = hostdata->min_period; + + spi_offset(STp) = offset; + spi_flags(STp) &= ~(NCR_700_DEV_NEGOTIATED_SYNC | + NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); + 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(Scsi_Device *SDp) +NCR_700_slave_configure(struct scsi_device *SDp) { struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; /* to do here: allocate memory; build a queue_full list */ if(SDp->tagged_supported) { - /* do TCQ stuff here */ + scsi_set_tag_type(SDp, MSG_ORDERED_TAG); + scsi_activate_tcq(SDp, NCR_700_DEFAULT_TAGS); + NCR_700_set_tag_neg_state(SDp, NCR_700_START_TAG_NEGOTIATION); } else { /* initialise to default depth */ scsi_adjust_queue_depth(SDp, 0, SDp->host->cmd_per_lun); } if(hostdata->fast) { /* Find the correct offset and period via domain validation */ - spi_dv_device(SDp); + if (!spi_initial_dv(SDp->sdev_target)) + spi_dv_device(SDp); } else { - spi_offset(SDp) = 0; - spi_period(SDp) = 0; + spi_offset(SDp->sdev_target) = 0; + spi_period(SDp->sdev_target) = 0; } return 0; } STATIC void -NCR_700_slave_destroy(Scsi_Device *SDp) +NCR_700_slave_destroy(struct scsi_device *SDp) { - /* to do here: deallocate memory */ + kfree(SDp->hostdata); + SDp->hostdata = NULL; } -static ssize_t -NCR_700_store_queue_depth(struct device *dev, const char *buf, size_t count) +static int +NCR_700_change_queue_depth(struct scsi_device *SDp, int depth) { - int depth; + if (depth > NCR_700_MAX_TAGS) + depth = NCR_700_MAX_TAGS; - struct scsi_device *SDp = to_scsi_device(dev); - depth = simple_strtoul(buf, NULL, 0); - if(depth > NCR_700_MAX_TAGS) - return -EINVAL; - scsi_adjust_queue_depth(SDp, MSG_ORDERED_TAG, depth); + scsi_adjust_queue_depth(SDp, scsi_get_tag_type(SDp), depth); + return depth; +} - return count; +static int NCR_700_change_queue_type(struct scsi_device *SDp, int tag_type) +{ + int change_tag = ((tag_type ==0 && scsi_get_tag_type(SDp) != 0) + || (tag_type != 0 && scsi_get_tag_type(SDp) == 0)); + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0]; + + scsi_set_tag_type(SDp, tag_type); + + /* We have a global (per target) flag to track whether TCQ is + * enabled, so we'll be turning it off for the entire target here. + * our tag algorithm will fail if we mix tagged and untagged commands, + * so quiesce the device before doing this */ + if (change_tag) + scsi_target_quiesce(SDp->sdev_target); + + if (!tag_type) { + /* shift back to the default unqueued number of commands + * (the user can still raise this) */ + scsi_deactivate_tcq(SDp, SDp->host->cmd_per_lun); + hostdata->tag_negotiated &= ~(1 << sdev_id(SDp)); + } else { + /* Here, we cleared the negotiation flag above, so this + * will force the driver to renegotiate */ + scsi_activate_tcq(SDp, SDp->queue_depth); + if (change_tag) + NCR_700_set_tag_neg_state(SDp, NCR_700_START_TAG_NEGOTIATION); + } + if (change_tag) + scsi_target_resume(SDp->sdev_target); + + return tag_type; } static ssize_t -NCR_700_show_active_tags(struct device *dev, char *buf) +NCR_700_show_active_tags(struct device *dev, struct device_attribute *attr, char *buf) { struct scsi_device *SDp = to_scsi_device(dev); return snprintf(buf, 20, "%d\n", NCR_700_get_depth(SDp)); } -static struct device_attribute NCR_700_queue_depth_attr = { - .attr = { - .name = "queue_depth", - .mode = S_IWUSR, - }, - .store = NCR_700_store_queue_depth, -}; - static struct device_attribute NCR_700_active_tags_attr = { .attr = { .name = "active_tags", @@ -2110,7 +2151,6 @@ static struct device_attribute NCR_700_active_tags_attr = { }; STATIC struct device_attribute *NCR_700_dev_attrs[] = { - &NCR_700_queue_depth_attr, &NCR_700_active_tags_attr, NULL, };