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