Subject: kern/10034: turbochannel audio for NetBSD/alpha and NetBSD/pmax
To: None <gnats-bugs@gnats.netbsd.org>
From: None <g.mcgarry@qut.edu.au>
List: netbsd-bugs
Date: 05/01/2000 15:38:22
>Number: 10034
>Category: kern
>Synopsis: turbochannel audio for NetBSD/alpha and NetBSD/pmax
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: kern-bug-people
>State: open
>Class: support
>Submitter-Id: net
>Arrival-Date: Mon May 01 15:39:00 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator: Gregory McGarry
>Release: 1.4X
>Organization:
>Environment:
NetBSD/pmax.
>Description:
Provides a turbochannel audio driver for the am7930, found in
NetBSD/pmax and NetBSD/alpha. I haven't tested on NetBSD/alpha,
however any changes should be minimal. Requires kern/10029 and
kern/10032. See also port-sparc/10033.
>How-To-Repeat:
>Fix:
*** /dev/null Mon May 1 12:50:13 2000
--- bba.c Mon May 1 13:42:02 2000
***************
*** 0 ****
--- 1,802 ----
+ /* $NetBSD$ */
+
+ /*
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ /* maxine/alpha baseboard audio (bba) */
+
+ #include "audio.h"
+ #if NAUDIO > 0
+
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/kernel.h>
+ #include <sys/device.h>
+ #include <sys/malloc.h>
+
+ #include <machine/bus.h>
+ #include <machine/autoconf.h>
+ #include <machine/cpu.h>
+
+ #include <vm/vm.h> /* for PAGE_SIZE */
+
+ #include <sys/audioio.h>
+ #include <dev/audio_if.h>
+
+ #include <dev/ic/am7930reg.h>
+ #include <dev/ic/am7930var.h>
+
+ #include <dev/tc/tcvar.h>
+ #include <dev/tc/ioasicreg.h>
+ #include <dev/tc/ioasicvar.h>
+
+ #ifdef pmax
+ #include <pmax/pmax/maxine.h>
+ #define IOASIC_CSR_ISDN_ENABLE XINE_CSR_ISDN_ENABLE
+ #define IOASIC_INTR_ISDN_TXLOAD IOASIC_INTR_ISDN_DS_TXLOAD
+ #define IOASIC_INTR_ISDN_RXLOAD IOASIC_INTR_ISDN_DS_RXLOAD
+ #ifdef IOASIC_INTR_ISDN_OVRUN
+ #undef IOASIC_INTR_ISDN_OVRUN
+ #endif
+ #define IOASIC_INTR_ISDN_OVRUN IOASIC_INTR_ISDN_DS_OVRUN
+ #endif
+
+ #ifdef AUDIO_DEBUG
+ #define DPRINTF(x) if (am7930debug) printf x
+ #else
+ #define DPRINTF(x)
+ #endif /* AUDIO_DEBUG */
+
+ #define BBA_MAX_DMA_SEGMENTS 16
+
+ struct bba_mem {
+ bus_addr_t addr;
+ bus_size_t size;
+ caddr_t kva;
+ struct bba_mem *next;
+ };
+
+ struct bba_dma_state {
+ bus_dmamap_t dmam; /* dma map */
+ int active;
+ int curseg; /* current segment in dma buffer */
+ void (*intr)__P((void *)); /* higher-level audio handler */
+ void *intr_arg;
+ };
+
+ struct bba_softc {
+ struct am7930_softc sc_am7930; /* glue to MI code */
+
+ bus_space_tag_t sc_bst; /* IOASIC bus tag/handle */
+ bus_space_handle_t sc_bsh;
+ bus_dma_tag_t sc_dmat;
+ bus_space_handle_t sc_codec_bsh; /* codec bus space handle */
+
+ struct bba_mem *sc_mem_head; /* list of buffers */
+
+ struct bba_dma_state sc_tx_dma_state;
+ struct bba_dma_state sc_rx_dma_state;
+ };
+
+ int bba_match __P((struct device *, struct cfdata *, void *));
+ void bba_attach __P((struct device *, struct device *, void *));
+
+ struct cfattach bba_ca = {
+ sizeof(struct bba_softc), bba_match, bba_attach
+ };
+
+ /*
+ * Define our interface into the am7930 MI driver.
+ */
+
+ u_int8_t bba_codec_iread __P((struct am7930_softc *, int));
+ u_int16_t bba_codec_iread16 __P((struct am7930_softc *, int));
+ void bba_codec_iwrite __P((struct am7930_softc *, int, u_int8_t));
+ void bba_codec_iwrite16 __P((struct am7930_softc *, int, u_int16_t));
+ void bba_onopen __P((struct am7930_softc *sc));
+ void bba_onclose __P((struct am7930_softc *sc));
+ void bba_output_conv __P((void *, u_int8_t *, int));
+ void bba_input_conv __P((void *, u_int8_t *, int));
+
+ struct am7930_glue bba_glue = {
+ bba_codec_iread,
+ bba_codec_iwrite,
+ bba_codec_iread16,
+ bba_codec_iwrite16,
+ bba_onopen,
+ bba_onclose,
+ 4,
+ bba_input_conv,
+ bba_output_conv,
+ };
+
+ /*
+ * Define our interface to the higher level audio driver.
+ */
+
+ int bba_round_blocksize __P((void *, int));
+ int bba_halt_output __P((void *));
+ int bba_halt_input __P((void *));
+ int bba_getdev __P((void *, struct audio_device *));
+ void *bba_allocm __P((void *, int, size_t, int, int));
+ void bba_freem __P((void *, void *, int));
+ size_t bba_round_buffersize __P((void *, int, size_t));
+ int bba_trigger_output __P((void *, void *, void *, int,
+ void (*)(void *), void *, struct audio_params *));
+ int bba_trigger_input __P((void *, void *, void *, int,
+ void (*)(void *), void *, struct audio_params *));
+
+ struct audio_hw_if sa_hw_if = {
+ am7930_open,
+ am7930_close,
+ 0,
+ am7930_query_encoding,
+ am7930_set_params,
+ bba_round_blocksize, /* md */
+ am7930_commit_settings,
+ 0,
+ 0,
+ 0,
+ 0,
+ bba_halt_output, /* md */
+ bba_halt_input, /* md */
+ 0,
+ bba_getdev,
+ 0,
+ am7930_set_port,
+ am7930_get_port,
+ am7930_query_devinfo,
+ bba_allocm, /* md */
+ bba_freem, /* md */
+ bba_round_buffersize, /* md */
+ 0,
+ am7930_get_props,
+ bba_trigger_output, /* md */
+ bba_trigger_input /* md */
+ };
+
+ struct audio_device bba_device = {
+ "am7930",
+ "x",
+ "bba"
+ };
+
+ int bba_intr __P((void *));
+ void bba_reset __P((struct bba_softc *, int));
+ void bba_codec_dwrite __P((struct am7930_softc *, int, u_int8_t));
+ u_int8_t bba_codec_dread __P((struct am7930_softc *, int));
+
+ int bba_match(parent, cf, aux)
+ struct device *parent;
+ struct cfdata *cf;
+ void *aux;
+ {
+ struct ioasicdev_attach_args *ia = aux;
+
+ if (strcmp(ia->iada_modname, "isdn") != 0 &&
+ strcmp(ia->iada_modname, "AMD79c30") != 0)
+ return 0;
+
+ return 1;
+ }
+
+
+ void
+ bba_attach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+ {
+ struct ioasicdev_attach_args *ia = aux;
+ struct bba_softc *sc = (struct bba_softc *)self;
+ struct am7930_softc *asc = &sc->sc_am7930;
+
+ sc->sc_bst = ((struct ioasic_softc *)parent)->sc_bst;
+ sc->sc_bsh = ((struct ioasic_softc *)parent)->sc_bsh;
+ sc->sc_dmat = ((struct ioasic_softc *)parent)->sc_dmat;
+
+ /* get the bus space handle for codec */
+ if (bus_space_subregion(sc->sc_bst, sc->sc_bsh,
+ ia->iada_offset, 0, &sc->sc_codec_bsh)) {
+ printf("%s: unable to map device\n", asc->sc_dev.dv_xname);
+ return;
+ }
+
+ printf("\n");
+
+ bba_reset(sc,1);
+
+ /*
+ * Set up glue for MI code early; we use some of it here.
+ */
+ asc->sc_glue = &bba_glue;
+
+ /*
+ * MI initialisation. We will be doing DMA.
+ */
+ am7930_init(asc, AUDIOAMD_DMA_MODE);
+
+ ioasic_intr_establish(parent, ia->iada_cookie, TC_IPL_NONE,
+ bba_intr, sc);
+
+ audio_attach_mi(&sa_hw_if, asc, &asc->sc_dev);
+ }
+
+
+ void
+ bba_onopen(sc)
+ struct am7930_softc *sc;
+ {
+ bba_reset((struct bba_softc *)sc, 0);
+ }
+
+
+ void
+ bba_onclose(sc)
+ struct am7930_softc *sc;
+ {
+ bba_halt_input((struct bba_softc *)sc);
+ bba_halt_output((struct bba_softc *)sc);
+ }
+
+
+ void
+ bba_reset(sc, reset)
+ struct bba_softc *sc;
+ int reset;
+ {
+ u_int32_t ssr;
+
+ /* disable any DMA and reset the codec */
+ ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
+ ssr &= ~(IOASIC_CSR_DMAEN_ISDN_T | IOASIC_CSR_DMAEN_ISDN_R);
+ if (reset)
+ ssr &= ~IOASIC_CSR_ISDN_ENABLE;
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
+ DELAY(10); /* 400ns required for codec to reset */
+
+ /* initialise DMA pointers */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR, -1);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR, -1);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR, -1);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR, -1);
+
+ /* take out of reset state */
+ if (reset) {
+ ssr |= IOASIC_CSR_ISDN_ENABLE;
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
+ }
+
+ }
+
+
+ void *
+ bba_allocm(addr, direction, size, pool, flags)
+ void *addr;
+ int direction;
+ size_t size;
+ int pool, flags;
+ {
+ struct am7930_softc *asc = addr;
+ struct bba_softc *sc = addr;
+ bus_dma_segment_t seg;
+ int rseg;
+ caddr_t kva;
+ struct bba_mem *m;
+ int state = 0;
+
+ DPRINTF(("bba_allocm: size = %d\n",size));
+
+ if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &seg,
+ 1, &rseg, BUS_DMA_NOWAIT)) {
+ printf("%s: can't allocate DMA buffer\n",
+ asc->sc_dev.dv_xname);
+ goto bad;
+ }
+ state |= 1;
+
+ if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, size,
+ &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
+ printf("%s: can't map DMA buffer\n", asc->sc_dev.dv_xname);
+ goto bad;
+ }
+ state |= 2;
+
+ m = malloc(sizeof(struct bba_mem), pool, flags);
+ if (m == NULL)
+ goto bad;
+ m->addr = seg.ds_addr;
+ m->size = seg.ds_len;
+ m->kva = kva;
+ m->next = sc->sc_mem_head;
+ sc->sc_mem_head = m;
+
+ return (void *)kva;
+
+ bad:
+ if (state & 2)
+ bus_dmamem_unmap(sc->sc_dmat, kva, size);
+ if (state & 1)
+ bus_dmamem_free(sc->sc_dmat, &seg, 1);
+ return NULL;
+ }
+
+
+ void
+ bba_freem(addr, ptr, pool)
+ void *addr;
+ void *ptr;
+ int pool;
+ {
+ struct bba_softc *sc = addr;
+ struct bba_mem **mp, *m;
+ bus_dma_segment_t seg;
+ caddr_t kva = (caddr_t)addr;
+
+ for (mp = &sc->sc_mem_head; *mp && (*mp)->kva != kva;
+ mp = &(*mp)->next)
+ /* nothing */ ;
+ m = *mp;
+ if (m != NULL) {
+ printf("bba_freem: freeing unallocted memory\n");
+ return;
+ }
+ *mp = m->next;
+ bus_dmamem_unmap(sc->sc_dmat, kva, m->size);
+
+ seg.ds_addr = m->addr;
+ seg.ds_len = m->size;
+ bus_dmamem_free(sc->sc_dmat, &seg, 1);
+ free(m, pool);
+ }
+
+
+ size_t
+ bba_round_buffersize(addr, direction, size)
+ void *addr;
+ int direction;
+ size_t size;
+ {
+ DPRINTF(("bba_round_buffersize: size=%d\n", size));
+
+ #define BBA_BUFFERSIZE (BBA_MAX_DMA_SEGMENTS * PAGE_SIZE)
+ return (size > BBA_BUFFERSIZE ? BBA_BUFFERSIZE : round_page(size));
+ }
+
+
+ int
+ bba_halt_output(addr)
+ void *addr;
+ {
+ struct bba_softc *sc = addr;
+ struct bba_dma_state *d = &sc->sc_tx_dma_state;
+ u_int32_t ssr;
+
+ /* disable any DMA */
+ ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
+ ssr &= ~IOASIC_CSR_DMAEN_ISDN_T;
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR, -1);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR, -1);
+
+ if (d->active) {
+ bus_dmamap_unload(sc->sc_dmat, d->dmam);
+ bus_dmamap_destroy(sc->sc_dmat, d->dmam);
+ d->active = 0;
+ }
+
+ return 0;
+ }
+
+
+ int
+ bba_halt_input(addr)
+ void *addr;
+ {
+ struct bba_softc *sc = addr;
+ struct bba_dma_state *d = &sc->sc_rx_dma_state;
+ u_int32_t ssr;
+
+ /* disable any DMA */
+ ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
+ ssr &= ~IOASIC_CSR_DMAEN_ISDN_R;
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR, -1);
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR, -1);
+
+ if (d->active) {
+ bus_dmamap_unload(sc->sc_dmat, d->dmam);
+ bus_dmamap_destroy(sc->sc_dmat, d->dmam);
+ d->active = 0;
+ }
+
+ return 0;
+ }
+
+
+ int
+ bba_getdev(addr, retp)
+ void *addr;
+ struct audio_device *retp;
+ {
+ *retp = bba_device;
+ return 0;
+ }
+
+
+ int
+ bba_trigger_output(addr, start, end, blksize, intr, arg, param)
+ void *addr;
+ void *start, *end;
+ int blksize;
+ void (*intr) __P((void *));
+ void *arg;
+ struct audio_params *param;
+ {
+ struct bba_softc *sc = addr;
+ struct bba_dma_state *d = &sc->sc_tx_dma_state;
+ u_int32_t ssr;
+ tc_addr_t phys, nphys;
+ int state = 0;
+
+ DPRINTF(("bba_trigger_output: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
+ addr, start, end, blksize, intr, arg));
+
+ if (bus_dmamap_create(sc->sc_dmat, (char *)end - (char *)start,
+ BBA_MAX_DMA_SEGMENTS, PAGE_SIZE, 0, BUS_DMA_NOWAIT, &d->dmam)) {
+ printf("bba_trigger_output: can't create DMA map\n");
+ goto bad;
+ }
+ state |= 1;
+
+ if (bus_dmamap_load(sc->sc_dmat, d->dmam, start,
+ (char *)end - (char *)start, NULL, BUS_DMA_NOWAIT)) {
+ printf("bba_trigger_output: can't load DMA map\n");
+ goto bad;
+ }
+ state |= 2;
+
+ /* disable any DMA */
+ ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
+ ssr &= ~IOASIC_CSR_DMAEN_ISDN_T;
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
+
+ d->intr = intr;
+ d->intr_arg = arg;
+ d->curseg = 1;
+
+ /* get physical address of buffer start */
+ phys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr;
+ nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg+1].ds_addr;
+
+ /* setup DMA pointer */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR,
+ IOASIC_DMA_ADDR(phys));
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR,
+ IOASIC_DMA_ADDR(nphys));
+
+ /* kick off DMA */
+ ssr |= IOASIC_CSR_DMAEN_ISDN_T;
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
+
+ wbflush();
+
+ d->active = 1;
+
+ return 0;
+
+ bad:
+ if (state & 2)
+ bus_dmamap_unload(sc->sc_dmat, d->dmam);
+ if (state & 1)
+ bus_dmamap_destroy(sc->sc_dmat, d->dmam);
+ return 1;
+ }
+
+
+ int
+ bba_trigger_input(addr, start, end, blksize, intr, arg, param)
+ void *addr;
+ void *start, *end;
+ int blksize;
+ void (*intr) __P((void *));
+ void *arg;
+ struct audio_params *param;
+ {
+ struct bba_softc *sc = (struct bba_softc *)addr;
+ struct bba_dma_state *d = &sc->sc_rx_dma_state;
+ tc_addr_t phys, nphys;
+ u_int32_t ssr;
+ int state = 0;
+
+ DPRINTF(("bba_trigger_input: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
+ addr, start, end, blksize, intr, arg));
+
+ if (bus_dmamap_create(sc->sc_dmat, (char *)end - (char *)start,
+ BBA_MAX_DMA_SEGMENTS, PAGE_SIZE, 0, BUS_DMA_NOWAIT, &d->dmam)) {
+ printf("bba_trigger_input: can't create DMA map\n");
+ goto bad;
+ }
+ state |= 1;
+
+ if (bus_dmamap_load(sc->sc_dmat, d->dmam, start,
+ (char *)end - (char *)start, NULL, BUS_DMA_NOWAIT)) {
+ printf("bba_trigger_input: can't load DMA map\n");
+ goto bad;
+ }
+ state |= 2;
+
+ /* disable any DMA */
+ ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
+ ssr &= ~IOASIC_CSR_DMAEN_ISDN_R;
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
+
+ d->intr = intr;
+ d->intr_arg = arg;
+ d->curseg = 1;
+
+ /* get physical address of buffer start */
+ phys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr;
+ nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg+1].ds_addr;
+
+ /* setup DMA pointer */
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR,
+ IOASIC_DMA_ADDR(phys));
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR,
+ IOASIC_DMA_ADDR(nphys));
+
+ /* kick off DMA */
+ ssr |= IOASIC_CSR_DMAEN_ISDN_R;
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
+
+ wbflush();
+
+ d->active = 1;
+
+ return 0;
+
+ bad:
+ if (state & 2)
+ bus_dmamap_unload(sc->sc_dmat, d->dmam);
+ if (state & 1)
+ bus_dmamap_destroy(sc->sc_dmat, d->dmam);
+ return 1;
+ }
+
+ int
+ bba_intr(addr)
+ void *addr;
+ {
+ struct bba_softc *sc = addr;
+ struct bba_dma_state *d;
+ tc_addr_t nphys;
+ int s, mask;
+
+ s = splaudio();
+
+ mask = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_INTR);
+
+ if (mask & IOASIC_INTR_ISDN_TXLOAD) {
+ d = &sc->sc_tx_dma_state;
+ d->curseg = (d->curseg+1) % d->dmam->dm_nsegs;
+ nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr;
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh,
+ IOASIC_ISDN_X_NEXTPTR, IOASIC_DMA_ADDR(nphys));
+ if (d->intr != NULL)
+ (*d->intr)(d->intr_arg);
+ }
+ if (mask & IOASIC_INTR_ISDN_RXLOAD) {
+ d = &sc->sc_rx_dma_state;
+ d->curseg = (d->curseg+1) % d->dmam->dm_nsegs;
+ nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr;
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh,
+ IOASIC_ISDN_R_NEXTPTR, IOASIC_DMA_ADDR(nphys));
+ if (d->intr != NULL)
+ (*d->intr)(d->intr_arg);
+ }
+
+ splx(s);
+
+ return 0;
+ }
+
+
+ void
+ bba_input_conv(v, p, cc)
+ void *v;
+ u_int8_t *p;
+ int cc;
+ {
+ u_int8_t *q = p;
+
+ DPRINTF(("bba_input_conv(): v=%p p=%p cc=%d\n", v, p, cc));
+
+ /*
+ * p points start of buffer
+ * cc is the number of bytes in the destination buffer
+ */
+
+ while (--cc >= 0) {
+ *p = ((*(u_int32_t *)q)>>16)&0xff;
+ q += 4;
+ p++;
+ }
+ }
+
+
+ void
+ bba_output_conv(v, p, cc)
+ void *v;
+ u_int8_t *p;
+ int cc;
+ {
+ u_int8_t *q = p;
+
+ DPRINTF(("bba_output_conv(): v=%p p=%p cc=%d\n", v, p, cc));
+
+ /*
+ * p points start of buffer
+ * cc is the number of bytes in the source buffer
+ */
+
+ p += cc;
+ q += cc * 4;
+ while (--cc >= 0) {
+ q -= 4;
+ p -= 1;
+ *(u_int32_t *)q = (*p<<16);
+ }
+ }
+
+
+ int
+ bba_round_blocksize(addr, blk)
+ void *addr;
+ int blk;
+ {
+ return (PAGE_SIZE);
+ }
+
+
+ /* indirect write */
+ void
+ bba_codec_iwrite(sc, reg, val)
+ struct am7930_softc *sc;
+ int reg;
+ u_int8_t val;
+ {
+ DPRINTF(("bba_codec_iwrite(): sc=%p, reg=%d, val=%d\n",sc,reg,val));
+
+ bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
+ bba_codec_dwrite(sc, AM7930_DREG_DR, val);
+ }
+
+
+ void
+ bba_codec_iwrite16(sc, reg, val)
+ struct am7930_softc *sc;
+ int reg;
+ u_int16_t val;
+ {
+ DPRINTF(("bba_codec_iwrite16(): sc=%p, reg=%d, val=%d\n",sc,reg,val));
+
+ bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
+ #if 0
+ bba_codec_dwrite(sc, AM7930_DREG_DR, val>>8);
+ bba_codec_dwrite(sc, AM7930_DREG_DR, val);
+ #else
+ bba_codec_dwrite(sc, AM7930_DREG_DR, val);
+ bba_codec_dwrite(sc, AM7930_DREG_DR, val>>8);
+ #endif
+ }
+
+
+ u_int16_t
+ bba_codec_iread16(sc, reg)
+ struct am7930_softc *sc;
+ int reg;
+ {
+ u_int16_t val;
+ DPRINTF(("bba_codec_iread16(): sc=%p, reg=%d\n",sc,reg));
+
+ bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
+ #if 0
+ bba_codec_dwrite(sc, AM7930_DREG_DR, val>>8);
+ bba_codec_dwrite(sc, AM7930_DREG_DR, val);
+ #else
+ val = bba_codec_dread(sc, AM7930_DREG_DR) << 8;
+ val |= bba_codec_dread(sc, AM7930_DREG_DR);
+ #endif
+
+ return val;
+ }
+
+
+ /* indirect read */
+ u_int8_t
+ bba_codec_iread(sc, reg)
+ struct am7930_softc *sc;
+ int reg;
+ {
+ u_int8_t val;
+
+ DPRINTF(("bba_codec_iread(): sc=%p, reg=%d\n",sc,reg));
+
+ bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
+ val = bba_codec_dread(sc, AM7930_DREG_DR);
+
+ DPRINTF(("read 0x%x (%d)\n", val, val));
+
+ return val;
+ }
+
+
+ #define TIMETOWASTE 50
+
+ /* direct write */
+ void
+ bba_codec_dwrite(asc, reg, val)
+ struct am7930_softc *asc;
+ int reg;
+ u_int8_t val;
+ {
+ struct bba_softc *sc = (struct bba_softc *)asc;
+ int i;
+
+ DPRINTF(("bba_codec_dwrite(): sc=%p, reg=%d, val=%d\n",sc,reg,val));
+
+ bus_space_write_4(sc->sc_bst, sc->sc_codec_bsh, (reg<<6), val);
+
+ for (i=0; i<TIMETOWASTE; i++) {};
+ }
+
+ /* direct read */
+ u_int8_t
+ bba_codec_dread(asc, reg)
+ struct am7930_softc *asc;
+ int reg;
+ {
+ struct bba_softc *sc = (struct bba_softc *)asc;
+ u_int8_t val;
+ int i;
+
+ DPRINTF(("bba_codec_dread(): sc=%p, reg=%d\n",sc,reg));
+
+ val = bus_space_read_1(sc->sc_bst, sc->sc_codec_bsh, (reg<<6));
+
+ for (i=0; i<TIMETOWASTE; i++) {};
+
+ return val;
+ }
+
+ #endif /* NAUDIO > 0 */
*** files.tc.orig Mon May 1 13:43:16 2000
--- files.tc Mon May 1 11:43:20 2000
***************
*** 24,33 ****
file dev/tc/if_le_ioasic.c le_ioasic
file dev/tc/if_le_tc.c le_tc
! # ioasic audio
! attach audioamd at ioasic with am7930_ioasic
! file dev/tc/am7930_ioasic.c am7930_ioasic
!
# DEC DEFTA TC FDDI Controller
device fta: pdq, fddi, ifnet, arp
--- 24,33 ----
file dev/tc/if_le_ioasic.c le_ioasic
file dev/tc/if_le_tc.c le_tc
! # baseboard audio
! device bba: audio,am7930
! attach bba at ioasic
! file dev/tc/bba.c bba
# DEC DEFTA TC FDDI Controller
device fta: pdq, fddi, ifnet, arp
*** dec_maxine.c.orig Mon May 1 13:46:40 2000
--- dec_maxine.c Mon May 1 13:29:40 2000
***************
*** 326,338 ****
CHECKINTR(SYS_DEV_LANCE, IOASIC_INTR_LANCE);
CHECKINTR(SYS_DEV_SCSI, IOASIC_INTR_SCSI);
/* CHECKINTR(SYS_DEV_OPT2, XINE_INTR_VINT); */
! /* CHECKINTR(SYS_DEV_ISDN, IOASIC_INTR_ISDN); */
/* CHECKINTR(SYS_DEV_FDC, IOASIC_INTR_FDC); */
CHECKINTR(SYS_DEV_OPT1, XINE_INTR_TC_1);
CHECKINTR(SYS_DEV_OPT0, XINE_INTR_TC_0);
! #define ERRORS (IOASIC_INTR_ISDN_OVRUN|IOASIC_INTR_ISDN_READ_E|IOASIC_INTR_SCSI_OVRUN|IOASIC_INTR_SCSI_READ_E|IOASIC_INTR_LANCE_READ_E)
! #define PTRLOAD (IOASIC_INTR_ISDN_PTR_LOAD|IOASIC_INTR_SCSI_PTR_LOAD)
#if 0
if (can_serve & IOASIC_INTR_SCSI_PTR_LOAD) {
--- 326,338 ----
CHECKINTR(SYS_DEV_LANCE, IOASIC_INTR_LANCE);
CHECKINTR(SYS_DEV_SCSI, IOASIC_INTR_SCSI);
/* CHECKINTR(SYS_DEV_OPT2, XINE_INTR_VINT); */
! CHECKINTR(SYS_DEV_ISDN, (IOASIC_INTR_ISDN_DS_TXLOAD | IOASIC_INTR_ISDN_DS_RXLOAD));
/* CHECKINTR(SYS_DEV_FDC, IOASIC_INTR_FDC); */
CHECKINTR(SYS_DEV_OPT1, XINE_INTR_TC_1);
CHECKINTR(SYS_DEV_OPT0, XINE_INTR_TC_0);
! #define ERRORS (IOASIC_INTR_ISDN|IOASIC_INTR_ISDN_OVRUN|IOASIC_INTR_ISDN_READ_E|IOASIC_INTR_SCSI_OVRUN|IOASIC_INTR_SCSI_READ_E|IOASIC_INTR_LANCE_READ_E)
! #define PTRLOAD (IOASIC_INTR_ISDN_DS_TXLOAD|IOASIC_INTR_ISDN_DS_RXLOAD|IOASIC_INTR_SCSI_PTR_LOAD)
#if 0
if (can_serve & IOASIC_INTR_SCSI_PTR_LOAD) {
*** conf.c.orig Mon May 1 13:48:13 2000
--- conf.c Mon May 1 11:47:36 2000
***************
*** 58,64 ****
bdev_decl(st);
bdev_decl(sw);
bdev_decl(vnd);
!
#include "rz.h"
#include "tz.h"
bdev_decl(rz);
--- 58,65 ----
bdev_decl(st);
bdev_decl(sw);
bdev_decl(vnd);
! #include "audio.h"
! cdev_decl(audio);
#include "rz.h"
#include "tz.h"
bdev_decl(rz);
***************
*** 285,290 ****
--- 286,292 ----
cdev_disk_init(NRAID,raid), /* 96: RAIDframe disk driver */
cdev_disk_init(NMD,md), /* 97: memory disk driver */
cdev_fbm_init(NPX,px), /* 98: PixelStamp board driver */
+ cdev_audio_init(NAUDIO,audio), /* 99 generic audio I/O */
};
int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
>Release-Note:
>Audit-Trail:
>Unformatted: