ucbsnd.c revision 1.4 1 /* $NetBSD: ucbsnd.c,v 1.4 2000/03/04 19:35:36 uch 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 int
682 ucbsndmmap(dev, off, prot)
683 dev_t dev;
684 int off, prot;
685 {
686 int error = 0;
687
688 /* not coded yet */
689
690 return (error);
691 }
692
693 /*
694 * Ring buffer.
695 */
696 int
697 ringbuf_allocate(rb, blksize, maxblk)
698 struct ring_buf *rb;
699 size_t blksize;
700 int maxblk;
701 {
702 rb->rb_bufsize = blksize * maxblk;
703 rb->rb_blksize = blksize;
704 rb->rb_maxblks = maxblk;
705 #if notyet
706 rb->rb_buf = (u_int32_t)malloc(rb->rb_bufsize, M_DEVBUF, M_WAITOK);
707 #else
708 rb->rb_buf = (u_int32_t)dmabuf_static;
709 #endif
710 if (rb->rb_buf == 0) {
711 printf("ringbuf_allocate: can't allocate buffer\n");
712 return 1;
713 }
714 memset((char*)rb->rb_buf, 0, rb->rb_bufsize);
715 #if notyet
716 rb->rb_bufcnt = malloc(rb->rb_maxblks * sizeof(size_t), M_DEVBUF,
717 M_WAITOK);
718 #else
719 rb->rb_bufcnt = dmabufcnt_static;
720 #endif
721 if (rb->rb_bufcnt == 0) {
722 printf("ringbuf_allocate: can't allocate buffer\n");
723 return 1;
724 }
725 memset((char*)rb->rb_bufcnt, 0, rb->rb_maxblks * sizeof(size_t));
726
727 ringbuf_reset(rb);
728
729 return 0;
730 }
731
732 void
733 ringbuf_deallocate(rb)
734 struct ring_buf *rb;
735 {
736 #if notyet
737 free((void*)rb->rb_buf, M_DEVBUF);
738 free(rb->rb_bufcnt, M_DEVBUF);
739 #endif
740 }
741
742 void
743 ringbuf_reset(rb)
744 struct ring_buf *rb;
745 {
746 rb->rb_outp = 0;
747 rb->rb_inp = 0;
748 }
749
750 int
751 ringbuf_full(rb)
752 struct ring_buf *rb;
753 {
754 int ret;
755
756 ret = rb->rb_outp == rb->rb_maxblks;
757
758 return ret;
759 }
760
761 void*
762 ringbuf_producer_get(rb)
763 struct ring_buf *rb;
764 {
765 u_int32_t ret;
766 int s;
767
768 s = splaudio();
769 ret = ringbuf_full(rb) ? 0 :
770 rb->rb_buf + rb->rb_inp * rb->rb_blksize;
771 splx(s);
772
773 return (void*)ret;
774 }
775
776 void
777 ringbuf_producer_return(rb, cnt)
778 struct ring_buf *rb;
779 size_t cnt;
780 {
781 int s;
782
783 assert(cnt <= rb->rb_blksize);
784
785 s = splaudio();
786 rb->rb_outp++;
787
788 rb->rb_bufcnt[rb->rb_inp] = cnt;
789 rb->rb_inp = (rb->rb_inp + 1) % rb->rb_maxblks;
790 splx(s);
791 }
792
793 void*
794 ringbuf_consumer_get(rb, cntp)
795 struct ring_buf *rb;
796 size_t *cntp;
797 {
798 u_int32_t p;
799 int idx;
800
801 if (rb->rb_outp == 0)
802 return 0;
803
804 idx = (rb->rb_inp - rb->rb_outp + rb->rb_maxblks) % rb->rb_maxblks;
805
806 p = rb->rb_buf + idx * rb->rb_blksize;
807 *cntp = rb->rb_bufcnt[idx];
808
809 return (void*)p;
810 }
811
812 void
813 ringbuf_consumer_return(rb)
814 struct ring_buf *rb;
815 {
816
817 if (rb->rb_outp > 0)
818 rb->rb_outp--;
819 }
820