Newer
Older
/* ++guenther: possible race with Falcon locking */
if (
!is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE)
!(hostdata->busy[tmp->device->id] & (1 << lun))
) {
/* ++guenther: just to be sure, this must be atomic */
local_irq_disable();
if (prev) {
REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
} else {
REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp));
hostdata->issue_queue = NEXT(tmp);
}
/* reenable interrupts after finding one */
local_irq_restore(flags);
/*
* Attempt to establish an I_T_L nexus here.
* On success, instance->hostdata->connected is set.
* On failure, we must add the command back to the
* issue queue so we can keep trying.
*/
dprintk(NDEBUG_MAIN, "scsi%d: main(): command for target %d "
"lun %d removed from issue_queue\n",
/*
* REQUEST SENSE commands are issued without tagged
* queueing, even on SCSI-II devices because the
* contingent allegiance condition exists for the
* entire unit.
*/
/* ++roman: ...and the standard also requires that
* REQUEST SENSE command are untagged.
*/
cmd_get_tag(tmp, tmp->cmnd[0] != REQUEST_SENSE);
if (!NCR5380_select(instance, tmp)) {
/* release if target did not response! */
maybe_release_dma_irq(instance);
local_irq_restore(flags);
break;
} else {
local_irq_disable();
LIST(tmp, hostdata->issue_queue);
SET_NEXT(tmp, hostdata->issue_queue);
dprintk(NDEBUG_MAIN, "scsi%d: main(): select() failed, "
"returned to issue_queue\n", HOSTNO);
if (hostdata->connected)
break;
}
} /* if target/lun/target queue is not busy */
} /* for issue_queue */
} /* if (!hostdata->connected) */
if (hostdata->connected
dprintk(NDEBUG_MAIN, "scsi%d: main: performing information transfer\n",
HOSTNO);
NCR5380_information_transfer(instance);
dprintk(NDEBUG_MAIN, "scsi%d: main: done set false\n", HOSTNO);
done = 0;
}
} while (!done);
/* Better allow ints _after_ 'main_running' has been cleared, else
an interrupt could believe we'll pick up the work it left for
us, but we won't see it anymore here... */
hostdata->main_running = 0;
}
#ifdef REAL_DMA
/*
* Function : void NCR5380_dma_complete (struct Scsi_Host *instance)
*
* Purpose : Called by interrupt handler when DMA finishes or a phase
* mismatch occurs (which would finish the DMA transfer).
*
* Inputs : instance - this instance of the NCR5380.
*
*/
static void NCR5380_dma_complete(struct Scsi_Host *instance)
int saved_data = 0, overrun = 0;
unsigned char p;
if (!hostdata->connected) {
printk(KERN_WARNING "scsi%d: received end of DMA interrupt with "
"no connected cmd\n", HOSTNO);
return;
if (hostdata->read_overruns) {
p = hostdata->connected->SCp.phase;
if (p & SR_IO) {
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_REG);
overrun = 1;
dprintk(NDEBUG_DMA, "scsi%d: read overrun handled\n", HOSTNO);
dprintk(NDEBUG_DMA, "scsi%d: real DMA transfer complete, basr 0x%X, sr 0x%X\n",
HOSTNO, NCR5380_read(BUS_AND_STATUS_REG),
NCR5380_read(STATUS_REG));
#if defined(CONFIG_SUN3)
if ((sun3scsi_dma_finish(rq_data_dir(hostdata->connected->request)))) {
pr_err("scsi%d: overrun in UDC counter -- not prepared to deal with this!\n",
instance->host_no);
BUG();
}
/* make sure we're not stuck in a data phase */
if ((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH | BASR_ACK)) ==
(BASR_PHASE_MATCH | BASR_ACK)) {
pr_err("scsi%d: BASR %02x\n", instance->host_no,
NCR5380_read(BUS_AND_STATUS_REG));
pr_err("scsi%d: bus stuck in data phase -- probably a single byte overrun!\n",
instance->host_no);
BUG();
}
#endif
(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
transferred = hostdata->dma_len - NCR5380_dma_residual(instance);
hostdata->dma_len = 0;
data = (unsigned char **)&hostdata->connected->SCp.ptr;
count = &hostdata->connected->SCp.this_residual;
*data += transferred;
*count -= transferred;
if (hostdata->read_overruns) {
if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) {
cnt = toPIO = hostdata->read_overruns;
dprintk(NDEBUG_DMA, "Got an input overrun, using saved byte\n");
*(*data)++ = saved_data;
(*count)--;
cnt--;
toPIO--;
}
dprintk(NDEBUG_DMA, "Doing %d-byte PIO to 0x%08lx\n", cnt, (long)*data);
NCR5380_transfer_pio(instance, &p, &cnt, data);
*count -= toPIO - cnt;
}
/**
* NCR5380_intr - generic NCR5380 irq handler
* @irq: interrupt number
* @dev_id: device info
* Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
* from the disconnected queue, and restarting NCR5380_main()
* as required.
static irqreturn_t NCR5380_intr(int irq, void *dev_id)
struct Scsi_Host *instance = dev_id;
int done = 1, handled = 0;
unsigned char basr;
dprintk(NDEBUG_INTR, "scsi%d: NCR5380 irq triggered\n", HOSTNO);
/* Look for pending interrupts */
basr = NCR5380_read(BUS_AND_STATUS_REG);
dprintk(NDEBUG_INTR, "scsi%d: BASR=%02x\n", HOSTNO, basr);
/* dispatch to appropriate routine if found and done=0 */
if (basr & BASR_IRQ) {
NCR5380_dprint(NDEBUG_INTR, instance);
if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) {
done = 0;
dprintk(NDEBUG_INTR, "scsi%d: SEL interrupt\n", HOSTNO);
NCR5380_reselect(instance);
(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
} else if (basr & BASR_PARITY_ERROR) {
dprintk(NDEBUG_INTR, "scsi%d: PARITY interrupt\n", HOSTNO);
(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
} else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {
dprintk(NDEBUG_INTR, "scsi%d: RESET interrupt\n", HOSTNO);
(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
} else {
/*
* The rest of the interrupt conditions can occur only during a
* DMA transfer
*/
/*
* We should only get PHASE MISMATCH and EOP interrupts if we have
* DMA enabled, so do a sanity check based on the current setting
* of the MODE register.
*/
if ((NCR5380_read(MODE_REG) & MR_DMA_MODE) &&
((basr & BASR_END_DMA_TRANSFER) ||
!(basr & BASR_PHASE_MATCH))) {
dprintk(NDEBUG_INTR, "scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO);
NCR5380_dma_complete( instance );
done = 0;
} else
/* MS: Ignore unknown phase mismatch interrupts (caused by EOP interrupt) */
dprintk(NDEBUG_INTR, "scsi%d: unknown interrupt, "
"BASR 0x%x, MR 0x%x, SR 0x%x\n",
HOSTNO, basr, NCR5380_read(MODE_REG),
NCR5380_read(STATUS_REG));
(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
#ifdef SUN3_SCSI_VME
dregs->csr |= CSR_DMA_ENABLE;
#endif
}
} /* if !(SELECTION || PARITY) */
handled = 1;
} /* BASR & IRQ */ else {
printk(KERN_NOTICE "scsi%d: interrupt without IRQ bit set in BASR, "
"BASR 0x%X, MR 0x%X, SR 0x%x\n", HOSTNO, basr,
NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));
(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
#ifdef SUN3_SCSI_VME
dregs->csr |= CSR_DMA_ENABLE;
#endif
dprintk(NDEBUG_INTR, "scsi%d: in int routine, calling main\n", HOSTNO);
/* Put a call to NCR5380_main() on the queue... */
queue_main(shost_priv(instance));
* Function : int NCR5380_select(struct Scsi_Host *instance,
* struct scsi_cmnd *cmd)
*
* Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command,
* including ARBITRATION, SELECTION, and initial message out for
* IDENTIFY and queue messages.
* Inputs : instance - instantiation of the 5380 driver on which this
* target lives, cmd - SCSI command to execute.
* Returns : -1 if selection could not execute for some reason,
* 0 if selection succeeded or failed because the target
* did not respond.
* Side effects :
* If bus busy, arbitration failed, etc, NCR5380_select() will exit
* with registers as they should have been on entry - ie
* SELECT_ENABLE will be set appropriately, the NCR5380
* will cease to drive any SCSI bus signals.
*
* If successful : I_T_L or I_T_L_Q nexus will be established,
* instance->connected will be set to cmd.
* SELECT interrupt will be disabled.
* If failed (no target) : cmd->scsi_done() will be called, and the
* cmd->result host byte set to DID_BAD_TARGET.
*/
static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
SETUP_HOSTDATA(instance);
unsigned char tmp[3], phase;
unsigned char *data;
int len;
unsigned long timeout;
unsigned long flags;
hostdata->restart_select = 0;
NCR5380_dprint(NDEBUG_ARBITRATION, instance);
dprintk(NDEBUG_ARBITRATION, "scsi%d: starting arbitration, id = %d\n", HOSTNO,
instance->this_id);
/*
* Set the phase bits to 0, otherwise the NCR5380 won't drive the
* data bus during SELECTION.
*/
local_irq_save(flags);
if (hostdata->connected) {
local_irq_restore(flags);
return -1;
}
NCR5380_write(TARGET_COMMAND_REG, 0);
/*
* Start arbitration.
*/
NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
NCR5380_write(MODE_REG, MR_ARBITRATE);
/* Wait for arbitration logic to complete */
{
unsigned long timeout = jiffies + 2*NCR_TIMEOUT;
while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) &&
time_before(jiffies, timeout) && !hostdata->connected)
;
if (time_after_eq(jiffies, timeout)) {
printk("scsi : arbitration timeout at %d\n", __LINE__);
NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return -1;
}
}
while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) &&
!hostdata->connected)
;
dprintk(NDEBUG_ARBITRATION, "scsi%d: arbitration complete\n", HOSTNO);
if (hostdata->connected) {
NCR5380_write(MODE_REG, MR_BASE);
return -1;
}
/*
* The arbitration delay is 2.2us, but this is a minimum and there is
* no maximum so we can safely sleep for ceil(2.2) usecs to accommodate
* the integral nature of udelay().
*
*/
udelay(3);
/* Check for lost arbitration */
if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
(NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) ||
(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
hostdata->connected) {
NCR5380_write(MODE_REG, MR_BASE);
dprintk(NDEBUG_ARBITRATION, "scsi%d: lost arbitration, deasserting MR_ARBITRATE\n",
/* after/during arbitration, BSY should be asserted.
IBM DPES-31080 Version S31Q works now */
/* Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman) */
NCR5380_write(INITIATOR_COMMAND_REG,
ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY);
if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
hostdata->connected) {
NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
dprintk(NDEBUG_ARBITRATION, "scsi%d: lost arbitration, deasserting ICR_ASSERT_SEL\n",
HOSTNO);
return -1;
}
/*
* Again, bus clear + bus settle time is 1.2us, however, this is
* a minimum so we'll udelay ceil(1.2)
*/
/* ++roman: But some targets (see above :-) seem to need a bit more... */
udelay(15);
if (hostdata->connected) {
NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
return -1;
}
dprintk(NDEBUG_ARBITRATION, "scsi%d: won arbitration\n", HOSTNO);
/*
* Now that we have won arbitration, start Selection process, asserting
* the host and target ID's on the SCSI bus.
*/
NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->device->id)));
/*
* Raise ATN while SEL is true before BSY goes false from arbitration,
* since this is the only way to guarantee that we'll get a MESSAGE OUT
* phase immediately after selection.
*/
NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY |
ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL ));
/*
* Reselect interrupts must be turned off prior to the dropping of BSY,
* otherwise we will trigger an interrupt.
*/
if (hostdata->connected) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
return -1;
}
NCR5380_write(SELECT_ENABLE_REG, 0);
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
/*
* The initiator shall then wait at least two deskew delays and release
* the BSY signal.
*/
udelay(1); /* wingel -- wait two bus deskew delay >2*45ns */
/* Reset BSY */
NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA |
ICR_ASSERT_ATN | ICR_ASSERT_SEL));
/*
* Something weird happens when we cease to drive BSY - looks
* like the board/chip is letting us do another read before the
* appropriate propagation delay has expired, and we're confusing
* a BSY signal from ourselves as the target's response to SELECTION.
*
* A small delay (the 'C++' frontend breaks the pipeline with an
* unnecessary jump, making it work on my 386-33/Trantor T128, the
* tighter 'C' code breaks and requires this) solves the problem -
* the 1 us delay is arbitrary, and only used because this delay will
* be the same on other platforms and since it works here, it should
* work there.
*
* wingel suggests that this could be due to failing to wait
* one deskew delay.
*/
dprintk(NDEBUG_SELECTION, "scsi%d: selecting target %d\n", HOSTNO, cmd->device->id);
/*
* The SCSI specification calls for a 250 ms timeout for the actual
* selection.
*/
timeout = jiffies + msecs_to_jiffies(250);
/*
* XXX very interesting - we're seeing a bounce where the BSY we
* asserted is being reflected / still asserted (propagation delay?)
* and it's detecting as true. Sigh.
*/
/* ++roman: If a target conformed to the SCSI standard, it wouldn't assert
* IO while SEL is true. But again, there are some disks out the in the
* world that do that nevertheless. (Somebody claimed that this announces
* reselection capability of the target.) So we better skip that test and
* only wait for BSY... (Famous german words: Der Klügere gibt nach :-)
*/
while (time_before(jiffies, timeout) &&
!(NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO)))
;
if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
NCR5380_reselect(instance);
printk(KERN_ERR "scsi%d: reselection after won arbitration?\n",
HOSTNO);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return -1;
}
while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY))
;
/*
* No less than two deskew delays after the initiator detects the
* BSY signal is true, it shall release the SEL signal and may
* change the DATA BUS. -wingel
*/
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
if (!(NCR5380_read(STATUS_REG) & SR_BSY)) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
if (hostdata->targets_present & (1 << cmd->device->id)) {
printk(KERN_ERR "scsi%d: weirdness\n", HOSTNO);
if (hostdata->restart_select)
printk(KERN_NOTICE "\trestart select\n");
NCR5380_dprint(NDEBUG_ANY, instance);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return -1;
}
cmd->result = DID_BAD_TARGET << 16;
cmd->scsi_done(cmd);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
dprintk(NDEBUG_SELECTION, "scsi%d: target did not respond within 250ms\n", HOSTNO);
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return 0;
}
hostdata->targets_present |= (1 << cmd->device->id);
/*
* 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 queuing 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 queuing 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))
;
dprintk(NDEBUG_SELECTION, "scsi%d: target %d selected, going into MESSAGE OUT phase.\n",
HOSTNO, cmd->device->id);
tmp[0] = IDENTIFY(1, cmd->device->lun);
if (cmd->tag != TAG_NONE) {
tmp[1] = hostdata->last_message = SIMPLE_QUEUE_TAG;
tmp[2] = cmd->tag;
len = 3;
} else
len = 1;
/* Send message(s) */
data = tmp;
phase = PHASE_MSGOUT;
NCR5380_transfer_pio(instance, &phase, &len, &data);
dprintk(NDEBUG_SELECTION, "scsi%d: nexus established.\n", HOSTNO);
/* XXX need to handle errors here */
hostdata->connected = cmd;
hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
#endif
#ifdef SUN3_SCSI_VME
dregs->csr |= CSR_INTR;
#endif
/*
* 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 entered without transferring
* maximum number of bytes, 0 if all bytes are transferred or exit
* 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)
register unsigned char p = *phase, tmp;
register int c = *count;
register unsigned char *d = *data;
/*
* 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))
;
dprintk(NDEBUG_HANDSHAKE, "scsi%d: REQ detected\n", HOSTNO);
/* Check for phase mismatch */
if ((tmp & PHASE_MASK) != p) {
dprintk(NDEBUG_PIO, "scsi%d: phase mismatch\n", HOSTNO);
NCR5380_dprint_phase(NDEBUG_PIO, instance);
/* 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);
/*
* 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);
NCR5380_dprint(NDEBUG_PIO, instance);
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);
NCR5380_dprint(NDEBUG_PIO, instance);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
}
} else {
NCR5380_dprint(NDEBUG_PIO, instance);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
}
while (NCR5380_read(STATUS_REG) & SR_REQ)
;
dprintk(NDEBUG_HANDSHAKE, "scsi%d: req false, handshake complete\n", HOSTNO);
/*
* We have several special cases to consider during REQ/ACK handshaking :
* 1. We were in MSGOUT phase, and we are on the last byte of the
* message. ATN must be dropped as ACK is dropped.
*
* 2. We are in a MSGIN phase, and we are on the last byte of the
* message. We must exit with ACK asserted, so that the calling
* code may raise ATN before dropping ACK to reject the message.
*
* 3. ACK and ATN are clear and the target may proceed as normal.
*/
if (!(p == PHASE_MSGIN && c == 1)) {
if (p == PHASE_MSGOUT && c > 1)
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
else
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
}
} while (--c);
dprintk(NDEBUG_PIO, "scsi%d: residual %d\n", HOSTNO, c);
*count = c;
*data = d;
tmp = NCR5380_read(STATUS_REG);
/* The phase read from the bus is valid if either REQ is (already)
* asserted or if ACK hasn't been released yet. The latter is the case if
* we're in MSGIN and all wanted bytes have been received.
*/
if ((tmp & SR_REQ) || (p == PHASE_MSGIN && c == 0))
*phase = tmp & PHASE_MASK;
else
*phase = PHASE_UNKNOWN;
if (!c || (*phase == p))
return 0;
else
return -1;
}
/*
* Function : do_abort (Scsi_Host *host)
*
* Purpose : abort the currently established nexus. Should only be
* called from a routine which can drop into a
*
* Returns : 0 on success, -1 on failure.
*/
static int do_abort(struct Scsi_Host *instance)
unsigned char tmp, *msgptr, phase;
int len;
/* Request message out phase */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
/*
* Wait for the target to indicate a valid phase by asserting
* REQ. Once this happens, we'll have either a MSGOUT phase
* and can immediately send the ABORT message, or we'll have some
* other phase and will have to source/sink data.
*
* We really don't care what value was on the bus or what value
* the target sees, so we just handshake.
*/
while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ))
;
NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
if ((tmp & PHASE_MASK) != PHASE_MSGOUT) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN |
ICR_ASSERT_ACK);
while (NCR5380_read(STATUS_REG) & SR_REQ)
;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
}
tmp = ABORT;
msgptr = &tmp;
len = 1;
phase = PHASE_MSGOUT;
NCR5380_transfer_pio(instance, &phase, &len, &msgptr);
/*
* If we got here, and the command completed successfully,
* we're about to go into bus free state.
*/
return len ? -1 : 0;
/*
* 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 entered without transferring
* maximum number of bytes, 0 if all bytes or transferred or exit
* 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)
SETUP_HOSTDATA(instance);
register int c = *count;
register unsigned char p = *phase;
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
unsigned long flags;
#if defined(CONFIG_SUN3)
/* sanity check */
if (!sun3_dma_setup_done) {
pr_err("scsi%d: transfer_dma without setup!\n",
instance->host_no);
BUG();
}
hostdata->dma_len = c;
dprintk(NDEBUG_DMA, "scsi%d: initializing DMA for %s, %d bytes %s %p\n",
instance->host_no, (p & SR_IO) ? "reading" : "writing",
c, (p & SR_IO) ? "to" : "from", *data);
/* netbsd turns off ints here, why not be safe and do it too */
local_irq_save(flags);
/* send start chain */
sun3scsi_dma_start(c, *data);
if (p & SR_IO) {
NCR5380_write(TARGET_COMMAND_REG, 1);
NCR5380_read(RESET_PARITY_INTERRUPT_REG);
NCR5380_write(INITIATOR_COMMAND_REG, 0);
NCR5380_write(MODE_REG,
(NCR5380_read(MODE_REG) | MR_DMA_MODE | MR_ENABLE_EOP_INTR));
NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
} else {
NCR5380_write(TARGET_COMMAND_REG, 0);
NCR5380_read(RESET_PARITY_INTERRUPT_REG);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_DATA);
NCR5380_write(MODE_REG,
(NCR5380_read(MODE_REG) | MR_DMA_MODE | MR_ENABLE_EOP_INTR));
NCR5380_write(START_DMA_SEND_REG, 0);
}
#ifdef SUN3_SCSI_VME
dregs->csr |= CSR_DMA_ENABLE;
#endif
local_irq_restore(flags);
sun3_dma_active = 1;
#else /* !defined(CONFIG_SUN3) */
register unsigned char *d = *data;
unsigned char tmp;
if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {
*phase = tmp;
return -1;
}
if (hostdata->read_overruns && (p & SR_IO))
c -= hostdata->read_overruns;
dprintk(NDEBUG_DMA, "scsi%d: initializing DMA for %s, %d bytes %s %p\n",
HOSTNO, (p & SR_IO) ? "reading" : "writing",
c, (p & SR_IO) ? "to" : "from", d);
NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);
if (!(hostdata->flags & FLAG_LATE_DMA_SETUP)) {
/* On the Medusa, it is a must to initialize the DMA before
* starting the NCR. This is also the cleaner way for the TT.
*/
local_irq_save(flags);
hostdata->dma_len = (p & SR_IO) ?
NCR5380_dma_read_setup(instance, d, c) :
NCR5380_dma_write_setup(instance, d, c);
local_irq_restore(flags);
}
if (p & SR_IO)
NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
else {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);
NCR5380_write(START_DMA_SEND_REG, 0);
}
if (hostdata->flags & FLAG_LATE_DMA_SETUP) {
/* On the Falcon, the DMA setup must be done after the last */
/* NCR access, else the DMA setup gets trashed!
*/
local_irq_save(flags);
hostdata->dma_len = (p & SR_IO) ?
NCR5380_dma_read_setup(instance, d, c) :
NCR5380_dma_write_setup(instance, d, c);
local_irq_restore(flags);
}
#endif /* !defined(CONFIG_SUN3) */
}
#endif /* defined(REAL_DMA) */
/*
* Function : NCR5380_information_transfer (struct Scsi_Host *instance)
*
* Purpose : run through the various SCSI phases and do as the target
* directs us to. Operates on the currently connected command,
* instance->connected.
*
* Inputs : instance, instance for which we are doing commands
*
* Side effects : SCSI things happen, the disconnected queue will be
* modified if a command disconnects, *instance->connected will
* change.
*
* XXX Note : we need to watch for bus free or a reset condition here
* to recover from an unexpected bus free condition.
static void NCR5380_information_transfer(struct Scsi_Host *instance)
SETUP_HOSTDATA(instance);
unsigned long flags;
unsigned char msgout = NOP;
int sink = 0;
int len;
unsigned char *data;
unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
struct scsi_cmnd *cmd = (struct scsi_cmnd *) hostdata->connected;
#ifdef SUN3_SCSI_VME
dregs->csr |= CSR_INTR;
#endif
while (1) {
tmp = NCR5380_read(STATUS_REG);
/* We only have a valid SCSI phase when REQ is asserted */
if (tmp & SR_REQ) {
phase = (tmp & PHASE_MASK);
if (phase != old_phase) {
old_phase = phase;
NCR5380_dprint_phase(NDEBUG_INFORMATION, instance);
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
#if defined(CONFIG_SUN3)
if (phase == PHASE_CMDOUT) {
#if defined(REAL_DMA)
void *d;
unsigned long count;
if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
count = cmd->SCp.buffer->length;
d = sg_virt(cmd->SCp.buffer);
} else {
count = cmd->SCp.this_residual;
d = cmd->SCp.ptr;
}
/* this command setup for dma yet? */
if ((count >= DMA_MIN_SIZE) && (sun3_dma_setup_done != cmd)) {
if (cmd->request->cmd_type == REQ_TYPE_FS) {
sun3scsi_dma_setup(d, count,
rq_data_dir(cmd->request));
sun3_dma_setup_done = cmd;
}
}
#endif
#ifdef SUN3_SCSI_VME
dregs->csr |= CSR_INTR;
#endif
}
#endif /* CONFIG_SUN3 */
if (sink && (phase != PHASE_MSGOUT)) {
NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));