1 /* $NetBSD: ucbsnd.c,v 1.19 2008/06/12 16:50:53 tsutsui 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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Device driver for PHILIPS UCB1200 Advanced modem/audio analog front-end 34 * Audio codec part. 35 * 36 * /dev/ucbsnd0 : sampling rate 22.154kHz monoral 16bit straight PCM device. 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: ucbsnd.c,v 1.19 2008/06/12 16:50:53 tsutsui Exp $"); 41 42 #include "opt_use_poll.h" 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/conf.h> 47 #include <sys/malloc.h> 48 #include <sys/device.h> 49 #include <sys/proc.h> 50 #include <sys/endian.h> 51 52 #include <mips/cache.h> 53 54 #include <machine/bus.h> 55 #include <machine/intr.h> 56 57 #include <hpcmips/tx/tx39var.h> 58 #include <hpcmips/tx/tx39sibvar.h> 59 #include <hpcmips/tx/tx39sibreg.h> 60 #include <hpcmips/tx/tx39icureg.h> 61 #include <hpcmips/tx/txsnd.h> 62 63 #include <hpcmips/dev/ucb1200var.h> 64 #include <hpcmips/dev/ucb1200reg.h> 65 66 #define AUDIOUNIT(x) (minor(x)&0x0f) 67 #define AUDIODEV(x) (minor(x)&0xf0) 68 69 #ifdef UCBSNDDEBUG 70 int ucbsnd_debug = 1; 71 #define DPRINTF(arg) if (ucbsnd_debug) printf arg; 72 #define DPRINTFN(n, arg) if (ucbsnd_debug > (n)) printf arg; 73 #else 74 #define DPRINTF(arg) 75 #define DPRINTFN(n, arg) 76 #endif 77 78 #define UCBSND_BUFBLOCK 5 79 /* 80 * XXX temporary DMA buffer 81 */ 82 static u_int8_t dmabuf_static[TX39_SIBDMA_SIZE * UCBSND_BUFBLOCK] __attribute__((__aligned__(16))); /* XXX */ 83 static size_t dmabufcnt_static[UCBSND_BUFBLOCK]; /* XXX */ 84 85 enum ucbsnd_state { 86 /* 0 */ UCBSND_IDLE, 87 /* 1 */ UCBSND_INIT, 88 /* 2 */ UCBSND_ENABLE_SAMPLERATE, 89 /* 3 */ UCBSND_ENABLE_OUTPUTPATH, 90 /* 4 */ UCBSND_ENABLE_SETVOLUME, 91 /* 5 */ UCBSND_ENABLE_SPEAKER0, 92 /* 6 */ UCBSND_ENABLE_SPEAKER1, 93 /* 7 */ UCBSND_TRANSITION_PIO, 94 /* 8 */ UCBSND_PIO, 95 /* 9 */ UCBSND_TRANSITION_DISABLE, 96 /*10 */ UCBSND_DISABLE_OUTPUTPATH, 97 /*11 */ UCBSND_DISABLE_SPEAKER0, 98 /*12 */ UCBSND_DISABLE_SPEAKER1, 99 /*13 */ UCBSND_DISABLE_SIB, 100 /*14 */ UCBSND_DMASTART, 101 /*15 */ UCBSND_DMAEND, 102 }; 103 104 struct ring_buf { 105 u_int32_t rb_buf; /* buffer start address */ 106 size_t *rb_bufcnt; /* effective data count (max rb_blksize)*/ 107 108 size_t rb_bufsize; /* total amount of buffer */ 109 int rb_blksize; /* DMA block size */ 110 int rb_maxblks; /* # of blocks in ring */ 111 112 int rb_inp; /* start of input (to buffer) */ 113 int rb_outp; /* output pointer */ 114 }; 115 116 struct ucbsnd_softc { 117 struct device sc_dev; 118 struct device *sc_sib; /* parent (TX39 SIB module) */ 119 struct device *sc_ucb; /* parent (UCB1200 module) */ 120 tx_chipset_tag_t sc_tc; 121 122 struct tx_sound_tag sc_tag; 123 int sc_mute; 124 125 /* 126 * audio codec state machine 127 */ 128 int sa_transfer_mode; 129 #define UCBSND_TRANSFERMODE_DMA 0 130 #define UCBSND_TRANSFERMODE_PIO 1 131 enum ucbsnd_state sa_state; 132 int sa_snd_attenuation; 133 #define UCBSND_DEFAULT_ATTENUATION 0 /* Full volume */ 134 int sa_snd_rate; /* passed down from SIB module */ 135 int sa_tel_rate; 136 void* sa_sf0ih; 137 void* sa_sndih; 138 int sa_retry; 139 int sa_cnt; /* misc counter */ 140 141 /* 142 * input buffer 143 */ 144 size_t sa_dmacnt; 145 struct ring_buf sc_rb; 146 }; 147 148 int ucbsnd_match(struct device*, struct cfdata*, void*); 149 void ucbsnd_attach(struct device*, struct device*, void*); 150 151 int ucbsnd_exec_output(void*); 152 int ucbsnd_busy(void*); 153 154 void ucbsnd_sound_init(struct ucbsnd_softc*); 155 void __ucbsnd_sound_click(tx_sound_tag_t); 156 void __ucbsnd_sound_mute(tx_sound_tag_t, int); 157 158 int ucbsndwrite_subr(struct ucbsnd_softc *, u_int32_t *, size_t, 159 struct uio *); 160 161 int ringbuf_allocate(struct ring_buf*, size_t, int); 162 void ringbuf_deallocate(struct ring_buf*); 163 void ringbuf_reset(struct ring_buf*); 164 int ringbuf_full(struct ring_buf*); 165 void *ringbuf_producer_get(struct ring_buf*); 166 void ringbuf_producer_return(struct ring_buf*, size_t); 167 void *ringbuf_consumer_get(struct ring_buf*, size_t*); 168 void ringbuf_consumer_return(struct ring_buf*); 169 170 CFATTACH_DECL(ucbsnd, sizeof(struct ucbsnd_softc), 171 ucbsnd_match, ucbsnd_attach, NULL, NULL); 172 173 dev_type_open(ucbsndopen); 174 dev_type_close(ucbsndclose); 175 dev_type_read(ucbsndread); 176 dev_type_write(ucbsndwrite); 177 178 const struct cdevsw ucbsnd_cdevsw = { 179 ucbsndopen, ucbsndclose, ucbsndread, ucbsndwrite, nullioctl, 180 nostop, notty, nopoll, nullmmap, nokqfilter, 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 lwp *l) 516 { 517 int unit = AUDIOUNIT(dev); 518 struct ucbsnd_softc *sc; 519 int s; 520 521 sc = device_lookup_private(&ucbsnd_cd, unit); 522 if (sc == 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 lwp *l) 534 { 535 int unit = AUDIOUNIT(dev); 536 struct ucbsnd_softc *sc; 537 538 sc = device_lookup_private(&ucbsnd_cd, unit); 539 if (sc == 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 sc = device_lookup_private(&ucbsnd_cd, unit); 553 if (sc == 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 sc = device_lookup_private(&ucbsnd_cd, unit); 597 if (sc == 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 /* 641 * Ring buffer. 642 */ 643 int 644 ringbuf_allocate(struct ring_buf *rb, size_t blksize, int maxblk) 645 { 646 rb->rb_bufsize = blksize * maxblk; 647 rb->rb_blksize = blksize; 648 rb->rb_maxblks = maxblk; 649 #if notyet 650 rb->rb_buf = (u_int32_t)malloc(rb->rb_bufsize, M_DEVBUF, M_WAITOK); 651 #else 652 rb->rb_buf = (u_int32_t)dmabuf_static; 653 #endif 654 if (rb->rb_buf == 0) { 655 printf("ringbuf_allocate: can't allocate buffer\n"); 656 return (1); 657 } 658 memset((char*)rb->rb_buf, 0, rb->rb_bufsize); 659 #if notyet 660 rb->rb_bufcnt = malloc(rb->rb_maxblks * sizeof(size_t), M_DEVBUF, 661 M_WAITOK); 662 #else 663 rb->rb_bufcnt = dmabufcnt_static; 664 #endif 665 if (rb->rb_bufcnt == 0) { 666 printf("ringbuf_allocate: can't allocate buffer\n"); 667 return (1); 668 } 669 memset((char*)rb->rb_bufcnt, 0, rb->rb_maxblks * sizeof(size_t)); 670 671 ringbuf_reset(rb); 672 673 return (0); 674 } 675 676 void 677 ringbuf_deallocate(struct ring_buf *rb) 678 { 679 #if notyet 680 free((void*)rb->rb_buf, M_DEVBUF); 681 free(rb->rb_bufcnt, M_DEVBUF); 682 #endif 683 } 684 685 void 686 ringbuf_reset(struct ring_buf *rb) 687 { 688 rb->rb_outp = 0; 689 rb->rb_inp = 0; 690 } 691 692 int 693 ringbuf_full(struct ring_buf *rb) 694 { 695 int ret; 696 697 ret = rb->rb_outp == rb->rb_maxblks; 698 699 return (ret); 700 } 701 702 void* 703 ringbuf_producer_get(struct ring_buf *rb) 704 { 705 u_int32_t ret; 706 int s; 707 708 s = splaudio(); 709 ret = ringbuf_full(rb) ? 0 : 710 rb->rb_buf + rb->rb_inp * rb->rb_blksize; 711 splx(s); 712 713 return (void *)ret; 714 } 715 716 void 717 ringbuf_producer_return(struct ring_buf *rb, size_t cnt) 718 { 719 int s; 720 721 assert(cnt <= rb->rb_blksize); 722 723 s = splaudio(); 724 rb->rb_outp++; 725 726 rb->rb_bufcnt[rb->rb_inp] = cnt; 727 rb->rb_inp = (rb->rb_inp + 1) % rb->rb_maxblks; 728 splx(s); 729 } 730 731 void* 732 ringbuf_consumer_get(struct ring_buf *rb, size_t *cntp) 733 { 734 u_int32_t p; 735 int idx; 736 737 if (rb->rb_outp == 0) 738 return (0); 739 740 idx = (rb->rb_inp - rb->rb_outp + rb->rb_maxblks) % rb->rb_maxblks; 741 742 p = rb->rb_buf + idx * rb->rb_blksize; 743 *cntp = rb->rb_bufcnt[idx]; 744 745 return (void *)p; 746 } 747 748 void 749 ringbuf_consumer_return(struct ring_buf *rb) 750 { 751 752 if (rb->rb_outp > 0) 753 rb->rb_outp--; 754 } 755