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