1 /* $NetBSD: ucbsnd.c,v 1.5 2000/06/26 04:55:41 simonb Exp $ */ 2 3 /* 4 * Copyright (c) 2000, by UCHIYAMA Yasushi 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. The name of the developer may NOT be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28 29 /* 30 * Device driver for PHILIPS UCB1200 Advanced modem/audio analog front-end 31 * Audio codec part. 32 * 33 * /dev/ucbsnd0 : sampling rate 22.154kHz monoral 16bit straight PCM device. 34 */ 35 #define UCBSNDDEBUG 36 37 #include "opt_tx39_debug.h" 38 #include "opt_use_poll.h" 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/conf.h> 43 #include <sys/malloc.h> 44 #include <sys/device.h> 45 #include <sys/proc.h> 46 #include <sys/endian.h> 47 48 #include <machine/bus.h> 49 #include <machine/intr.h> 50 51 #include <hpcmips/tx/tx39var.h> 52 #include <hpcmips/tx/tx39sibvar.h> 53 #include <hpcmips/tx/tx39sibreg.h> 54 #include <hpcmips/tx/tx39icureg.h> 55 #include <hpcmips/tx/txsnd.h> 56 57 #include <hpcmips/dev/ucb1200var.h> 58 #include <hpcmips/dev/ucb1200reg.h> 59 60 #define AUDIOUNIT(x) (minor(x)&0x0f) 61 #define AUDIODEV(x) (minor(x)&0xf0) 62 #define splaudio splbio /* XXX */ 63 64 #ifdef UCBSNDDEBUG 65 int ucbsnd_debug = 1; 66 #define DPRINTF(arg) if (ucbsnd_debug) printf arg; 67 #define DPRINTFN(n, arg) if (ucbsnd_debug > (n)) printf arg; 68 #else 69 #define DPRINTF(arg) 70 #define DPRINTFN(n, arg) 71 #endif 72 73 #define UCBSND_BUFBLOCK 5 74 /* 75 * XXX temporary DMA buffer 76 */ 77 static u_int8_t dmabuf_static[TX39_SIBDMA_SIZE * UCBSND_BUFBLOCK] __attribute__((__aligned__(16))); /* XXX */ 78 static size_t dmabufcnt_static[UCBSND_BUFBLOCK]; /* XXX */ 79 80 enum ucbsnd_state { 81 /* 0 */ UCBSND_IDLE, 82 /* 1 */ UCBSND_INIT, 83 /* 2 */ UCBSND_ENABLE_SAMPLERATE, 84 /* 3 */ UCBSND_ENABLE_OUTPUTPATH, 85 /* 4 */ UCBSND_ENABLE_SETVOLUME, 86 /* 5 */ UCBSND_ENABLE_SPEAKER0, 87 /* 6 */ UCBSND_ENABLE_SPEAKER1, 88 /* 7 */ UCBSND_TRANSITION_PIO, 89 /* 8 */ UCBSND_PIO, 90 /* 9 */ UCBSND_TRANSITION_DISABLE, 91 /*10 */ UCBSND_DISABLE_OUTPUTPATH, 92 /*11 */ UCBSND_DISABLE_SPEAKER0, 93 /*12 */ UCBSND_DISABLE_SPEAKER1, 94 /*13 */ UCBSND_DISABLE_SIB, 95 /*14 */ UCBSND_DMASTART, 96 /*15 */ UCBSND_DMAEND, 97 }; 98 99 struct ring_buf { 100 u_int32_t rb_buf; /* buffer start address */ 101 size_t *rb_bufcnt; /* effective data count (max rb_blksize)*/ 102 103 size_t rb_bufsize; /* total amount of buffer */ 104 int rb_blksize; /* DMA block size */ 105 int rb_maxblks; /* # of blocks in ring */ 106 107 int rb_inp; /* start of input (to buffer) */ 108 int rb_outp; /* output pointer */ 109 }; 110 111 struct ucbsnd_softc { 112 struct device sc_dev; 113 struct device *sc_sib; /* parent (TX39 SIB module) */ 114 struct device *sc_ucb; /* parent (UCB1200 module) */ 115 tx_chipset_tag_t sc_tc; 116 117 struct tx_sound_tag sc_tag; 118 int sc_mute; 119 120 /* 121 * audio codec state machine 122 */ 123 int sa_transfer_mode; 124 #define UCBSND_TRANSFERMODE_DMA 0 125 #define UCBSND_TRANSFERMODE_PIO 1 126 enum ucbsnd_state sa_state; 127 int sa_snd_attenuation; 128 #define UCBSND_DEFAULT_ATTENUATION 0 /* Full volume */ 129 int sa_snd_rate; /* passed down from SIB module */ 130 int sa_tel_rate; 131 void* sa_sf0ih; 132 void* sa_sndih; 133 int sa_retry; 134 int sa_cnt; /* misc counter */ 135 136 /* 137 * input buffer 138 */ 139 size_t sa_dmacnt; 140 struct ring_buf sc_rb; 141 }; 142 143 cdev_decl(ucbsnd); 144 145 int ucbsnd_match __P((struct device*, struct cfdata*, void*)); 146 void ucbsnd_attach __P((struct device*, struct device*, void*)); 147 148 int ucbsnd_exec_output __P((void*)); 149 int ucbsnd_busy __P((void*)); 150 151 void ucbsnd_sound_init __P((struct ucbsnd_softc*)); 152 void __ucbsnd_sound_click __P((tx_sound_tag_t)); 153 void __ucbsnd_sound_mute __P((tx_sound_tag_t, int)); 154 155 int ucbsndwrite_subr __P((struct ucbsnd_softc *, u_int32_t *, size_t, 156 struct uio *)); 157 158 int ringbuf_allocate __P((struct ring_buf*, size_t, int)); 159 void ringbuf_deallocate __P((struct ring_buf*)); 160 void ringbuf_reset __P((struct ring_buf*)); 161 int ringbuf_full __P((struct ring_buf*)); 162 void *ringbuf_producer_get __P((struct ring_buf*)); 163 void ringbuf_producer_return __P((struct ring_buf*, size_t)); 164 void *ringbuf_consumer_get __P((struct ring_buf*, size_t*)); 165 void ringbuf_consumer_return __P((struct ring_buf*)); 166 167 struct cfattach ucbsnd_ca = { 168 sizeof(struct ucbsnd_softc), ucbsnd_match, ucbsnd_attach 169 }; 170 171 int 172 ucbsnd_match(parent, cf, aux) 173 struct device *parent; 174 struct cfdata *cf; 175 void *aux; 176 { 177 return 1; 178 } 179 180 void 181 ucbsnd_attach(parent, self, aux) 182 struct device *parent; 183 struct device *self; 184 void *aux; 185 { 186 struct ucb1200_attach_args *ucba = aux; 187 struct ucbsnd_softc *sc = (void*)self; 188 tx_chipset_tag_t tc; 189 190 tc = sc->sc_tc = ucba->ucba_tc; 191 sc->sc_sib = ucba->ucba_sib; 192 sc->sc_ucb = ucba->ucba_ucb; 193 194 /* register sound functions */ 195 ucbsnd_sound_init(sc); 196 197 sc->sa_snd_rate = ucba->ucba_snd_rate; 198 sc->sa_tel_rate = ucba->ucba_tel_rate; 199 200 sc->sa_snd_attenuation = UCBSND_DEFAULT_ATTENUATION; 201 #define KHZ(a) ((a) / 1000), (((a) % 1000)) 202 printf(": audio %d.%03d kHz telecom %d.%03d kHz", 203 KHZ((tx39sib_clock(sc->sc_sib) * 2) / 204 (sc->sa_snd_rate * 64)), 205 KHZ((tx39sib_clock(sc->sc_sib) * 2) / 206 (sc->sa_tel_rate * 64))); 207 208 ucb1200_state_install(parent, ucbsnd_busy, self, 209 UCB1200_SND_MODULE); 210 211 ringbuf_allocate(&sc->sc_rb, TX39_SIBDMA_SIZE, UCBSND_BUFBLOCK); 212 213 printf("\n"); 214 } 215 216 int 217 ucbsnd_busy(arg) 218 void *arg; 219 { 220 struct ucbsnd_softc *sc = arg; 221 222 return sc->sa_state != UCBSND_IDLE; 223 } 224 225 int 226 ucbsnd_exec_output(arg) 227 void *arg; 228 { 229 struct ucbsnd_softc *sc = arg; 230 tx_chipset_tag_t tc = sc->sc_tc; 231 txreg_t reg; 232 u_int32_t *buf; 233 size_t bufcnt; 234 235 switch (sc->sa_state) { 236 default: 237 panic("ucbsnd_exec_output: invalid state %d", sc->sa_state); 238 /* NOTREACHED */ 239 break; 240 241 case UCBSND_IDLE: 242 /* nothing to do */ 243 return 0; 244 245 case UCBSND_INIT: 246 sc->sa_sf0ih = tx_intr_establish( 247 tc, MAKEINTR(1, TX39_INTRSTATUS1_SIBSF0INT), 248 IST_EDGE, IPL_TTY, ucbsnd_exec_output, sc); 249 250 sc->sa_state = UCBSND_ENABLE_SAMPLERATE; 251 return 0; 252 253 case UCBSND_ENABLE_SAMPLERATE: 254 /* Enable UCB1200 side sample rate */ 255 reg = TX39_SIBSF0_WRITE; 256 reg = TX39_SIBSF0_REGADDR_SET(reg, UCB1200_AUDIOCTRLA_REG); 257 reg = TX39_SIBSF0_REGDATA_SET(reg, sc->sa_snd_rate); 258 tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 259 260 sc->sa_state = UCBSND_ENABLE_OUTPUTPATH; 261 return 0; 262 263 case UCBSND_ENABLE_OUTPUTPATH: 264 /* Enable UCB1200 side */ 265 reg = TX39_SIBSF0_WRITE; 266 reg = TX39_SIBSF0_REGADDR_SET(reg, UCB1200_AUDIOCTRLB_REG); 267 reg = TX39_SIBSF0_REGDATA_SET(reg, sc->sa_snd_attenuation | 268 UCB1200_AUDIOCTRLB_OUTEN); 269 tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 270 271 /* Enable SIB side */ 272 reg = tx_conf_read(tc, TX39_SIBCTRL_REG); 273 tx_conf_write(tc, TX39_SIBCTRL_REG, 274 reg | TX39_SIBCTRL_ENSND); 275 276 sc->sa_state = UCBSND_ENABLE_SPEAKER0; 277 sc->sa_retry = 10; 278 return 0; 279 case UCBSND_ENABLE_SPEAKER0: 280 /* Speaker on */ 281 282 reg = TX39_SIBSF0_REGADDR_SET(0, UCB1200_IO_DATA_REG); 283 tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 284 285 sc->sa_state = UCBSND_ENABLE_SPEAKER1; 286 return 0; 287 288 case UCBSND_ENABLE_SPEAKER1: 289 reg = tx_conf_read(tc, TX39_SIBSF0STAT_REG); 290 if ((TX39_SIBSF0_REGADDR(reg) != UCB1200_IO_DATA_REG) && 291 --sc->sa_retry > 0) { 292 293 sc->sa_state = UCBSND_ENABLE_SPEAKER0; 294 return 0; 295 } 296 297 if (sc->sa_retry <= 0) { 298 printf("ucbsnd_exec_output: subframe0 busy\n"); 299 300 sc->sa_state = UCBSND_IDLE; 301 return 0; 302 } 303 304 reg |= TX39_SIBSF0_WRITE; 305 reg |= UCB1200_IO_DATA_SPEAKER; 306 tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 307 308 /* 309 * Begin to transfer. 310 */ 311 switch (sc->sa_transfer_mode) { 312 case UCBSND_TRANSFERMODE_DMA: 313 sc->sa_state = UCBSND_DMASTART; 314 sc->sa_dmacnt = 0; 315 break; 316 case UCBSND_TRANSFERMODE_PIO: 317 sc->sa_state = UCBSND_TRANSITION_PIO; 318 break; 319 } 320 321 return 0; 322 case UCBSND_DMASTART: 323 /* get data */ 324 if (sc->sa_dmacnt) /* return previous buffer */ 325 ringbuf_consumer_return(&sc->sc_rb); 326 buf = ringbuf_consumer_get(&sc->sc_rb, &bufcnt); 327 if (buf == 0) { 328 sc->sa_state = UCBSND_DMAEND; 329 return 0; 330 } 331 332 if (sc->sa_dmacnt == 0) { 333 /* change interrupt source */ 334 if (sc->sa_sf0ih) { 335 tx_intr_disestablish(tc, sc->sa_sf0ih); 336 sc->sa_sf0ih = 0; 337 } 338 sc->sa_sndih = tx_intr_establish( 339 tc, MAKEINTR(1, TX39_INTRSTATUS1_SND1_0INT), 340 IST_EDGE, IPL_TTY, ucbsnd_exec_output, sc); 341 } else { 342 wakeup(&sc->sc_rb); 343 } 344 345 /* set DMA buffer address */ 346 tx_conf_write(tc, TX39_SIBSNDTXSTART_REG, 347 MIPS_KSEG0_TO_PHYS(buf)); 348 349 /* set DMA buffer size */ 350 tx_conf_write(tc, TX39_SIBSIZE_REG, 351 TX39_SIBSIZE_SNDSIZE_SET(0, bufcnt)); 352 353 tx_conf_write(tc, TX39_SIBSF0CTRL_REG, TX39_SIBSF0_SNDVALID); 354 355 /* kick DMA */ 356 reg = tx_conf_read(tc, TX39_SIBDMACTRL_REG); 357 reg |= TX39_SIBDMACTRL_ENDMATXSND; 358 tx_conf_write(tc, TX39_SIBDMACTRL_REG, reg); 359 360 /* set next */ 361 sc->sa_dmacnt += bufcnt; 362 363 break; 364 365 case UCBSND_DMAEND: 366 sc->sa_state = UCBSND_TRANSITION_DISABLE; 367 break; 368 case UCBSND_TRANSITION_PIO: 369 /* change interrupt source */ 370 if (sc->sa_sf0ih) { 371 tx_intr_disestablish(tc, sc->sa_sf0ih); 372 sc->sa_sf0ih = 0; 373 } 374 sc->sa_sndih = tx_intr_establish( 375 tc, MAKEINTR(1, TX39_INTRSTATUS1_SNDININT), 376 IST_EDGE, IPL_TTY, ucbsnd_exec_output, sc); 377 378 sc->sa_state = UCBSND_PIO; 379 sc->sa_cnt = 0; 380 return 0; 381 382 case UCBSND_PIO: 383 { 384 /* PIO test routine */ 385 int dummy_data = sc->sa_cnt * 3; 386 tx_conf_write(tc, TX39_SIBSNDHOLD_REG, 387 dummy_data << 16 | dummy_data); 388 tx_conf_write(tc, TX39_SIBSF0CTRL_REG, TX39_SIBSF0_SNDVALID); 389 if (sc->sa_cnt++ > 50) { 390 sc->sa_state = UCBSND_TRANSITION_DISABLE; 391 } 392 return 0; 393 } 394 case UCBSND_TRANSITION_DISABLE: 395 /* change interrupt source */ 396 if (sc->sa_sndih) { 397 tx_intr_disestablish(tc, sc->sa_sndih); 398 sc->sa_sndih = 0; 399 } 400 sc->sa_sf0ih = tx_intr_establish( 401 tc, MAKEINTR(1, TX39_INTRSTATUS1_SIBSF0INT), 402 IST_EDGE, IPL_TTY, ucbsnd_exec_output, sc); 403 404 sc->sa_state = UCBSND_DISABLE_OUTPUTPATH; 405 return 0; 406 407 case UCBSND_DISABLE_OUTPUTPATH: 408 /* disable codec output path and mute */ 409 reg = TX39_SIBSF0_WRITE; 410 reg = TX39_SIBSF0_REGADDR_SET(reg, UCB1200_AUDIOCTRLB_REG); 411 reg = TX39_SIBSF0_REGDATA_SET(reg, UCB1200_AUDIOCTRLB_MUTE); 412 tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 413 414 sc->sa_state = UCBSND_DISABLE_SPEAKER0; 415 sc->sa_retry = 10; 416 return 0; 417 418 case UCBSND_DISABLE_SPEAKER0: 419 /* Speaker off */ 420 reg = TX39_SIBSF0_REGADDR_SET(0, UCB1200_IO_DATA_REG); 421 tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 422 423 sc->sa_state = UCBSND_DISABLE_SPEAKER1; 424 return 0; 425 426 case UCBSND_DISABLE_SPEAKER1: 427 reg = tx_conf_read(tc, TX39_SIBSF0STAT_REG); 428 if ((TX39_SIBSF0_REGADDR(reg) != UCB1200_IO_DATA_REG) && 429 --sc->sa_retry > 0) { 430 431 sc->sa_state = UCBSND_DISABLE_SPEAKER0; 432 return 0; 433 } 434 435 if (sc->sa_retry <= 0) { 436 printf("ucbsnd_exec_output: subframe0 busy\n"); 437 438 sc->sa_state = UCBSND_IDLE; 439 return 0; 440 } 441 442 reg |= TX39_SIBSF0_WRITE; 443 reg &= ~UCB1200_IO_DATA_SPEAKER; 444 tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 445 446 sc->sa_state = UCBSND_DISABLE_SIB; 447 return 0; 448 449 case UCBSND_DISABLE_SIB: 450 /* Disable SIB side */ 451 reg = tx_conf_read(tc, TX39_SIBCTRL_REG); 452 reg &= ~TX39_SIBCTRL_ENSND; 453 tx_conf_write(tc, TX39_SIBCTRL_REG, reg); 454 455 /* end audio disable sequence */ 456 if (sc->sa_sf0ih) { 457 tx_intr_disestablish(tc, sc->sa_sf0ih); 458 sc->sa_sf0ih = 0; 459 } 460 sc->sa_state = UCBSND_IDLE; 461 462 return 0; 463 } 464 465 return 0; 466 } 467 468 /* 469 * global sound interface. 470 */ 471 void 472 ucbsnd_sound_init(sc) 473 struct ucbsnd_softc *sc; 474 { 475 tx_sound_tag_t ts = &sc->sc_tag; 476 tx_chipset_tag_t tc = sc->sc_tc; 477 478 ts->ts_v = sc; 479 ts->ts_click = __ucbsnd_sound_click; 480 ts->ts_mute = __ucbsnd_sound_mute; 481 482 tx_conf_register_sound(tc, ts); 483 } 484 485 void 486 __ucbsnd_sound_click(arg) 487 tx_sound_tag_t arg; 488 { 489 struct ucbsnd_softc *sc = (void*)arg; 490 491 if (!sc->sc_mute && sc->sa_state == UCBSND_IDLE) { 492 sc->sa_transfer_mode = UCBSND_TRANSFERMODE_PIO; 493 sc->sa_state = UCBSND_INIT; 494 ucbsnd_exec_output((void*)sc); 495 } 496 } 497 498 void 499 __ucbsnd_sound_mute(arg, onoff) 500 tx_sound_tag_t arg; 501 int onoff; 502 { 503 struct ucbsnd_softc *sc = (void*)arg; 504 sc->sc_mute = onoff; 505 } 506 507 /* 508 * device access 509 */ 510 extern struct cfdriver ucbsnd_cd; 511 512 int 513 ucbsndopen(dev, flags, ifmt, p) 514 dev_t dev; 515 int flags, ifmt; 516 struct proc *p; 517 { 518 int unit = AUDIOUNIT(dev); 519 struct ucbsnd_softc *sc; 520 int s; 521 522 if (unit >= ucbsnd_cd.cd_ndevs || 523 (sc = ucbsnd_cd.cd_devs[unit]) == NULL) 524 return (ENXIO); 525 526 s = splaudio(); 527 ringbuf_reset(&sc->sc_rb); 528 splx(s); 529 530 return (0); 531 } 532 533 int 534 ucbsndclose(dev, flags, ifmt, p) 535 dev_t dev; 536 int flags, ifmt; 537 struct proc *p; 538 { 539 int unit = AUDIOUNIT(dev); 540 struct ucbsnd_softc *sc; 541 542 if (unit >= ucbsnd_cd.cd_ndevs || 543 (sc = ucbsnd_cd.cd_devs[unit]) == NULL) 544 return (ENXIO); 545 546 return (0); 547 } 548 549 int 550 ucbsndread(dev, uio, ioflag) 551 dev_t dev; 552 struct uio *uio; 553 int ioflag; 554 { 555 int unit = AUDIOUNIT(dev); 556 struct ucbsnd_softc *sc; 557 int error = 0; 558 559 if (unit >= ucbsnd_cd.cd_ndevs || 560 (sc = ucbsnd_cd.cd_devs[unit]) == NULL) 561 return (ENXIO); 562 /* not supported yet */ 563 564 return (error); 565 } 566 567 int 568 ucbsndwrite_subr(sc, buf, bufsize, uio) 569 struct ucbsnd_softc *sc; 570 u_int32_t *buf; 571 size_t bufsize; 572 struct uio *uio; 573 { 574 int i, s, error; 575 576 error = uiomove(buf, bufsize, uio); 577 /* 578 * inverse endian for UCB1200 579 */ 580 for (i = 0; i < bufsize / sizeof(int); i++) 581 buf[i] = htobe32(buf[i]); 582 MachFlushCache(); 583 584 ringbuf_producer_return(&sc->sc_rb, bufsize); 585 586 s = splaudio(); 587 if (sc->sa_state == UCBSND_IDLE && ringbuf_full(&sc->sc_rb)) { 588 sc->sa_transfer_mode = UCBSND_TRANSFERMODE_DMA; 589 sc->sa_state = UCBSND_INIT; 590 ucbsnd_exec_output((void*)sc); 591 } 592 splx(s); 593 594 return error; 595 } 596 597 int 598 ucbsndwrite(dev, uio, ioflag) 599 dev_t dev; 600 struct uio *uio; 601 int ioflag; 602 { 603 int unit = AUDIOUNIT(dev); 604 struct ucbsnd_softc *sc; 605 int len, error = 0; 606 int i, n, s, rest; 607 void *buf; 608 609 if (unit >= ucbsnd_cd.cd_ndevs || 610 (sc = ucbsnd_cd.cd_devs[unit]) == NULL) 611 return (ENXIO); 612 613 len = uio->uio_resid; 614 n = (len + TX39_SIBDMA_SIZE - 1) / TX39_SIBDMA_SIZE; 615 rest = len % TX39_SIBDMA_SIZE; 616 617 if (rest) 618 --n; 619 620 for (i = 0; i < n; i++) { 621 while (!(buf = ringbuf_producer_get(&sc->sc_rb))) { 622 error = tsleep(&sc->sc_rb, PRIBIO, "ucbsnd", 1000); 623 if (error) 624 goto errout; 625 } 626 627 error = ucbsndwrite_subr(sc, buf, TX39_SIBDMA_SIZE, uio); 628 if (error) 629 goto out; 630 } 631 632 if (rest) { 633 while (!(buf = ringbuf_producer_get(&sc->sc_rb))) { 634 error = tsleep(&sc->sc_rb, PRIBIO, "ucbsnd", 1000); 635 if (error) 636 goto errout; 637 } 638 639 error = ucbsndwrite_subr(sc, buf, rest, uio); 640 } 641 642 out: 643 return (error); 644 errout: 645 printf("%s: timeout. reset ring-buffer.\n", sc->sc_dev.dv_xname); 646 s = splaudio(); 647 ringbuf_reset(&sc->sc_rb); 648 splx(s); 649 650 return (error); 651 } 652 653 int 654 ucbsndioctl(dev, cmd, addr, flag, p) 655 dev_t dev; 656 u_long cmd; 657 caddr_t addr; 658 int flag; 659 struct proc *p; 660 { 661 int error = 0; 662 663 /* not coded yet */ 664 665 return (error); 666 } 667 668 int 669 ucbsndpoll(dev, events, p) 670 dev_t dev; 671 int events; 672 struct proc *p; 673 { 674 int error = 0; 675 676 /* not coded yet */ 677 678 return (error); 679 } 680 681 paddr_t 682 ucbsndmmap(dev, off, prot) 683 dev_t dev; 684 off_t off; 685 int prot; 686 { 687 int error = 0; 688 689 /* not coded yet */ 690 691 return (error); 692 } 693 694 /* 695 * Ring buffer. 696 */ 697 int 698 ringbuf_allocate(rb, blksize, maxblk) 699 struct ring_buf *rb; 700 size_t blksize; 701 int maxblk; 702 { 703 rb->rb_bufsize = blksize * maxblk; 704 rb->rb_blksize = blksize; 705 rb->rb_maxblks = maxblk; 706 #if notyet 707 rb->rb_buf = (u_int32_t)malloc(rb->rb_bufsize, M_DEVBUF, M_WAITOK); 708 #else 709 rb->rb_buf = (u_int32_t)dmabuf_static; 710 #endif 711 if (rb->rb_buf == 0) { 712 printf("ringbuf_allocate: can't allocate buffer\n"); 713 return 1; 714 } 715 memset((char*)rb->rb_buf, 0, rb->rb_bufsize); 716 #if notyet 717 rb->rb_bufcnt = malloc(rb->rb_maxblks * sizeof(size_t), M_DEVBUF, 718 M_WAITOK); 719 #else 720 rb->rb_bufcnt = dmabufcnt_static; 721 #endif 722 if (rb->rb_bufcnt == 0) { 723 printf("ringbuf_allocate: can't allocate buffer\n"); 724 return 1; 725 } 726 memset((char*)rb->rb_bufcnt, 0, rb->rb_maxblks * sizeof(size_t)); 727 728 ringbuf_reset(rb); 729 730 return 0; 731 } 732 733 void 734 ringbuf_deallocate(rb) 735 struct ring_buf *rb; 736 { 737 #if notyet 738 free((void*)rb->rb_buf, M_DEVBUF); 739 free(rb->rb_bufcnt, M_DEVBUF); 740 #endif 741 } 742 743 void 744 ringbuf_reset(rb) 745 struct ring_buf *rb; 746 { 747 rb->rb_outp = 0; 748 rb->rb_inp = 0; 749 } 750 751 int 752 ringbuf_full(rb) 753 struct ring_buf *rb; 754 { 755 int ret; 756 757 ret = rb->rb_outp == rb->rb_maxblks; 758 759 return ret; 760 } 761 762 void* 763 ringbuf_producer_get(rb) 764 struct ring_buf *rb; 765 { 766 u_int32_t ret; 767 int s; 768 769 s = splaudio(); 770 ret = ringbuf_full(rb) ? 0 : 771 rb->rb_buf + rb->rb_inp * rb->rb_blksize; 772 splx(s); 773 774 return (void*)ret; 775 } 776 777 void 778 ringbuf_producer_return(rb, cnt) 779 struct ring_buf *rb; 780 size_t cnt; 781 { 782 int s; 783 784 assert(cnt <= rb->rb_blksize); 785 786 s = splaudio(); 787 rb->rb_outp++; 788 789 rb->rb_bufcnt[rb->rb_inp] = cnt; 790 rb->rb_inp = (rb->rb_inp + 1) % rb->rb_maxblks; 791 splx(s); 792 } 793 794 void* 795 ringbuf_consumer_get(rb, cntp) 796 struct ring_buf *rb; 797 size_t *cntp; 798 { 799 u_int32_t p; 800 int idx; 801 802 if (rb->rb_outp == 0) 803 return 0; 804 805 idx = (rb->rb_inp - rb->rb_outp + rb->rb_maxblks) % rb->rb_maxblks; 806 807 p = rb->rb_buf + idx * rb->rb_blksize; 808 *cntp = rb->rb_bufcnt[idx]; 809 810 return (void*)p; 811 } 812 813 void 814 ringbuf_consumer_return(rb) 815 struct ring_buf *rb; 816 { 817 818 if (rb->rb_outp > 0) 819 rb->rb_outp--; 820 } 821