xref: /netbsd-src/sys/dev/tc/bba.c (revision 4472dbe5e3bd91ef2540bada7a7ca7384627ff9b)
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