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