bba.c revision 1.13 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