1 /* $NetBSD: bba.c,v 1.22 2004/10/29 12:57:26 yamt 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/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: bba.c,v 1.22 2004/10/29 12:57:26 yamt Exp $"); 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/kernel.h> 44 #include <sys/device.h> 45 #include <sys/malloc.h> 46 47 #include <machine/bus.h> 48 #include <machine/autoconf.h> 49 #include <machine/cpu.h> 50 51 #include <sys/audioio.h> 52 #include <dev/audio_if.h> 53 54 #include <dev/ic/am7930reg.h> 55 #include <dev/ic/am7930var.h> 56 57 #include <dev/tc/tcvar.h> 58 #include <dev/tc/ioasicreg.h> 59 #include <dev/tc/ioasicvar.h> 60 61 #ifdef AUDIO_DEBUG 62 #define DPRINTF(x) if (am7930debug) printf x 63 #else 64 #define DPRINTF(x) 65 #endif /* AUDIO_DEBUG */ 66 67 #define BBA_MAX_DMA_SEGMENTS 16 68 #define BBA_DMABUF_SIZE (BBA_MAX_DMA_SEGMENTS*IOASIC_DMA_BLOCKSIZE) 69 #define BBA_DMABUF_ALIGN IOASIC_DMA_BLOCKSIZE 70 #define BBA_DMABUF_BOUNDARY 0 71 72 struct bba_mem { 73 struct bba_mem *next; 74 bus_addr_t addr; 75 bus_size_t size; 76 caddr_t kva; 77 }; 78 79 struct bba_dma_state { 80 bus_dmamap_t dmam; /* DMA map */ 81 int active; 82 int curseg; /* current segment in DMA buffer */ 83 void (*intr)__P((void *)); /* higher-level audio handler */ 84 void *intr_arg; 85 }; 86 87 struct bba_softc { 88 struct am7930_softc sc_am7930; /* glue to MI code */ 89 90 bus_space_tag_t sc_bst; /* IOASIC bus tag/handle */ 91 bus_space_handle_t sc_bsh; 92 bus_dma_tag_t sc_dmat; 93 bus_space_handle_t sc_codec_bsh; /* codec bus space handle */ 94 95 struct bba_mem *sc_mem_head; /* list of buffers */ 96 97 struct bba_dma_state sc_tx_dma_state; 98 struct bba_dma_state sc_rx_dma_state; 99 }; 100 101 int bba_match __P((struct device *, struct cfdata *, void *)); 102 void bba_attach __P((struct device *, struct device *, void *)); 103 104 CFATTACH_DECL(bba, sizeof(struct bba_softc), 105 bba_match, bba_attach, NULL, NULL); 106 107 /* 108 * Define our interface into the am7930 MI driver. 109 */ 110 111 u_int8_t bba_codec_iread __P((struct am7930_softc *, int)); 112 u_int16_t bba_codec_iread16 __P((struct am7930_softc *, int)); 113 void bba_codec_iwrite __P((struct am7930_softc *, int, u_int8_t)); 114 void bba_codec_iwrite16 __P((struct am7930_softc *, int, u_int16_t)); 115 void bba_onopen __P((struct am7930_softc *sc)); 116 void bba_onclose __P((struct am7930_softc *sc)); 117 void bba_output_conv __P((void *, u_int8_t *, int)); 118 void bba_input_conv __P((void *, u_int8_t *, int)); 119 120 struct am7930_glue bba_glue = { 121 bba_codec_iread, 122 bba_codec_iwrite, 123 bba_codec_iread16, 124 bba_codec_iwrite16, 125 bba_onopen, 126 bba_onclose, 127 4, 128 bba_input_conv, 129 bba_output_conv, 130 }; 131 132 /* 133 * Define our interface to the higher level audio driver. 134 */ 135 136 int bba_round_blocksize __P((void *, int)); 137 int bba_halt_output __P((void *)); 138 int bba_halt_input __P((void *)); 139 int bba_getdev __P((void *, struct audio_device *)); 140 void *bba_allocm __P((void *, int, size_t, struct malloc_type *, int)); 141 void bba_freem __P((void *, void *, struct malloc_type *)); 142 size_t bba_round_buffersize __P((void *, int, size_t)); 143 int bba_get_props __P((void *)); 144 paddr_t bba_mappage __P((void *, void *, off_t, int)); 145 int bba_trigger_output __P((void *, void *, void *, int, 146 void (*)(void *), void *, struct audio_params *)); 147 int bba_trigger_input __P((void *, void *, void *, int, 148 void (*)(void *), void *, struct audio_params *)); 149 150 const struct audio_hw_if sa_hw_if = { 151 am7930_open, 152 am7930_close, 153 0, 154 am7930_query_encoding, 155 am7930_set_params, 156 bba_round_blocksize, /* md */ 157 am7930_commit_settings, 158 0, 159 0, 160 0, 161 0, 162 bba_halt_output, /* md */ 163 bba_halt_input, /* md */ 164 0, 165 bba_getdev, 166 0, 167 am7930_set_port, 168 am7930_get_port, 169 am7930_query_devinfo, 170 bba_allocm, /* md */ 171 bba_freem, /* md */ 172 bba_round_buffersize, /* md */ 173 bba_mappage, 174 bba_get_props, 175 bba_trigger_output, /* md */ 176 bba_trigger_input, /* md */ 177 0, 178 }; 179 180 struct audio_device bba_device = { 181 "am7930", 182 "x", 183 "bba" 184 }; 185 186 int bba_intr __P((void *)); 187 void bba_reset __P((struct bba_softc *, int)); 188 void bba_codec_dwrite __P((struct am7930_softc *, int, u_int8_t)); 189 u_int8_t bba_codec_dread __P((struct am7930_softc *, int)); 190 191 int bba_match(parent, cf, aux) 192 struct device *parent; 193 struct cfdata *cf; 194 void *aux; 195 { 196 struct ioasicdev_attach_args *ia = aux; 197 198 if (strcmp(ia->iada_modname, "isdn") != 0 && 199 strcmp(ia->iada_modname, "AMD79c30") != 0) 200 return 0; 201 202 return 1; 203 } 204 205 206 void 207 bba_attach(parent, self, aux) 208 struct device *parent; 209 struct device *self; 210 void *aux; 211 { 212 struct ioasicdev_attach_args *ia = aux; 213 struct bba_softc *sc = (struct bba_softc *)self; 214 struct am7930_softc *asc = &sc->sc_am7930; 215 216 sc->sc_bst = ((struct ioasic_softc *)parent)->sc_bst; 217 sc->sc_bsh = ((struct ioasic_softc *)parent)->sc_bsh; 218 sc->sc_dmat = ((struct ioasic_softc *)parent)->sc_dmat; 219 220 /* get the bus space handle for codec */ 221 if (bus_space_subregion(sc->sc_bst, sc->sc_bsh, 222 ia->iada_offset, 0, &sc->sc_codec_bsh)) { 223 printf("%s: unable to map device\n", asc->sc_dev.dv_xname); 224 return; 225 } 226 227 printf("\n"); 228 229 bba_reset(sc,1); 230 231 /* 232 * Set up glue for MI code early; we use some of it here. 233 */ 234 asc->sc_glue = &bba_glue; 235 236 /* 237 * MI initialisation. We will be doing DMA. 238 */ 239 am7930_init(asc, AUDIOAMD_DMA_MODE); 240 241 ioasic_intr_establish(parent, ia->iada_cookie, TC_IPL_NONE, 242 bba_intr, sc); 243 244 audio_attach_mi(&sa_hw_if, asc, &asc->sc_dev); 245 } 246 247 248 void 249 bba_onopen(sc) 250 struct am7930_softc *sc; 251 { 252 } 253 254 255 void 256 bba_onclose(sc) 257 struct am7930_softc *sc; 258 { 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 struct malloc_type *pool; 298 int 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 struct malloc_type *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