* */
#define NCR_700_VERSION "2.8"
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/string.h>
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);
"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.
*
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;
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 */
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));
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);
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;
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)" : "");
* 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;
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,
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 ||
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",
* 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);
/* 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;
}
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);
}
}
}
/* 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);
}
* will refuse all tags, so send the request sense as untagged
* */
if((hostdata->tag_negotiated & (1<<scmd_id(SCp)))
- && (slot->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);
}
/* 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++) {
__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,
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]);
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];
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)
STATIC void
NCR_700_slave_destroy(struct scsi_device *SDp)
{
- kfree(SDp->hostdata);
- SDp->hostdata = NULL;
+ /* to do here: deallocate memory */
}
static int