Commit e9db3198 authored by Finn Thain's avatar Finn Thain Committed by Martin K. Petersen

sun3_scsi: Adopt NCR5380.c core driver

Add support for the custom Sun 3 DMA logic to the NCR5380.c core driver.
This code is copied from atari_NCR5380.c.
Signed-off-by: default avatarFinn Thain <fthain@telegraphics.com.au>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Tested-by: default avatarMichael Schmitz <schmitzmic@gmail.com>
Tested-by: default avatarOndrej Zary <linux@rainbow-software.org>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 52d3e561
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
/* Ported to Atari by Roman Hodek and others. */ /* Ported to Atari by Roman Hodek and others. */
/* Adapted for the Sun 3 by Sam Creasey. */
/* /*
* Further development / testing that should be done : * Further development / testing that should be done :
* *
...@@ -858,6 +860,23 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) ...@@ -858,6 +860,23 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance)
} }
} }
#ifdef 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();
}
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
NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(MODE_REG, MR_BASE);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
NCR5380_read(RESET_PARITY_INTERRUPT_REG); NCR5380_read(RESET_PARITY_INTERRUPT_REG);
...@@ -981,10 +1000,16 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) ...@@ -981,10 +1000,16 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id)
NCR5380_read(RESET_PARITY_INTERRUPT_REG); NCR5380_read(RESET_PARITY_INTERRUPT_REG);
dsprintk(NDEBUG_INTR, instance, "unknown interrupt\n"); dsprintk(NDEBUG_INTR, instance, "unknown interrupt\n");
#ifdef SUN3_SCSI_VME
dregs->csr |= CSR_DMA_ENABLE;
#endif
} }
handled = 1; handled = 1;
} else { } else {
shost_printk(KERN_NOTICE, instance, "interrupt without IRQ bit\n"); shost_printk(KERN_NOTICE, instance, "interrupt without IRQ bit\n");
#ifdef SUN3_SCSI_VME
dregs->csr |= CSR_DMA_ENABLE;
#endif
} }
spin_unlock_irqrestore(&hostdata->lock, flags); spin_unlock_irqrestore(&hostdata->lock, flags);
...@@ -1274,6 +1299,10 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, ...@@ -1274,6 +1299,10 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance,
hostdata->connected = cmd; hostdata->connected = cmd;
hostdata->busy[cmd->device->id] |= 1 << cmd->device->lun; hostdata->busy[cmd->device->id] |= 1 << cmd->device->lun;
#ifdef SUN3_SCSI_VME
dregs->csr |= CSR_INTR;
#endif
initialize_SCp(cmd); initialize_SCp(cmd);
cmd = NULL; cmd = NULL;
...@@ -1557,6 +1586,11 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, ...@@ -1557,6 +1586,11 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n", dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n",
(p & SR_IO) ? "receive" : "send", c, d); (p & SR_IO) ? "receive" : "send", c, d);
#ifdef CONFIG_SUN3
/* send start chain */
sun3scsi_dma_start(c, *data);
#endif
NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY |
MR_ENABLE_EOP_INTR); MR_ENABLE_EOP_INTR);
...@@ -1577,6 +1611,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, ...@@ -1577,6 +1611,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
*/ */
if (p & SR_IO) { if (p & SR_IO) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
NCR5380_io_delay(1); NCR5380_io_delay(1);
NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0); NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
} else { } else {
...@@ -1587,6 +1622,13 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, ...@@ -1587,6 +1622,13 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
NCR5380_io_delay(1); NCR5380_io_delay(1);
} }
#ifdef CONFIG_SUN3
#ifdef SUN3_SCSI_VME
dregs->csr |= CSR_DMA_ENABLE;
#endif
sun3_dma_active = 1;
#endif
if (hostdata->flags & FLAG_LATE_DMA_SETUP) { if (hostdata->flags & FLAG_LATE_DMA_SETUP) {
/* On the Falcon, the DMA setup must be done after the last /* On the Falcon, the DMA setup must be done after the last
* NCR access, else the DMA setup gets trashed! * NCR access, else the DMA setup gets trashed!
...@@ -1718,6 +1760,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) ...@@ -1718,6 +1760,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
unsigned char phase, tmp, extended_msg[10], old_phase = 0xff; unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
struct scsi_cmnd *cmd; struct scsi_cmnd *cmd;
#ifdef SUN3_SCSI_VME
dregs->csr |= CSR_INTR;
#endif
while ((cmd = hostdata->connected)) { while ((cmd = hostdata->connected)) {
struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd);
...@@ -1729,6 +1775,31 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) ...@@ -1729,6 +1775,31 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
old_phase = phase; old_phase = phase;
NCR5380_dprint_phase(NDEBUG_INFORMATION, instance); NCR5380_dprint_phase(NDEBUG_INFORMATION, instance);
} }
#ifdef CONFIG_SUN3
if (phase == PHASE_CMDOUT) {
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;
}
if (sun3_dma_setup_done != cmd &&
sun3scsi_dma_xfer_len(count, cmd) > 0) {
sun3scsi_dma_setup(instance, d, count,
rq_data_dir(cmd->request));
sun3_dma_setup_done = cmd;
}
#ifdef SUN3_SCSI_VME
dregs->csr |= CSR_INTR;
#endif
}
#endif /* CONFIG_SUN3 */
if (sink && (phase != PHASE_MSGOUT)) { if (sink && (phase != PHASE_MSGOUT)) {
NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
...@@ -1811,6 +1882,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) ...@@ -1811,6 +1882,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
(unsigned char **)&cmd->SCp.ptr); (unsigned char **)&cmd->SCp.ptr);
cmd->SCp.this_residual -= transfersize - len; cmd->SCp.this_residual -= transfersize - len;
} }
#ifdef CONFIG_SUN3
if (sun3_dma_setup_done == cmd)
sun3_dma_setup_done = NULL;
#endif
return; return;
case PHASE_MSGIN: case PHASE_MSGIN:
len = 1; len = 1;
...@@ -1889,6 +1964,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) ...@@ -1889,6 +1964,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
/* Enable reselect interrupts */ /* Enable reselect interrupts */
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
#ifdef SUN3_SCSI_VME
dregs->csr |= CSR_DMA_ENABLE;
#endif
return; return;
/* /*
* The SCSI data pointer is *IMPLICITLY* saved on a disconnect * The SCSI data pointer is *IMPLICITLY* saved on a disconnect
...@@ -2040,10 +2118,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) ...@@ -2040,10 +2118,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
{ {
struct NCR5380_hostdata *hostdata = shost_priv(instance); struct NCR5380_hostdata *hostdata = shost_priv(instance);
unsigned char target_mask; unsigned char target_mask;
unsigned char lun, phase; unsigned char lun;
int len;
unsigned char msg[3]; unsigned char msg[3];
unsigned char *data;
struct NCR5380_cmd *ncmd; struct NCR5380_cmd *ncmd;
struct scsi_cmnd *tmp; struct scsi_cmnd *tmp;
...@@ -2085,15 +2161,26 @@ static void NCR5380_reselect(struct Scsi_Host *instance) ...@@ -2085,15 +2161,26 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
return; return;
} }
len = 1; #ifdef CONFIG_SUN3
data = msg; /* acknowledge toggle to MSGIN */
phase = PHASE_MSGIN; NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(PHASE_MSGIN));
/* peek at the byte without really hitting the bus */
msg[0] = NCR5380_read(CURRENT_SCSI_DATA_REG);
#else
{
int len = 1;
unsigned char *data = msg;
unsigned char phase = PHASE_MSGIN;
NCR5380_transfer_pio(instance, &phase, &len, &data); NCR5380_transfer_pio(instance, &phase, &len, &data);
if (len) { if (len) {
do_abort(instance); do_abort(instance);
return; return;
} }
}
#endif /* CONFIG_SUN3 */
if (!(msg[0] & 0x80)) { if (!(msg[0] & 0x80)) {
shost_printk(KERN_ERR, instance, "expecting IDENTIFY message, got "); shost_printk(KERN_ERR, instance, "expecting IDENTIFY message, got ");
...@@ -2141,6 +2228,30 @@ static void NCR5380_reselect(struct Scsi_Host *instance) ...@@ -2141,6 +2228,30 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
return; return;
} }
#ifdef CONFIG_SUN3
{
void *d;
unsigned long count;
if (!tmp->SCp.this_residual && tmp->SCp.buffers_residual) {
count = tmp->SCp.buffer->length;
d = sg_virt(tmp->SCp.buffer);
} else {
count = tmp->SCp.this_residual;
d = tmp->SCp.ptr;
}
if (sun3_dma_setup_done != tmp &&
sun3scsi_dma_xfer_len(count, tmp) > 0) {
sun3scsi_dma_setup(instance, d, count,
rq_data_dir(tmp->request));
sun3_dma_setup_done = tmp;
}
}
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
#endif /* CONFIG_SUN3 */
/* Accept message by clearing ACK */ /* Accept message by clearing ACK */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
......
...@@ -54,10 +54,8 @@ ...@@ -54,10 +54,8 @@
#define NCR5380_abort sun3scsi_abort #define NCR5380_abort sun3scsi_abort
#define NCR5380_info sun3scsi_info #define NCR5380_info sun3scsi_info
#define NCR5380_dma_read_setup(instance, data, count) \ #define NCR5380_dma_recv_setup(instance, data, count) (count)
sun3scsi_dma_setup(instance, data, count, 0) #define NCR5380_dma_send_setup(instance, data, count) (count)
#define NCR5380_dma_write_setup(instance, data, count) \
sun3scsi_dma_setup(instance, data, count, 1)
#define NCR5380_dma_residual(instance) \ #define NCR5380_dma_residual(instance) \
sun3scsi_dma_residual(instance) sun3scsi_dma_residual(instance)
#define NCR5380_dma_xfer_len(instance, cmd, phase) \ #define NCR5380_dma_xfer_len(instance, cmd, phase) \
...@@ -406,7 +404,7 @@ static int sun3scsi_dma_finish(int write_flag) ...@@ -406,7 +404,7 @@ static int sun3scsi_dma_finish(int write_flag)
} }
#include "atari_NCR5380.c" #include "NCR5380.c"
#ifdef SUN3_SCSI_VME #ifdef SUN3_SCSI_VME
#define SUN3_SCSI_NAME "Sun3 NCR5380 VME SCSI" #define SUN3_SCSI_NAME "Sun3 NCR5380 VME SCSI"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment