1 /* $NetBSD: ucbsnd.c,v 1.17 2007/12/03 15:33:42 ad 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 46 #include <sys/cdefs.h> 47 __KERNEL_RCSID(0, "$NetBSD: ucbsnd.c,v 1.17 2007/12/03 15:33:42 ad Exp $"); 48 49 #include "opt_use_poll.h" 50 51 #include <sys/param.h> 52 #include <sys/systm.h> 53 #include <sys/conf.h> 54 #include <sys/malloc.h> 55 #include <sys/device.h> 56 #include <sys/proc.h> 57 #include <sys/endian.h> 58 59 #include <mips/cache.h> 60 61 #include <machine/bus.h> 62 #include <machine/intr.h> 63 64 #include <hpcmips/tx/tx39var.h> 65 #include <hpcmips/tx/tx39sibvar.h> 66 #include <hpcmips/tx/tx39sibreg.h> 67 #include <hpcmips/tx/tx39icureg.h> 68 #include <hpcmips/tx/txsnd.h> 69 70 #include <hpcmips/dev/ucb1200var.h> 71 #include <hpcmips/dev/ucb1200reg.h> 72 73 #define AUDIOUNIT(x) (minor(x)&0x0f) 74 #define AUDIODEV(x) (minor(x)&0xf0) 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 int ucbsnd_match(struct device*, struct cfdata*, void*); 156 void ucbsnd_attach(struct device*, struct device*, void*); 157 158 int ucbsnd_exec_output(void*); 159 int ucbsnd_busy(void*); 160 161 void ucbsnd_sound_init(struct ucbsnd_softc*); 162 void __ucbsnd_sound_click(tx_sound_tag_t); 163 void __ucbsnd_sound_mute(tx_sound_tag_t, int); 164 165 int ucbsndwrite_subr(struct ucbsnd_softc *, u_int32_t *, size_t, 166 struct uio *); 167 168 int ringbuf_allocate(struct ring_buf*, size_t, int); 169 void ringbuf_deallocate(struct ring_buf*); 170 void ringbuf_reset(struct ring_buf*); 171 int ringbuf_full(struct ring_buf*); 172 void *ringbuf_producer_get(struct ring_buf*); 173 void ringbuf_producer_return(struct ring_buf*, size_t); 174 void *ringbuf_consumer_get(struct ring_buf*, size_t*); 175 void ringbuf_consumer_return(struct ring_buf*); 176 177 CFATTACH_DECL(ucbsnd, sizeof(struct ucbsnd_softc), 178 ucbsnd_match, ucbsnd_attach, NULL, NULL); 179 180 dev_type_open(ucbsndopen); 181 dev_type_close(ucbsndclose); 182 dev_type_read(ucbsndread); 183 dev_type_write(ucbsndwrite); 184 185 const struct cdevsw ucbsnd_cdevsw = { 186 ucbsndopen, ucbsndclose, ucbsndread, ucbsndwrite, nullioctl, 187 nostop, notty, nopoll, nullmmap, nokqfilter, 188 }; 189 190 int 191 ucbsnd_match(struct device *parent, struct cfdata *cf, void *aux) 192 { 193 194 return (1); 195 } 196 197 void 198 ucbsnd_attach(struct device *parent, struct device *self, void *aux) 199 { 200 struct ucb1200_attach_args *ucba = aux; 201 struct ucbsnd_softc *sc = (void*)self; 202 tx_chipset_tag_t tc; 203 204 tc = sc->sc_tc = ucba->ucba_tc; 205 sc->sc_sib = ucba->ucba_sib; 206 sc->sc_ucb = ucba->ucba_ucb; 207 208 /* register sound functions */ 209 ucbsnd_sound_init(sc); 210 211 sc->sa_snd_rate = ucba->ucba_snd_rate; 212 sc->sa_tel_rate = ucba->ucba_tel_rate; 213 214 sc->sa_snd_attenuation = UCBSND_DEFAULT_ATTENUATION; 215 #define KHZ(a) ((a) / 1000), (((a) % 1000)) 216 printf(": audio %d.%03d kHz telecom %d.%03d kHz", 217 KHZ((tx39sib_clock(sc->sc_sib) * 2) / 218 (sc->sa_snd_rate * 64)), 219 KHZ((tx39sib_clock(sc->sc_sib) * 2) / 220 (sc->sa_tel_rate * 64))); 221 222 ucb1200_state_install(parent, ucbsnd_busy, self, 223 UCB1200_SND_MODULE); 224 225 ringbuf_allocate(&sc->sc_rb, TX39_SIBDMA_SIZE, UCBSND_BUFBLOCK); 226 227 printf("\n"); 228 } 229 230 int 231 ucbsnd_busy(void *arg) 232 { 233 struct ucbsnd_softc *sc = arg; 234 235 return (sc->sa_state != UCBSND_IDLE); 236 } 237 238 int 239 ucbsnd_exec_output(void *arg) 240 { 241 struct ucbsnd_softc *sc = arg; 242 tx_chipset_tag_t tc = sc->sc_tc; 243 txreg_t reg; 244 u_int32_t *buf; 245 size_t bufcnt; 246 247 switch (sc->sa_state) { 248 default: 249 panic("ucbsnd_exec_output: invalid state %d", sc->sa_state); 250 /* NOTREACHED */ 251 break; 252 253 case UCBSND_IDLE: 254 /* nothing to do */ 255 return (0); 256 257 case UCBSND_INIT: 258 sc->sa_sf0ih = tx_intr_establish( 259 tc, MAKEINTR(1, TX39_INTRSTATUS1_SIBSF0INT), 260 IST_EDGE, IPL_TTY, ucbsnd_exec_output, sc); 261 262 sc->sa_state = UCBSND_ENABLE_SAMPLERATE; 263 return (0); 264 265 case UCBSND_ENABLE_SAMPLERATE: 266 /* Enable UCB1200 side sample rate */ 267 reg = TX39_SIBSF0_WRITE; 268 reg = TX39_SIBSF0_REGADDR_SET(reg, UCB1200_AUDIOCTRLA_REG); 269 reg = TX39_SIBSF0_REGDATA_SET(reg, sc->sa_snd_rate); 270 tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 271 272 sc->sa_state = UCBSND_ENABLE_OUTPUTPATH; 273 return (0); 274 275 case UCBSND_ENABLE_OUTPUTPATH: 276 /* Enable UCB1200 side */ 277 reg = TX39_SIBSF0_WRITE; 278 reg = TX39_SIBSF0_REGADDR_SET(reg, UCB1200_AUDIOCTRLB_REG); 279 reg = TX39_SIBSF0_REGDATA_SET(reg, sc->sa_snd_attenuation | 280 UCB1200_AUDIOCTRLB_OUTEN); 281 tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 282 283 /* Enable SIB side */ 284 reg = tx_conf_read(tc, TX39_SIBCTRL_REG); 285 tx_conf_write(tc, TX39_SIBCTRL_REG, 286 reg | TX39_SIBCTRL_ENSND); 287 288 sc->sa_state = UCBSND_ENABLE_SPEAKER0; 289 sc->sa_retry = 10; 290 return (0); 291 case UCBSND_ENABLE_SPEAKER0: 292 /* Speaker on */ 293 294 reg = TX39_SIBSF0_REGADDR_SET(0, UCB1200_IO_DATA_REG); 295 tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 296 297 sc->sa_state = UCBSND_ENABLE_SPEAKER1; 298 return (0); 299 300 case UCBSND_ENABLE_SPEAKER1: 301 reg = tx_conf_read(tc, TX39_SIBSF0STAT_REG); 302 if ((TX39_SIBSF0_REGADDR(reg) != UCB1200_IO_DATA_REG) && 303 --sc->sa_retry > 0) { 304 305 sc->sa_state = UCBSND_ENABLE_SPEAKER0; 306 return (0); 307 } 308 309 if (sc->sa_retry <= 0) { 310 printf("ucbsnd_exec_output: subframe0 busy\n"); 311 312 sc->sa_state = UCBSND_IDLE; 313 return (0); 314 } 315 316 reg |= TX39_SIBSF0_WRITE; 317 reg |= UCB1200_IO_DATA_SPEAKER; 318 tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 319 320 /* 321 * Begin to transfer. 322 */ 323 switch (sc->sa_transfer_mode) { 324 case UCBSND_TRANSFERMODE_DMA: 325 sc->sa_state = UCBSND_DMASTART; 326 sc->sa_dmacnt = 0; 327 break; 328 case UCBSND_TRANSFERMODE_PIO: 329 sc->sa_state = UCBSND_TRANSITION_PIO; 330 break; 331 } 332 333 return (0); 334 case UCBSND_DMASTART: 335 /* get data */ 336 if (sc->sa_dmacnt) /* return previous buffer */ 337 ringbuf_consumer_return(&sc->sc_rb); 338 buf = ringbuf_consumer_get(&sc->sc_rb, &bufcnt); 339 if (buf == 0) { 340 sc->sa_state = UCBSND_DMAEND; 341 return (0); 342 } 343 344 if (sc->sa_dmacnt == 0) { 345 /* change interrupt source */ 346 if (sc->sa_sf0ih) { 347 tx_intr_disestablish(tc, sc->sa_sf0ih); 348 sc->sa_sf0ih = 0; 349 } 350 sc->sa_sndih = tx_intr_establish( 351 tc, MAKEINTR(1, TX39_INTRSTATUS1_SND1_0INT), 352 IST_EDGE, IPL_TTY, ucbsnd_exec_output, sc); 353 } else { 354 wakeup(&sc->sc_rb); 355 } 356 357 /* set DMA buffer address */ 358 tx_conf_write(tc, TX39_SIBSNDTXSTART_REG, 359 MIPS_KSEG0_TO_PHYS(buf)); 360 361 /* set DMA buffer size */ 362 tx_conf_write(tc, TX39_SIBSIZE_REG, 363 TX39_SIBSIZE_SNDSIZE_SET(0, bufcnt)); 364 365 tx_conf_write(tc, TX39_SIBSF0CTRL_REG, TX39_SIBSF0_SNDVALID); 366 367 /* kick DMA */ 368 reg = tx_conf_read(tc, TX39_SIBDMACTRL_REG); 369 reg |= TX39_SIBDMACTRL_ENDMATXSND; 370 tx_conf_write(tc, TX39_SIBDMACTRL_REG, reg); 371 372 /* set next */ 373 sc->sa_dmacnt += bufcnt; 374 375 break; 376 377 case UCBSND_DMAEND: 378 sc->sa_state = UCBSND_TRANSITION_DISABLE; 379 break; 380 case UCBSND_TRANSITION_PIO: 381 /* change interrupt source */ 382 if (sc->sa_sf0ih) { 383 tx_intr_disestablish(tc, sc->sa_sf0ih); 384 sc->sa_sf0ih = 0; 385 } 386 sc->sa_sndih = tx_intr_establish( 387 tc, MAKEINTR(1, TX39_INTRSTATUS1_SNDININT), 388 IST_EDGE, IPL_TTY, ucbsnd_exec_output, sc); 389 390 sc->sa_state = UCBSND_PIO; 391 sc->sa_cnt = 0; 392 return (0); 393 394 case UCBSND_PIO: 395 { 396 /* PIO test routine */ 397 int dummy_data = sc->sa_cnt * 3; 398 tx_conf_write(tc, TX39_SIBSNDHOLD_REG, 399 dummy_data << 16 | dummy_data); 400 tx_conf_write(tc, TX39_SIBSF0CTRL_REG, TX39_SIBSF0_SNDVALID); 401 if (sc->sa_cnt++ > 50) { 402 sc->sa_state = UCBSND_TRANSITION_DISABLE; 403 } 404 return (0); 405 } 406 case UCBSND_TRANSITION_DISABLE: 407 /* change interrupt source */ 408 if (sc->sa_sndih) { 409 tx_intr_disestablish(tc, sc->sa_sndih); 410 sc->sa_sndih = 0; 411 } 412 sc->sa_sf0ih = tx_intr_establish( 413 tc, MAKEINTR(1, TX39_INTRSTATUS1_SIBSF0INT), 414 IST_EDGE, IPL_TTY, ucbsnd_exec_output, sc); 415 416 sc->sa_state = UCBSND_DISABLE_OUTPUTPATH; 417 return (0); 418 419 case UCBSND_DISABLE_OUTPUTPATH: 420 /* disable codec output path and mute */ 421 reg = TX39_SIBSF0_WRITE; 422 reg = TX39_SIBSF0_REGADDR_SET(reg, UCB1200_AUDIOCTRLB_REG); 423 reg = TX39_SIBSF0_REGDATA_SET(reg, UCB1200_AUDIOCTRLB_MUTE); 424 tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 425 426 sc->sa_state = UCBSND_DISABLE_SPEAKER0; 427 sc->sa_retry = 10; 428 return (0); 429 430 case UCBSND_DISABLE_SPEAKER0: 431 /* Speaker off */ 432 reg = TX39_SIBSF0_REGADDR_SET(0, UCB1200_IO_DATA_REG); 433 tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 434 435 sc->sa_state = UCBSND_DISABLE_SPEAKER1; 436 return (0); 437 438 case UCBSND_DISABLE_SPEAKER1: 439 reg = tx_conf_read(tc, TX39_SIBSF0STAT_REG); 440 if ((TX39_SIBSF0_REGADDR(reg) != UCB1200_IO_DATA_REG) && 441 --sc->sa_retry > 0) { 442 443 sc->sa_state = UCBSND_DISABLE_SPEAKER0; 444 return (0); 445 } 446 447 if (sc->sa_retry <= 0) { 448 printf("ucbsnd_exec_output: subframe0 busy\n"); 449 450 sc->sa_state = UCBSND_IDLE; 451 return (0); 452 } 453 454 reg |= TX39_SIBSF0_WRITE; 455 reg &= ~UCB1200_IO_DATA_SPEAKER; 456 tx_conf_write(tc, TX39_SIBSF0CTRL_REG, reg); 457 458 sc->sa_state = UCBSND_DISABLE_SIB; 459 return (0); 460 461 case UCBSND_DISABLE_SIB: 462 /* Disable SIB side */ 463 reg = tx_conf_read(tc, TX39_SIBCTRL_REG); 464 reg &= ~TX39_SIBCTRL_ENSND; 465 tx_conf_write(tc, TX39_SIBCTRL_REG, reg); 466 467 /* end audio disable sequence */ 468 if (sc->sa_sf0ih) { 469 tx_intr_disestablish(tc, sc->sa_sf0ih); 470 sc->sa_sf0ih = 0; 471 } 472 sc->sa_state = UCBSND_IDLE; 473 474 return (0); 475 } 476 477 return (0); 478 } 479 480 /* 481 * global sound interface. 482 */ 483 void 484 ucbsnd_sound_init(struct ucbsnd_softc *sc) 485 { 486 tx_sound_tag_t ts = &sc->sc_tag; 487 tx_chipset_tag_t tc = sc->sc_tc; 488 489 ts->ts_v = sc; 490 ts->ts_click = __ucbsnd_sound_click; 491 ts->ts_mute = __ucbsnd_sound_mute; 492 493 tx_conf_register_sound(tc, ts); 494 } 495 496 void 497 __ucbsnd_sound_click(tx_sound_tag_t arg) 498 { 499 struct ucbsnd_softc *sc = (void*)arg; 500 501 if (!sc->sc_mute && sc->sa_state == UCBSND_IDLE) { 502 sc->sa_transfer_mode = UCBSND_TRANSFERMODE_PIO; 503 sc->sa_state = UCBSND_INIT; 504 ucbsnd_exec_output((void*)sc); 505 } 506 } 507 508 void 509 __ucbsnd_sound_mute(tx_sound_tag_t arg, int onoff) 510 { 511 struct ucbsnd_softc *sc = (void*)arg; 512 513 sc->sc_mute = onoff; 514 } 515 516 /* 517 * device access 518 */ 519 extern struct cfdriver ucbsnd_cd; 520 521 int 522 ucbsndopen(dev_t dev, int flags, int ifmt, struct lwp *l) 523 { 524 int unit = AUDIOUNIT(dev); 525 struct ucbsnd_softc *sc; 526 int s; 527 528 if (unit >= ucbsnd_cd.cd_ndevs || 529 (sc = ucbsnd_cd.cd_devs[unit]) == NULL) 530 return (ENXIO); 531 532 s = splaudio(); 533 ringbuf_reset(&sc->sc_rb); 534 splx(s); 535 536 return (0); 537 } 538 539 int 540 ucbsndclose(dev_t dev, int flags, int ifmt, struct lwp *l) 541 { 542 int unit = AUDIOUNIT(dev); 543 struct ucbsnd_softc *sc; 544 545 if (unit >= ucbsnd_cd.cd_ndevs || 546 (sc = ucbsnd_cd.cd_devs[unit]) == NULL) 547 return (ENXIO); 548 549 return (0); 550 } 551 552 int 553 ucbsndread(dev_t dev, struct uio *uio, 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(struct ucbsnd_softc *sc, u_int32_t *buf, size_t bufsize, 569 struct uio *uio) 570 { 571 int i, s, error; 572 573 error = uiomove(buf, bufsize, uio); 574 /* 575 * inverse endian for UCB1200 576 */ 577 for (i = 0; i < bufsize / sizeof(int); i++) 578 buf[i] = htobe32(buf[i]); 579 mips_dcache_wbinv_range((vaddr_t)buf, bufsize); 580 581 ringbuf_producer_return(&sc->sc_rb, bufsize); 582 583 s = splaudio(); 584 if (sc->sa_state == UCBSND_IDLE && ringbuf_full(&sc->sc_rb)) { 585 sc->sa_transfer_mode = UCBSND_TRANSFERMODE_DMA; 586 sc->sa_state = UCBSND_INIT; 587 ucbsnd_exec_output((void*)sc); 588 } 589 splx(s); 590 591 return (error); 592 } 593 594 int 595 ucbsndwrite(dev_t dev, struct uio *uio, int ioflag) 596 { 597 int unit = AUDIOUNIT(dev); 598 struct ucbsnd_softc *sc; 599 int len, error = 0; 600 int i, n, s, rest; 601 void *buf; 602 603 if (unit >= ucbsnd_cd.cd_ndevs || 604 (sc = ucbsnd_cd.cd_devs[unit]) == NULL) 605 return (ENXIO); 606 607 len = uio->uio_resid; 608 n = (len + TX39_SIBDMA_SIZE - 1) / TX39_SIBDMA_SIZE; 609 rest = len % TX39_SIBDMA_SIZE; 610 611 if (rest) 612 --n; 613 614 for (i = 0; i < n; i++) { 615 while (!(buf = ringbuf_producer_get(&sc->sc_rb))) { 616 error = tsleep(&sc->sc_rb, PRIBIO, "ucbsnd", 1000); 617 if (error) 618 goto errout; 619 } 620 621 error = ucbsndwrite_subr(sc, buf, TX39_SIBDMA_SIZE, uio); 622 if (error) 623 goto out; 624 } 625 626 if (rest) { 627 while (!(buf = ringbuf_producer_get(&sc->sc_rb))) { 628 error = tsleep(&sc->sc_rb, PRIBIO, "ucbsnd", 1000); 629 if (error) 630 goto errout; 631 } 632 633 error = ucbsndwrite_subr(sc, buf, rest, uio); 634 } 635 636 out: 637 return (error); 638 errout: 639 printf("%s: timeout. reset ring-buffer.\n", sc->sc_dev.dv_xname); 640 s = splaudio(); 641 ringbuf_reset(&sc->sc_rb); 642 splx(s); 643 644 return (error); 645 } 646 647 /* 648 * Ring buffer. 649 */ 650 int 651 ringbuf_allocate(struct ring_buf *rb, size_t blksize, int maxblk) 652 { 653 rb->rb_bufsize = blksize * maxblk; 654 rb->rb_blksize = blksize; 655 rb->rb_maxblks = maxblk; 656 #if notyet 657 rb->rb_buf = (u_int32_t)malloc(rb->rb_bufsize, M_DEVBUF, M_WAITOK); 658 #else 659 rb->rb_buf = (u_int32_t)dmabuf_static; 660 #endif 661 if (rb->rb_buf == 0) { 662 printf("ringbuf_allocate: can't allocate buffer\n"); 663 return (1); 664 } 665 memset((char*)rb->rb_buf, 0, rb->rb_bufsize); 666 #if notyet 667 rb->rb_bufcnt = malloc(rb->rb_maxblks * sizeof(size_t), M_DEVBUF, 668 M_WAITOK); 669 #else 670 rb->rb_bufcnt = dmabufcnt_static; 671 #endif 672 if (rb->rb_bufcnt == 0) { 673 printf("ringbuf_allocate: can't allocate buffer\n"); 674 return (1); 675 } 676 memset((char*)rb->rb_bufcnt, 0, rb->rb_maxblks * sizeof(size_t)); 677 678 ringbuf_reset(rb); 679 680 return (0); 681 } 682 683 void 684 ringbuf_deallocate(struct ring_buf *rb) 685 { 686 #if notyet 687 free((void*)rb->rb_buf, M_DEVBUF); 688 free(rb->rb_bufcnt, M_DEVBUF); 689 #endif 690 } 691 692 void 693 ringbuf_reset(struct ring_buf *rb) 694 { 695 rb->rb_outp = 0; 696 rb->rb_inp = 0; 697 } 698 699 int 700 ringbuf_full(struct ring_buf *rb) 701 { 702 int ret; 703 704 ret = rb->rb_outp == rb->rb_maxblks; 705 706 return (ret); 707 } 708 709 void* 710 ringbuf_producer_get(struct ring_buf *rb) 711 { 712 u_int32_t ret; 713 int s; 714 715 s = splaudio(); 716 ret = ringbuf_full(rb) ? 0 : 717 rb->rb_buf + rb->rb_inp * rb->rb_blksize; 718 splx(s); 719 720 return (void *)ret; 721 } 722 723 void 724 ringbuf_producer_return(struct ring_buf *rb, size_t cnt) 725 { 726 int s; 727 728 assert(cnt <= rb->rb_blksize); 729 730 s = splaudio(); 731 rb->rb_outp++; 732 733 rb->rb_bufcnt[rb->rb_inp] = cnt; 734 rb->rb_inp = (rb->rb_inp + 1) % rb->rb_maxblks; 735 splx(s); 736 } 737 738 void* 739 ringbuf_consumer_get(struct ring_buf *rb, size_t *cntp) 740 { 741 u_int32_t p; 742 int idx; 743 744 if (rb->rb_outp == 0) 745 return (0); 746 747 idx = (rb->rb_inp - rb->rb_outp + rb->rb_maxblks) % rb->rb_maxblks; 748 749 p = rb->rb_buf + idx * rb->rb_blksize; 750 *cntp = rb->rb_bufcnt[idx]; 751 752 return (void *)p; 753 } 754 755 void 756 ringbuf_consumer_return(struct ring_buf *rb) 757 { 758 759 if (rb->rb_outp > 0) 760 rb->rb_outp--; 761 } 762