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