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