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