1 /* $NetBSD: bba.c,v 1.8 2000/06/28 17:05:20 mrg 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 <uvm/uvm_extern.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_REGISTER_SHIFT 6 67 #define BBA_MAX_DMA_SEGMENTS 16 68 #define BBA_DMABUF_SIZE (BBA_MAX_DMA_SEGMENTS*PAGE_SIZE) 69 #define BBA_DMABUF_ALIGN PAGE_SIZE 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 struct cfattach bba_ca = { 105 sizeof(struct bba_softc), bba_match, bba_attach 106 }; 107 108 /* 109 * Define our interface into the am7930 MI driver. 110 */ 111 112 u_int8_t bba_codec_iread __P((struct am7930_softc *, int)); 113 u_int16_t bba_codec_iread16 __P((struct am7930_softc *, int)); 114 void bba_codec_iwrite __P((struct am7930_softc *, int, u_int8_t)); 115 void bba_codec_iwrite16 __P((struct am7930_softc *, int, u_int16_t)); 116 void bba_onopen __P((struct am7930_softc *sc)); 117 void bba_onclose __P((struct am7930_softc *sc)); 118 void bba_output_conv __P((void *, u_int8_t *, int)); 119 void bba_input_conv __P((void *, u_int8_t *, int)); 120 121 struct am7930_glue bba_glue = { 122 bba_codec_iread, 123 bba_codec_iwrite, 124 bba_codec_iread16, 125 bba_codec_iwrite16, 126 bba_onopen, 127 bba_onclose, 128 4, 129 bba_input_conv, 130 bba_output_conv, 131 }; 132 133 /* 134 * Define our interface to the higher level audio driver. 135 */ 136 137 int bba_round_blocksize __P((void *, int)); 138 int bba_halt_output __P((void *)); 139 int bba_halt_input __P((void *)); 140 int bba_getdev __P((void *, struct audio_device *)); 141 void *bba_allocm __P((void *, int, size_t, int, int)); 142 void bba_freem __P((void *, void *, int)); 143 size_t bba_round_buffersize __P((void *, int, size_t)); 144 int bba_get_props __P((void *)); 145 paddr_t bba_mappage __P((void *, void *, off_t, int)); 146 int bba_trigger_output __P((void *, void *, void *, int, 147 void (*)(void *), void *, struct audio_params *)); 148 int bba_trigger_input __P((void *, void *, void *, int, 149 void (*)(void *), void *, struct audio_params *)); 150 151 struct audio_hw_if sa_hw_if = { 152 am7930_open, 153 am7930_close, 154 0, 155 am7930_query_encoding, 156 am7930_set_params, 157 bba_round_blocksize, /* md */ 158 am7930_commit_settings, 159 0, 160 0, 161 0, 162 0, 163 bba_halt_output, /* md */ 164 bba_halt_input, /* md */ 165 0, 166 bba_getdev, 167 0, 168 am7930_set_port, 169 am7930_get_port, 170 am7930_query_devinfo, 171 bba_allocm, /* md */ 172 bba_freem, /* md */ 173 bba_round_buffersize, /* md */ 174 bba_mappage, 175 bba_get_props, 176 bba_trigger_output, /* md */ 177 bba_trigger_input /* md */ 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 bba_reset((struct bba_softc *)sc, 0); 253 } 254 255 256 void 257 bba_onclose(sc) 258 struct am7930_softc *sc; 259 { 260 bba_halt_input((struct bba_softc *)sc); 261 bba_halt_output((struct bba_softc *)sc); 262 } 263 264 265 void 266 bba_reset(sc, reset) 267 struct bba_softc *sc; 268 int reset; 269 { 270 u_int32_t ssr; 271 272 /* disable any DMA and reset the codec */ 273 ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR); 274 ssr &= ~(IOASIC_CSR_DMAEN_ISDN_T | IOASIC_CSR_DMAEN_ISDN_R); 275 if (reset) 276 ssr &= ~IOASIC_CSR_ISDN_ENABLE; 277 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr); 278 DELAY(10); /* 400ns required for codec to reset */ 279 280 /* initialise DMA pointers */ 281 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR, -1); 282 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR, -1); 283 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR, -1); 284 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR, -1); 285 286 /* take out of reset state */ 287 if (reset) { 288 ssr |= IOASIC_CSR_ISDN_ENABLE; 289 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr); 290 } 291 292 } 293 294 295 void * 296 bba_allocm(addr, direction, size, pool, flags) 297 void *addr; 298 int direction; 299 size_t size; 300 int pool, flags; 301 { 302 struct am7930_softc *asc = addr; 303 struct bba_softc *sc = addr; 304 bus_dma_segment_t seg; 305 int rseg; 306 caddr_t kva; 307 struct bba_mem *m; 308 int w; 309 int state = 0; 310 311 DPRINTF(("bba_allocm: size = %d\n",size)); 312 313 w = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK; 314 315 if (bus_dmamem_alloc(sc->sc_dmat, size, BBA_DMABUF_ALIGN, 316 BBA_DMABUF_BOUNDARY, &seg, 1, &rseg, w)) { 317 printf("%s: can't allocate DMA buffer\n", 318 asc->sc_dev.dv_xname); 319 goto bad; 320 } 321 state |= 1; 322 323 if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, size, 324 &kva, w | BUS_DMA_COHERENT)) { 325 printf("%s: can't map DMA buffer\n", asc->sc_dev.dv_xname); 326 goto bad; 327 } 328 state |= 2; 329 330 m = malloc(sizeof(struct bba_mem), pool, flags); 331 if (m == NULL) 332 goto bad; 333 m->addr = seg.ds_addr; 334 m->size = seg.ds_len; 335 m->kva = kva; 336 m->next = sc->sc_mem_head; 337 sc->sc_mem_head = m; 338 339 return (void *)kva; 340 341 bad: 342 if (state & 2) 343 bus_dmamem_unmap(sc->sc_dmat, kva, size); 344 if (state & 1) 345 bus_dmamem_free(sc->sc_dmat, &seg, 1); 346 return NULL; 347 } 348 349 350 void 351 bba_freem(addr, ptr, pool) 352 void *addr; 353 void *ptr; 354 int pool; 355 { 356 struct bba_softc *sc = addr; 357 struct bba_mem **mp, *m; 358 bus_dma_segment_t seg; 359 caddr_t kva = (caddr_t)addr; 360 361 for (mp = &sc->sc_mem_head; *mp && (*mp)->kva != kva; 362 mp = &(*mp)->next) 363 /* nothing */ ; 364 m = *mp; 365 if (m == NULL) { 366 printf("bba_freem: freeing unallocated memory\n"); 367 return; 368 } 369 *mp = m->next; 370 bus_dmamem_unmap(sc->sc_dmat, kva, m->size); 371 372 seg.ds_addr = m->addr; 373 seg.ds_len = m->size; 374 bus_dmamem_free(sc->sc_dmat, &seg, 1); 375 free(m, pool); 376 } 377 378 379 size_t 380 bba_round_buffersize(addr, direction, size) 381 void *addr; 382 int direction; 383 size_t size; 384 { 385 DPRINTF(("bba_round_buffersize: size=%d\n", size)); 386 387 return (size > BBA_DMABUF_SIZE ? BBA_DMABUF_SIZE : round_page(size)); 388 } 389 390 391 int 392 bba_halt_output(addr) 393 void *addr; 394 { 395 struct bba_softc *sc = addr; 396 struct bba_dma_state *d = &sc->sc_tx_dma_state; 397 u_int32_t ssr; 398 399 /* disable any DMA */ 400 ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR); 401 ssr &= ~IOASIC_CSR_DMAEN_ISDN_T; 402 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr); 403 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR, -1); 404 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR, -1); 405 406 if (d->active) { 407 bus_dmamap_unload(sc->sc_dmat, d->dmam); 408 bus_dmamap_destroy(sc->sc_dmat, d->dmam); 409 d->active = 0; 410 } 411 412 return 0; 413 } 414 415 416 int 417 bba_halt_input(addr) 418 void *addr; 419 { 420 struct bba_softc *sc = addr; 421 struct bba_dma_state *d = &sc->sc_rx_dma_state; 422 u_int32_t ssr; 423 424 /* disable any DMA */ 425 ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR); 426 ssr &= ~IOASIC_CSR_DMAEN_ISDN_R; 427 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr); 428 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR, -1); 429 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR, -1); 430 431 if (d->active) { 432 bus_dmamap_unload(sc->sc_dmat, d->dmam); 433 bus_dmamap_destroy(sc->sc_dmat, d->dmam); 434 d->active = 0; 435 } 436 437 return 0; 438 } 439 440 441 int 442 bba_getdev(addr, retp) 443 void *addr; 444 struct audio_device *retp; 445 { 446 *retp = bba_device; 447 return 0; 448 } 449 450 451 int 452 bba_trigger_output(addr, start, end, blksize, intr, arg, param) 453 void *addr; 454 void *start, *end; 455 int blksize; 456 void (*intr) __P((void *)); 457 void *arg; 458 struct audio_params *param; 459 { 460 struct bba_softc *sc = addr; 461 struct bba_dma_state *d = &sc->sc_tx_dma_state; 462 u_int32_t ssr; 463 tc_addr_t phys, nphys; 464 int state = 0; 465 466 DPRINTF(("bba_trigger_output: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n", 467 addr, start, end, blksize, intr, arg)); 468 469 /* disable any DMA */ 470 ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR); 471 ssr &= ~IOASIC_CSR_DMAEN_ISDN_T; 472 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr); 473 474 if (bus_dmamap_create(sc->sc_dmat, (char *)end - (char *)start, 475 BBA_MAX_DMA_SEGMENTS, PAGE_SIZE, BBA_DMABUF_BOUNDARY, 476 BUS_DMA_NOWAIT, &d->dmam)) { 477 printf("bba_trigger_output: can't create DMA map\n"); 478 goto bad; 479 } 480 state |= 1; 481 482 if (bus_dmamap_load(sc->sc_dmat, d->dmam, start, 483 (char *)end - (char *)start, NULL, BUS_DMA_NOWAIT)) { 484 printf("bba_trigger_output: can't load DMA map\n"); 485 goto bad; 486 } 487 state |= 2; 488 489 d->intr = intr; 490 d->intr_arg = arg; 491 d->curseg = 1; 492 493 /* get physical address of buffer start */ 494 phys = (tc_addr_t)d->dmam->dm_segs[0].ds_addr; 495 nphys = (tc_addr_t)d->dmam->dm_segs[1].ds_addr; 496 497 /* setup DMA pointer */ 498 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR, 499 IOASIC_DMA_ADDR(phys)); 500 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR, 501 IOASIC_DMA_ADDR(nphys)); 502 503 /* kick off DMA */ 504 ssr |= IOASIC_CSR_DMAEN_ISDN_T; 505 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr); 506 507 d->active = 1; 508 509 return 0; 510 511 bad: 512 if (state & 2) 513 bus_dmamap_unload(sc->sc_dmat, d->dmam); 514 if (state & 1) 515 bus_dmamap_destroy(sc->sc_dmat, d->dmam); 516 return 1; 517 } 518 519 520 int 521 bba_trigger_input(addr, start, end, blksize, intr, arg, param) 522 void *addr; 523 void *start, *end; 524 int blksize; 525 void (*intr) __P((void *)); 526 void *arg; 527 struct audio_params *param; 528 { 529 struct bba_softc *sc = (struct bba_softc *)addr; 530 struct bba_dma_state *d = &sc->sc_rx_dma_state; 531 tc_addr_t phys, nphys; 532 u_int32_t ssr; 533 int state = 0; 534 535 DPRINTF(("bba_trigger_input: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n", 536 addr, start, end, blksize, intr, arg)); 537 538 /* disable any DMA */ 539 ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR); 540 ssr &= ~IOASIC_CSR_DMAEN_ISDN_R; 541 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr); 542 543 if (bus_dmamap_create(sc->sc_dmat, (char *)end - (char *)start, 544 BBA_MAX_DMA_SEGMENTS, PAGE_SIZE, BBA_DMABUF_BOUNDARY, 545 BUS_DMA_NOWAIT, &d->dmam)) { 546 printf("bba_trigger_input: can't create DMA map\n"); 547 goto bad; 548 } 549 state |= 1; 550 551 if (bus_dmamap_load(sc->sc_dmat, d->dmam, start, 552 (char *)end - (char *)start, NULL, BUS_DMA_NOWAIT)) { 553 printf("bba_trigger_input: can't load DMA map\n"); 554 goto bad; 555 } 556 state |= 2; 557 558 d->intr = intr; 559 d->intr_arg = arg; 560 d->curseg = 1; 561 562 /* get physical address of buffer start */ 563 phys = (tc_addr_t)d->dmam->dm_segs[0].ds_addr; 564 nphys = (tc_addr_t)d->dmam->dm_segs[1].ds_addr; 565 566 /* setup DMA pointer */ 567 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR, 568 IOASIC_DMA_ADDR(phys)); 569 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR, 570 IOASIC_DMA_ADDR(nphys)); 571 572 /* kick off DMA */ 573 ssr |= IOASIC_CSR_DMAEN_ISDN_R; 574 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr); 575 576 d->active = 1; 577 578 return 0; 579 580 bad: 581 if (state & 2) 582 bus_dmamap_unload(sc->sc_dmat, d->dmam); 583 if (state & 1) 584 bus_dmamap_destroy(sc->sc_dmat, d->dmam); 585 return 1; 586 } 587 588 int 589 bba_intr(addr) 590 void *addr; 591 { 592 struct bba_softc *sc = addr; 593 struct bba_dma_state *d; 594 tc_addr_t nphys; 595 int s, mask; 596 597 s = splaudio(); 598 599 mask = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_INTR); 600 601 if (mask & IOASIC_INTR_ISDN_TXLOAD) { 602 d = &sc->sc_tx_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_X_NEXTPTR, IOASIC_DMA_ADDR(nphys)); 607 if (d->intr != NULL) 608 (*d->intr)(d->intr_arg); 609 } 610 if (mask & IOASIC_INTR_ISDN_RXLOAD) { 611 d = &sc->sc_rx_dma_state; 612 d->curseg = (d->curseg+1) % d->dmam->dm_nsegs; 613 nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr; 614 bus_space_write_4(sc->sc_bst, sc->sc_bsh, 615 IOASIC_ISDN_R_NEXTPTR, IOASIC_DMA_ADDR(nphys)); 616 if (d->intr != NULL) 617 (*d->intr)(d->intr_arg); 618 } 619 620 splx(s); 621 622 return 0; 623 } 624 625 int 626 bba_get_props(addr) 627 void *addr; 628 { 629 return (AUDIO_PROP_MMAP | am7930_get_props(addr)); 630 } 631 632 paddr_t 633 bba_mappage(addr, mem, offset, prot) 634 void *addr; 635 void *mem; 636 off_t offset; 637 int prot; 638 { 639 struct bba_softc *sc = addr; 640 struct bba_mem **mp; 641 bus_dma_segment_t seg; 642 caddr_t kva = (caddr_t)mem; 643 644 for (mp = &sc->sc_mem_head; *mp && (*mp)->kva != kva; 645 mp = &(*mp)->next) 646 /* nothing */ ; 647 if (*mp == NULL || offset < 0) { 648 return -1; 649 } 650 651 seg.ds_addr = (*mp)->addr; 652 seg.ds_len = (*mp)->size; 653 654 return bus_dmamem_mmap(sc->sc_dmat, &seg, 1, offset, 655 prot, BUS_DMA_WAITOK); 656 } 657 658 659 void 660 bba_input_conv(v, p, cc) 661 void *v; 662 u_int8_t *p; 663 int cc; 664 { 665 u_int8_t *q = p; 666 667 DPRINTF(("bba_input_conv(): v=%p p=%p cc=%d\n", v, p, cc)); 668 669 /* 670 * p points start of buffer 671 * cc is the number of bytes in the destination buffer 672 */ 673 674 while (--cc >= 0) { 675 *p = ((*(u_int32_t *)q)>>16)&0xff; 676 q += 4; 677 p++; 678 } 679 } 680 681 682 void 683 bba_output_conv(v, p, cc) 684 void *v; 685 u_int8_t *p; 686 int cc; 687 { 688 u_int8_t *q = p; 689 690 DPRINTF(("bba_output_conv(): v=%p p=%p cc=%d\n", v, p, cc)); 691 692 /* 693 * p points start of buffer 694 * cc is the number of bytes in the source buffer 695 */ 696 697 p += cc; 698 q += cc * 4; 699 while (--cc >= 0) { 700 q -= 4; 701 p -= 1; 702 *(u_int32_t *)q = (*p<<16); 703 } 704 } 705 706 707 int 708 bba_round_blocksize(addr, blk) 709 void *addr; 710 int blk; 711 { 712 return (PAGE_SIZE); 713 } 714 715 716 /* indirect write */ 717 void 718 bba_codec_iwrite(sc, reg, val) 719 struct am7930_softc *sc; 720 int reg; 721 u_int8_t val; 722 { 723 DPRINTF(("bba_codec_iwrite(): sc=%p, reg=%d, val=%d\n",sc,reg,val)); 724 725 bba_codec_dwrite(sc, AM7930_DREG_CR, reg); 726 bba_codec_dwrite(sc, AM7930_DREG_DR, val); 727 } 728 729 730 void 731 bba_codec_iwrite16(sc, reg, val) 732 struct am7930_softc *sc; 733 int reg; 734 u_int16_t val; 735 { 736 DPRINTF(("bba_codec_iwrite16(): sc=%p, reg=%d, val=%d\n",sc,reg,val)); 737 738 bba_codec_dwrite(sc, AM7930_DREG_CR, reg); 739 bba_codec_dwrite(sc, AM7930_DREG_DR, val); 740 bba_codec_dwrite(sc, AM7930_DREG_DR, val>>8); 741 } 742 743 744 u_int16_t 745 bba_codec_iread16(sc, reg) 746 struct am7930_softc *sc; 747 int reg; 748 { 749 u_int16_t val; 750 DPRINTF(("bba_codec_iread16(): sc=%p, reg=%d\n",sc,reg)); 751 752 bba_codec_dwrite(sc, AM7930_DREG_CR, reg); 753 val = bba_codec_dread(sc, AM7930_DREG_DR) << 8; 754 val |= bba_codec_dread(sc, AM7930_DREG_DR); 755 756 return val; 757 } 758 759 760 /* indirect read */ 761 u_int8_t 762 bba_codec_iread(sc, reg) 763 struct am7930_softc *sc; 764 int reg; 765 { 766 u_int8_t val; 767 768 DPRINTF(("bba_codec_iread(): sc=%p, reg=%d\n",sc,reg)); 769 770 bba_codec_dwrite(sc, AM7930_DREG_CR, reg); 771 val = bba_codec_dread(sc, AM7930_DREG_DR); 772 773 DPRINTF(("read 0x%x (%d)\n", val, val)); 774 775 return val; 776 } 777 778 779 #define TIMETOWASTE 50 780 781 /* direct write */ 782 void 783 bba_codec_dwrite(asc, reg, val) 784 struct am7930_softc *asc; 785 int reg; 786 u_int8_t val; 787 { 788 struct bba_softc *sc = (struct bba_softc *)asc; 789 int i; 790 791 DPRINTF(("bba_codec_dwrite(): sc=%p, reg=%d, val=%d\n",sc,reg,val)); 792 793 bus_space_write_4(sc->sc_bst, sc->sc_codec_bsh, 794 (reg<<BBA_REGISTER_SHIFT), val); 795 796 for (i=0; i<TIMETOWASTE; i++) {}; 797 } 798 799 /* direct read */ 800 u_int8_t 801 bba_codec_dread(asc, reg) 802 struct am7930_softc *asc; 803 int reg; 804 { 805 struct bba_softc *sc = (struct bba_softc *)asc; 806 u_int8_t val; 807 int i; 808 809 DPRINTF(("bba_codec_dread(): sc=%p, reg=%d\n",sc,reg)); 810 811 val = bus_space_read_1(sc->sc_bst, sc->sc_codec_bsh, 812 (reg<<BBA_REGISTER_SHIFT)); 813 814 for (i=0; i<TIMETOWASTE; i++) {}; 815 816 return val; 817 } 818