Home | History | Annotate | Line # | Download | only in tc
bba.c revision 1.1
      1 /* $NetBSD: bba.c,v 1.1 2000/05/02 06:43:05 augustss Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *        This product includes software developed by the NetBSD
     18  *        Foundation, Inc. and its contributors.
     19  * 4. Neither the name of The NetBSD Foundation nor the names of its
     20  *    contributors may be used to endorse or promote products derived
     21  *    from this software without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     24  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     25  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     26  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     27  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     33  * POSSIBILITY OF SUCH DAMAGE.
     34  */
     35 
     36 /* maxine/alpha baseboard audio (bba) */
     37 
     38 #include "audio.h"
     39 #if NAUDIO > 0
     40 
     41 #include <sys/param.h>
     42 #include <sys/systm.h>
     43 #include <sys/kernel.h>
     44 #include <sys/device.h>
     45 #include <sys/malloc.h>
     46 
     47 #include <machine/bus.h>
     48 #include <machine/autoconf.h>
     49 #include <machine/cpu.h>
     50 
     51 #include <vm/vm.h>	/* for PAGE_SIZE */
     52 
     53 #include <sys/audioio.h>
     54 #include <dev/audio_if.h>
     55 
     56 #include <dev/ic/am7930reg.h>
     57 #include <dev/ic/am7930var.h>
     58 
     59 #include <dev/tc/tcvar.h>
     60 #include <dev/tc/ioasicreg.h>
     61 #include <dev/tc/ioasicvar.h>
     62 
     63 #ifdef pmax
     64 #include <pmax/pmax/maxine.h>
     65 #define IOASIC_CSR_ISDN_ENABLE	XINE_CSR_ISDN_ENABLE
     66 #define IOASIC_INTR_ISDN_TXLOAD	IOASIC_INTR_ISDN_DS_TXLOAD
     67 #define IOASIC_INTR_ISDN_RXLOAD	IOASIC_INTR_ISDN_DS_RXLOAD
     68 #ifdef IOASIC_INTR_ISDN_OVRUN
     69 #undef IOASIC_INTR_ISDN_OVRUN
     70 #endif
     71 #define IOASIC_INTR_ISDN_OVRUN	IOASIC_INTR_ISDN_DS_OVRUN
     72 #endif
     73 
     74 #ifdef AUDIO_DEBUG
     75 #define DPRINTF(x)	if (am7930debug) printf x
     76 #else
     77 #define DPRINTF(x)
     78 #endif  /* AUDIO_DEBUG */
     79 
     80 #define BBA_MAX_DMA_SEGMENTS	16
     81 
     82 struct bba_mem {
     83 	bus_addr_t addr;
     84 	bus_size_t size;
     85 	caddr_t kva;
     86         struct bba_mem *next;
     87 };
     88 
     89 struct bba_dma_state {
     90 	bus_dmamap_t dmam;		/* dma map */
     91 	int active;
     92 	int curseg;			/* current segment in dma buffer */
     93 	void (*intr)__P((void *));	/* higher-level audio handler */
     94 	void *intr_arg;
     95 };
     96 
     97 struct bba_softc {
     98 	struct am7930_softc sc_am7930;		/* glue to MI code */
     99 
    100 	bus_space_tag_t sc_bst;			/* IOASIC bus tag/handle */
    101 	bus_space_handle_t sc_bsh;
    102 	bus_dma_tag_t sc_dmat;
    103 	bus_space_handle_t sc_codec_bsh;	/* codec bus space handle */
    104 
    105 	struct bba_mem *sc_mem_head;		/* list of buffers */
    106 
    107 	struct bba_dma_state sc_tx_dma_state;
    108 	struct bba_dma_state sc_rx_dma_state;
    109 };
    110 
    111 int	bba_match __P((struct device *, struct cfdata *, void *));
    112 void	bba_attach __P((struct device *, struct device *, void *));
    113 
    114 struct cfattach bba_ca = {
    115 	sizeof(struct bba_softc), bba_match, bba_attach
    116 };
    117 
    118 /*
    119  * Define our interface into the am7930 MI driver.
    120  */
    121 
    122 u_int8_t	bba_codec_iread __P((struct am7930_softc *, int));
    123 u_int16_t	bba_codec_iread16 __P((struct am7930_softc *, int));
    124 void	bba_codec_iwrite __P((struct am7930_softc *, int, u_int8_t));
    125 void	bba_codec_iwrite16 __P((struct am7930_softc *, int, u_int16_t));
    126 void	bba_onopen __P((struct am7930_softc *sc));
    127 void	bba_onclose __P((struct am7930_softc *sc));
    128 void	bba_output_conv __P((void *, u_int8_t *, int));
    129 void	bba_input_conv __P((void *, u_int8_t *, int));
    130 
    131 struct am7930_glue bba_glue = {
    132 	bba_codec_iread,
    133 	bba_codec_iwrite,
    134 	bba_codec_iread16,
    135 	bba_codec_iwrite16,
    136 	bba_onopen,
    137 	bba_onclose,
    138 	4,
    139 	bba_input_conv,
    140 	bba_output_conv,
    141 };
    142 
    143 /*
    144  * Define our interface to the higher level audio driver.
    145  */
    146 
    147 int	bba_round_blocksize __P((void *, int));
    148 int	bba_halt_output __P((void *));
    149 int	bba_halt_input __P((void *));
    150 int	bba_getdev __P((void *, struct audio_device *));
    151 void	*bba_allocm __P((void *, int, size_t, int, int));
    152 void	bba_freem __P((void *, void *, int));
    153 size_t	bba_round_buffersize __P((void *, int, size_t));
    154 int	bba_trigger_output __P((void *, void *, void *, int,
    155 		void (*)(void *), void *, struct audio_params *));
    156 int	bba_trigger_input __P((void *, void *, void *, int,
    157 		void (*)(void *), void *, struct audio_params *));
    158 
    159 struct audio_hw_if sa_hw_if = {
    160 	am7930_open,
    161 	am7930_close,
    162 	0,
    163 	am7930_query_encoding,
    164 	am7930_set_params,
    165 	bba_round_blocksize,		/* md */
    166 	am7930_commit_settings,
    167 	0,
    168 	0,
    169 	0,
    170 	0,
    171 	bba_halt_output,		/* md */
    172 	bba_halt_input,			/* md */
    173 	0,
    174 	bba_getdev,
    175 	0,
    176 	am7930_set_port,
    177 	am7930_get_port,
    178 	am7930_query_devinfo,
    179 	bba_allocm,			/* md */
    180 	bba_freem,			/* md */
    181 	bba_round_buffersize,		/* md */
    182 	0,
    183 	am7930_get_props,
    184 	bba_trigger_output,		/* md */
    185 	bba_trigger_input		/* md */
    186 };
    187 
    188 struct audio_device bba_device = {
    189 	"am7930",
    190 	"x",
    191 	"bba"
    192 };
    193 
    194 int	bba_intr __P((void *));
    195 void	bba_reset __P((struct bba_softc *, int));
    196 void	bba_codec_dwrite __P((struct am7930_softc *, int, u_int8_t));
    197 u_int8_t	bba_codec_dread __P((struct am7930_softc *, int));
    198 
    199 int bba_match(parent, cf, aux)
    200 	struct device *parent;
    201 	struct cfdata *cf;
    202 	void *aux;
    203 {
    204 	struct ioasicdev_attach_args *ia = aux;
    205 
    206         if (strcmp(ia->iada_modname, "isdn") != 0 &&
    207             strcmp(ia->iada_modname, "AMD79c30") != 0)
    208                 return 0;
    209 
    210 	return 1;
    211 }
    212 
    213 
    214 void
    215 bba_attach(parent, self, aux)
    216 	struct device *parent;
    217 	struct device *self;
    218 	void *aux;
    219 {
    220 	struct ioasicdev_attach_args *ia = aux;
    221 	struct bba_softc *sc = (struct bba_softc *)self;
    222 	struct am7930_softc *asc = &sc->sc_am7930;
    223 
    224 	sc->sc_bst = ((struct ioasic_softc *)parent)->sc_bst;
    225 	sc->sc_bsh = ((struct ioasic_softc *)parent)->sc_bsh;
    226 	sc->sc_dmat = ((struct ioasic_softc *)parent)->sc_dmat;
    227 
    228 	/* get the bus space handle for codec */
    229 	if (bus_space_subregion(sc->sc_bst, sc->sc_bsh,
    230 		ia->iada_offset, 0, &sc->sc_codec_bsh)) {
    231 		printf("%s: unable to map device\n", asc->sc_dev.dv_xname);
    232 		return;
    233 	}
    234 
    235 	printf("\n");
    236 
    237 	bba_reset(sc,1);
    238 
    239 	/*
    240 	 * Set up glue for MI code early; we use some of it here.
    241 	 */
    242 	asc->sc_glue = &bba_glue;
    243 
    244 	/*
    245 	 *  MI initialisation.  We will be doing DMA.
    246 	 */
    247 	am7930_init(asc, AUDIOAMD_DMA_MODE);
    248 
    249 	ioasic_intr_establish(parent, ia->iada_cookie, TC_IPL_NONE,
    250 		 bba_intr, sc);
    251 
    252 	audio_attach_mi(&sa_hw_if, asc, &asc->sc_dev);
    253 }
    254 
    255 
    256 void
    257 bba_onopen(sc)
    258 	struct am7930_softc *sc;
    259 {
    260 	bba_reset((struct bba_softc *)sc, 0);
    261 }
    262 
    263 
    264 void
    265 bba_onclose(sc)
    266 	struct am7930_softc *sc;
    267 {
    268 	bba_halt_input((struct bba_softc *)sc);
    269 	bba_halt_output((struct bba_softc *)sc);
    270 }
    271 
    272 
    273 void
    274 bba_reset(sc, reset)
    275 	struct bba_softc *sc;
    276 	int reset;
    277 {
    278 	u_int32_t ssr;
    279 
    280 	/* disable any DMA and reset the codec */
    281 	ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
    282 	ssr &= ~(IOASIC_CSR_DMAEN_ISDN_T | IOASIC_CSR_DMAEN_ISDN_R);
    283 	if (reset)
    284 		ssr &= ~IOASIC_CSR_ISDN_ENABLE;
    285 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
    286 	DELAY(10);	/* 400ns required for codec to reset */
    287 
    288 	/* initialise DMA pointers */
    289 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR, -1);
    290 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR, -1);
    291 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR, -1);
    292 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR, -1);
    293 
    294 	/* take out of reset state */
    295 	if (reset) {
    296 		ssr |= IOASIC_CSR_ISDN_ENABLE;
    297 		bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
    298 	}
    299 
    300 }
    301 
    302 
    303 void *
    304 bba_allocm(addr, direction, size, pool, flags)
    305 	void *addr;
    306 	int direction;
    307 	size_t size;
    308 	int pool, flags;
    309 {
    310 	struct am7930_softc *asc = addr;
    311 	struct bba_softc *sc = addr;
    312 	bus_dma_segment_t seg;
    313 	int rseg;
    314 	caddr_t kva;
    315 	struct bba_mem *m;
    316 	int state = 0;
    317 
    318 	DPRINTF(("bba_allocm: size = %d\n",size));
    319 
    320 	if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &seg,
    321 		1, &rseg, BUS_DMA_NOWAIT)) {
    322 		printf("%s: can't allocate DMA buffer\n",
    323 			asc->sc_dev.dv_xname);
    324 		goto bad;
    325 	}
    326 	state |= 1;
    327 
    328 	if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, size,
    329 		&kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
    330 		printf("%s: can't map DMA buffer\n", asc->sc_dev.dv_xname);
    331 		goto bad;
    332 	}
    333 	state |= 2;
    334 
    335 	m = malloc(sizeof(struct bba_mem), pool, flags);
    336 	if (m == NULL)
    337 		goto bad;
    338 	m->addr = seg.ds_addr;
    339 	m->size = seg.ds_len;
    340         m->kva = kva;
    341         m->next = sc->sc_mem_head;
    342         sc->sc_mem_head = m;
    343 
    344         return (void *)kva;
    345 
    346 bad:
    347 	if (state & 2)
    348 		bus_dmamem_unmap(sc->sc_dmat, kva, size);
    349 	if (state & 1)
    350 		bus_dmamem_free(sc->sc_dmat, &seg, 1);
    351 	return NULL;
    352 }
    353 
    354 
    355 void
    356 bba_freem(addr, ptr, pool)
    357 	void *addr;
    358 	void *ptr;
    359 	int pool;
    360 {
    361 	struct bba_softc *sc = addr;
    362         struct bba_mem **mp, *m;
    363 	bus_dma_segment_t seg;
    364         caddr_t kva = (caddr_t)addr;
    365 
    366 	for (mp = &sc->sc_mem_head; *mp && (*mp)->kva != kva;
    367 		mp = &(*mp)->next)
    368 		/* nothing */ ;
    369 	m = *mp;
    370 	if (m != NULL) {
    371 		printf("bba_freem: freeing unallocted memory\n");
    372 		return;
    373 	}
    374 	*mp = m->next;
    375 	bus_dmamem_unmap(sc->sc_dmat, kva, m->size);
    376 
    377         seg.ds_addr = m->addr;
    378         seg.ds_len = m->size;
    379 	bus_dmamem_free(sc->sc_dmat, &seg, 1);
    380         free(m, pool);
    381 }
    382 
    383 
    384 size_t
    385 bba_round_buffersize(addr, direction, size)
    386 	void *addr;
    387 	int direction;
    388 	size_t size;
    389 {
    390 	DPRINTF(("bba_round_buffersize: size=%d\n", size));
    391 
    392 #define BBA_BUFFERSIZE (BBA_MAX_DMA_SEGMENTS * PAGE_SIZE)
    393 	return  (size > BBA_BUFFERSIZE ? BBA_BUFFERSIZE : round_page(size));
    394 }
    395 
    396 
    397 int
    398 bba_halt_output(addr)
    399 	void *addr;
    400 {
    401 	struct bba_softc *sc = addr;
    402 	struct bba_dma_state *d = &sc->sc_tx_dma_state;
    403 	u_int32_t ssr;
    404 
    405 	/* disable any DMA */
    406 	ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
    407 	ssr &= ~IOASIC_CSR_DMAEN_ISDN_T;
    408 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
    409 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR, -1);
    410 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR, -1);
    411 
    412 	if (d->active) {
    413 		bus_dmamap_unload(sc->sc_dmat, d->dmam);
    414 		bus_dmamap_destroy(sc->sc_dmat, d->dmam);
    415 		d->active = 0;
    416 	}
    417 
    418 	return 0;
    419 }
    420 
    421 
    422 int
    423 bba_halt_input(addr)
    424 	void *addr;
    425 {
    426 	struct bba_softc *sc = addr;
    427 	struct bba_dma_state *d = &sc->sc_rx_dma_state;
    428 	u_int32_t ssr;
    429 
    430 	/* disable any DMA */
    431 	ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
    432 	ssr &= ~IOASIC_CSR_DMAEN_ISDN_R;
    433 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
    434 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR, -1);
    435 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR, -1);
    436 
    437 	if (d->active) {
    438 		bus_dmamap_unload(sc->sc_dmat, d->dmam);
    439 		bus_dmamap_destroy(sc->sc_dmat, d->dmam);
    440 		d->active = 0;
    441 	}
    442 
    443 	return 0;
    444 }
    445 
    446 
    447 int
    448 bba_getdev(addr, retp)
    449 	void *addr;
    450 	struct audio_device *retp;
    451 {
    452 	*retp = bba_device;
    453 	return 0;
    454 }
    455 
    456 
    457 int
    458 bba_trigger_output(addr, start, end, blksize, intr, arg, param)
    459 	void *addr;
    460 	void *start, *end;
    461 	int blksize;
    462 	void (*intr) __P((void *));
    463 	void *arg;
    464 	struct audio_params *param;
    465 {
    466 	struct bba_softc *sc = addr;
    467 	struct bba_dma_state *d = &sc->sc_tx_dma_state;
    468 	u_int32_t ssr;
    469         tc_addr_t phys, nphys;
    470 	int state = 0;
    471 
    472 	DPRINTF(("bba_trigger_output: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
    473 		addr, start, end, blksize, intr, arg));
    474 
    475 	if (bus_dmamap_create(sc->sc_dmat, (char *)end - (char *)start,
    476 		BBA_MAX_DMA_SEGMENTS, PAGE_SIZE, 0, BUS_DMA_NOWAIT, &d->dmam)) {
    477 		printf("bba_trigger_output: can't create DMA map\n");
    478 		goto bad;
    479 	}
    480 	state |= 1;
    481 
    482 	if (bus_dmamap_load(sc->sc_dmat, d->dmam, start,
    483 		(char *)end - (char *)start, NULL, BUS_DMA_NOWAIT)) {
    484 		printf("bba_trigger_output: can't load DMA map\n");
    485 		goto bad;
    486 	}
    487 	state |= 2;
    488 
    489 	/* disable any DMA */
    490 	ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
    491 	ssr &= ~IOASIC_CSR_DMAEN_ISDN_T;
    492 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
    493 
    494 	d->intr = intr;
    495 	d->intr_arg = arg;
    496 	d->curseg = 1;
    497 
    498 	/* get physical address of buffer start */
    499 	phys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr;
    500 	nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg+1].ds_addr;
    501 
    502 	/* setup DMA pointer */
    503 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR,
    504 		IOASIC_DMA_ADDR(phys));
    505 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR,
    506 		IOASIC_DMA_ADDR(nphys));
    507 
    508 	/* kick off DMA */
    509 	ssr |= IOASIC_CSR_DMAEN_ISDN_T;
    510 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
    511 
    512 	wbflush();
    513 
    514 	d->active = 1;
    515 
    516 	return 0;
    517 
    518 bad:
    519 	if (state & 2)
    520 		bus_dmamap_unload(sc->sc_dmat, d->dmam);
    521 	if (state & 1)
    522 		bus_dmamap_destroy(sc->sc_dmat, d->dmam);
    523 	return 1;
    524 }
    525 
    526 
    527 int
    528 bba_trigger_input(addr, start, end, blksize, intr, arg, param)
    529 	void *addr;
    530 	void *start, *end;
    531 	int blksize;
    532 	void (*intr) __P((void *));
    533 	void *arg;
    534 	struct audio_params *param;
    535 {
    536 	struct bba_softc *sc = (struct bba_softc *)addr;
    537 	struct bba_dma_state *d = &sc->sc_rx_dma_state;
    538         tc_addr_t phys, nphys;
    539 	u_int32_t ssr;
    540 	int state = 0;
    541 
    542 	DPRINTF(("bba_trigger_input: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
    543 		addr, start, end, blksize, intr, arg));
    544 
    545 	if (bus_dmamap_create(sc->sc_dmat, (char *)end - (char *)start,
    546 		BBA_MAX_DMA_SEGMENTS, PAGE_SIZE, 0, BUS_DMA_NOWAIT, &d->dmam)) {
    547 		printf("bba_trigger_input: can't create DMA map\n");
    548 		goto bad;
    549 	}
    550 	state |= 1;
    551 
    552 	if (bus_dmamap_load(sc->sc_dmat, d->dmam, start,
    553 		(char *)end - (char *)start, NULL, BUS_DMA_NOWAIT)) {
    554 		printf("bba_trigger_input: can't load DMA map\n");
    555 		goto bad;
    556 	}
    557 	state |= 2;
    558 
    559 	/* disable any DMA */
    560 	ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
    561 	ssr &= ~IOASIC_CSR_DMAEN_ISDN_R;
    562 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
    563 
    564 	d->intr = intr;
    565 	d->intr_arg = arg;
    566 	d->curseg = 1;
    567 
    568 	/* get physical address of buffer start */
    569 	phys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr;
    570 	nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg+1].ds_addr;
    571 
    572 	/* setup DMA pointer */
    573 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR,
    574 		IOASIC_DMA_ADDR(phys));
    575 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR,
    576 		IOASIC_DMA_ADDR(nphys));
    577 
    578 	/* kick off DMA */
    579 	ssr |= IOASIC_CSR_DMAEN_ISDN_R;
    580 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
    581 
    582 	wbflush();
    583 
    584 	d->active = 1;
    585 
    586 	return 0;
    587 
    588 bad:
    589 	if (state & 2)
    590 		bus_dmamap_unload(sc->sc_dmat, d->dmam);
    591 	if (state & 1)
    592 		bus_dmamap_destroy(sc->sc_dmat, d->dmam);
    593 	return 1;
    594 }
    595 
    596 int
    597 bba_intr(addr)
    598 	void *addr;
    599 {
    600 	struct bba_softc *sc = addr;
    601 	struct bba_dma_state *d;
    602 	tc_addr_t nphys;
    603 	int s, mask;
    604 
    605 	s = splaudio();
    606 
    607 	mask = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_INTR);
    608 
    609 	if (mask & IOASIC_INTR_ISDN_TXLOAD) {
    610 		d = &sc->sc_tx_dma_state;
    611 		d->curseg = (d->curseg+1) % d->dmam->dm_nsegs;
    612 		nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr;
    613 		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
    614 			IOASIC_ISDN_X_NEXTPTR, IOASIC_DMA_ADDR(nphys));
    615 		if (d->intr != NULL)
    616 			(*d->intr)(d->intr_arg);
    617 	}
    618 	if (mask & IOASIC_INTR_ISDN_RXLOAD) {
    619 		d = &sc->sc_rx_dma_state;
    620 		d->curseg = (d->curseg+1) % d->dmam->dm_nsegs;
    621 		nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr;
    622 		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
    623 			IOASIC_ISDN_R_NEXTPTR, IOASIC_DMA_ADDR(nphys));
    624 		if (d->intr != NULL)
    625 			(*d->intr)(d->intr_arg);
    626 	}
    627 
    628 	splx(s);
    629 
    630 	return 0;
    631 }
    632 
    633 
    634 void
    635 bba_input_conv(v, p, cc)
    636 	void *v;
    637 	u_int8_t *p;
    638 	int cc;
    639 {
    640 	u_int8_t *q = p;
    641 
    642 	DPRINTF(("bba_input_conv(): v=%p p=%p cc=%d\n", v, p, cc));
    643 
    644 	/*
    645 	 * p points start of buffer
    646 	 * cc is the number of bytes in the destination buffer
    647 	 */
    648 
    649 	while (--cc >= 0) {
    650 		*p = ((*(u_int32_t *)q)>>16)&0xff;
    651 		q += 4;
    652 		p++;
    653 	}
    654 }
    655 
    656 
    657 void
    658 bba_output_conv(v, p, cc)
    659 	void *v;
    660 	u_int8_t *p;
    661 	int cc;
    662 {
    663 	u_int8_t *q = p;
    664 
    665 	DPRINTF(("bba_output_conv(): v=%p p=%p cc=%d\n", v, p, cc));
    666 
    667 	/*
    668 	 * p points start of buffer
    669 	 * cc is the number of bytes in the source buffer
    670 	 */
    671 
    672 	p += cc;
    673 	q += cc * 4;
    674 	while (--cc >= 0) {
    675 		q -= 4;
    676 		p -= 1;
    677 		*(u_int32_t *)q = (*p<<16);
    678 	}
    679 }
    680 
    681 
    682 int
    683 bba_round_blocksize(addr, blk)
    684 	void *addr;
    685 	int blk;
    686 {
    687 	return (PAGE_SIZE);
    688 }
    689 
    690 
    691 /* indirect write */
    692 void
    693 bba_codec_iwrite(sc, reg, val)
    694 	struct am7930_softc *sc;
    695 	int reg;
    696 	u_int8_t val;
    697 {
    698 	DPRINTF(("bba_codec_iwrite(): sc=%p, reg=%d, val=%d\n",sc,reg,val));
    699 
    700 	bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
    701 	bba_codec_dwrite(sc, AM7930_DREG_DR, val);
    702 }
    703 
    704 
    705 void
    706 bba_codec_iwrite16(sc, reg, val)
    707 	struct am7930_softc *sc;
    708 	int reg;
    709 	u_int16_t val;
    710 {
    711 	DPRINTF(("bba_codec_iwrite16(): sc=%p, reg=%d, val=%d\n",sc,reg,val));
    712 
    713 	bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
    714 #if 0
    715 	bba_codec_dwrite(sc, AM7930_DREG_DR, val>>8);
    716 	bba_codec_dwrite(sc, AM7930_DREG_DR, val);
    717 #else
    718 	bba_codec_dwrite(sc, AM7930_DREG_DR, val);
    719 	bba_codec_dwrite(sc, AM7930_DREG_DR, val>>8);
    720 #endif
    721 }
    722 
    723 
    724 u_int16_t
    725 bba_codec_iread16(sc, reg)
    726 	struct am7930_softc *sc;
    727 	int reg;
    728 {
    729 	u_int16_t val;
    730 	DPRINTF(("bba_codec_iread16(): sc=%p, reg=%d\n",sc,reg));
    731 
    732 	bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
    733 #if 0
    734 	bba_codec_dwrite(sc, AM7930_DREG_DR, val>>8);
    735 	bba_codec_dwrite(sc, AM7930_DREG_DR, val);
    736 #else
    737 	val = bba_codec_dread(sc, AM7930_DREG_DR) << 8;
    738 	val |= bba_codec_dread(sc, AM7930_DREG_DR);
    739 #endif
    740 
    741 	return val;
    742 }
    743 
    744 
    745 /* indirect read */
    746 u_int8_t
    747 bba_codec_iread(sc, reg)
    748 	struct am7930_softc *sc;
    749 	int reg;
    750 {
    751 	u_int8_t val;
    752 
    753 	DPRINTF(("bba_codec_iread(): sc=%p, reg=%d\n",sc,reg));
    754 
    755 	bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
    756 	val = bba_codec_dread(sc, AM7930_DREG_DR);
    757 
    758 	DPRINTF(("read 0x%x (%d)\n", val, val));
    759 
    760 	return val;
    761 }
    762 
    763 
    764 #define TIMETOWASTE	50
    765 
    766 /* direct write */
    767 void
    768 bba_codec_dwrite(asc, reg, val)
    769 	struct am7930_softc *asc;
    770 	int reg;
    771 	u_int8_t val;
    772 {
    773 	struct bba_softc *sc = (struct bba_softc *)asc;
    774 	int i;
    775 
    776 	DPRINTF(("bba_codec_dwrite(): sc=%p, reg=%d, val=%d\n",sc,reg,val));
    777 
    778 	bus_space_write_4(sc->sc_bst, sc->sc_codec_bsh, (reg<<6), val);
    779 
    780 	for (i=0; i<TIMETOWASTE; i++) {};
    781 }
    782 
    783 /* direct read */
    784 u_int8_t
    785 bba_codec_dread(asc, reg)
    786 	struct am7930_softc *asc;
    787 	int reg;
    788 {
    789 	struct bba_softc *sc = (struct bba_softc *)asc;
    790 	u_int8_t val;
    791 	int i;
    792 
    793 	DPRINTF(("bba_codec_dread(): sc=%p, reg=%d\n",sc,reg));
    794 
    795 	val = bus_space_read_1(sc->sc_bst, sc->sc_codec_bsh, (reg<<6));
    796 
    797 	for (i=0; i<TIMETOWASTE; i++) {};
    798 
    799 	return val;
    800 }
    801 
    802 #endif /* NAUDIO > 0 */
    803