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