atari_NCR5380: Refactor Falcon special cases
Make the atari_NCR5380.c core driver usable by sun3_scsi, mac_scsi and others by moving some of the Falcon-specific code out of the core driver: !IS_A_TT, atari_read_overruns and falcon_dont_release. Replace these with hostdata variables and flags. FLAG_CHECK_LAST_BYTE_SENT is unused in atari_NCR5380.c so don't set it. Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Reviewed-by: Hannes Reinecke <hare@suse.de> Tested-by: Michael Schmitz <schmitzmic@gmail.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
f527590278
commit
ef1081cbf0
3 changed files with 31 additions and 24 deletions
|
@ -241,6 +241,7 @@
|
||||||
#define FLAG_NCR53C400 4 /* NCR53c400 */
|
#define FLAG_NCR53C400 4 /* NCR53c400 */
|
||||||
#define FLAG_NO_PSEUDO_DMA 8 /* Inhibit DMA */
|
#define FLAG_NO_PSEUDO_DMA 8 /* Inhibit DMA */
|
||||||
#define FLAG_DTC3181E 16 /* DTC3181E */
|
#define FLAG_DTC3181E 16 /* DTC3181E */
|
||||||
|
#define FLAG_LATE_DMA_SETUP 32 /* Setup NCR before DMA H/W */
|
||||||
|
|
||||||
#ifndef ASM
|
#ifndef ASM
|
||||||
struct NCR5380_hostdata {
|
struct NCR5380_hostdata {
|
||||||
|
@ -269,6 +270,9 @@ struct NCR5380_hostdata {
|
||||||
struct delayed_work coroutine; /* our co-routine */
|
struct delayed_work coroutine; /* our co-routine */
|
||||||
struct scsi_eh_save ses;
|
struct scsi_eh_save ses;
|
||||||
char info[256];
|
char info[256];
|
||||||
|
int read_overruns; /* number of bytes to cut from a
|
||||||
|
* transfer to handle chip overruns */
|
||||||
|
int retain_dma_intr;
|
||||||
#ifdef PSEUDO_DMA
|
#ifdef PSEUDO_DMA
|
||||||
unsigned spin_max_r;
|
unsigned spin_max_r;
|
||||||
unsigned spin_max_w;
|
unsigned spin_max_w;
|
||||||
|
|
|
@ -839,7 +839,7 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
|
||||||
hostdata->connected = NULL;
|
hostdata->connected = NULL;
|
||||||
hostdata->issue_queue = NULL;
|
hostdata->issue_queue = NULL;
|
||||||
hostdata->disconnected_queue = NULL;
|
hostdata->disconnected_queue = NULL;
|
||||||
hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT;
|
hostdata->flags = flags;
|
||||||
|
|
||||||
if (!the_template) {
|
if (!the_template) {
|
||||||
the_template = instance->hostt;
|
the_template = instance->hostt;
|
||||||
|
@ -1054,7 +1054,7 @@ static void NCR5380_main(struct work_struct *work)
|
||||||
hostdata->issue_queue = NEXT(tmp);
|
hostdata->issue_queue = NEXT(tmp);
|
||||||
}
|
}
|
||||||
SET_NEXT(tmp, NULL);
|
SET_NEXT(tmp, NULL);
|
||||||
falcon_dont_release++;
|
hostdata->retain_dma_intr++;
|
||||||
|
|
||||||
/* reenable interrupts after finding one */
|
/* reenable interrupts after finding one */
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
|
@ -1082,7 +1082,7 @@ static void NCR5380_main(struct work_struct *work)
|
||||||
cmd_get_tag(tmp, tmp->cmnd[0] != REQUEST_SENSE);
|
cmd_get_tag(tmp, tmp->cmnd[0] != REQUEST_SENSE);
|
||||||
#endif
|
#endif
|
||||||
if (!NCR5380_select(instance, tmp)) {
|
if (!NCR5380_select(instance, tmp)) {
|
||||||
falcon_dont_release--;
|
hostdata->retain_dma_intr--;
|
||||||
/* release if target did not response! */
|
/* release if target did not response! */
|
||||||
falcon_release_lock_if_possible(hostdata);
|
falcon_release_lock_if_possible(hostdata);
|
||||||
break;
|
break;
|
||||||
|
@ -1094,7 +1094,7 @@ static void NCR5380_main(struct work_struct *work)
|
||||||
#ifdef SUPPORT_TAGS
|
#ifdef SUPPORT_TAGS
|
||||||
cmd_free_tag(tmp);
|
cmd_free_tag(tmp);
|
||||||
#endif
|
#endif
|
||||||
falcon_dont_release--;
|
hostdata->retain_dma_intr--;
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
dprintk(NDEBUG_MAIN, "scsi%d: main(): select() failed, "
|
dprintk(NDEBUG_MAIN, "scsi%d: main(): select() failed, "
|
||||||
"returned to issue_queue\n", HOSTNO);
|
"returned to issue_queue\n", HOSTNO);
|
||||||
|
@ -1151,7 +1151,7 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atari_read_overruns) {
|
if (hostdata->read_overruns) {
|
||||||
p = hostdata->connected->SCp.phase;
|
p = hostdata->connected->SCp.phase;
|
||||||
if (p & SR_IO) {
|
if (p & SR_IO) {
|
||||||
udelay(10);
|
udelay(10);
|
||||||
|
@ -1181,9 +1181,9 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance)
|
||||||
*data += transfered;
|
*data += transfered;
|
||||||
*count -= transfered;
|
*count -= transfered;
|
||||||
|
|
||||||
if (atari_read_overruns) {
|
if (hostdata->read_overruns) {
|
||||||
if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) {
|
if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) {
|
||||||
cnt = toPIO = atari_read_overruns;
|
cnt = toPIO = hostdata->read_overruns;
|
||||||
if (overrun) {
|
if (overrun) {
|
||||||
dprintk(NDEBUG_DMA, "Got an input overrun, using saved byte\n");
|
dprintk(NDEBUG_DMA, "Got an input overrun, using saved byte\n");
|
||||||
*(*data)++ = saved_data;
|
*(*data)++ = saved_data;
|
||||||
|
@ -1838,8 +1838,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atari_read_overruns && (p & SR_IO))
|
if (hostdata->read_overruns && (p & SR_IO))
|
||||||
c -= atari_read_overruns;
|
c -= hostdata->read_overruns;
|
||||||
|
|
||||||
dprintk(NDEBUG_DMA, "scsi%d: initializing DMA for %s, %d bytes %s %p\n",
|
dprintk(NDEBUG_DMA, "scsi%d: initializing DMA for %s, %d bytes %s %p\n",
|
||||||
HOSTNO, (p & SR_IO) ? "reading" : "writing",
|
HOSTNO, (p & SR_IO) ? "reading" : "writing",
|
||||||
|
@ -1851,7 +1851,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
|
||||||
NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);
|
NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);
|
||||||
#endif /* def REAL_DMA */
|
#endif /* def REAL_DMA */
|
||||||
|
|
||||||
if (IS_A_TT()) {
|
if (!(hostdata->flags & FLAG_LATE_DMA_SETUP)) {
|
||||||
/* On the Medusa, it is a must to initialize the DMA before
|
/* On the Medusa, it is a must to initialize the DMA before
|
||||||
* starting the NCR. This is also the cleaner way for the TT.
|
* starting the NCR. This is also the cleaner way for the TT.
|
||||||
*/
|
*/
|
||||||
|
@ -1869,7 +1869,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
|
||||||
NCR5380_write(START_DMA_SEND_REG, 0);
|
NCR5380_write(START_DMA_SEND_REG, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_A_TT()) {
|
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!
|
||||||
*/
|
*/
|
||||||
|
@ -2084,7 +2084,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
|
||||||
/* Accept message by clearing ACK */
|
/* Accept message by clearing ACK */
|
||||||
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
|
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
|
||||||
/* ++guenther: possible race with Falcon locking */
|
/* ++guenther: possible race with Falcon locking */
|
||||||
falcon_dont_release++;
|
hostdata->retain_dma_intr++;
|
||||||
hostdata->connected = NULL;
|
hostdata->connected = NULL;
|
||||||
dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %llu "
|
dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %llu "
|
||||||
"completed\n", HOSTNO, cmd->device->id, cmd->device->lun);
|
"completed\n", HOSTNO, cmd->device->id, cmd->device->lun);
|
||||||
|
@ -2167,7 +2167,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
|
||||||
while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
|
while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
|
||||||
barrier();
|
barrier();
|
||||||
|
|
||||||
falcon_dont_release--;
|
hostdata->retain_dma_intr--;
|
||||||
/* ++roman: For Falcon SCSI, release the lock on the
|
/* ++roman: For Falcon SCSI, release the lock on the
|
||||||
* ST-DMA here if no other commands are waiting on the
|
* ST-DMA here if no other commands are waiting on the
|
||||||
* disconnected queue.
|
* disconnected queue.
|
||||||
|
@ -2474,7 +2474,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
/* ++guenther: prevent race with falcon_release_lock */
|
/* ++guenther: prevent race with falcon_release_lock */
|
||||||
falcon_dont_release++;
|
hostdata->retain_dma_intr++;
|
||||||
if (prev) {
|
if (prev) {
|
||||||
REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
|
REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
|
||||||
SET_NEXT(prev, NEXT(tmp));
|
SET_NEXT(prev, NEXT(tmp));
|
||||||
|
@ -2512,7 +2512,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
|
||||||
hostdata->connected = tmp;
|
hostdata->connected = tmp;
|
||||||
dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %llu, tag = %d\n",
|
dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %llu, tag = %d\n",
|
||||||
HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag);
|
HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag);
|
||||||
falcon_dont_release--;
|
hostdata->retain_dma_intr--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -196,8 +196,6 @@ static char *atari_dma_orig_addr;
|
||||||
/* mask for address bits that can't be used with the ST-DMA */
|
/* mask for address bits that can't be used with the ST-DMA */
|
||||||
static unsigned long atari_dma_stram_mask;
|
static unsigned long atari_dma_stram_mask;
|
||||||
#define STRAM_ADDR(a) (((a) & atari_dma_stram_mask) == 0)
|
#define STRAM_ADDR(a) (((a) & atari_dma_stram_mask) == 0)
|
||||||
/* number of bytes to cut from a transfer to handle NCR overruns */
|
|
||||||
static int atari_read_overruns;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int setup_can_queue = -1;
|
static int setup_can_queue = -1;
|
||||||
|
@ -446,8 +444,6 @@ static void atari_scsi_fetch_restbytes(void)
|
||||||
#endif /* REAL_DMA */
|
#endif /* REAL_DMA */
|
||||||
|
|
||||||
|
|
||||||
static int falcon_dont_release = 0;
|
|
||||||
|
|
||||||
/* This function releases the lock on the DMA chip if there is no
|
/* This function releases the lock on the DMA chip if there is no
|
||||||
* connected command and the disconnected queue is empty.
|
* connected command and the disconnected queue is empty.
|
||||||
*/
|
*/
|
||||||
|
@ -464,7 +460,7 @@ static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata)
|
||||||
if (!hostdata->disconnected_queue &&
|
if (!hostdata->disconnected_queue &&
|
||||||
!hostdata->issue_queue &&
|
!hostdata->issue_queue &&
|
||||||
!hostdata->connected &&
|
!hostdata->connected &&
|
||||||
!falcon_dont_release &&
|
!hostdata->retain_dma_intr &&
|
||||||
stdma_is_locked_by(scsi_falcon_intr))
|
stdma_is_locked_by(scsi_falcon_intr))
|
||||||
stdma_release();
|
stdma_release();
|
||||||
|
|
||||||
|
@ -846,6 +842,7 @@ static int __init atari_scsi_probe(struct platform_device *pdev)
|
||||||
struct Scsi_Host *instance;
|
struct Scsi_Host *instance;
|
||||||
int error;
|
int error;
|
||||||
struct resource *irq;
|
struct resource *irq;
|
||||||
|
int host_flags = 0;
|
||||||
|
|
||||||
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||||
if (!irq)
|
if (!irq)
|
||||||
|
@ -942,7 +939,9 @@ static int __init atari_scsi_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
instance->irq = irq->start;
|
instance->irq = irq->start;
|
||||||
|
|
||||||
NCR5380_init(instance, 0);
|
host_flags |= IS_A_TT() ? 0 : FLAG_LATE_DMA_SETUP;
|
||||||
|
|
||||||
|
NCR5380_init(instance, host_flags);
|
||||||
|
|
||||||
if (IS_A_TT()) {
|
if (IS_A_TT()) {
|
||||||
error = request_irq(instance->irq, scsi_tt_intr, 0,
|
error = request_irq(instance->irq, scsi_tt_intr, 0,
|
||||||
|
@ -965,12 +964,16 @@ static int __init atari_scsi_probe(struct platform_device *pdev)
|
||||||
*
|
*
|
||||||
* In principle it should be sufficient to do max. 1 byte with
|
* In principle it should be sufficient to do max. 1 byte with
|
||||||
* PIO, but there is another problem on the Medusa with the DMA
|
* PIO, but there is another problem on the Medusa with the DMA
|
||||||
* rest data register. So 'atari_read_overruns' is currently set
|
* rest data register. So read_overruns is currently set
|
||||||
* to 4 to avoid having transfers that aren't a multiple of 4.
|
* to 4 to avoid having transfers that aren't a multiple of 4.
|
||||||
* If the rest data bug is fixed, this can be lowered to 1.
|
* If the rest data bug is fixed, this can be lowered to 1.
|
||||||
*/
|
*/
|
||||||
if (MACH_IS_MEDUSA)
|
if (MACH_IS_MEDUSA) {
|
||||||
atari_read_overruns = 4;
|
struct NCR5380_hostdata *hostdata =
|
||||||
|
shost_priv(instance);
|
||||||
|
|
||||||
|
hostdata->read_overruns = 4;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
/* Nothing to do for the interrupt: the ST-DMA is initialized
|
/* Nothing to do for the interrupt: the ST-DMA is initialized
|
||||||
|
|
Loading…
Add table
Reference in a new issue