1 /* $NetBSD: bba.c,v 1.18 2002/10/02 16:53:01 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/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: bba.c,v 1.18 2002/10/02 16:53:01 thorpej 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, int, int)); 141 void bba_freem __P((void *, void *, int)); 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 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 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 : 388 roundup(size, IOASIC_DMA_BLOCKSIZE)); 389 } 390 391 392 int 393 bba_halt_output(addr) 394 void *addr; 395 { 396 struct bba_softc *sc = addr; 397 struct bba_dma_state *d = &sc->sc_tx_dma_state; 398 u_int32_t ssr; 399 400 /* disable any DMA */ 401 ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR); 402 ssr &= ~IOASIC_CSR_DMAEN_ISDN_T; 403 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr); 404 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR, -1); 405 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR, -1); 406 407 if (d->active) { 408 bus_dmamap_unload(sc->sc_dmat, d->dmam); 409 bus_dmamap_destroy(sc->sc_dmat, d->dmam); 410 d->active = 0; 411 } 412 413 return 0; 414 } 415 416 417 int 418 bba_halt_input(addr) 419 void *addr; 420 { 421 struct bba_softc *sc = addr; 422 struct bba_dma_state *d = &sc->sc_rx_dma_state; 423 u_int32_t ssr; 424 425 /* disable any DMA */ 426 ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR); 427 ssr &= ~IOASIC_CSR_DMAEN_ISDN_R; 428 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr); 429 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR, -1); 430 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR, -1); 431 432 if (d->active) { 433 bus_dmamap_unload(sc->sc_dmat, d->dmam); 434 bus_dmamap_destroy(sc->sc_dmat, d->dmam); 435 d->active = 0; 436 } 437 438 return 0; 439 } 440 441 442 int 443 bba_getdev(addr, retp) 444 void *addr; 445 struct audio_device *retp; 446 { 447 *retp = bba_device; 448 return 0; 449 } 450 451 452 int 453 bba_trigger_output(addr, start, end, blksize, intr, arg, param) 454 void *addr; 455 void *start, *end; 456 int blksize; 457 void (*intr) __P((void *)); 458 void *arg; 459 struct audio_params *param; 460 { 461 struct bba_softc *sc = addr; 462 struct bba_dma_state *d = &sc->sc_tx_dma_state; 463 u_int32_t ssr; 464 tc_addr_t phys, nphys; 465 int state = 0; 466 467 DPRINTF(("bba_trigger_output: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n", 468 addr, start, end, blksize, intr, arg)); 469 470 /* disable any DMA */ 471 ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR); 472 ssr &= ~IOASIC_CSR_DMAEN_ISDN_T; 473 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr); 474 475 if (bus_dmamap_create(sc->sc_dmat, (char *)end - (char *)start, 476 BBA_MAX_DMA_SEGMENTS, IOASIC_DMA_BLOCKSIZE, 477 BBA_DMABUF_BOUNDARY, BUS_DMA_NOWAIT, &d->dmam)) { 478 printf("bba_trigger_output: can't create DMA map\n"); 479 goto bad; 480 } 481 state |= 1; 482 483 if (bus_dmamap_load(sc->sc_dmat, d->dmam, start, 484 (char *)end - (char *)start, NULL, BUS_DMA_WRITE|BUS_DMA_NOWAIT)) { 485 printf("bba_trigger_output: can't load DMA map\n"); 486 goto bad; 487 } 488 state |= 2; 489 490 d->intr = intr; 491 d->intr_arg = arg; 492 d->curseg = 1; 493 494 /* get physical address of buffer start */ 495 phys = (tc_addr_t)d->dmam->dm_segs[0].ds_addr; 496 nphys = (tc_addr_t)d->dmam->dm_segs[1].ds_addr; 497 498 /* setup DMA pointer */ 499 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR, 500 IOASIC_DMA_ADDR(phys)); 501 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR, 502 IOASIC_DMA_ADDR(nphys)); 503 504 /* kick off DMA */ 505 ssr |= IOASIC_CSR_DMAEN_ISDN_T; 506 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr); 507 508 d->active = 1; 509 510 return 0; 511 512 bad: 513 if (state & 2) 514 bus_dmamap_unload(sc->sc_dmat, d->dmam); 515 if (state & 1) 516 bus_dmamap_destroy(sc->sc_dmat, d->dmam); 517 return 1; 518 } 519 520 521 int 522 bba_trigger_input(addr, start, end, blksize, intr, arg, param) 523 void *addr; 524 void *start, *end; 525 int blksize; 526 void (*intr) __P((void *)); 527 void *arg; 528 struct audio_params *param; 529 { 530 struct bba_softc *sc = (struct bba_softc *)addr; 531 struct bba_dma_state *d = &sc->sc_rx_dma_state; 532 tc_addr_t phys, nphys; 533 u_int32_t ssr; 534 int state = 0; 535 536 DPRINTF(("bba_trigger_input: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n", 537 addr, start, end, blksize, intr, arg)); 538 539 /* disable any DMA */ 540 ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR); 541 ssr &= ~IOASIC_CSR_DMAEN_ISDN_R; 542 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr); 543 544 if (bus_dmamap_create(sc->sc_dmat, (char *)end - (char *)start, 545 BBA_MAX_DMA_SEGMENTS, IOASIC_DMA_BLOCKSIZE, 546 BBA_DMABUF_BOUNDARY, BUS_DMA_NOWAIT, &d->dmam)) { 547 printf("bba_trigger_input: can't create DMA map\n"); 548 goto bad; 549 } 550 state |= 1; 551 552 if (bus_dmamap_load(sc->sc_dmat, d->dmam, start, 553 (char *)end - (char *)start, NULL, BUS_DMA_READ|BUS_DMA_NOWAIT)) { 554 printf("bba_trigger_input: can't load DMA map\n"); 555 goto bad; 556 } 557 state |= 2; 558 559 d->intr = intr; 560 d->intr_arg = arg; 561 d->curseg = 1; 562 563 /* get physical address of buffer start */ 564 phys = (tc_addr_t)d->dmam->dm_segs[0].ds_addr; 565 nphys = (tc_addr_t)d->dmam->dm_segs[1].ds_addr; 566 567 /* setup DMA pointer */ 568 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR, 569 IOASIC_DMA_ADDR(phys)); 570 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR, 571 IOASIC_DMA_ADDR(nphys)); 572 573 /* kick off DMA */ 574 ssr |= IOASIC_CSR_DMAEN_ISDN_R; 575 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr); 576 577 d->active = 1; 578 579 return 0; 580 581 bad: 582 if (state & 2) 583 bus_dmamap_unload(sc->sc_dmat, d->dmam); 584 if (state & 1) 585 bus_dmamap_destroy(sc->sc_dmat, d->dmam); 586 return 1; 587 } 588 589 int 590 bba_intr(addr) 591 void *addr; 592 { 593 struct bba_softc *sc = addr; 594 struct bba_dma_state *d; 595 tc_addr_t nphys; 596 int s, mask; 597 598 s = splaudio(); 599 600 mask = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_INTR); 601 602 if (mask & IOASIC_INTR_ISDN_TXLOAD) { 603 d = &sc->sc_tx_dma_state; 604 d->curseg = (d->curseg+1) % d->dmam->dm_nsegs; 605 nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr; 606 bus_space_write_4(sc->sc_bst, sc->sc_bsh, 607 IOASIC_ISDN_X_NEXTPTR, IOASIC_DMA_ADDR(nphys)); 608 if (d->intr != NULL) 609 (*d->intr)(d->intr_arg); 610 } 611 if (mask & IOASIC_INTR_ISDN_RXLOAD) { 612 d = &sc->sc_rx_dma_state; 613 d->curseg = (d->curseg+1) % d->dmam->dm_nsegs; 614 nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr; 615 bus_space_write_4(sc->sc_bst, sc->sc_bsh, 616 IOASIC_ISDN_R_NEXTPTR, IOASIC_DMA_ADDR(nphys)); 617 if (d->intr != NULL) 618 (*d->intr)(d->intr_arg); 619 } 620 621 splx(s); 622 623 return 0; 624 } 625 626 int 627 bba_get_props(addr) 628 void *addr; 629 { 630 return (AUDIO_PROP_MMAP | am7930_get_props(addr)); 631 } 632 633 paddr_t 634 bba_mappage(addr, mem, offset, prot) 635 void *addr; 636 void *mem; 637 off_t offset; 638 int prot; 639 { 640 struct bba_softc *sc = addr; 641 struct bba_mem **mp; 642 bus_dma_segment_t seg; 643 caddr_t kva = (caddr_t)mem; 644 645 for (mp = &sc->sc_mem_head; *mp && (*mp)->kva != kva; 646 mp = &(*mp)->next) 647 /* nothing */ ; 648 if (*mp == NULL || offset < 0) { 649 return -1; 650 } 651 652 seg.ds_addr = (*mp)->addr; 653 seg.ds_len = (*mp)->size; 654 655 return bus_dmamem_mmap(sc->sc_dmat, &seg, 1, offset, 656 prot, BUS_DMA_WAITOK); 657 } 658 659 660 void 661 bba_input_conv(v, p, cc) 662 void *v; 663 u_int8_t *p; 664 int cc; 665 { 666 u_int8_t *q = p; 667 668 DPRINTF(("bba_input_conv(): v=%p p=%p cc=%d\n", v, p, cc)); 669 670 /* 671 * p points start of buffer 672 * cc is the number of bytes in the destination buffer 673 */ 674 675 while (--cc >= 0) { 676 *p = ((*(u_int32_t *)q)>>16)&0xff; 677 q += 4; 678 p++; 679 } 680 } 681 682 683 void 684 bba_output_conv(v, p, cc) 685 void *v; 686 u_int8_t *p; 687 int cc; 688 { 689 u_int8_t *q = p; 690 691 DPRINTF(("bba_output_conv(): v=%p p=%p cc=%d\n", v, p, cc)); 692 693 /* 694 * p points start of buffer 695 * cc is the number of bytes in the source buffer 696 */ 697 698 p += cc; 699 q += cc * 4; 700 while (--cc >= 0) { 701 q -= 4; 702 p -= 1; 703 *(u_int32_t *)q = (*p<<16); 704 } 705 } 706 707 708 int 709 bba_round_blocksize(addr, blk) 710 void *addr; 711 int blk; 712 { 713 return (IOASIC_DMA_BLOCKSIZE); 714 } 715 716 717 /* indirect write */ 718 void 719 bba_codec_iwrite(sc, reg, val) 720 struct am7930_softc *sc; 721 int reg; 722 u_int8_t val; 723 { 724 DPRINTF(("bba_codec_iwrite(): sc=%p, reg=%d, val=%d\n",sc,reg,val)); 725 726 bba_codec_dwrite(sc, AM7930_DREG_CR, reg); 727 bba_codec_dwrite(sc, AM7930_DREG_DR, val); 728 } 729 730 731 void 732 bba_codec_iwrite16(sc, reg, val) 733 struct am7930_softc *sc; 734 int reg; 735 u_int16_t val; 736 { 737 DPRINTF(("bba_codec_iwrite16(): sc=%p, reg=%d, val=%d\n",sc,reg,val)); 738 739 bba_codec_dwrite(sc, AM7930_DREG_CR, reg); 740 bba_codec_dwrite(sc, AM7930_DREG_DR, val); 741 bba_codec_dwrite(sc, AM7930_DREG_DR, val>>8); 742 } 743 744 745 u_int16_t 746 bba_codec_iread16(sc, reg) 747 struct am7930_softc *sc; 748 int reg; 749 { 750 u_int16_t val; 751 DPRINTF(("bba_codec_iread16(): sc=%p, reg=%d\n",sc,reg)); 752 753 bba_codec_dwrite(sc, AM7930_DREG_CR, reg); 754 val = bba_codec_dread(sc, AM7930_DREG_DR) << 8; 755 val |= bba_codec_dread(sc, AM7930_DREG_DR); 756 757 return val; 758 } 759 760 761 /* indirect read */ 762 u_int8_t 763 bba_codec_iread(sc, reg) 764 struct am7930_softc *sc; 765 int reg; 766 { 767 u_int8_t val; 768 769 DPRINTF(("bba_codec_iread(): sc=%p, reg=%d\n",sc,reg)); 770 771 bba_codec_dwrite(sc, AM7930_DREG_CR, reg); 772 val = bba_codec_dread(sc, AM7930_DREG_DR); 773 774 DPRINTF(("read 0x%x (%d)\n", val, val)); 775 776 return val; 777 } 778 779 /* direct write */ 780 void 781 bba_codec_dwrite(asc, reg, val) 782 struct am7930_softc *asc; 783 int reg; 784 u_int8_t val; 785 { 786 struct bba_softc *sc = (struct bba_softc *)asc; 787 788 DPRINTF(("bba_codec_dwrite(): sc=%p, reg=%d, val=%d\n",sc,reg,val)); 789 790 #if defined(__alpha__) 791 bus_space_write_4(sc->sc_bst, sc->sc_codec_bsh, 792 reg << 2, val << 8); 793 #else 794 bus_space_write_4(sc->sc_bst, sc->sc_codec_bsh, 795 reg << 6, val); 796 #endif 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 807 DPRINTF(("bba_codec_dread(): sc=%p, reg=%d\n",sc,reg)); 808 809 #if defined(__alpha__) 810 return ((bus_space_read_4(sc->sc_bst, sc->sc_codec_bsh, 811 reg << 2) >> 8) & 0xff); 812 #else 813 return (bus_space_read_4(sc->sc_bst, sc->sc_codec_bsh, 814 reg << 6) & 0xff); 815 #endif 816 } 817