?? ncr5380.c
字號:
#endif
/*
* The SCSI specification calls for a 250 ms timeout for the actual
* selection.
*/
timeout = jiffies + 25;
/*
* XXX very interesting - we're seeing a bounce where the BSY we
* asserted is being reflected / still asserted (propogation delay?)
* and it's detecting as true. Sigh.
*/
while ((jiffies < timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY));
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
if (!(NCR5380_read(STATUS_REG) & SR_BSY)) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
cmd->result = DID_BAD_TARGET << 16;
cmd->scsi_done(cmd);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
#if (NDEBUG & NDEBUG_SELECTION)
printk("scsi%d : target did not respond within 250ms\n",
instance->host_no);
#endif
return 0;
}
/*
* Since we followed the SCSI spec, and raised ATN while SEL
* was true but before BSY was false during selection, the information
* transfer phase should be a MESSAGE OUT phase so that we can send the
* IDENTIFY message.
*
* If SCSI-II tagged queing is enabled, we also send a SIMPLE_QUEUE_TAG
* message (2 bytes) with a tag ID that we increment with every command
* until it wraps back to 0.
*
* XXX - it turns out that there are some broken SCSI-II devices,
* which claim to support tagged queing but fail when more than
* some number of commands are issued at once.
*/
/* Wait for start of REQ/ACK handshake */
while (!(NCR5380_read(STATUS_REG) & SR_REQ));
#if (NDEBUG & NDEBUG_SELECTION)
printk("scsi%d : target %d selected, going into MESSAGE OUT phase.\n",
instance->host_no, cmd->target);
#endif
tmp[0] = IDENTIFY(((instance->irq == IRQ_NONE) ? 0 : 1), cmd->lun);
#ifdef SCSI2
if (scsi_devices[cmd->index].tagged_queue && (tag != TAG_NONE)) {
tmp[1] = SIMPLE_QUEUE_TAG;
if (tag == TAG_NEXT) {
/* 0 is TAG_NONE, used to imply no tag for this command */
if (scsi_devices[cmd->index].current_tag == 0)
scsi_devices[cmd->index].current_tag = 1;
cmd->tag = scsi_devices[cmd->index].current_tag;
scsi_devices[cmd->index].current_tag++;
} else
cmd->tag = (unsigned char) tag;
tmp[2] = cmd->tag;
hostdata->last_message = SIMPLE_QUEUE_TAG;
len = 3;
} else
#endif /* def SCSI2 */
{
len = 1;
cmd->tag=0;
}
/* Send message(s) */
data = tmp;
phase = PHASE_MSGOUT;
NCR5380_transfer_pio(instance, &phase, &len, &data);
#if (NDEBUG & NDEBUG_SELECTION)
printk("scsi%d : nexus established.\n", instance->host_no);
#endif
/* XXX need to handle errors here */
hostdata->connected = cmd;
#ifdef SCSI2
if (!scsi_devices[cmd->index].tagged_queue)
#endif
hostdata->busy[cmd->target] |= (1 << cmd->lun);
initialize_SCp(cmd);
return 0;
}
/*
* Function : int NCR5380_transfer_pio (struct Scsi_Host *instance,
* unsigned char *phase, int *count, unsigned char **data)
*
* Purpose : transfers data in given phase using polled I/O
*
* Inputs : instance - instance of driver, *phase - pointer to
* what phase is expected, *count - pointer to number of
* bytes to transfer, **data - pointer to data pointer.
*
* Returns : -1 when different phase is enterred without transfering
* maximum number of bytes, 0 if all bytes or transfered or exit
* is in same phase.
*
* Also, *phase, *count, *data are modified in place.
*
* XXX Note : handling for bus free may be useful.
*/
/*
* Note : this code is not as quick as it could be, however it
* IS 100% reliable, and for the actual data transfer where speed
* counts, we will always do a pseudo DMA or DMA transfer.
*/
static int NCR5380_transfer_pio (struct Scsi_Host *instance,
unsigned char *phase, int *count, unsigned char **data) {
NCR5380_local_declare();
register unsigned char p = *phase, tmp;
register int c = *count;
register unsigned char *d = *data;
NCR5380_setup(instance);
/*
* The NCR5380 chip will only drive the SCSI bus when the
* phase specified in the appropriate bits of the TARGET COMMAND
* REGISTER match the STATUS REGISTER
*/
NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
do {
/*
* Wait for assertion of REQ, after which the phase bits will be
* valid
*/
while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ));
#if (NDEBUG & NDEBUG_HANDSHAKE)
printk("scsi%d : REQ detected\n", instance->host_no);
#endif
/* Check for phase mismatch */
if ((tmp & PHASE_MASK) != p) {
#if (NDEBUG & NDEBUG_PIO)
printk("scsi%d : phase mismatch\n", instance->host_no);
NCR5380_print_phase(instance);
#endif
break;
}
/* Do actual transfer from SCSI bus to / from memory */
if (!(p & SR_IO))
NCR5380_write(OUTPUT_DATA_REG, *d);
else
*d = NCR5380_read(CURRENT_SCSI_DATA_REG);
++d;
/*
* The SCSI standard suggests that in MSGOUT phase, the initiator
* should drop ATN on the last byte of the message phase
* after REQ has been asserted for the handshake but before
* the initiator raises ACK.
*/
if (!(p & SR_IO)) {
if (!((p & SR_MSG) && c > 1)) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
ICR_ASSERT_DATA);
#if (NDEBUG & NDEBUG_PIO)
NCR5380_print(instance);
#endif
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
ICR_ASSERT_DATA | ICR_ASSERT_ACK);
} else {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
ICR_ASSERT_DATA | ICR_ASSERT_ATN);
#if (NDEBUG & NDEBUG_PIO)
NCR5380_print(instance);
#endif
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
}
} else {
#if (NDEBUG & NDEBUG_PIO)
NCR5380_print(instance);
#endif
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
}
while (NCR5380_read(STATUS_REG) & SR_REQ);
#if (NDEBUG & NDEBUG_HANDSHAKE)
printk("scsi%d : req false, handshake complete\n", instance->host_no);
#endif
if (!(p == PHASE_MSGOUT && c > 1))
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
else
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
} while (--c);
#if (NDEBUG & NDEBUG_PIO)
printk("scsi%d : residual %d\n", instance->host_no, c);
#endif
*count = c;
*data = d;
tmp = NCR5380_read(STATUS_REG);
if (tmp & SR_REQ)
*phase = tmp & PHASE_MASK;
else
*phase = PHASE_UNKNOWN;
if (!c || (*phase == p))
return 0;
else
return -1;
}
#if defined(REAL_DMA) || defined(PSEUDO_DMA) || defined (REAL_DMA_POLL)
/*
* Function : int NCR5380_transfer_dma (struct Scsi_Host *instance,
* unsigned char *phase, int *count, unsigned char **data)
*
* Purpose : transfers data in given phase using either real
* or pseudo DMA.
*
* Inputs : instance - instance of driver, *phase - pointer to
* what phase is expected, *count - pointer to number of
* bytes to transfer, **data - pointer to data pointer.
*
* Returns : -1 when different phase is enterred without transfering
* maximum number of bytes, 0 if all bytes or transfered or exit
* is in same phase.
*
* Also, *phase, *count, *data are modified in place.
*
*/
static int NCR5380_transfer_dma (struct Scsi_Host *instance,
unsigned char *phase, int *count, unsigned char **data) {
NCR5380_local_declare();
register int c = *count;
register unsigned char p = *phase;
register unsigned char *d = *data;
unsigned char tmp;
int foo;
#if defined(REAL_DMA_POLL)
int cnt, toPIO;
unsigned char saved_data = 0, overrun = 0, residue;
#endif
struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
instance->hostdata;
NCR5380_setup(instance);
if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {
*phase = tmp;
return -1;
}
#if defined(REAL_DMA) || defined(REAL_DMA_POLL)
#ifdef READ_OVERRUNS
if (p & SR_IO) {
c -= 2;
}
#endif
#if (NDEBUG & NDEBUG_DMA)
printk("scsi%d : initializing DMA channel %d for %s, %d bytes %s %0x\n",
instance->host_no, instance->dma_channel, (p & SR_IO) ? "reading" :
"writing", c, (p & SR_IO) ? "to" : "from", (unsigned) d);
#endif
hostdata->dma_len = (p & SR_IO) ?
NCR5380_dma_read_setup(instance, d, c) :
NCR5380_dma_write_setup(instance, d, c);
#endif
NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
#ifdef REAL_DMA
NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);
#elif defined(REAL_DMA_POLL)
NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE);
#else
/*
* Note : on my sample board, watch-dog timeouts occured when interrupts
* were not disabled for the duration of a single DMA transfer, from
* before the setting of DMA mode to after transfer of the last byte.
*/
#if defined(PSEUDO_DMA) && !defined(UNSAFE)
cli();
#endif
NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE);
#endif /* def REAL_DMA */
#if (NDEBUG & NDEBUG_DMA) & 0
printk("scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG));
#endif
if (p & SR_IO)
NCR5380_write(START_DMA_INITIATOR_RECIEVE_REG, 0);
else {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
NCR5380_write(START_DMA_SEND_REG, 0);
}
#if defined(REAL_DMA_POLL)
do {
tmp = NCR5380_read(BUS_AND_STATUS_REG);
} while ((tmp & BASR_PHASE_MATCH) && !(tmp & (BASR_BUSY_ERROR |
BASR_END_DMA_TRANSFER)));
/*
At this point, either we've completed DMA, or we have a phase mismatch,
or we've unexpectedly lost BUSY (which is a real error).
For write DMAs, we want to wait until the last byte has been
transferred out over the bus before we turn off DMA mode. Alas, there
seems to be no terribly good way of doing this on a 5380 under all
conditions. For non-scatter-gather operations, we can wait until REQ
and ACK both go false, or until a phase mismatch occurs. Gather-writes
are nastier, since the device will be expecting more data than we
are prepared to send it, and REQ will remain asserted. On a 53C8[01] we
could test LAST BIT SENT to assure transfer (I imagine this is precisely
why this signal was added to the newer chips) but on the older 538[01]
this signal does not exist. The workaround for this lack is a watchdog;
we bail out of the wait-loop after a modest amount of wait-time if
the usual exit conditions are not met. Not a terribly clean or
correct solution :-%
Reads are equally tricky due to a nasty characteristic of the NCR5380.
If the chip is in DMA mode for an READ, it will respond to a target's
REQ by latching the SCSI data into the INPUT DATA register and asserting
ACK, even if it has _already_ been notified by the DMA controller that
the current DMA transfer has completed! If the NCR5380 is then taken
out of DMA mode, this already-acknowledged byte is lost.
This is not a problem for "one DMA transfer per command" reads, because
the situation will never arise... either all of the data is DMA'ed
properly, or the target switches to MESSAGE IN phase to signal a
disconnection (either operation bringing the DMA to a clean halt).
However, in order to handle scatter-reads, we must work around the
problem. The chosen fix is to DMA N-2 bytes, then check for the
condition before taking the NCR5380 out of DMA mode. One or two extra
bytes are tranferred via PIO as necessary to fill out the original
request.
*/
if (p & SR_IO) {
#ifdef READ_OVERRUNS
udelay(10);
if (((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH|BASR_ACK)) ==
(BASR_PHASE_MATCH | BASR_ACK))) {
saved_data = NCR5380_read(INPUT_DATA_REGISTER);
overrun = 1;
}
#endif
} else {
int limit = 100;
while (((tmp = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_ACK) ||
(NCR5380_read(STATUS_REG) & SR_REQ)) {
if (!(tmp & BASR_PHASE_MATCH)) break;
if (--limit < 0) break;
}
}
#if (NDEBUG & NDEBUG_DMA)
printk("scsi%d : polled DMA transfer complete, basr 0x%X, sr 0x%X\n",
instance->host_no, tmp, NCR5380_read(STATUS_REG));
#endif
NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
residue = NCR5380_dma_residual(instance);
c -= residue;
*count -= c;
*data += c;
*phase = NCR5380_read(STATUS_REG) & PHASE_MASK;
#ifdef READ_OVERRUNS
if (*phase == p && (p & SR_IO) && residue == 0) {
if (overrun) {
#if (NDEBUG & NDEBUG_DMA)
printk("Got an input overrun, using saved byte\n");
#endif
**data = saved_data;
*data += 1;
*count -= 1;
cnt = toPIO = 1;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -