Use direct DMA with the IOASIC ASC SCSI interface. DMA buffering can be
re-enabled with ASC_IOASIC_BOUNCE. All DMA buffered processing is now done in the bus-specific DMA routines in asc_ioasic.c and asc_tc.c. Disable several informational messages dealing with non-empty FIFO conditions, but allow enabling with ASC_DIAGNOSTIC for troubleshooting.
This commit is contained in:
parent
1f7596052f
commit
0ae3de1a27
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: asc.c,v 1.39 1997/06/16 03:46:29 jonathan Exp $ */
|
||||
/* $NetBSD: asc.c,v 1.40 1997/07/28 19:39:22 mhitch Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -449,12 +449,12 @@ void asc_minphys __P((struct buf *bp));
|
|||
* bus-parent shared attach function
|
||||
*/
|
||||
void
|
||||
ascattach(asc, dmabufsize, bus_speed)
|
||||
ascattach(asc, bus_speed)
|
||||
register asc_softc_t asc;
|
||||
int dmabufsize;
|
||||
int bus_speed;
|
||||
{
|
||||
register asc_regmap_t *regs;
|
||||
int id, s, i;
|
||||
int id, s;
|
||||
|
||||
int unit;
|
||||
|
||||
|
@ -521,21 +521,6 @@ ascattach(asc, dmabufsize, bus_speed)
|
|||
id = asc->sc_id;
|
||||
splx(s);
|
||||
|
||||
/*
|
||||
* Statically partition the DMA buffer between targets.
|
||||
* This way we will eventually be able to attach/detach
|
||||
* drives on-fly. And 18k/target is plenty for normal use.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Give each target its own DMA buffer region.
|
||||
* We may want to try ping ponging buffers later.
|
||||
*/
|
||||
for (i = 0; i < ASC_NCMD; i++) {
|
||||
asc->st[i].dmaBufAddr = asc->buff + dmabufsize * i;
|
||||
asc->st[i].dmaBufSize = dmabufsize;
|
||||
}
|
||||
|
||||
/* Hack for old-sytle SCSI-device probe */
|
||||
(void) pmax_add_scsi(&ascdriver, unit);
|
||||
|
||||
|
@ -730,12 +715,8 @@ asc_startcmd(asc, target)
|
|||
state->script = (script_t *)0;
|
||||
state->msg_out = SCSI_NO_OP;
|
||||
|
||||
/*
|
||||
* Copy command data to the DMA buffer.
|
||||
*/
|
||||
len = scsicmd->cmdlen;
|
||||
state->dmalen = len;
|
||||
bcopy(scsicmd->cmd, state->dmaBufAddr, len);
|
||||
|
||||
/* check for simple SCSI command with no data transfer */
|
||||
if ((state->buflen = scsicmd->buflen) == 0) {
|
||||
|
@ -780,7 +761,8 @@ asc_startcmd(asc, target)
|
|||
tc_mb();
|
||||
|
||||
/* initialize the DMA */
|
||||
(*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_WRITE);
|
||||
len = (*asc->dma_start)(asc, state, scsicmd->cmd, ASCDMA_WRITE,
|
||||
len, 0);
|
||||
ASC_TC_PUT(regs, len);
|
||||
readback(regs->asc_cmd);
|
||||
|
||||
|
@ -1014,14 +996,16 @@ again:
|
|||
/* flush any data in the FIFO */
|
||||
if (fifo) {
|
||||
if (state->flags & DMA_OUT) {
|
||||
#if 0
|
||||
#ifdef ASC_DIAGNOSTIC
|
||||
printf("asc: DMA_OUT, fifo resid %d, len %d, flags 0x%x\n",
|
||||
fifo, len, state->flags);
|
||||
#endif
|
||||
#endif /* ASC_DIAGNOSTIC */
|
||||
len += fifo;
|
||||
} else if (state->flags & DMA_IN) {
|
||||
#ifdef ASC_DIAGNOSTIC
|
||||
printf("asc_intr: IN: dmalen %d len %d fifo %d\n",
|
||||
state->dmalen, len, fifo); /* XXX */
|
||||
#endif /* ASC_DIAGNOSTIC */
|
||||
} else
|
||||
printf("asc_intr: dmalen %d len %d fifo %d\n",
|
||||
state->dmalen, len, fifo); /* XXX */
|
||||
|
@ -1077,8 +1061,8 @@ again:
|
|||
len = state->dmalen;
|
||||
state->flags &= ~DMA_IN_PROGRESS;
|
||||
do_in:
|
||||
state->dmalen = len; /* dma_end needs actual length */
|
||||
(*asc->dma_end)(asc, state, ASCDMA_READ);
|
||||
bcopy(state->dmaBufAddr, state->buf, len);
|
||||
state->buf += len;
|
||||
state->buflen -= len;
|
||||
}
|
||||
|
@ -1448,10 +1432,10 @@ asc_dma_in(asc, status, ss, ir)
|
|||
* There may be some bytes in the FIFO if synchonous transfers
|
||||
* are in progress.
|
||||
*/
|
||||
(*asc->dma_end)(asc, state, ASCDMA_READ);
|
||||
ASC_TC_GET(regs, len);
|
||||
len = state->dmalen - len;
|
||||
bcopy(state->dmaBufAddr, state->buf, len);
|
||||
state->dmalen = len; /* dma_end may need actual length */
|
||||
(*asc->dma_end)(asc, state, ASCDMA_READ);
|
||||
state->buf += len;
|
||||
state->buflen -= len;
|
||||
}
|
||||
|
@ -1472,7 +1456,7 @@ asc_dma_in(asc, status, ss, ir)
|
|||
*/
|
||||
if (state->sync_offset == 0)
|
||||
async_fifo_junk = regs->asc_fifo;
|
||||
#ifdef DEBUG
|
||||
#ifdef ASC_DIAGNOSTIC
|
||||
printf("%s: asc_dma_in: FIFO count %x flags %x sync_offset %d",
|
||||
asc->sc_dev.dv_xname, regs->asc_flags,
|
||||
state->flags, state->sync_offset);
|
||||
|
@ -1480,10 +1464,10 @@ asc_dma_in(asc, status, ss, ir)
|
|||
printf("\n");
|
||||
else
|
||||
printf(" unexpected fifo data %x\n", async_fifo_junk);
|
||||
#ifdef DIAGNOSTIC
|
||||
#ifdef DEBUG
|
||||
asc_DumpLog("asc_dma_in");
|
||||
#endif /* DIAGNOSTIC */
|
||||
#endif /* DEBUG */
|
||||
#endif /* ASC_DIAGNOSTIC */
|
||||
|
||||
}
|
||||
/* setup to start reading the next chunk */
|
||||
|
@ -1494,10 +1478,8 @@ asc_dma_in(asc, status, ss, ir)
|
|||
else
|
||||
asc_logp[-1].resid = len;
|
||||
#endif
|
||||
if (len > state->dmaBufSize)
|
||||
len = state->dmaBufSize;
|
||||
len = (*asc->dma_start)(asc, state, state->buf, ASCDMA_READ, len, 0);
|
||||
state->dmalen = len;
|
||||
(*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_READ);
|
||||
ASC_TC_PUT(regs, len);
|
||||
#ifdef DEBUG
|
||||
if (asc_debug > 2)
|
||||
|
@ -1525,8 +1507,6 @@ asc_last_dma_in(asc, status, ss, ir)
|
|||
register State *state = &asc->st[asc->target];
|
||||
register int len, fifo;
|
||||
|
||||
/* copy data from buffer to main memory */
|
||||
(*asc->dma_end)(asc, state, ASCDMA_READ);
|
||||
ASC_TC_GET(regs, len);
|
||||
fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
|
||||
#ifdef DEBUG
|
||||
|
@ -1541,8 +1521,9 @@ asc_last_dma_in(asc, status, ss, ir)
|
|||
}
|
||||
state->flags &= ~DMA_IN_PROGRESS;
|
||||
len = state->dmalen - len;
|
||||
state->dmalen = len; /* dma_end may need actual length */
|
||||
(*asc->dma_end)(asc, state, ASCDMA_READ);
|
||||
state->buflen -= len;
|
||||
bcopy(state->dmaBufAddr, state->buf, len);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
@ -1565,10 +1546,8 @@ asc_resume_in(asc, status, ss, ir)
|
|||
else
|
||||
asc_logp[-1].resid = len;
|
||||
#endif
|
||||
if (len > state->dmaBufSize)
|
||||
len = state->dmaBufSize;
|
||||
len = (*asc->dma_start)(asc, state, state->buf, ASCDMA_READ, len, 0);
|
||||
state->dmalen = len;
|
||||
(*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_READ);
|
||||
ASC_TC_PUT(regs, len);
|
||||
#ifdef DEBUG
|
||||
if (asc_debug > 2)
|
||||
|
@ -1603,7 +1582,7 @@ asc_resume_dma_in(asc, status, ss, ir)
|
|||
if ((off & 1) && state->sync_offset) {
|
||||
printf("asc_resume_dma_in: odd xfer dmalen %d len %d off %d\n",
|
||||
state->dmalen, len, off); /* XXX */
|
||||
regs->asc_res_fifo = state->dmaBufAddr[off];
|
||||
regs->asc_res_fifo = state->buf[off];
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (asc_logp == asc_log)
|
||||
|
@ -1611,7 +1590,7 @@ asc_resume_dma_in(asc, status, ss, ir)
|
|||
else
|
||||
asc_logp[-1].resid = len;
|
||||
#endif
|
||||
(*asc->dma_start)(asc, state, state->dmaBufAddr + off, ASCDMA_READ);
|
||||
len = (*asc->dma_start)(asc, state, state->buf + off, ASCDMA_READ, len, off);
|
||||
ASC_TC_PUT(regs, len);
|
||||
#ifdef DEBUG
|
||||
if (asc_debug > 2)
|
||||
|
@ -1670,11 +1649,8 @@ asc_dma_out(asc, status, ss, ir)
|
|||
else
|
||||
asc_logp[-1].resid = len;
|
||||
#endif
|
||||
if (len > state->dmaBufSize)
|
||||
len = state->dmaBufSize;
|
||||
len = (*asc->dma_start)(asc, state, state->buf, ASCDMA_WRITE, len, 0);
|
||||
state->dmalen = len;
|
||||
bcopy(state->buf, state->dmaBufAddr, len);
|
||||
(*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_WRITE);
|
||||
ASC_TC_PUT(regs, len);
|
||||
#ifdef DEBUG
|
||||
if (asc_debug > 2)
|
||||
|
@ -1740,11 +1716,8 @@ asc_resume_out(asc, status, ss, ir)
|
|||
else
|
||||
asc_logp[-1].resid = len;
|
||||
#endif
|
||||
if (len > state->dmaBufSize)
|
||||
len = state->dmaBufSize;
|
||||
len = (*asc->dma_start)(asc, state, state->buf, ASCDMA_WRITE, len, 0);
|
||||
state->dmalen = len;
|
||||
bcopy(state->buf, state->dmaBufAddr, len);
|
||||
(*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_WRITE);
|
||||
ASC_TC_PUT(regs, len);
|
||||
#ifdef DEBUG
|
||||
if (asc_debug > 2)
|
||||
|
@ -1779,7 +1752,7 @@ asc_resume_dma_out(asc, status, ss, ir)
|
|||
if (off & 1) {
|
||||
printf("asc_resume_dma_out: odd xfer dmalen %d len %d off %d\n",
|
||||
state->dmalen, len, off); /* XXX */
|
||||
regs->asc_fifo = state->dmaBufAddr[off];
|
||||
regs->asc_fifo = state->buf[off];
|
||||
off++;
|
||||
len--;
|
||||
}
|
||||
|
@ -1789,7 +1762,8 @@ asc_resume_dma_out(asc, status, ss, ir)
|
|||
else
|
||||
asc_logp[-1].resid = len;
|
||||
#endif
|
||||
(*asc->dma_start)(asc, state, state->dmaBufAddr + off, ASCDMA_WRITE);
|
||||
/* XXX may result in redundant copy of data */
|
||||
len = (*asc->dma_start)(asc, state, state->buf + off, ASCDMA_WRITE, len, off);
|
||||
ASC_TC_PUT(regs, len);
|
||||
#ifdef DEBUG
|
||||
if (asc_debug > 2)
|
||||
|
@ -2100,7 +2074,6 @@ asc_disconnect(asc, status, ss, ir)
|
|||
return (1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
asc_timeout(arg)
|
||||
void *arg;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: asc_ioasic.c,v 1.10 1997/07/21 05:39:02 jonathan Exp $ */
|
||||
/* $NetBSD: asc_ioasic.c,v 1.11 1997/07/28 19:39:25 mhitch Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 1996 The Board of Trustees of The Leland Stanford
|
||||
|
@ -13,6 +13,8 @@
|
|||
* express or implied warranty.
|
||||
*
|
||||
*/
|
||||
#define USE_CACHED_BUFFER 0
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
|
@ -35,6 +37,7 @@
|
|||
#include <pmax/pmax/pmaxtype.h>
|
||||
extern int pmax_boardtype;
|
||||
|
||||
extern vm_offset_t kvtophys __P((vm_offset_t));
|
||||
|
||||
/*
|
||||
* Autoconfiguration data for config.
|
||||
|
@ -50,9 +53,12 @@ struct cfattach asc_ioasic_ca = {
|
|||
* DMA callback declarations
|
||||
*/
|
||||
|
||||
#ifdef ASC_IOASIC_BOUNCE
|
||||
extern u_long asc_iomem;
|
||||
static void
|
||||
asic_dma_start __P((asc_softc_t asc, State *state, caddr_t cp, int flag));
|
||||
#endif
|
||||
static int
|
||||
asic_dma_start __P((asc_softc_t asc, State *state, caddr_t cp, int flag,
|
||||
int len, int off));
|
||||
|
||||
static void
|
||||
asic_dma_end __P((asc_softc_t asc, State *state, int flag));
|
||||
|
@ -86,7 +92,10 @@ asc_ioasic_attach(parent, self, aux)
|
|||
{
|
||||
register struct ioasicdev_attach_args *d = aux;
|
||||
register asc_softc_t asc = (asc_softc_t) self;
|
||||
int bufsiz;
|
||||
#ifdef ASC_IOASIC_BOUNCE
|
||||
u_char *buff;
|
||||
int i;
|
||||
#endif
|
||||
|
||||
void *ascaddr;
|
||||
int unit;
|
||||
|
@ -105,9 +114,27 @@ asc_ioasic_attach(parent, self, aux)
|
|||
* (2) timing based on turbochannel frequency
|
||||
*/
|
||||
|
||||
/* XXX why cached? Device registers must be uncached. */
|
||||
asc->buff = (u_char *)MIPS_PHYS_TO_KSEG0(asc_iomem);
|
||||
bufsiz = 8192;
|
||||
#ifdef ASC_IOASIC_BOUNCE
|
||||
#if USE_CACHED_BUFFER
|
||||
/* XXX Use cached address for DMA buffer to increase raw read speed */
|
||||
buff = (u_char *)MIPS_PHYS_TO_KSEG0(asc_iomem);
|
||||
#else
|
||||
buff = (u_char *)MIPS_PHYS_TO_KSEG1(asc_iomem);
|
||||
#endif /* USE_CACHED_BUFFER */
|
||||
/*
|
||||
* Statically partition the DMA buffer between targets.
|
||||
* This way we will eventually be able to attach/detach
|
||||
* drives on-fly. And 18k/target is plenty for normal use.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Give each target its own DMA buffer region.
|
||||
* We may want to try ping ponging buffers later.
|
||||
*/
|
||||
for (i = 0; i < ASC_NCMD; i++)
|
||||
asc->st[i].dmaBufAddr = buff + 8192 * i;
|
||||
|
||||
#endif /* ASC_IOASIC_BOUNCE */
|
||||
*((volatile int *)IOASIC_REG_SCSI_DMAPTR(ioasic_base)) = -1;
|
||||
*((volatile int *)IOASIC_REG_SCSI_DMANPTR(ioasic_base)) = -1;
|
||||
*((volatile int *)IOASIC_REG_SCSI_SCR(ioasic_base)) = 0;
|
||||
|
@ -115,7 +142,7 @@ asc_ioasic_attach(parent, self, aux)
|
|||
asc->dma_end = asic_dma_end;
|
||||
|
||||
/* digital meters show IOASIC 53c94s are clocked at approx 25MHz */
|
||||
ascattach(asc, bufsiz, ASC_SPEED_25_MHZ);
|
||||
ascattach(asc, ASC_SPEED_25_MHZ);
|
||||
|
||||
/* tie pseudo-slot to device */
|
||||
|
||||
|
@ -128,12 +155,14 @@ asc_ioasic_attach(parent, self, aux)
|
|||
* DMA handling routines. For a turbochannel device, just set the dmar.
|
||||
* For the I/O ASIC, handle the actual DMA interface.
|
||||
*/
|
||||
static void
|
||||
asic_dma_start(asc, state, cp, flag)
|
||||
static int
|
||||
asic_dma_start(asc, state, cp, flag, len, off)
|
||||
asc_softc_t asc;
|
||||
State *state;
|
||||
caddr_t cp;
|
||||
int flag;
|
||||
int len;
|
||||
int off;
|
||||
{
|
||||
register volatile u_int *ssr = (volatile u_int *)
|
||||
IOASIC_REG_CSR(ioasic_base);
|
||||
|
@ -143,16 +172,61 @@ asic_dma_start(asc, state, cp, flag)
|
|||
*ssr &= ~IOASIC_CSR_DMAEN_SCSI;
|
||||
*((volatile int *)IOASIC_REG_SCSI_SCR(ioasic_base)) = 0;
|
||||
|
||||
#ifdef MIPS3
|
||||
#ifndef ASC_IOASIC_BOUNCE
|
||||
/* restrict len to the maximum the IOASIC can transfer */
|
||||
if (len > ((caddr_t)mips_trunc_page(cp + NBPG * 2) - cp))
|
||||
len = (caddr_t)mips_trunc_page(cp + NBPG * 2) - cp;
|
||||
|
||||
/* If R4K, writeback and invalidate the buffer */
|
||||
if (CPUISMIPS3)
|
||||
mips3_HitFlushDCache((vm_offset_t)cp, state->dmalen);
|
||||
mips3_HitFlushDCache((vm_offset_t)cp, len);
|
||||
|
||||
/* Get physical address of buffer start, no next phys addr */
|
||||
phys = (u_int)kvtophys((vm_offset_t)cp);
|
||||
nphys = -1;
|
||||
|
||||
/* Compute 2nd DMA pointer only if next page is part of this I/O */
|
||||
if ((NBPG - (phys & (NBPG - 1))) < len) {
|
||||
cp = (caddr_t)mips_trunc_page(cp + NBPG);
|
||||
nphys = (u_int)kvtophys((vm_offset_t)cp);
|
||||
}
|
||||
|
||||
/* If not R4K, need to invalidate cache lines for both physical segments */
|
||||
if (!CPUISMIPS3 && flag == ASCDMA_READ) {
|
||||
MachFlushDCache(MIPS_PHYS_TO_KSEG0(phys),
|
||||
nphys == 0xffffffff ? len : NBPG - (phys & (NBPG - 1)));
|
||||
if (nphys != 0xffffffff)
|
||||
MachFlushDCache(MIPS_PHYS_TO_KSEG0(nphys),
|
||||
NBPG); /* XXX */
|
||||
}
|
||||
#else /* ASC_IOASIC_BOUNCE */
|
||||
/* restrict len to the maximum the IOASIC can transfer */
|
||||
if (len > ((caddr_t)mips_trunc_page(state->dmaBufAddr + off + NBPG * 2) - (caddr_t)(state->dmaBufAddr + off)))
|
||||
len = (caddr_t)mips_trunc_page(state->dmaBufAddr + off + NBPG * 2) - (caddr_t)(state->dmaBufAddr + off);
|
||||
|
||||
if (flag == ASCDMA_WRITE)
|
||||
bcopy(cp, state->dmaBufAddr + off, len);
|
||||
cp = state->dmaBufAddr + off;
|
||||
#if USE_CACHED_BUFFER
|
||||
#ifdef MIPS3
|
||||
/* If R4K, need to writeback the bounce buffer */
|
||||
if (CPUISMIPS3)
|
||||
mips3_HitFlushDCache((vm_offset_t)cp, len);
|
||||
#endif /* MIPS3 */
|
||||
phys = MIPS_KSEG0_TO_PHYS(cp);
|
||||
cp = (caddr_t)mips_trunc_page(cp + NBPG);
|
||||
nphys = MIPS_KSEG0_TO_PHYS(cp);
|
||||
#else
|
||||
phys = MIPS_KSEG1_TO_PHYS(cp);
|
||||
cp = (caddr_t)mips_trunc_page(cp + NBPG);
|
||||
nphys = MIPS_KSEG1_TO_PHYS(cp);
|
||||
#endif /* USE_CACHED_BUFFER */
|
||||
#endif /* ASC_IOASIC_BOUNCE */
|
||||
|
||||
#ifdef notyet
|
||||
asc->dma_next = cp;
|
||||
asc->dma_xfer = state->dmalen - (nphys - phys);
|
||||
#endif
|
||||
|
||||
*(volatile int *)IOASIC_REG_SCSI_DMAPTR(ioasic_base) =
|
||||
IOASIC_DMA_ADDR(phys);
|
||||
|
@ -163,6 +237,7 @@ asic_dma_start(asc, state, cp, flag)
|
|||
else
|
||||
*ssr = (*ssr & ~IOASIC_CSR_SCSI_DIR) | IOASIC_CSR_DMAEN_SCSI;
|
||||
wbflush();
|
||||
return (len);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -180,12 +255,18 @@ asic_dma_end(asc, state, flag)
|
|||
int nb;
|
||||
|
||||
*ssr &= ~IOASIC_CSR_DMAEN_SCSI;
|
||||
#if USE_CACHED_BUFFER /* XXX - Should uncached address always be used? */
|
||||
to = (u_short *)MIPS_PHYS_TO_KSEG0(*dmap >> 3);
|
||||
#else
|
||||
to = (u_short *)MIPS_PHYS_TO_KSEG1(*dmap >> 3);
|
||||
#endif
|
||||
*dmap = -1;
|
||||
*((volatile int *)IOASIC_REG_SCSI_DMANPTR(ioasic_base)) = -1;
|
||||
wbflush();
|
||||
|
||||
if (flag == ASCDMA_READ) {
|
||||
#if !defined(ASC_IOASIC_BOUNCE) && USE_CACHED_BUFFER
|
||||
/* Invalidate cache for the buffer */
|
||||
#ifdef MIPS3
|
||||
if (CPUISMIPS3)
|
||||
MachFlushDCache(MIPS_KSEG1_TO_PHYS(state->dmaBufAddr),
|
||||
|
@ -195,6 +276,7 @@ asic_dma_end(asc, state, flag)
|
|||
MachFlushDCache(MIPS_PHYS_TO_KSEG0(
|
||||
MIPS_KSEG1_TO_PHYS(state->dmaBufAddr)),
|
||||
state->dmalen);
|
||||
#endif /* USE_CACHED_BUFFER */
|
||||
if ( (nb = *((int *)IOASIC_REG_SCSI_SCR(ioasic_base))) != 0) {
|
||||
/* pick up last upto6 bytes, sigh. */
|
||||
|
||||
|
@ -210,6 +292,9 @@ asic_dma_end(asc, state, flag)
|
|||
*to++ = w;
|
||||
}
|
||||
}
|
||||
#ifdef ASC_IOASIC_BOUNCE
|
||||
bcopy(state->dmaBufAddr, state->buf, state->dmalen);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: asc_tc.c,v 1.6 1997/07/21 05:39:05 jonathan Exp $ */
|
||||
/* $NetBSD: asc_tc.c,v 1.7 1997/07/28 19:39:26 mhitch Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 1996 The Board of Trustees of The Leland Stanford
|
||||
|
@ -45,9 +45,9 @@ struct cfattach asc_tc_ca = {
|
|||
* DMA callbacks
|
||||
*/
|
||||
|
||||
static void
|
||||
static int
|
||||
tc_dma_start __P((struct asc_softc *asc, struct scsi_state *state,
|
||||
caddr_t cp, int flag));
|
||||
caddr_t cp, int flag, int len, int off));
|
||||
|
||||
static void
|
||||
tc_dma_end __P((struct asc_softc *asc, struct scsi_state *state,
|
||||
|
@ -84,7 +84,8 @@ asc_tc_attach(parent, self, aux)
|
|||
{
|
||||
register struct tc_attach_args *t = aux;
|
||||
register asc_softc_t asc = (asc_softc_t) self;
|
||||
int bufsiz, speed;
|
||||
u_char *buff;
|
||||
int i, speed;
|
||||
|
||||
void *ascaddr;
|
||||
int unit;
|
||||
|
@ -108,8 +109,21 @@ asc_tc_attach(parent, self, aux)
|
|||
* Fall through for turbochannel option.
|
||||
*/
|
||||
asc->dmar = (volatile int *)(ascaddr + ASC_OFFSET_DMAR);
|
||||
asc->buff = (u_char *)(ascaddr + ASC_OFFSET_RAM);
|
||||
bufsiz = PER_TGT_DMA_SIZE;
|
||||
buff = (u_char *)(ascaddr + ASC_OFFSET_RAM);
|
||||
|
||||
/*
|
||||
* Statically partition the DMA buffer between targets.
|
||||
* This way we will eventually be able to attach/detach
|
||||
* drives on-fly. And 18k/target is plenty for normal use.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Give each target its own DMA buffer region.
|
||||
* We may want to try ping ponging buffers later.
|
||||
*/
|
||||
for (i = 0; i < ASC_NCMD; i++)
|
||||
asc->st[i].dmaBufAddr = buff + PER_TGT_DMA_SIZE * i;
|
||||
|
||||
asc->dma_start = tc_dma_start;
|
||||
asc->dma_end = tc_dma_end;
|
||||
|
||||
|
@ -132,7 +146,7 @@ asc_tc_attach(parent, self, aux)
|
|||
break;
|
||||
};
|
||||
|
||||
ascattach(asc, bufsiz, speed);
|
||||
ascattach(asc, speed);
|
||||
|
||||
/* tie pseudo-slot to device */
|
||||
tc_intr_establish(parent, t->ta_cookie, TC_IPL_BIO,
|
||||
|
@ -144,18 +158,25 @@ asc_tc_attach(parent, self, aux)
|
|||
* DMA handling routines. For a turbochannel device, just set the dmar.
|
||||
* For the I/O ASIC, handle the actual DMA interface.
|
||||
*/
|
||||
static void
|
||||
tc_dma_start(asc, state, cp, flag)
|
||||
static int
|
||||
tc_dma_start(asc, state, cp, flag, len, off)
|
||||
asc_softc_t asc;
|
||||
State *state;
|
||||
caddr_t cp;
|
||||
int flag;
|
||||
int len;
|
||||
int off;
|
||||
{
|
||||
|
||||
if (len > PER_TGT_DMA_SIZE)
|
||||
len = PER_TGT_DMA_SIZE;
|
||||
if (flag == ASCDMA_WRITE)
|
||||
*asc->dmar = ASC_DMAR_WRITE | ASC_DMA_ADDR(cp);
|
||||
bcopy(cp, state->dmaBufAddr + off, len);
|
||||
if (flag == ASCDMA_WRITE)
|
||||
*asc->dmar = ASC_DMAR_WRITE | ASC_DMA_ADDR(state->dmaBufAddr + off);
|
||||
else
|
||||
*asc->dmar = ASC_DMA_ADDR(cp);
|
||||
*asc->dmar = ASC_DMA_ADDR(state->dmaBufAddr + off);
|
||||
return (len);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -164,5 +185,6 @@ tc_dma_end(asc, state, flag)
|
|||
State *state;
|
||||
int flag;
|
||||
{
|
||||
|
||||
if (flag == ASCDMA_READ)
|
||||
bcopy(state->dmaBufAddr, state->buf, state->dmalen);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ascvar.h,v 1.1 1996/09/25 21:07:56 jonathan Exp $ */
|
||||
/* $NetBSD: ascvar.h,v 1.2 1997/07/28 19:39:27 mhitch Exp $ */
|
||||
|
||||
|
||||
/*
|
||||
|
@ -11,7 +11,6 @@ typedef struct scsi_state {
|
|||
int statusByte; /* status byte returned during STATUS_PHASE */
|
||||
int error; /* errno to pass back to device driver */
|
||||
u_char *dmaBufAddr; /* DMA buffer address */
|
||||
u_int dmaBufSize; /* DMA buffer size */
|
||||
int dmalen; /* amount to transfer in this chunk */
|
||||
int dmaresid; /* amount not transfered if chunk suspended */
|
||||
int buflen; /* total remaining amount of data to transfer */
|
||||
|
@ -44,7 +43,6 @@ struct asc_softc {
|
|||
struct device sc_dev; /* us as a device */
|
||||
asc_regmap_t *regs; /* chip address */
|
||||
volatile int *dmar; /* DMA address register address */
|
||||
u_char *buff; /* RAM buffer address (uncached) */
|
||||
int sc_id; /* SCSI ID of this interface */
|
||||
int myidmask; /* ~(1 << myid) */
|
||||
int state; /* current SCSI connection state */
|
||||
|
@ -53,9 +51,9 @@ struct asc_softc {
|
|||
ScsiCmd *cmd[ASC_NCMD]; /* active command indexed by SCSI ID */
|
||||
State st[ASC_NCMD]; /* state info for each active command */
|
||||
/* Start dma routine */
|
||||
void (*dma_start) __P((struct asc_softc *asc,
|
||||
int (*dma_start) __P((struct asc_softc *asc,
|
||||
struct scsi_state *state,
|
||||
caddr_t cp, int flag));
|
||||
caddr_t cp, int flag, int len, int off));
|
||||
/* End dma routine */
|
||||
void (*dma_end) __P((struct asc_softc *asc,
|
||||
struct scsi_state *state, int flag));
|
||||
|
@ -82,7 +80,7 @@ typedef struct asc_softc *asc_softc_t;
|
|||
#define ASC_SPEED_25_MHZ 250
|
||||
#define ASC_SPEED_12_5_MHZ 125
|
||||
|
||||
void ascattach __P((struct asc_softc *asc, int dmabufsiz, int bus_speed));
|
||||
void ascattach __P((struct asc_softc *asc, int bus_speed));
|
||||
int asc_intr __P ((void *asc));
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue