Add support to the ISA DMA framework for auto-initialize mode.

Add experimental SB16 code, disabled for now.
This commit is contained in:
mycroft 1996-03-01 04:08:13 +00:00
parent 16f5230c39
commit 546ad9e88b
12 changed files with 279 additions and 154 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: wd.c,v 1.145 1996/01/08 21:21:56 mycroft Exp $ */
/* $NetBSD: wd.c,v 1.146 1996/03/01 04:08:51 mycroft Exp $ */
/*
* Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
@ -53,6 +53,7 @@
#include <machine/pio.h>
#include <dev/isa/isavar.h>
#include <dev/isa/isadmavar.h>
#include <dev/isa/wdreg.h>
#define WAITTIME (4 * hz) /* time to wait for a completion */
@ -661,7 +662,8 @@ loop:
WDCC_READDMA : WDCC_WRITEDMA;
/* Start the DMA channel and bounce the buffer if
necessary. */
isa_dmastart(bp->b_flags & B_READ,
isa_dmastart(
bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
bp->b_data + wd->sc_skip,
wd->sc_nbytes, wdc->sc_drq);
break;
@ -765,8 +767,8 @@ wdcintr(arg)
/* Turn off the DMA channel and unbounce the buffer. */
if (wd->sc_mode == WDM_DMA)
isa_dmadone(bp->b_flags & B_READ, bp->b_data + wd->sc_skip,
wd->sc_nbytes, wdc->sc_drq);
isa_dmadone(bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
bp->b_data + wd->sc_skip, wd->sc_nbytes, wdc->sc_drq);
/* Have we an error? */
if (wdc->sc_status & WDCS_ERR) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: ad1848.c,v 1.8 1996/02/05 21:32:26 scottr Exp $ */
/* $NetBSD: ad1848.c,v 1.9 1996/03/01 04:08:24 mycroft Exp $ */
/*
* Copyright (c) 1994 John Brezak
@ -276,7 +276,7 @@ ad1848_forceintr(sc)
* it is needed (and you pay the latency). Also, you might
* never need the buffer anyway.)
*/
isa_dmastart(B_READ, &dmabuf, 1, sc->sc_drq);
isa_dmastart(DMAMODE_READ, &dmabuf, 1, sc->sc_drq);
ad_write(sc, SP_LOWER_BASE_COUNT, 0);
ad_write(sc, SP_UPPER_BASE_COUNT, 0);
@ -1520,10 +1520,10 @@ ad1848_dma_input(addr, p, cc, intr, arg)
sc->sc_locked = 1;
sc->sc_intr = intr;
sc->sc_arg = arg;
sc->sc_dma_flags = B_READ;
sc->sc_dma_flags = DMAMODE_READ;
sc->sc_dma_bp = p;
sc->sc_dma_cnt = cc;
isa_dmastart(B_READ, p, cc, sc->sc_recdrq);
isa_dmastart(DMAMODE_READ, p, cc, sc->sc_recdrq);
if (sc->precision == 16)
cc >>= 1;
@ -1575,10 +1575,10 @@ ad1848_dma_output(addr, p, cc, intr, arg)
sc->sc_locked = 1;
sc->sc_intr = intr;
sc->sc_arg = arg;
sc->sc_dma_flags = B_WRITE;
sc->sc_dma_flags = DMAMODE_WRITE;
sc->sc_dma_bp = p;
sc->sc_dma_cnt = cc;
isa_dmastart(B_WRITE, p, cc, sc->sc_drq);
isa_dmastart(DMAMODE_WRITE, p, cc, sc->sc_drq);
if (sc->precision == 16)
cc >>= 1;
@ -1621,7 +1621,7 @@ ad1848_intr(arg)
if (sc->sc_intr && (status & INTERRUPT_STATUS)) {
/* ACK DMA read because it may be in a bounce buffer */
/* XXX Do write to mask DMA ? */
if (sc->sc_dma_flags & B_READ)
if (sc->sc_dma_flags & DMAMODE_READ)
isa_dmadone(sc->sc_dma_flags, sc->sc_dma_bp, sc->sc_dma_cnt - 1, sc->sc_recdrq);
(*sc->sc_intr)(sc->sc_arg);
retval = 1;

View File

@ -1,4 +1,4 @@
/* $NetBSD: gus.c,v 1.9 1996/02/17 04:49:50 jtk Exp $ */
/* $NetBSD: gus.c,v 1.10 1996/03/01 04:08:31 mycroft Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@ -1399,7 +1399,7 @@ gus_dmaout_dointr(sc)
register int port = sc->sc_iobase;
/* sc->sc_dmaoutcnt - 1 because DMA controller counts from zero?. */
isa_dmadone(B_WRITE,
isa_dmadone(DMAMODE_WRITE,
sc->sc_dmaoutaddr,
sc->sc_dmaoutcnt - 1,
sc->sc_drq);
@ -1909,7 +1909,7 @@ gusdmaout(sc, flags, gusaddr, buffaddr, length)
sc->sc_dmaoutaddr = (u_char *) buffaddr;
sc->sc_dmaoutcnt = length;
isa_dmastart(B_WRITE, buffaddr, length, sc->sc_drq);
isa_dmastart(DMAMODE_WRITE, buffaddr, length, sc->sc_drq);
/*
* Set up DMA address - use the upper 16 bits ONLY
@ -3253,7 +3253,7 @@ gus_dma_input(addr, buf, size, callback, arg)
dmac |= GUSMASK_SAMPLE_INVBIT;
if (sc->sc_channels == 2)
dmac |= GUSMASK_SAMPLE_STEREO;
isa_dmastart(B_READ, (caddr_t) buf, size, sc->sc_recdrq);
isa_dmastart(DMAMODE_READ, (caddr_t) buf, size, sc->sc_recdrq);
DMAPRINTF(("gus_dma_input isa_dmastarted\n"));
sc->sc_flags |= GUS_DMAIN_ACTIVE;
@ -3280,7 +3280,7 @@ gus_dmain_intr(sc)
DMAPRINTF(("gus_dmain_intr called\n"));
if (sc->sc_dmainintr) {
isa_dmadone(B_READ, sc->sc_dmainaddr, sc->sc_dmaincnt - 1,
isa_dmadone(DMAMODE_READ, sc->sc_dmainaddr, sc->sc_dmaincnt - 1,
sc->sc_recdrq);
callback = sc->sc_dmainintr;
arg = sc->sc_inarg;

View File

@ -1,4 +1,4 @@
/* $NetBSD: isadma.c,v 1.14 1996/02/22 06:21:48 mycroft Exp $ */
/* $NetBSD: isadma.c,v 1.15 1996/03/01 04:08:48 mycroft Exp $ */
#include <sys/param.h>
#include <sys/systm.h>
@ -24,8 +24,16 @@ static char bounced[8]; /* XXX */
static u_int8_t dma_finished;
/* high byte of address is stored in this port for i-th dma channel */
static int dmapageport[8] =
{ 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a };
static int dmapageport[8] = {
0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a
};
static u_int8_t dmamode[4] = {
DMA37MD_WRITE | DMA37MD_SINGLE,
DMA37MD_READ | DMA37MD_SINGLE,
DMA37MD_WRITE | DMA37MD_LOOP,
DMA37MD_READ | DMA37MD_LOOP
};
/*
* isa_dmacascade(): program 8237 DMA controller channel to accept
@ -43,11 +51,13 @@ isa_dmacascade(chan)
/* set dma channel mode, and set dma channel mode */
if ((chan & 4) == 0) {
outb(DMA1_MODE, DMA37MD_CASCADE | chan);
outb(DMA1_MODE, chan | DMA37MD_CASCADE);
outb(DMA1_SMSK, chan);
} else {
outb(DMA2_MODE, DMA37MD_CASCADE | (chan & 3));
outb(DMA2_SMSK, chan & 3);
chan &= 3;
outb(DMA2_MODE, chan | DMA37MD_CASCADE);
outb(DMA2_SMSK, chan);
}
}
@ -82,7 +92,7 @@ isa_dmastart(flags, addr, nbytes, chan)
newaddr = dma_bounce[chan];
*(int *) newaddr = 0; /* XXX */
/* copy bounce buffer on write */
if ((flags & B_READ) == 0)
if ((flags & DMAMODE_READ) == 0)
bcopy(addr, newaddr, nbytes);
addr = newaddr;
}
@ -98,17 +108,17 @@ isa_dmastart(flags, addr, nbytes, chan)
* byte mode channels.
*/
/* set dma channel mode, and reset address ff */
if (flags & B_READ)
outb(DMA1_MODE, chan | DMA37MD_SINGLE | DMA37MD_WRITE);
if (flags & DMAMODE_READ)
outb(DMA1_MODE, chan | dmamode[flags]);
else
outb(DMA1_MODE, chan | DMA37MD_SINGLE | DMA37MD_READ);
outb(DMA1_MODE, chan | dmamode[flags]);
outb(DMA1_FFC, 0);
/* send start address */
waport = DMA1_CHN(chan);
waport = DMA1_CHN(chan);
outb(dmapageport[chan], phys>>16);
outb(waport, phys);
outb(waport, phys>>8);
outb(dmapageport[chan], phys>>16);
/* send count */
outb(waport + 1, --nbytes);
@ -117,22 +127,25 @@ isa_dmastart(flags, addr, nbytes, chan)
/* unmask channel */
outb(DMA1_SMSK, chan | DMA37SM_CLEAR);
} else {
chan &= 3;
/*
* Program one of DMA channels 4..7. These are
* word mode channels.
*/
/* set dma channel mode, and reset address ff */
if (flags & B_READ)
outb(DMA2_MODE, (chan & 3) | DMA37MD_SINGLE | DMA37MD_WRITE);
if (flags & DMAMODE_READ)
outb(DMA2_MODE, chan | dmamode[flags]);
else
outb(DMA2_MODE, (chan & 3) | DMA37MD_SINGLE | DMA37MD_READ);
outb(DMA2_MODE, chan | dmamode[flags]);
outb(DMA2_FFC, 0);
/* send start address */
waport = DMA2_CHN(chan & 3);
outb(waport, phys>>1);
outb(waport, phys>>9);
waport = DMA2_CHN(chan);
outb(dmapageport[chan], phys>>16);
phys >>= 1;
outb(waport, phys);
outb(waport, phys>>8);
/* send count */
nbytes >>= 1;
@ -140,7 +153,7 @@ isa_dmastart(flags, addr, nbytes, chan)
outb(waport + 2, nbytes>>8);
/* unmask channel */
outb(DMA2_SMSK, (chan & 3) | DMA37SM_CLEAR);
outb(DMA2_SMSK, chan | DMA37SM_CLEAR);
}
}

View File

@ -1,4 +1,8 @@
/* $NetBSD: isadmavar.h,v 1.3 1996/02/20 04:17:06 mycroft Exp $ */
/* $NetBSD: isadmavar.h,v 1.4 1996/03/01 04:08:46 mycroft Exp $ */
#define DMAMODE_WRITE 0
#define DMAMODE_READ 1
#define DMAMODE_LOOP 2
void isa_dmacascade __P((int));
void isa_dmastart __P((int, caddr_t, vm_size_t, int));

View File

@ -1,4 +1,4 @@
/* $NetBSD: pas.c,v 1.12 1996/02/16 08:18:34 mycroft Exp $ */
/* $NetBSD: pas.c,v 1.13 1996/03/01 04:08:43 mycroft Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@ -407,7 +407,7 @@ pasforceintr(aux)
* it is needed (and you pay the latency). Also, you might
* never need the buffer anyway.)
*/
at_dma(1, &dmabuf, 1, ia->ia_drq);
at_dma(DMAMODE_READ, &dmabuf, 1, ia->ia_drq);
if (pas_wdsp(iobase, SB_DSP_RDMA) == 0) {
(void)pas_wdsp(iobase, 0);
(void)pas_wdsp(iobase, 0);

View File

@ -1,4 +1,4 @@
/* $NetBSD: sb.c,v 1.30 1996/02/16 08:18:32 mycroft Exp $ */
/* $NetBSD: sb.c,v 1.31 1996/03/01 04:08:45 mycroft Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@ -247,7 +247,7 @@ sbforceintr(aux)
* it is needed (and you pay the latency). Also, you might
* never need the buffer anyway.)
*/
at_dma(B_READ, &dmabuf, 1, ia->ia_drq);
at_dma(DMAMODE_READ, &dmabuf, 1, ia->ia_drq);
if (sbdsp_wdsp(iobase, SB_DSP_RDMA) == 0) {
(void)sbdsp_wdsp(iobase, 0);
(void)sbdsp_wdsp(iobase, 0);

View File

@ -1,4 +1,4 @@
/* $NetBSD: sbdsp.c,v 1.22 1996/02/20 11:48:50 mycroft Exp $ */
/* $NetBSD: sbdsp.c,v 1.23 1996/03/01 04:08:38 mycroft Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@ -123,12 +123,13 @@ sb_printsc(struct sbdsp_softc *sc)
printf("open %d dmachan %d iobase %x\n",
sc->sc_open, sc->sc_drq, sc->sc_iobase);
printf("itc %d imode %d otc %d omode %d encoding %x\n",
sc->sc_itc, sc->sc_imode, sc->sc_otc, sc->sc_omode, sc->encoding);
printf("irate %d itc %d imode %d orate %d otc %d omode %d encoding %x\n",
sc->sc_irate, sc->sc_itc, sc->sc_imode,
sc->sc_orate, sc->sc_otc, sc->sc_omode, sc->encoding);
printf("outport %d inport %d spkron %d nintr %d\n",
sc->out_port, sc->in_port, sc->spkr_state, sc->sc_interrupts);
printf("chans %x intr %x arg %x\n",
sc->sc_chans, sc->sc_intr, sc->sc_arg);
printf("precision %d channels %d intr %x arg %x\n",
sc->sc_precision, sc->sc_channels, sc->sc_intr, sc->sc_arg);
printf("gain: ");
for (i = 0; i < SB_NDEVS; i++)
printf("%d ", sc->gain[i]);
@ -169,12 +170,15 @@ sbdsp_attach(sc)
register int iobase = sc->sc_iobase;
/* Set defaults */
if (ISSBPROCLASS(sc))
sc->sc_itc = sc->sc_otc = SBPRO_ADC_HS_MAX;
if (ISSB16CLASS(sc))
sc->sc_irate = sc->sc_orate = 8000;
else if (ISSBPROCLASS(sc))
sc->sc_itc = sc->sc_otc = SB_8K;
else
sc->sc_itc = sc->sc_otc = SBCLA_ADC_HS_MAX;
sc->sc_chans = 1;
sc->encoding = AUDIO_ENCODING_LINEAR;
sc->sc_itc = sc->sc_otc = SB_8K;
sc->sc_precision = 8;
sc->sc_channels = 1;
sc->encoding = AUDIO_ENCODING_ULAW;
(void) sbdsp_set_in_port(sc, SB_MIC_PORT);
(void) sbdsp_set_out_port(sc, SB_SPEAKER);
@ -201,6 +205,18 @@ sbdsp_attach(sc)
printf(": dsp v%d.%02d\n",
SBVER_MAJOR(sc->sc_model), SBVER_MINOR(sc->sc_model));
#ifdef notyet
sbdsp_mix_write(sc, SBP_SET_IRQ, 0x04);
sbdsp_mix_write(sc, SBP_SET_DRQ, 0x22);
printf("sbdsp_attach: irq=%02x, drq=%02x\n",
sbdsp_mix_read(sc, SBP_SET_IRQ),
sbdsp_mix_read(sc, SBP_SET_DRQ));
#else
if (ISSB16CLASS(sc))
sc->sc_model = 0x0300;
#endif
}
/*
@ -238,7 +254,10 @@ sbdsp_set_in_sr(addr, sr)
{
register struct sbdsp_softc *sc = addr;
return (sbdsp_srtotc(sc, sr, SB_INPUT_RATE, &sc->sc_itc, &sc->sc_imode));
if (ISSB16CLASS(sc))
return (sbdsp_setrate(sc, sr, SB_INPUT_RATE, &sc->sc_irate));
else
return (sbdsp_srtotc(sc, sr, SB_INPUT_RATE, &sc->sc_itc, &sc->sc_imode));
}
u_long
@ -247,7 +266,10 @@ sbdsp_get_in_sr(addr)
{
register struct sbdsp_softc *sc = addr;
return (sbdsp_tctosr(sc, sc->sc_itc));
if (ISSB16CLASS(sc))
return (sc->sc_irate);
else
return (sbdsp_tctosr(sc, sc->sc_itc));
}
int
@ -257,7 +279,10 @@ sbdsp_set_out_sr(addr, sr)
{
register struct sbdsp_softc *sc = addr;
return (sbdsp_srtotc(sc, sr, SB_OUTPUT_RATE, &sc->sc_otc, &sc->sc_omode));
if (ISSB16CLASS(sc))
return (sbdsp_setrate(sc, sr, SB_OUTPUT_RATE, &sc->sc_orate));
else
return (sbdsp_srtotc(sc, sr, SB_OUTPUT_RATE, &sc->sc_otc, &sc->sc_omode));
}
u_long
@ -266,7 +291,10 @@ sbdsp_get_out_sr(addr)
{
register struct sbdsp_softc *sc = addr;
return (sbdsp_tctosr(sc, sc->sc_otc));
if (ISSB16CLASS(sc))
return (sc->sc_orate);
else
return (sbdsp_tctosr(sc, sc->sc_otc));
}
int
@ -292,13 +320,13 @@ sbdsp_query_encoding(addr, fp)
}
int
sbdsp_set_encoding(addr, enc)
sbdsp_set_encoding(addr, encoding)
void *addr;
u_int enc;
u_int encoding;
{
register struct sbdsp_softc *sc = addr;
switch(enc){
switch (encoding) {
case AUDIO_ENCODING_ULAW:
sc->encoding = AUDIO_ENCODING_ULAW;
break;
@ -308,6 +336,7 @@ sbdsp_set_encoding(addr, enc)
default:
return (EINVAL);
}
return (0);
}
@ -321,13 +350,22 @@ sbdsp_get_encoding(addr)
}
int
sbdsp_set_precision(addr, prec)
sbdsp_set_precision(addr, precision)
void *addr;
u_int prec;
u_int precision;
{
register struct sbdsp_softc *sc = addr;
if (ISSB16CLASS(sc)) {
if (precision != 16 && precision != 8)
return (EINVAL);
sc->sc_precision = precision;
} else {
if (precision != 8)
return (EINVAL);
sc->sc_precision = precision;
}
if (prec != 8)
return (EINVAL);
return (0);
}
@ -335,36 +373,32 @@ int
sbdsp_get_precision(addr)
void *addr;
{
return (8);
register struct sbdsp_softc *sc = addr;
return (sc->sc_precision);
}
int
sbdsp_set_channels(addr, chans)
sbdsp_set_channels(addr, channels)
void *addr;
int chans;
int channels;
{
register struct sbdsp_softc *sc = addr;
if (ISSBPROCLASS(sc)) {
if (chans != 1 && chans != 2)
if (channels != 1 && channels != 2)
return (EINVAL);
sc->sc_chans = chans;
#if 0
if (rval = sbdsp_set_in_sr_real(addr, sc->sc_irate))
return rval;
#endif
sbdsp_mix_write(sc, SBP_STEREO,
(sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
(chans == 2 ? SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
/* recording channels needs to be done right when we start
DMA recording. Just record number of channels for now
and set stereo when ready. */
sc->sc_channels = channels;
sc->sc_dmadir = SB_DMA_NONE;
/*
* XXXX
* With 2 channels, SBPro can't do more than 22kHz.
* No framework to check this.
*/
} else {
if (chans != 1)
if (channels != 1)
return (EINVAL);
sc->sc_chans = chans;
sc->sc_channels = channels;
}
return (0);
@ -376,18 +410,7 @@ sbdsp_get_channels(addr)
{
register struct sbdsp_softc *sc = addr;
#if 0
/* recording stereo may frob the mixer output */
if (ISSBPROCLASS(sc)) {
if ((sbdsp_mix_read(sc, SBP_STEREO) & SBP_PLAYMODE_MASK) == SBP_PLAYMODE_STEREO)
sc->sc_chans = 2;
else
sc->sc_chans = 1;
} else
sc->sc_chans = 1;
#endif
return (sc->sc_chans);
return (sc->sc_channels);
}
int
@ -555,13 +578,19 @@ sbdsp_round_blocksize(addr, blk)
sc->sc_last_hs_size = 0;
/* Higher speeds need bigger blocks to avoid popping and silence gaps. */
if ((sc->sc_otc > SB_8K || sc->sc_itc > SB_8K) &&
(blk > NBPG/2 || blk < NBPG/4))
blk = NBPG/2;
if (blk < NBPG/4 || blk > NBPG/2) {
if (ISSB16CLASS(sc)) {
if (sc->sc_orate > 8000 || sc->sc_irate > 8000)
blk = NBPG/2;
} else {
if (sc->sc_otc > SB_8K || sc->sc_itc < SB_8K)
blk = NBPG/2;
}
}
/* don't try to DMA too much at once, though. */
if (blk > NBPG)
blk = NBPG;
if (sc->sc_chans == 2)
if (sc->sc_channels == 2)
return (blk & ~1); /* must be even to preserve stereo separation */
else
return (blk); /* Anything goes :-) */
@ -671,6 +700,24 @@ sbdsp_reset(sc)
return 0;
}
int
sbdsp16_wait(iobase)
int iobase;
{
register int i;
for (i = SBDSP_NPOLL; --i >= 0; ) {
register u_char x;
x = inb(iobase + SBP_DSP_WSTAT);
delay(10);
if ((x & SB_DSP_BUSY) == 0)
continue;
return 0;
}
++sberr.wdsp;
return -1;
}
/*
* Write a byte to the dsp.
* XXX We are at the mercy of the card as we use a
@ -814,6 +861,24 @@ sbdsp_contdma(addr)
return(0);
}
int
sbdsp_setrate(sc, sr, isdac, ratep)
register struct sbdsp_softc *sc;
int sr;
int isdac;
int *ratep;
{
/*
* XXXX
* More checks here?
*/
if (sr < 5000 || sr > 44100)
return (EINVAL);
*ratep = sr;
return (0);
}
/*
* Convert a linear sampling rate into the DAC time constant.
* Set *mode to indicate the high/low-speed DMA operation.
@ -902,7 +967,7 @@ sbdsp_tctosr(sc, tc)
}
int
sbdsp_set_tc(sc, tc)
sbdsp_set_timeconst(sc, tc)
register struct sbdsp_softc *sc;
int tc;
{
@ -912,10 +977,10 @@ sbdsp_set_tc(sc, tc)
* A SBPro in stereo mode uses time constants at double the
* actual rate.
*/
if (ISSBPRO(sc) && sc->sc_chans == 2)
if (ISSBPRO(sc) && sc->sc_channels == 2)
tc = 256 - ((256 - tc) / 2);
DPRINTF(("sbdsp_set_tc: sc=%p tc=%d\n", sc, tc));
DPRINTF(("sbdsp_set_timeconst: sc=%p tc=%d\n", sc, tc));
iobase = sc->sc_iobase;
if (sbdsp_wdsp(iobase, SB_DSP_TIMECONST) < 0 ||
@ -940,15 +1005,15 @@ sbdsp_dma_input(addr, p, cc, intr, arg)
if (sbdspdebug > 1)
Dprintf("sbdsp_dma_input: cc=%d 0x%x (0x%x)\n", cc, intr, arg);
#endif
if (sc->sc_chans == 2 && (cc & 1)) {
if (sc->sc_channels == 2 && (cc & 1)) {
DPRINTF(("sbdsp_dma_input: stereo input, odd bytecnt\n"));
return EIO;
}
iobase = sc->sc_iobase;
if (sc->sc_dmadir != SB_DMA_IN) {
if (ISSBPROCLASS(sc)) {
if (sc->sc_chans == 2) {
if (ISSBPRO(sc)) {
if (sc->sc_channels == 2) {
if (sbdsp_wdsp(iobase, SB_DSP_RECORD_STEREO) < 0)
goto badmode;
sbdsp_mix_write(sc, SBP_INFILTER,
@ -963,26 +1028,45 @@ sbdsp_dma_input(addr, p, cc, intr, arg)
}
}
sbdsp_set_tc(sc, sc->sc_itc);
if (ISSB16CLASS(sc)) {
if (sbdsp_wdsp(iobase, SB_DSP16_INPUTRATE) < 0 ||
sbdsp_wdsp(iobase, sc->sc_irate >> 8) < 0 ||
sbdsp_wdsp(iobase, sc->sc_irate) < 0)
goto giveup;
} else
sbdsp_set_timeconst(sc, sc->sc_itc);
sc->sc_dmadir = SB_DMA_IN;
}
isa_dmastart(B_READ, p, cc, sc->sc_drq);
isa_dmastart(DMAMODE_READ, p, cc, sc->sc_drq);
sc->sc_intr = intr;
sc->sc_arg = arg;
sc->dmaflags = B_READ;
sc->dmaflags = DMAMODE_READ;
sc->dmaaddr = p;
sc->dmacnt = --cc; /* DMA controller is strange...? */
sc->dmacnt = cc; /* DMA controller is strange...? */
if (sc->sc_imode == SB_ADAC_LS) {
if (sc->sc_precision == 16)
cc >>= 1;
--cc;
if (ISSB16CLASS(sc)) {
if (sbdsp_wdsp(iobase, sc->sc_precision == 16 ? SB_DSP16_RDMA_16 :
SB_DSP16_RDMA_8) < 0 ||
sbdsp_wdsp(iobase, (sc->sc_precision == 16 ? 0x10 : 0x00) |
(sc->sc_channels == 2 ? 0x20 : 0x00)) < 0 ||
sbdsp16_wait(iobase) ||
sbdsp_wdsp(iobase, cc) < 0 ||
sbdsp_wdsp(iobase, cc >> 8) < 0) {
DPRINTF(("sbdsp_dma_input: SB16 DMA start failed\n"));
goto giveup;
}
} else if (sc->sc_imode == SB_ADAC_LS) {
if (sbdsp_wdsp(iobase, SB_DSP_RDMA) < 0 ||
sbdsp_wdsp(iobase, cc) < 0 ||
sbdsp_wdsp(iobase, cc >> 8) < 0) {
DPRINTF(("sbdsp_dma_input: LS DMA start failed\n"));
goto giveup;
}
}
else {
} else {
if (cc != sc->sc_last_hs_size) {
if (sbdsp_wdsp(iobase, SB_DSP_BLOCKSIZE) < 0 ||
sbdsp_wdsp(iobase, cc) < 0 ||
@ -1005,7 +1089,7 @@ giveup:
badmode:
DPRINTF(("sbdsp_dma_input: can't set %s mode\n",
sc->sc_chans == 2 ? "stereo" : "mono"));
sc->sc_channels == 2 ? "stereo" : "mono"));
return EIO;
}
@ -1024,41 +1108,60 @@ sbdsp_dma_output(addr, p, cc, intr, arg)
if (sbdspdebug > 1)
Dprintf("sbdsp_dma_output: cc=%d 0x%x (0x%x)\n", cc, intr, arg);
#endif
if (sc->sc_chans == 2 && (cc & 1)) {
if (sc->sc_channels == 2 && (cc & 1)) {
DPRINTF(("stereo playback odd bytes (%d)\n", cc));
return EIO;
}
iobase = sc->sc_iobase;
if (sc->sc_dmadir != SB_DMA_OUT) {
if (ISSBPROCLASS(sc)) {
if (ISSBPRO(sc)) {
/* make sure we re-set stereo mixer bit when we start
output. */
sbdsp_mix_write(sc, SBP_STEREO,
(sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
(sc->sc_chans == 2 ? SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
(sc->sc_channels == 2 ? SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
}
sbdsp_set_tc(sc, sc->sc_otc);
if (ISSB16CLASS(sc)) {
if (sbdsp_wdsp(iobase, SB_DSP16_OUTPUTRATE) < 0 ||
sbdsp_wdsp(iobase, sc->sc_orate >> 8) < 0 ||
sbdsp_wdsp(iobase, sc->sc_orate) < 0)
goto giveup;
} else
sbdsp_set_timeconst(sc, sc->sc_otc);
sc->sc_dmadir = SB_DMA_OUT;
}
isa_dmastart(B_WRITE, p, cc, sc->sc_drq);
isa_dmastart(DMAMODE_WRITE, p, cc, sc->sc_drq);
sc->sc_intr = intr;
sc->sc_arg = arg;
sc->dmaflags = B_WRITE;
sc->dmaflags = DMAMODE_WRITE;
sc->dmaaddr = p;
sc->dmacnt = --cc; /* a vagary of how DMA works, apparently. */
sc->dmacnt = cc; /* a vagary of how DMA works, apparently. */
if (sc->sc_omode == SB_ADAC_LS) {
if (sc->sc_precision == 16)
cc >>= 1;
--cc;
if (ISSB16CLASS(sc)) {
if (sbdsp_wdsp(iobase, sc->sc_precision == 16 ? SB_DSP16_WDMA_16 :
SB_DSP16_WDMA_8) < 0 ||
sbdsp_wdsp(iobase, (sc->sc_precision == 16 ? 0x10 : 0x00) |
(sc->sc_channels == 2 ? 0x20 : 0x00)) < 0 ||
sbdsp16_wait(iobase) ||
sbdsp_wdsp(iobase, cc) < 0 ||
sbdsp_wdsp(iobase, cc >> 8) < 0) {
DPRINTF(("sbdsp_dma_output: SB16 DMA start failed\n"));
goto giveup;
}
} else if (sc->sc_omode == SB_ADAC_LS) {
if (sbdsp_wdsp(iobase, SB_DSP_WDMA) < 0 ||
sbdsp_wdsp(iobase, cc) < 0 ||
sbdsp_wdsp(iobase, cc >> 8) < 0) {
DPRINTF(("sbdsp_dma_output: LS DMA start failed\n"));
goto giveup;
}
}
else {
} else {
if (cc != sc->sc_last_hs_size) {
if (sbdsp_wdsp(iobase, SB_DSP_BLOCKSIZE) < 0 ||
sbdsp_wdsp(iobase, cc) < 0 ||
@ -1099,13 +1202,15 @@ sbdsp_intr(arg)
Dprintf("sbdsp_intr: intr=0x%x\n", sc->sc_intr);
#endif
if (!isa_dmafinished(sc->sc_drq)) {
#if 0
printf("sbdsp_intr: not finished\n");
#endif
return 0;
}
sc->sc_interrupts++;
/* clear interrupt */
#ifdef notyet
x = sbdsp_mix_read(sc, 0x82);
x = inb(sc->sc_iobase + 15);
#endif
x = inb(sc->sc_iobase + SBP_DSP_RSTAT);
delay(10);
#if 0
@ -1115,15 +1220,6 @@ sbdsp_intr(arg)
} else
#endif
if (sc->sc_intr != 0) {
/*
* The SBPro used to develop and test this driver often
* generated dma underruns--it interrupted to signal
* completion of the DMA input recording block, but the
* ISA DMA controller didn't think the channel was
* finished. Maybe this is just a bus speed issue, I dunno,
* but it seems strange and leads to channel-flipping with
* stereo recording. Sigh.
*/
isa_dmadone(sc->dmaflags, sc->dmaaddr, sc->dmacnt, sc->sc_drq);
(*sc->sc_intr)(sc->sc_arg);
}
@ -1172,14 +1268,14 @@ sbdsp_midi_output(sc, v)
#endif
u_int
sbdsp_get_silence(enc)
int enc;
sbdsp_get_silence(encoding)
int encoding;
{
#define ULAW_SILENCE 0x7f
#define LINEAR_SILENCE 0
u_int auzero;
switch (enc) {
switch (encoding) {
case AUDIO_ENCODING_ULAW:
auzero = ULAW_SILENCE;
break;

View File

@ -1,4 +1,4 @@
/* $NetBSD: sbdspvar.h,v 1.10 1996/02/18 16:36:52 jtk Exp $ */
/* $NetBSD: sbdspvar.h,v 1.11 1996/03/01 04:08:20 mycroft Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@ -79,7 +79,8 @@ struct sbdsp_softc {
int sc_iobase; /* I/O port base address */
int sc_irq; /* interrupt */
int sc_drq; /* DMA */
int sc_drq; /* DMA (8-bit) */
int sc_drq16; /* DMA (16-bit) */
u_short sc_open; /* reference count of open calls */
@ -94,8 +95,8 @@ struct sbdsp_softc {
u_int spkr_state; /* non-null is on */
int sc_itc; /* Sample rate for input */
int sc_otc; /* ...and output */
int sc_irate, sc_itc; /* Sample rate for input */
int sc_orate, sc_otc; /* ...and output */
int sc_imode;
int sc_omode;
@ -111,7 +112,8 @@ struct sbdsp_softc {
caddr_t dmaaddr;
vm_size_t dmacnt;
int sc_last_hs_size; /* last HS dma size */
int sc_chans; /* # of channels */
int sc_precision; /* size of samples */
int sc_channels; /* # of channels */
int sc_dmadir; /* DMA direction */
#define SB_DMA_NONE 0
#define SB_DMA_IN 1
@ -122,14 +124,14 @@ struct sbdsp_softc {
#define SBVER_MINOR(v) ((v)&0xff)
};
#define ISSBPRO(sc) \
(SBVER_MAJOR((sc)->sc_model) == 3)
#define ISSBPROCLASS(sc) \
(SBVER_MAJOR((sc)->sc_model) > 2)
#define ISSBPRO(sc) \
(SBVER_MAJOR((sc)->sc_model) == 3)
#define ISSB16CLASS(sc) \
(SBVER_MAJOR((sc)->sc_model) > 3)
(SBVER_MAJOR((sc)->sc_model) > 3)
#ifdef _KERNEL

View File

@ -1,4 +1,4 @@
/* $NetBSD: sbreg.h,v 1.14 1996/02/20 11:15:17 mycroft Exp $ */
/* $NetBSD: sbreg.h,v 1.15 1996/03/01 04:08:13 mycroft Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@ -150,6 +150,8 @@
#define SB_MIDI_UART_INTR 0x35 /* enter UART mode w/ read intrs */
#define SB_MIDI_WRITE 0x38 /* write a MIDI byte (non-UART mode) */
#define SB_DSP_TIMECONST 0x40 /* set ADAC time constant */
#define SB_DSP16_OUTPUTRATE 0x41 /* set ADAC output rate */
#define SB_DSP16_INPUTRATE 0x42 /* set ADAC input rate */
#define SB_DSP_BLOCKSIZE 0x48 /* set blk size for high speed xfer */
#define SB_DSP_WDMA_4 0x74 /* begin 4-bit ADPCM DMA output */
#define SB_DSP_WDMA_2_6 0x76 /* begin 2.6-bit ADPCM DMA output */
@ -158,6 +160,10 @@
#define SB_DSP_HS_INPUT 0x99 /* set high speed mode for rdma */
#define SB_DSP_RECORD_MONO 0xA0 /* set mono recording */
#define SB_DSP_RECORD_STEREO 0xA8 /* set stereo recording */
#define SB_DSP16_WDMA_16 0xB6 /* begin 16-bit linear output */
#define SB_DSP16_RDMA_16 0xBE /* begin 16-bit linear input */
#define SB_DSP16_WDMA_8 0xC6 /* begin 8-bit linear output */
#define SB_DSP16_RDMA_8 0xCE /* begin 8-bit linear input */
#define SB_DSP_HALT 0xd0 /* temporarilty suspend DMA */
#define SB_DSP_SPKR_ON 0xd1 /* turn speaker on */
#define SB_DSP_SPKR_OFF 0xd3 /* turn speaker off */

View File

@ -1,4 +1,4 @@
/* $NetBSD: wd.c,v 1.145 1996/01/08 21:21:56 mycroft Exp $ */
/* $NetBSD: wd.c,v 1.146 1996/03/01 04:08:51 mycroft Exp $ */
/*
* Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
@ -53,6 +53,7 @@
#include <machine/pio.h>
#include <dev/isa/isavar.h>
#include <dev/isa/isadmavar.h>
#include <dev/isa/wdreg.h>
#define WAITTIME (4 * hz) /* time to wait for a completion */
@ -661,7 +662,8 @@ loop:
WDCC_READDMA : WDCC_WRITEDMA;
/* Start the DMA channel and bounce the buffer if
necessary. */
isa_dmastart(bp->b_flags & B_READ,
isa_dmastart(
bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
bp->b_data + wd->sc_skip,
wd->sc_nbytes, wdc->sc_drq);
break;
@ -765,8 +767,8 @@ wdcintr(arg)
/* Turn off the DMA channel and unbounce the buffer. */
if (wd->sc_mode == WDM_DMA)
isa_dmadone(bp->b_flags & B_READ, bp->b_data + wd->sc_skip,
wd->sc_nbytes, wdc->sc_drq);
isa_dmadone(bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
bp->b_data + wd->sc_skip, wd->sc_nbytes, wdc->sc_drq);
/* Have we an error? */
if (wdc->sc_status & WDCS_ERR) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: wt.c,v 1.28 1996/01/12 00:54:23 thorpej Exp $ */
/* $NetBSD: wt.c,v 1.29 1996/03/01 04:08:40 mycroft Exp $ */
/*
* Streamer tape driver.
@ -138,7 +138,7 @@ struct wt_softc {
void *dmavaddr; /* virtual address of dma i/o buffer */
size_t dmatotal; /* size of i/o buffer */
int dmaflags; /* i/o direction, B_READ or B_WRITE */
int dmaflags; /* i/o direction */
size_t dmacount; /* resulting length of dma i/o */
u_short error; /* code for error encountered */
@ -668,7 +668,7 @@ wtintr(arg)
/*
* Clean up dma.
*/
if ((sc->dmaflags & B_READ) &&
if ((sc->dmaflags & DMAMODE_READ) &&
(sc->dmatotal - sc->dmacount) < sc->bsize) {
/* If reading short block, copy the internal buffer
* to the user memory. */
@ -682,7 +682,7 @@ wtintr(arg)
*/
if ((x & sc->NOEXCEP) == 0) {
WTDBPRINT(("i/o exception\n"));
wtsense(sc, 1, (sc->dmaflags & B_READ) ? TP_WRP : 0);
wtsense(sc, 1, (sc->dmaflags & DMAMODE_READ) ? TP_WRP : 0);
if (sc->error & (TP_EOM | TP_FIL))
sc->flags |= TPVOL; /* end of file */
else
@ -857,7 +857,7 @@ wtdma(sc)
outb(sc->SDMAPORT, 0);
}
if ((sc->dmaflags & B_READ) &&
if ((sc->dmaflags & DMAMODE_READ) &&
(sc->dmatotal - sc->dmacount) < sc->bsize) {
/* Reading short block; do it through the internal buffer. */
isa_dmastart(sc->dmaflags, sc->buf, sc->bsize, sc->chan);
@ -885,7 +885,7 @@ wtstart(sc, flag, vaddr, len)
sc->dmavaddr = vaddr;
sc->dmatotal = len;
sc->dmacount = 0;
sc->dmaflags = flag;
sc->dmaflags = flag & B_READ ? DMAMODE_READ : DMAMODE_WRITE;
wtdma(sc);
return 1;
}