This source file includes following definitions.
- audioprobe
- audioattach
- audioactivate
- audiodetach
- au_portof
- au_check_ports
- audio_attach_mi
- audioprint
- audio_printsc
- audio_print_params
- audio_alloc_ring
- audio_free_ring
- audioopen
- audioclose
- audioread
- audiowrite
- audioioctl
- audiopoll
- audiommap
- audio_init_ringbuffer
- audio_initbufs
- audio_calcwater
- audio_sleep_timo
- audio_sleep
- audio_wakeup
- audio_open
- audio_init_record
- audio_init_play
- audio_drain
- audio_close
- audio_read
- audio_clear
- audio_calc_blksize
- audio_fill_silence
- audio_silence_copyout
- audio_write
- audio_ioctl
- audio_selwakeup
- audio_poll
- audio_mmap
- audiostartr
- audiostartp
- audio_pint_silence
- audio_pint
- audio_rint
- audio_check_params
- au_set_lr_value
- au_set_gain
- au_get_lr_value
- au_get_gain
- au_set_port
- au_get_port
- audiosetinfo
- audiogetinfo
- mixer_open
- mixer_remove
- mixer_signal
- mixer_close
- mixer_ioctl
- audiokqfilter
- filt_audiordetach
- filt_audioread
- filt_audiowdetach
- filt_audiowrite
- wskbd_get_mixerdev
- wskbd_set_mixervolume
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 #include "audio.h"
65 #if NAUDIO > 0
66
67 #include <sys/param.h>
68 #include <sys/ioctl.h>
69 #include <sys/fcntl.h>
70 #include <sys/vnode.h>
71 #include <sys/selinfo.h>
72 #include <sys/poll.h>
73 #include <sys/malloc.h>
74 #include <sys/proc.h>
75 #include <sys/systm.h>
76 #include <sys/syslog.h>
77 #include <sys/kernel.h>
78 #include <sys/signalvar.h>
79 #include <sys/conf.h>
80 #include <sys/audioio.h>
81 #include <sys/device.h>
82
83 #include <dev/audio_if.h>
84 #include <dev/audiovar.h>
85
86 #include <dev/rndvar.h>
87
88 #include <machine/endian.h>
89
90 #include "wskbd.h"
91
92 #ifdef AUDIO_DEBUG
93 #define DPRINTF(x) if (audiodebug) printf x
94 #define DPRINTFN(n,x) if (audiodebug>(n)) printf x
95 int audiodebug = 0;
96 #else
97 #define DPRINTF(x)
98 #define DPRINTFN(n,x)
99 #endif
100
101 #define ROUNDSIZE(x) x &= -16
102
103 int audio_blk_ms = AUDIO_BLK_MS;
104
105 int audiosetinfo(struct audio_softc *, struct audio_info *);
106 int audiogetinfo(struct audio_softc *, struct audio_info *);
107
108 int audio_open(dev_t, struct audio_softc *, int, int, struct proc *);
109 int audio_close(dev_t, int, int, struct proc *);
110 int audio_read(dev_t, struct uio *, int);
111 int audio_write(dev_t, struct uio *, int);
112 int audio_ioctl(dev_t, u_long, caddr_t, int, struct proc *);
113 int audio_poll(dev_t, int, struct proc *);
114 paddr_t audio_mmap(dev_t, off_t, int);
115
116 int mixer_open(dev_t, struct audio_softc *, int, int, struct proc *);
117 int mixer_close(dev_t, int, int, struct proc *);
118 int mixer_ioctl(dev_t, u_long, caddr_t, int, struct proc *);
119 static void mixer_remove(struct audio_softc *, struct proc *p);
120 static void mixer_signal(struct audio_softc *);
121
122 void audio_init_record(struct audio_softc *);
123 void audio_init_play(struct audio_softc *);
124 int audiostartr(struct audio_softc *);
125 int audiostartp(struct audio_softc *);
126 void audio_rint(void *);
127 void audio_pint(void *);
128 int audio_check_params(struct audio_params *);
129
130 void audio_calc_blksize(struct audio_softc *, int);
131 void audio_fill_silence(struct audio_params *, u_char *, int);
132 int audio_silence_copyout(struct audio_softc *, int, struct uio *);
133
134 void audio_init_ringbuffer(struct audio_ringbuffer *);
135 int audio_initbufs(struct audio_softc *);
136 void audio_calcwater(struct audio_softc *);
137 static __inline int audio_sleep_timo(int *, char *, int);
138 static __inline int audio_sleep(int *, char *);
139 static __inline void audio_wakeup(int *);
140 void audio_selwakeup(struct audio_softc *sc, int play);
141 int audio_drain(struct audio_softc *);
142 void audio_clear(struct audio_softc *);
143 static __inline void audio_pint_silence(struct audio_softc *, struct audio_ringbuffer *, u_char *, int);
144
145 int audio_alloc_ring(struct audio_softc *, struct audio_ringbuffer *, int, int);
146 void audio_free_ring(struct audio_softc *, struct audio_ringbuffer *);
147
148 int audioprint(void *, const char *);
149
150 int audioprobe(struct device *, void *, void *);
151 void audioattach(struct device *, struct device *, void *);
152 int audiodetach(struct device *, int);
153 int audioactivate(struct device *, enum devact);
154
155 struct portname {
156 char *name;
157 int mask;
158 };
159 static struct portname itable[] = {
160 { AudioNmicrophone, AUDIO_MICROPHONE },
161 { AudioNline, AUDIO_LINE_IN },
162 { AudioNcd, AUDIO_CD },
163 { 0 }
164 };
165 static struct portname otable[] = {
166 { AudioNspeaker, AUDIO_SPEAKER },
167 { AudioNheadphone, AUDIO_HEADPHONE },
168 { AudioNline, AUDIO_LINE_OUT },
169 { 0 }
170 };
171 void au_check_ports(struct audio_softc *, struct au_mixer_ports *,
172 mixer_devinfo_t *, int, char *, char *,
173 struct portname *);
174 int au_set_gain(struct audio_softc *, struct au_mixer_ports *,
175 int, int);
176 void au_get_gain(struct audio_softc *, struct au_mixer_ports *,
177 u_int *, u_char *);
178 int au_set_port(struct audio_softc *, struct au_mixer_ports *,
179 u_int);
180 int au_get_port(struct audio_softc *, struct au_mixer_ports *);
181 int au_get_lr_value(struct audio_softc *, mixer_ctrl_t *,
182 int *, int *r);
183 int au_set_lr_value(struct audio_softc *, mixer_ctrl_t *,
184 int, int);
185 int au_portof(struct audio_softc *, char *);
186
187
188
189 struct audio_params audio_default =
190 { 8000, AUDIO_ENCODING_ULAW, 8, 1, 0, 1 };
191
192 struct cfattach audio_ca = {
193 sizeof(struct audio_softc), audioprobe, audioattach,
194 audiodetach, audioactivate
195 };
196
197 struct cfdriver audio_cd = {
198 NULL, "audio", DV_DULL
199 };
200
201 void filt_audiowdetach(struct knote *);
202 int filt_audiowrite(struct knote *, long);
203
204 struct filterops audiowrite_filtops =
205 { 1, NULL, filt_audiowdetach, filt_audiowrite};
206
207 void filt_audiordetach(struct knote *);
208 int filt_audioread(struct knote *, long);
209
210 struct filterops audioread_filtops =
211 { 1, NULL, filt_audiordetach, filt_audioread};
212
213 #if NWSKBD > 0
214
215 int wskbd_get_mixerdev(struct audio_softc *, int, int *);
216 int wskbd_set_mixervolume(long);
217 #endif
218
219 int
220 audioprobe(struct device *parent, void *match, void *aux)
221 {
222 struct audio_attach_args *sa = aux;
223
224 DPRINTF(("audioprobe: type=%d sa=%p hw=%p\n",
225 sa->type, sa, sa->hwif));
226 return (sa->type == AUDIODEV_TYPE_AUDIO) ? 1 : 0;
227 }
228
229 void
230 audioattach(struct device *parent, struct device *self, void *aux)
231 {
232 struct audio_softc *sc = (void *)self;
233 struct audio_attach_args *sa = aux;
234 struct audio_hw_if *hwp = sa->hwif;
235 void *hdlp = sa->hdl;
236 int error;
237 mixer_devinfo_t mi;
238 int iclass, oclass, mclass;
239
240 printf("\n");
241
242 #ifdef DIAGNOSTIC
243 if (hwp == 0 ||
244 hwp->open == 0 ||
245 hwp->close == 0 ||
246 hwp->query_encoding == 0 ||
247 hwp->set_params == 0 ||
248 (hwp->start_output == 0 && hwp->trigger_output == 0) ||
249 (hwp->start_input == 0 && hwp->trigger_input == 0) ||
250 hwp->halt_output == 0 ||
251 hwp->halt_input == 0 ||
252 hwp->getdev == 0 ||
253 hwp->set_port == 0 ||
254 hwp->get_port == 0 ||
255 hwp->query_devinfo == 0 ||
256 hwp->get_props == 0) {
257 printf("audio: missing method\n");
258 sc->hw_if = 0;
259 return;
260 }
261 #endif
262
263 sc->hw_if = hwp;
264 sc->hw_hdl = hdlp;
265 sc->sc_dev = parent;
266
267 error = audio_alloc_ring(sc, &sc->sc_pr, AUMODE_PLAY, AU_RING_SIZE);
268 if (error) {
269 sc->hw_if = 0;
270 printf("audio: could not allocate play buffer\n");
271 return;
272 }
273 error = audio_alloc_ring(sc, &sc->sc_rr, AUMODE_RECORD, AU_RING_SIZE);
274 if (error) {
275 audio_free_ring(sc, &sc->sc_pr);
276 sc->hw_if = 0;
277 printf("audio: could not allocate record buffer\n");
278 return;
279 }
280
281
282
283
284 sc->sc_pparams = audio_default;
285 sc->sc_rparams = audio_default;
286
287
288 sc->sc_blkset = 0;
289 audio_calc_blksize(sc, AUMODE_RECORD);
290 audio_calc_blksize(sc, AUMODE_PLAY);
291 audio_init_ringbuffer(&sc->sc_rr);
292 audio_init_ringbuffer(&sc->sc_pr);
293 audio_calcwater(sc);
294
295 iclass = oclass = mclass = -1;
296 sc->sc_inports.index = -1;
297 sc->sc_inports.nports = 0;
298 sc->sc_inports.isenum = 0;
299 sc->sc_inports.allports = 0;
300 sc->sc_outports.index = -1;
301 sc->sc_outports.nports = 0;
302 sc->sc_outports.isenum = 0;
303 sc->sc_outports.allports = 0;
304 sc->sc_monitor_port = -1;
305 for(mi.index = 0; ; mi.index++) {
306 if (hwp->query_devinfo(hdlp, &mi) != 0)
307 break;
308 if (mi.type == AUDIO_MIXER_CLASS &&
309 strcmp(mi.label.name, AudioCrecord) == 0)
310 iclass = mi.index;
311 if (mi.type == AUDIO_MIXER_CLASS &&
312 strcmp(mi.label.name, AudioCmonitor) == 0)
313 mclass = mi.index;
314 if (mi.type == AUDIO_MIXER_CLASS &&
315 strcmp(mi.label.name, AudioCoutputs) == 0)
316 oclass = mi.index;
317 }
318 for(mi.index = 0; ; mi.index++) {
319 if (hwp->query_devinfo(hdlp, &mi) != 0)
320 break;
321 if (mi.type == AUDIO_MIXER_CLASS)
322 continue;
323 au_check_ports(sc, &sc->sc_inports, &mi, iclass,
324 AudioNsource, AudioNrecord, itable);
325 au_check_ports(sc, &sc->sc_outports, &mi, oclass,
326 AudioNoutput, AudioNmaster, otable);
327 if (mi.mixer_class == mclass &&
328 (strcmp(mi.label.name, AudioNmonitor) == 0))
329 sc->sc_monitor_port = mi.index;
330 if ((sc->sc_monitor_port == -1) && (mi.mixer_class == oclass) &&
331 (strcmp(mi.label.name, AudioNmonitor) == 0))
332 sc->sc_monitor_port = mi.index;
333 }
334 DPRINTF(("audio_attach: inputs ports=0x%x, output ports=0x%x\n",
335 sc->sc_inports.allports, sc->sc_outports.allports));
336 }
337
338 int
339 audioactivate(struct device *self, enum devact act)
340 {
341 struct audio_softc *sc = (struct audio_softc *)self;
342
343 switch (act) {
344 case DVACT_ACTIVATE:
345 break;
346
347 case DVACT_DEACTIVATE:
348 sc->sc_dying = 1;
349 break;
350 }
351 return (0);
352 }
353
354 int
355 audiodetach(struct device *self, int flags)
356 {
357 struct audio_softc *sc = (struct audio_softc *)self;
358 int maj, mn;
359 int s;
360
361 DPRINTF(("audio_detach: sc=%p flags=%d\n", sc, flags));
362
363 sc->sc_dying = 1;
364
365 wakeup(&sc->sc_wchan);
366 wakeup(&sc->sc_rchan);
367 s = splaudio();
368 if (--sc->sc_refcnt >= 0) {
369 if (tsleep(&sc->sc_refcnt, PZERO, "auddet", hz * 120))
370 printf("audiodetach: %s didn't detach\n",
371 sc->dev.dv_xname);
372 }
373 splx(s);
374
375
376 audio_free_ring(sc, &sc->sc_pr);
377 audio_free_ring(sc, &sc->sc_rr);
378
379
380 for (maj = 0; maj < nchrdev; maj++)
381 if (cdevsw[maj].d_open == audioopen)
382 break;
383
384
385 mn = self->dv_unit;
386 vdevgone(maj, mn | SOUND_DEVICE, mn | SOUND_DEVICE, VCHR);
387 vdevgone(maj, mn | AUDIO_DEVICE, mn | AUDIO_DEVICE, VCHR);
388 vdevgone(maj, mn | AUDIOCTL_DEVICE, mn | AUDIOCTL_DEVICE, VCHR);
389 vdevgone(maj, mn | MIXER_DEVICE, mn | MIXER_DEVICE, VCHR);
390
391 return (0);
392 }
393
394 int
395 au_portof(struct audio_softc *sc, char *name)
396 {
397 mixer_devinfo_t mi;
398
399 for(mi.index = 0;
400 sc->hw_if->query_devinfo(sc->hw_hdl, &mi) == 0;
401 mi.index++)
402 if (strcmp(mi.label.name, name) == 0)
403 return mi.index;
404 return -1;
405 }
406
407 void
408 au_check_ports(struct audio_softc *sc, struct au_mixer_ports *ports,
409 mixer_devinfo_t *mi, int cls, char *name, char *mname, struct portname *tbl)
410 {
411 int i, j;
412
413 if (mi->mixer_class != cls)
414 return;
415 if (strcmp(mi->label.name, mname) == 0) {
416 ports->master = mi->index;
417 return;
418 }
419 if (strcmp(mi->label.name, name) != 0)
420 return;
421 if (mi->type == AUDIO_MIXER_ENUM) {
422 ports->index = mi->index;
423 for(i = 0; tbl[i].name; i++) {
424 for(j = 0; j < mi->un.e.num_mem; j++) {
425 if (strcmp(mi->un.e.member[j].label.name,
426 tbl[i].name) == 0) {
427 ports->aumask[ports->nports] = tbl[i].mask;
428 ports->misel [ports->nports] = mi->un.e.member[j].ord;
429 ports->miport[ports->nports++] =
430 au_portof(sc, mi->un.e.member[j].label.name);
431 ports->allports |= tbl[i].mask;
432 }
433 }
434 }
435 ports->isenum = 1;
436 } else if (mi->type == AUDIO_MIXER_SET) {
437 ports->index = mi->index;
438 for(i = 0; tbl[i].name; i++) {
439 for(j = 0; j < mi->un.s.num_mem; j++) {
440 if (strcmp(mi->un.s.member[j].label.name,
441 tbl[i].name) == 0) {
442 ports->aumask[ports->nports] = tbl[i].mask;
443 ports->misel [ports->nports] = mi->un.s.member[j].mask;
444 ports->miport[ports->nports++] =
445 au_portof(sc, mi->un.s.member[j].label.name);
446 ports->allports |= tbl[i].mask;
447 }
448 }
449 }
450 }
451 }
452
453
454
455
456
457 struct device *
458 audio_attach_mi(struct audio_hw_if *ahwp, void *hdlp, struct device *dev)
459 {
460 struct audio_attach_args arg;
461
462 #ifdef DIAGNOSTIC
463 if (ahwp == NULL) {
464 printf ("audio_attach_mi: NULL\n");
465 return 0;
466 }
467 #endif
468
469 arg.type = AUDIODEV_TYPE_AUDIO;
470 arg.hwif = ahwp;
471 arg.hdl = hdlp;
472 return config_found(dev, &arg, audioprint);
473 }
474
475 #if NAUDIO > 0
476 int
477 audioprint(void *aux, const char *pnp)
478 {
479 struct audio_attach_args *arg = aux;
480 const char *type;
481
482 if (pnp != NULL) {
483 switch (arg->type) {
484 case AUDIODEV_TYPE_AUDIO:
485 type = "audio";
486 break;
487 case AUDIODEV_TYPE_OPL:
488 type = "opl";
489 break;
490 case AUDIODEV_TYPE_MPU:
491 type = "mpu";
492 break;
493 default:
494 panic("audioprint: unknown type %d", arg->type);
495 }
496 printf("%s at %s", type, pnp);
497 }
498 return (UNCONF);
499 }
500
501 #endif
502
503 #ifdef AUDIO_DEBUG
504 void audio_printsc(struct audio_softc *);
505 void audio_print_params(char *, struct audio_params *);
506
507 void
508 audio_printsc(struct audio_softc *sc)
509 {
510 printf("hwhandle %p hw_if %p ", sc->hw_hdl, sc->hw_if);
511 printf("open 0x%x mode 0x%x\n", sc->sc_open, sc->sc_mode);
512 printf("rchan 0x%x wchan 0x%x ", sc->sc_rchan, sc->sc_wchan);
513 printf("rring used 0x%x pring used=%d\n", sc->sc_rr.used, sc->sc_pr.used);
514 printf("rbus 0x%x pbus 0x%x ", sc->sc_rbus, sc->sc_pbus);
515 printf("blksize %d", sc->sc_pr.blksize);
516 printf("hiwat %d lowat %d\n", sc->sc_pr.usedhigh, sc->sc_pr.usedlow);
517 }
518
519 void
520 audio_print_params(char *s, struct audio_params *p)
521 {
522 printf("audio: %s sr=%ld, enc=%d, chan=%d, prec=%d\n", s,
523 p->sample_rate, p->encoding, p->channels, p->precision);
524 }
525 #endif
526
527 int
528 audio_alloc_ring(struct audio_softc *sc, struct audio_ringbuffer *r,
529 int direction, int bufsize)
530 {
531 struct audio_hw_if *hw = sc->hw_if;
532 void *hdl = sc->hw_hdl;
533
534
535
536 if (bufsize < AUMINBUF)
537 bufsize = AUMINBUF;
538 ROUNDSIZE(bufsize);
539 if (hw->round_buffersize)
540 bufsize = hw->round_buffersize(hdl, direction, bufsize);
541 r->bufsize = bufsize;
542 if (hw->allocm)
543 r->start = hw->allocm(hdl, direction, r->bufsize, M_DEVBUF,
544 M_WAITOK);
545 else
546 r->start = malloc(bufsize, M_DEVBUF, M_WAITOK);
547 if (r->start == 0)
548 return ENOMEM;
549 return 0;
550 }
551
552 void
553 audio_free_ring(struct audio_softc *sc, struct audio_ringbuffer *r)
554 {
555 if (sc->hw_if->freem) {
556 sc->hw_if->freem(sc->hw_hdl, r->start, M_DEVBUF);
557 } else {
558 free(r->start, M_DEVBUF);
559 }
560 }
561
562 int
563 audioopen(dev_t dev, int flags, int ifmt, struct proc *p)
564 {
565 int unit = AUDIOUNIT(dev);
566 struct audio_softc *sc;
567 int error;
568
569 if (unit >= audio_cd.cd_ndevs ||
570 (sc = audio_cd.cd_devs[unit]) == NULL)
571 return ENXIO;
572
573 if (sc->sc_dying)
574 return (EIO);
575
576 if (!sc->hw_if)
577 return (ENXIO);
578
579 sc->sc_refcnt ++;
580 switch (AUDIODEV(dev)) {
581 case SOUND_DEVICE:
582 case AUDIO_DEVICE:
583 case AUDIOCTL_DEVICE:
584 error = audio_open(dev, sc, flags, ifmt, p);
585 break;
586 case MIXER_DEVICE:
587 error = mixer_open(dev, sc, flags, ifmt, p);
588 break;
589 default:
590 error = ENXIO;
591 break;
592 }
593
594 if (--sc->sc_refcnt < 0)
595 wakeup(&sc->sc_refcnt);
596
597 return (error);
598 }
599
600 int
601 audioclose(dev_t dev, int flags, int ifmt, struct proc *p)
602 {
603
604 switch (AUDIODEV(dev)) {
605 case SOUND_DEVICE:
606 case AUDIO_DEVICE:
607 return (audio_close(dev, flags, ifmt, p));
608 case MIXER_DEVICE:
609 return (mixer_close(dev, flags, ifmt, p));
610 case AUDIOCTL_DEVICE:
611 return 0;
612 default:
613 return (ENXIO);
614 }
615 }
616
617 int
618 audioread(dev_t dev, struct uio *uio, int ioflag)
619 {
620 int unit = AUDIOUNIT(dev);
621 struct audio_softc *sc;
622 int error;
623
624 if (unit >= audio_cd.cd_ndevs ||
625 (sc = audio_cd.cd_devs[unit]) == NULL)
626 return ENXIO;
627
628 if (sc->sc_dying)
629 return (EIO);
630
631 sc->sc_refcnt ++;
632 switch (AUDIODEV(dev)) {
633 case SOUND_DEVICE:
634 case AUDIO_DEVICE:
635 error = audio_read(dev, uio, ioflag);
636 break;
637 case AUDIOCTL_DEVICE:
638 case MIXER_DEVICE:
639 error = ENODEV;
640 break;
641 default:
642 error = ENXIO;
643 break;
644 }
645
646 if (--sc->sc_refcnt < 0)
647 wakeup(&sc->sc_refcnt);
648 return (error);
649 }
650
651 int
652 audiowrite(dev_t dev, struct uio *uio, int ioflag)
653 {
654 int unit = AUDIOUNIT(dev);
655 struct audio_softc *sc;
656 int error;
657
658 if (unit >= audio_cd.cd_ndevs ||
659 (sc = audio_cd.cd_devs[unit]) == NULL)
660 return ENXIO;
661
662 if (sc->sc_dying)
663 return (EIO);
664
665 sc->sc_refcnt ++;
666 switch (AUDIODEV(dev)) {
667 case SOUND_DEVICE:
668 case AUDIO_DEVICE:
669 error = audio_write(dev, uio, ioflag);
670 break;
671 case AUDIOCTL_DEVICE:
672 case MIXER_DEVICE:
673 error = ENODEV;
674 break;
675 default:
676 error = ENXIO;
677 break;
678 }
679
680 if (--sc->sc_refcnt < 0)
681 wakeup(&sc->sc_refcnt);
682 return (error);
683 }
684
685 int
686 audioioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
687 {
688 int unit = AUDIOUNIT(dev);
689 struct audio_softc *sc;
690 int error;
691
692 if (unit >= audio_cd.cd_ndevs ||
693 (sc = audio_cd.cd_devs[unit]) == NULL)
694 return ENXIO;
695
696 if (sc->sc_dying)
697 return (EIO);
698
699 sc->sc_refcnt ++;
700 switch (AUDIODEV(dev)) {
701 case SOUND_DEVICE:
702 case AUDIO_DEVICE:
703 case AUDIOCTL_DEVICE:
704 error = audio_ioctl(dev, cmd, addr, flag, p);
705 break;
706 case MIXER_DEVICE:
707 error = mixer_ioctl(dev, cmd, addr, flag, p);
708 break;
709 default:
710 error = ENXIO;
711 break;
712 }
713
714 if (--sc->sc_refcnt < 0)
715 wakeup(&sc->sc_refcnt);
716 return (error);
717 }
718
719 int
720 audiopoll(dev_t dev, int events, struct proc *p)
721 {
722 int unit = AUDIOUNIT(dev);
723 struct audio_softc *sc;
724 int error;
725
726 if (unit >= audio_cd.cd_ndevs ||
727 (sc = audio_cd.cd_devs[unit]) == NULL)
728 return POLLERR;
729
730 if (sc->sc_dying)
731 return POLLERR;
732
733 sc->sc_refcnt ++;
734 switch (AUDIODEV(dev)) {
735 case SOUND_DEVICE:
736 case AUDIO_DEVICE:
737 error = audio_poll(dev, events, p);
738 break;
739 case AUDIOCTL_DEVICE:
740 case MIXER_DEVICE:
741 error = 0;
742 break;
743 default:
744 error = 0;
745 break;
746 }
747
748 if (--sc->sc_refcnt < 0)
749 wakeup(&sc->sc_refcnt);
750 return (error);
751 }
752
753 paddr_t
754 audiommap(dev_t dev, off_t off, int prot)
755 {
756 int unit = AUDIOUNIT(dev);
757 struct audio_softc *sc;
758 int ret;
759
760 if (unit >= audio_cd.cd_ndevs ||
761 (sc = audio_cd.cd_devs[unit]) == NULL)
762 return (-1);
763
764 if (sc->sc_dying)
765 return (-1);
766
767 sc->sc_refcnt ++;
768 switch (AUDIODEV(dev)) {
769 case SOUND_DEVICE:
770 case AUDIO_DEVICE:
771 ret = audio_mmap(dev, off, prot);
772 break;
773 case AUDIOCTL_DEVICE:
774 case MIXER_DEVICE:
775 ret = -1;
776 break;
777 default:
778 ret = -1;
779 break;
780 }
781
782 if (--sc->sc_refcnt < 0)
783 wakeup(&sc->sc_refcnt);
784 return (ret);
785 }
786
787
788
789
790 void
791 audio_init_ringbuffer(struct audio_ringbuffer *rp)
792 {
793 int nblks;
794 int blksize = rp->blksize;
795
796 if (blksize < AUMINBLK)
797 blksize = AUMINBLK;
798 nblks = rp->bufsize / blksize;
799 if (nblks < AUMINNOBLK) {
800 nblks = AUMINNOBLK;
801 blksize = rp->bufsize / nblks;
802 ROUNDSIZE(blksize);
803 }
804 DPRINTF(("audio_init_ringbuffer: blksize=%d\n", blksize));
805 rp->blksize = blksize;
806 rp->maxblks = nblks;
807 rp->used = 0;
808 rp->end = rp->start + nblks * blksize;
809 rp->inp = rp->outp = rp->start;
810 rp->stamp = 0;
811 rp->stamp_last = 0;
812 rp->drops = 0;
813 rp->pdrops = 0;
814 rp->copying = 0;
815 rp->needfill = 0;
816 rp->mmapped = 0;
817 }
818
819 int
820 audio_initbufs(struct audio_softc *sc)
821 {
822 struct audio_hw_if *hw = sc->hw_if;
823 int error;
824
825 DPRINTF(("audio_initbufs: mode=0x%x\n", sc->sc_mode));
826 audio_init_ringbuffer(&sc->sc_rr);
827 if (hw->init_input && (sc->sc_mode & AUMODE_RECORD)) {
828 error = hw->init_input(sc->hw_hdl, sc->sc_rr.start,
829 sc->sc_rr.end - sc->sc_rr.start);
830 if (error)
831 return error;
832 }
833
834 audio_init_ringbuffer(&sc->sc_pr);
835 sc->sc_sil_count = 0;
836 if (hw->init_output && (sc->sc_mode & AUMODE_PLAY)) {
837 error = hw->init_output(sc->hw_hdl, sc->sc_pr.start,
838 sc->sc_pr.end - sc->sc_pr.start);
839 if (error)
840 return error;
841 }
842
843 #ifdef AUDIO_INTR_TIME
844 sc->sc_pnintr = 0;
845 sc->sc_pblktime = (u_long)(
846 (u_long)sc->sc_pr.blksize * 100000 /
847 (u_long)(sc->sc_pparams.precision / NBBY *
848 sc->sc_pparams.channels *
849 sc->sc_pparams.sample_rate)) * 10;
850 DPRINTF(("audio: play blktime = %lu for %d\n",
851 sc->sc_pblktime, sc->sc_pr.blksize));
852 sc->sc_rnintr = 0;
853 sc->sc_rblktime = (u_long)(
854 (u_long)sc->sc_rr.blksize * 100000 /
855 (u_long)(sc->sc_rparams.precision / NBBY *
856 sc->sc_rparams.channels *
857 sc->sc_rparams.sample_rate)) * 10;
858 DPRINTF(("audio: record blktime = %lu for %d\n",
859 sc->sc_rblktime, sc->sc_rr.blksize));
860 #endif
861
862 return 0;
863 }
864
865 void
866 audio_calcwater(struct audio_softc *sc)
867 {
868 sc->sc_pr.usedhigh = sc->sc_pr.end - sc->sc_pr.start;
869 sc->sc_pr.usedlow = sc->sc_pr.usedhigh * 3 / 4;
870 if (sc->sc_pr.usedlow == sc->sc_pr.usedhigh)
871 sc->sc_pr.usedlow -= sc->sc_pr.blksize;
872 sc->sc_rr.usedhigh = sc->sc_rr.end - sc->sc_rr.start - sc->sc_rr.blksize;
873 sc->sc_rr.usedlow = 0;
874 }
875
876 static __inline int
877 audio_sleep_timo(int *chan, char *label, int timo)
878 {
879 int st;
880
881 if (!label)
882 label = "audio";
883
884 DPRINTFN(3, ("audio_sleep_timo: chan=%p, label=%s, timo=%d\n",
885 chan, label, timo));
886 *chan = 1;
887 st = tsleep(chan, PWAIT | PCATCH, label, timo);
888 *chan = 0;
889 #ifdef AUDIO_DEBUG
890 if (st != 0)
891 printf("audio_sleep: woke up st=%d\n", st);
892 #endif
893 return (st);
894 }
895
896 static __inline int
897 audio_sleep(int *chan, char *label)
898 {
899 return audio_sleep_timo(chan, label, 0);
900 }
901
902
903 static __inline void
904 audio_wakeup(int *chan)
905 {
906 DPRINTFN(3, ("audio_wakeup: chan=%p, *chan=%d\n", chan, *chan));
907 if (*chan) {
908 wakeup(chan);
909 *chan = 0;
910 }
911 }
912
913 int
914 audio_open(dev_t dev, struct audio_softc *sc, int flags, int ifmt,
915 struct proc *p)
916 {
917 int error;
918 int mode;
919 struct audio_info ai;
920
921 DPRINTF(("audio_open: dev=0x%x flags=0x%x sc=%p hdl=%p\n", dev, flags, sc, sc->hw_hdl));
922
923 if (ISDEVAUDIOCTL(dev))
924 return 0;
925
926 if ((sc->sc_open & (AUOPEN_READ|AUOPEN_WRITE)) != 0)
927 return (EBUSY);
928
929 error = sc->hw_if->open(sc->hw_hdl, flags);
930 if (error)
931 return (error);
932
933 sc->sc_async_audio = 0;
934 sc->sc_rchan = 0;
935 sc->sc_wchan = 0;
936 sc->sc_blkset = 0;
937 sc->sc_sil_count = 0;
938 sc->sc_rbus = 0;
939 sc->sc_pbus = 0;
940 sc->sc_eof = 0;
941 sc->sc_playdrop = 0;
942
943 sc->sc_full_duplex = 0;
944
945
946
947
948
949 mode = 0;
950 if (flags & FREAD) {
951 sc->sc_open |= AUOPEN_READ;
952 mode |= AUMODE_RECORD;
953 }
954 if (flags & FWRITE) {
955 sc->sc_open |= AUOPEN_WRITE;
956 mode |= AUMODE_PLAY | AUMODE_PLAY_ALL;
957 }
958
959
960
961
962
963
964 if (ISDEVAUDIO(dev)) {
965
966 sc->sc_rparams = audio_default;
967 sc->sc_pparams = audio_default;
968 }
969 #ifdef DIAGNOSTIC
970
971
972
973
974
975 if (sc->sc_rparams.precision == 0 || sc->sc_pparams.precision == 0) {
976 printf("audio_open: 0 precision\n");
977 error = EINVAL;
978 goto bad;
979 }
980 #endif
981
982 AUDIO_INITINFO(&ai);
983 ai.record.sample_rate = sc->sc_rparams.sample_rate;
984 ai.record.encoding = sc->sc_rparams.encoding;
985 ai.record.channels = sc->sc_rparams.channels;
986 ai.record.precision = sc->sc_rparams.precision;
987 ai.record.pause = 0;
988 ai.play.sample_rate = sc->sc_pparams.sample_rate;
989 ai.play.encoding = sc->sc_pparams.encoding;
990 ai.play.channels = sc->sc_pparams.channels;
991 ai.play.precision = sc->sc_pparams.precision;
992 ai.play.pause = 0;
993 ai.mode = mode;
994 sc->sc_pr.blksize = sc->sc_rr.blksize = 0;
995 error = audiosetinfo(sc, &ai);
996 if (error)
997 goto bad;
998
999 DPRINTF(("audio_open: done sc_mode = 0x%x\n", sc->sc_mode));
1000
1001 return 0;
1002
1003 bad:
1004 sc->hw_if->close(sc->hw_hdl);
1005 sc->sc_open = 0;
1006 sc->sc_mode = 0;
1007 sc->sc_full_duplex = 0;
1008 return error;
1009 }
1010
1011
1012
1013
1014 void
1015 audio_init_record(struct audio_softc *sc)
1016 {
1017 int s = splaudio();
1018
1019 if (sc->hw_if->speaker_ctl &&
1020 (!sc->sc_full_duplex || (sc->sc_mode & AUMODE_PLAY) == 0))
1021 sc->hw_if->speaker_ctl(sc->hw_hdl, SPKR_OFF);
1022 splx(s);
1023 }
1024
1025
1026
1027
1028 void
1029 audio_init_play(struct audio_softc *sc)
1030 {
1031 int s = splaudio();
1032
1033 sc->sc_wstamp = sc->sc_pr.stamp;
1034 if (sc->hw_if->speaker_ctl)
1035 sc->hw_if->speaker_ctl(sc->hw_hdl, SPKR_ON);
1036 splx(s);
1037 }
1038
1039 int
1040 audio_drain(struct audio_softc *sc)
1041 {
1042 int error, drops;
1043 struct audio_ringbuffer *cb = &sc->sc_pr;
1044 int s;
1045
1046 DPRINTF(("audio_drain: enter busy=%d used=%d\n",
1047 sc->sc_pbus, sc->sc_pr.used));
1048 if (sc->sc_pr.mmapped || sc->sc_pr.used <= 0)
1049 return 0;
1050 if (!sc->sc_pbus) {
1051
1052
1053
1054 int cc;
1055 u_char *inp = cb->inp;
1056
1057 cc = cb->blksize - (inp - cb->start) % cb->blksize;
1058 if (sc->sc_pparams.sw_code) {
1059 int ncc = cc / sc->sc_pparams.factor;
1060 audio_fill_silence(&sc->sc_pparams, inp, ncc);
1061 sc->sc_pparams.sw_code(sc->hw_hdl, inp, ncc);
1062 } else
1063 audio_fill_silence(&sc->sc_pparams, inp, cc);
1064 inp += cc;
1065 if (inp >= cb->end)
1066 inp = cb->start;
1067 s = splaudio();
1068 cb->used += cc;
1069 cb->inp = inp;
1070 error = audiostartp(sc);
1071 splx(s);
1072 if (error)
1073 return error;
1074 }
1075
1076
1077
1078
1079
1080
1081 #ifdef DIAGNOSTIC
1082 if (cb->copying) {
1083 printf("audio_drain: copying in progress!?!\n");
1084 cb->copying = 0;
1085 }
1086 #endif
1087 drops = cb->drops;
1088 error = 0;
1089 s = splaudio();
1090 while (cb->drops == drops && !error) {
1091 DPRINTF(("audio_drain: used=%d, drops=%ld\n", sc->sc_pr.used, cb->drops));
1092
1093
1094
1095
1096 error = audio_sleep_timo(&sc->sc_wchan, "aud_dr", 30*hz);
1097 if (sc->sc_dying)
1098 error = EIO;
1099 }
1100 splx(s);
1101 return error;
1102 }
1103
1104
1105
1106
1107
1108 int
1109 audio_close(dev_t dev, int flags, int ifmt, struct proc *p)
1110 {
1111 int unit = AUDIOUNIT(dev);
1112 struct audio_softc *sc = audio_cd.cd_devs[unit];
1113 struct audio_hw_if *hw = sc->hw_if;
1114 int s;
1115
1116 DPRINTF(("audio_close: unit=%d flags=0x%x\n", unit, flags));
1117
1118 s = splaudio();
1119
1120 if ((flags & FREAD) && sc->sc_rbus) {
1121
1122
1123
1124
1125
1126 if (!sc->sc_full_duplex || sc->hw_if->halt_input != sc->hw_if->halt_output)
1127 sc->hw_if->halt_input(sc->hw_hdl);
1128 sc->sc_rbus = 0;
1129 }
1130
1131
1132
1133 sc->sc_pr.usedlow = sc->sc_pr.blksize;
1134
1135
1136
1137
1138 if ((flags & FWRITE) && sc->sc_pbus) {
1139 if (!sc->sc_pr.pause && !audio_drain(sc) && hw->drain)
1140 (void)hw->drain(sc->hw_hdl);
1141 sc->hw_if->halt_output(sc->hw_hdl);
1142 sc->sc_pbus = 0;
1143 }
1144
1145 hw->close(sc->hw_hdl);
1146
1147
1148
1149
1150
1151
1152 if ((flags & FREAD) || ((flags & (FREAD|FWRITE)) == 0)) {
1153 sc->sc_open &= ~AUOPEN_READ;
1154 sc->sc_mode &= ~AUMODE_RECORD;
1155 }
1156 if ((flags & FWRITE) || ((flags & (FREAD|FWRITE)) == 0)) {
1157 sc->sc_open &= ~AUOPEN_WRITE;
1158 sc->sc_mode &= ~(AUMODE_PLAY|AUMODE_PLAY_ALL);
1159 }
1160
1161 sc->sc_async_audio = 0;
1162 sc->sc_full_duplex = 0;
1163 splx(s);
1164 DPRINTF(("audio_close: done\n"));
1165
1166 return (0);
1167 }
1168
1169 int
1170 audio_read(dev_t dev, struct uio *uio, int ioflag)
1171 {
1172 int unit = AUDIOUNIT(dev);
1173 struct audio_softc *sc = audio_cd.cd_devs[unit];
1174 struct audio_ringbuffer *cb = &sc->sc_rr;
1175 u_char *outp;
1176 int error, s, used, cc, n;
1177
1178 if (cb->mmapped)
1179 return EINVAL;
1180
1181 DPRINTFN(1,("audio_read: cc=%d mode=%d\n",
1182 uio->uio_resid, sc->sc_mode));
1183
1184 error = 0;
1185
1186
1187
1188
1189 if (!sc->sc_full_duplex &&
1190 (sc->sc_mode & AUMODE_PLAY)) {
1191 while (uio->uio_resid > 0 && !error) {
1192 s = splaudio();
1193 for(;;) {
1194 cc = sc->sc_pr.stamp - sc->sc_wstamp;
1195 if (cc > 0)
1196 break;
1197 DPRINTF(("audio_read: stamp=%lu, wstamp=%lu\n",
1198 sc->sc_pr.stamp, sc->sc_wstamp));
1199 if (ioflag & IO_NDELAY) {
1200 splx(s);
1201 return EWOULDBLOCK;
1202 }
1203 error = audio_sleep(&sc->sc_rchan, "aud_hr");
1204 if (sc->sc_dying)
1205 error = EIO;
1206 if (error) {
1207 splx(s);
1208 return error;
1209 }
1210 }
1211 splx(s);
1212
1213 if (uio->uio_resid < cc / sc->sc_rparams.factor)
1214 cc = uio->uio_resid * sc->sc_rparams.factor;
1215 DPRINTFN(1, ("audio_read: reading in write mode, cc=%d\n", cc));
1216 error = audio_silence_copyout(sc,
1217 cc / sc->sc_rparams.factor, uio);
1218 sc->sc_wstamp += cc;
1219 }
1220 return (error);
1221 }
1222 while (uio->uio_resid > 0 && !error) {
1223 s = splaudio();
1224 while (cb->used <= 0) {
1225 if (!sc->sc_rbus && !sc->sc_rr.pause) {
1226 error = audiostartr(sc);
1227 if (error) {
1228 splx(s);
1229 return error;
1230 }
1231 }
1232 if (ioflag & IO_NDELAY) {
1233 splx(s);
1234 return (EWOULDBLOCK);
1235 }
1236 DPRINTFN(2, ("audio_read: sleep used=%d\n", cb->used));
1237 error = audio_sleep(&sc->sc_rchan, "aud_rd");
1238 if (sc->sc_dying)
1239 error = EIO;
1240 if (error) {
1241 splx(s);
1242 return error;
1243 }
1244 }
1245 used = cb->used;
1246 outp = cb->outp;
1247 cb->copying = 1;
1248 splx(s);
1249 cc = used - cb->usedlow;
1250 n = cb->end - outp;
1251 if (n < cc)
1252 cc = n;
1253
1254
1255 if (uio->uio_resid < cc / sc->sc_rparams.factor)
1256 cc = uio->uio_resid * sc->sc_rparams.factor;
1257
1258 if (sc->sc_rparams.sw_code)
1259 sc->sc_rparams.sw_code(sc->hw_hdl, outp, cc);
1260 DPRINTFN(1,("audio_read: outp=%p, cc=%d\n", outp, cc));
1261 error = uiomove(outp, cc / sc->sc_rparams.factor, uio);
1262 used -= cc;
1263 outp += cc;
1264 if (outp >= cb->end)
1265 outp = cb->start;
1266 s = splaudio();
1267 cb->outp = outp;
1268 cb->used = used;
1269 cb->copying = 0;
1270 splx(s);
1271 }
1272 return (error);
1273 }
1274
1275 void
1276 audio_clear(struct audio_softc *sc)
1277 {
1278 int s = splaudio();
1279
1280 if (sc->sc_rbus) {
1281 audio_wakeup(&sc->sc_rchan);
1282 sc->hw_if->halt_input(sc->hw_hdl);
1283 sc->sc_rbus = 0;
1284 }
1285 if (sc->sc_pbus) {
1286 audio_wakeup(&sc->sc_wchan);
1287 sc->hw_if->halt_output(sc->hw_hdl);
1288 sc->sc_pbus = 0;
1289 }
1290 splx(s);
1291 }
1292
1293 void
1294 audio_calc_blksize(struct audio_softc *sc, int mode)
1295 {
1296 struct audio_hw_if *hw = sc->hw_if;
1297 struct audio_params *parm;
1298 struct audio_ringbuffer *rb;
1299 int bs;
1300
1301 if (sc->sc_blkset)
1302 return;
1303
1304 if (mode == AUMODE_PLAY) {
1305 parm = &sc->sc_pparams;
1306 rb = &sc->sc_pr;
1307 } else {
1308 parm = &sc->sc_rparams;
1309 rb = &sc->sc_rr;
1310 }
1311
1312 bs = parm->sample_rate * audio_blk_ms / 1000 *
1313 parm->channels * parm->precision / NBBY *
1314 parm->factor;
1315 ROUNDSIZE(bs);
1316 if (hw->round_blocksize)
1317 bs = hw->round_blocksize(sc->hw_hdl, bs);
1318 rb->blksize = bs;
1319
1320 DPRINTF(("audio_calc_blksize: %s blksize=%d\n",
1321 mode == AUMODE_PLAY ? "play" : "record", bs));
1322 }
1323
1324 void
1325 audio_fill_silence(struct audio_params *params, u_char *p, int n)
1326 {
1327 u_char auzero0, auzero1 = 0;
1328 int nfill = 1;
1329
1330 switch (params->encoding) {
1331 case AUDIO_ENCODING_ULAW:
1332 auzero0 = 0x7f;
1333 break;
1334 case AUDIO_ENCODING_ALAW:
1335 auzero0 = 0x55;
1336 break;
1337 case AUDIO_ENCODING_MPEG_L1_STREAM:
1338 case AUDIO_ENCODING_MPEG_L1_PACKETS:
1339 case AUDIO_ENCODING_MPEG_L1_SYSTEM:
1340 case AUDIO_ENCODING_MPEG_L2_STREAM:
1341 case AUDIO_ENCODING_MPEG_L2_PACKETS:
1342 case AUDIO_ENCODING_MPEG_L2_SYSTEM:
1343 case AUDIO_ENCODING_ADPCM:
1344 case AUDIO_ENCODING_SLINEAR_LE:
1345 case AUDIO_ENCODING_SLINEAR_BE:
1346 auzero0 = 0;
1347 break;
1348 case AUDIO_ENCODING_ULINEAR_LE:
1349 case AUDIO_ENCODING_ULINEAR_BE:
1350 if (params->precision == 16) {
1351 nfill = 2;
1352 if (params->encoding == AUDIO_ENCODING_ULINEAR_LE) {
1353 auzero0 = 0;
1354 auzero1 = 0x80;
1355 } else {
1356 auzero0 = 0x80;
1357 auzero1 = 0;
1358 }
1359 } else
1360 auzero0 = 0x80;
1361 break;
1362 default:
1363 DPRINTF(("audio: bad encoding %d\n", params->encoding));
1364 auzero0 = 0;
1365 break;
1366 }
1367 if (nfill == 1) {
1368 while (--n >= 0)
1369 *p++ = auzero0;
1370 } else {
1371 while (n > 1) {
1372 *p++ = auzero0;
1373 *p++ = auzero1;
1374 n -= 2;
1375 }
1376 }
1377 }
1378
1379 int
1380 audio_silence_copyout(struct audio_softc *sc, int n, struct uio *uio)
1381 {
1382 int error;
1383 int k;
1384 u_char zerobuf[128];
1385
1386 audio_fill_silence(&sc->sc_rparams, zerobuf, sizeof zerobuf);
1387
1388 error = 0;
1389 while (n > 0 && uio->uio_resid > 0 && !error) {
1390 k = min(n, min(uio->uio_resid, sizeof zerobuf));
1391 error = uiomove(zerobuf, k, uio);
1392 n -= k;
1393 }
1394 return (error);
1395 }
1396
1397 int
1398 audio_write(dev_t dev, struct uio *uio, int ioflag)
1399 {
1400 int unit = AUDIOUNIT(dev);
1401 struct audio_softc *sc = audio_cd.cd_devs[unit];
1402 struct audio_ringbuffer *cb = &sc->sc_pr;
1403 u_char *inp, *einp;
1404 int saveerror, error, s, n, cc, used;
1405
1406 DPRINTFN(2, ("audio_write: sc=%p(unit=%d) count=%d used=%d(hi=%d)\n", sc, unit,
1407 uio->uio_resid, sc->sc_pr.used, sc->sc_pr.usedhigh));
1408
1409 if (cb->mmapped)
1410 return EINVAL;
1411
1412 if (uio->uio_resid == 0) {
1413 sc->sc_eof++;
1414 return 0;
1415 }
1416
1417
1418
1419
1420 if (!sc->sc_full_duplex &&
1421 (sc->sc_mode & AUMODE_RECORD)) {
1422 uio->uio_offset += uio->uio_resid;
1423 uio->uio_resid = 0;
1424 DPRINTF(("audio_write: half-dpx read busy\n"));
1425 return (0);
1426 }
1427
1428 if (!(sc->sc_mode & AUMODE_PLAY_ALL) && sc->sc_playdrop > 0) {
1429 n = min(sc->sc_playdrop, uio->uio_resid * sc->sc_pparams.factor);
1430 DPRINTF(("audio_write: playdrop %d\n", n));
1431 uio->uio_offset += n / sc->sc_pparams.factor;
1432 uio->uio_resid -= n / sc->sc_pparams.factor;
1433 sc->sc_playdrop -= n;
1434 if (uio->uio_resid == 0)
1435 return 0;
1436 }
1437
1438 DPRINTFN(1, ("audio_write: sr=%ld, enc=%d, prec=%d, chan=%d, sw=%p, fact=%d\n",
1439 sc->sc_pparams.sample_rate, sc->sc_pparams.encoding,
1440 sc->sc_pparams.precision, sc->sc_pparams.channels,
1441 sc->sc_pparams.sw_code, sc->sc_pparams.factor));
1442
1443 error = 0;
1444 while (uio->uio_resid > 0 && !error) {
1445 s = splaudio();
1446 while (cb->used >= cb->usedhigh) {
1447 DPRINTFN(2, ("audio_write: sleep used=%d lowat=%d hiwat=%d\n",
1448 cb->used, cb->usedlow, cb->usedhigh));
1449 if (ioflag & IO_NDELAY) {
1450 splx(s);
1451 return (EWOULDBLOCK);
1452 }
1453 error = audio_sleep(&sc->sc_wchan, "aud_wr");
1454 if (sc->sc_dying)
1455 error = EIO;
1456 if (error) {
1457 splx(s);
1458 return error;
1459 }
1460 }
1461 used = cb->used;
1462 inp = cb->inp;
1463 cb->copying = 1;
1464 splx(s);
1465 cc = cb->usedhigh - used;
1466 n = cb->end - inp;
1467 if (sc->sc_pparams.factor != 1) {
1468
1469 n /= sc->sc_pparams.factor;
1470 cc /= sc->sc_pparams.factor;
1471 }
1472 if (n < cc)
1473 cc = n;
1474 if (uio->uio_resid < cc)
1475 cc = uio->uio_resid;
1476
1477 #ifdef DIAGNOSTIC
1478
1479
1480
1481
1482 if (cc == 0) {
1483 printf("audio_write: cc == 0, swcode=%p, factor=%d\n",
1484 sc->sc_pparams.sw_code, sc->sc_pparams.factor);
1485 cb->copying = 0;
1486 return EINVAL;
1487 }
1488 #endif
1489 DPRINTFN(1, ("audio_write: uiomove cc=%d inp=%p, left=%d\n",
1490 cc, inp, uio->uio_resid));
1491 n = uio->uio_resid;
1492 error = uiomove(inp, cc, uio);
1493 cc = n - uio->uio_resid;
1494 #ifdef AUDIO_DEBUG
1495 if (error)
1496 printf("audio_write:(1) uiomove failed %d; cc=%d inp=%p\n",
1497 error, cc, inp);
1498 #endif
1499
1500
1501
1502
1503
1504 if (sc->sc_pparams.sw_code) {
1505 sc->sc_pparams.sw_code(sc->hw_hdl, inp, cc);
1506
1507 cc *= sc->sc_pparams.factor;
1508 DPRINTFN(1, ("audio_write: expanded cc=%d\n", cc));
1509 }
1510
1511 einp = cb->inp + cc;
1512 if (einp >= cb->end)
1513 einp = cb->start;
1514
1515 s = splaudio();
1516
1517
1518
1519
1520 sc->sc_sil_count = 0;
1521
1522 cb->inp = einp;
1523 cb->used += cc;
1524
1525
1526
1527
1528 if (cb->needfill &&
1529 (inp - cb->start) / cb->blksize ==
1530 (einp - cb->start) / cb->blksize) {
1531
1532 cc = cb->blksize - (einp - cb->start) % cb->blksize;
1533 DPRINTF(("audio_write: partial fill %d\n", cc));
1534 } else
1535 cc = 0;
1536 cb->needfill = 0;
1537 cb->copying = 0;
1538 if (!sc->sc_pbus && !cb->pause) {
1539 saveerror = error;
1540 error = audiostartp(sc);
1541 if (saveerror != 0) {
1542
1543 error = saveerror;
1544 }
1545 }
1546 splx(s);
1547 if (cc) {
1548 DPRINTFN(1, ("audio_write: fill %d\n", cc));
1549 if (sc->sc_pparams.sw_code) {
1550 int ncc = cc / sc->sc_pparams.factor;
1551 audio_fill_silence(&sc->sc_pparams, einp, ncc);
1552 sc->sc_pparams.sw_code(sc->hw_hdl, einp, ncc);
1553 } else
1554 audio_fill_silence(&sc->sc_pparams, einp, cc);
1555 }
1556 }
1557 return (error);
1558 }
1559
1560 int
1561 audio_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
1562 {
1563 int unit = AUDIOUNIT(dev);
1564 struct audio_softc *sc = audio_cd.cd_devs[unit];
1565 struct audio_hw_if *hw = sc->hw_if;
1566 struct audio_offset *ao;
1567 int error = 0, s, offs, fd;
1568 int rbus, pbus;
1569
1570 DPRINTF(("audio_ioctl(%d,'%c',%d)\n",
1571 IOCPARM_LEN(cmd), IOCGROUP(cmd), cmd&0xff));
1572 switch (cmd) {
1573 case FIONBIO:
1574
1575 break;
1576
1577 case FIOASYNC:
1578 if (*(int *)addr) {
1579 if (sc->sc_async_audio)
1580 return (EBUSY);
1581 sc->sc_async_audio = p;
1582 DPRINTF(("audio_ioctl: FIOASYNC %p\n", p));
1583 } else
1584 sc->sc_async_audio = 0;
1585 break;
1586
1587 case AUDIO_FLUSH:
1588 DPRINTF(("AUDIO_FLUSH\n"));
1589 rbus = sc->sc_rbus;
1590 pbus = sc->sc_pbus;
1591 audio_clear(sc);
1592 s = splaudio();
1593 error = audio_initbufs(sc);
1594 if (error) {
1595 splx(s);
1596 return error;
1597 }
1598 sc->sc_rr.pause = 0;
1599 sc->sc_pr.pause = 0;
1600 if ((sc->sc_mode & AUMODE_PLAY) && !sc->sc_pbus && pbus)
1601 error = audiostartp(sc);
1602 if (!error &&
1603 (sc->sc_mode & AUMODE_RECORD) && !sc->sc_rbus && rbus)
1604 error = audiostartr(sc);
1605 splx(s);
1606 break;
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623 case AUDIO_RERROR:
1624 *(int *)addr = (sc->sc_rr.drops * NBBY) /
1625 (sc->sc_rparams.factor * sc->sc_rparams.channels *
1626 sc->sc_rparams.precision);
1627 break;
1628
1629 case AUDIO_PERROR:
1630 *(int *)addr = (sc->sc_pr.drops * NBBY) /
1631 (sc->sc_pparams.factor * sc->sc_pparams.channels *
1632 sc->sc_pparams.precision);
1633 break;
1634
1635
1636
1637
1638 case AUDIO_GETIOFFS:
1639 s = splaudio();
1640
1641 ao = (struct audio_offset *)addr;
1642 ao->samples = sc->sc_rr.stamp;
1643 ao->deltablks = (sc->sc_rr.stamp - sc->sc_rr.stamp_last) / sc->sc_rr.blksize;
1644 sc->sc_rr.stamp_last = sc->sc_rr.stamp;
1645 ao->offset = sc->sc_rr.inp - sc->sc_rr.start;
1646 splx(s);
1647 break;
1648
1649 case AUDIO_GETOOFFS:
1650 s = splaudio();
1651
1652 ao = (struct audio_offset *)addr;
1653 offs = sc->sc_pr.outp - sc->sc_pr.start + sc->sc_pr.blksize;
1654 if (sc->sc_pr.start + offs >= sc->sc_pr.end)
1655 offs = 0;
1656 ao->samples = sc->sc_pr.stamp;
1657 ao->deltablks = (sc->sc_pr.stamp - sc->sc_pr.stamp_last) / sc->sc_pr.blksize;
1658 sc->sc_pr.stamp_last = sc->sc_pr.stamp;
1659 ao->offset = offs;
1660 splx(s);
1661 break;
1662
1663
1664
1665
1666
1667 case AUDIO_WSEEK:
1668 *(u_long *)addr = sc->sc_pr.used / sc->sc_pparams.factor;
1669 break;
1670
1671 case AUDIO_SETINFO:
1672 DPRINTF(("AUDIO_SETINFO mode=0x%x\n", sc->sc_mode));
1673 error = audiosetinfo(sc, (struct audio_info *)addr);
1674 break;
1675
1676 case AUDIO_GETINFO:
1677 DPRINTF(("AUDIO_GETINFO\n"));
1678 error = audiogetinfo(sc, (struct audio_info *)addr);
1679 break;
1680
1681 case AUDIO_DRAIN:
1682 DPRINTF(("AUDIO_DRAIN\n"));
1683 error = audio_drain(sc);
1684 if (!error && hw->drain)
1685 error = hw->drain(sc->hw_hdl);
1686 break;
1687
1688 case AUDIO_GETDEV:
1689 DPRINTF(("AUDIO_GETDEV\n"));
1690 error = hw->getdev(sc->hw_hdl, (audio_device_t *)addr);
1691 break;
1692
1693 case AUDIO_GETENC:
1694 DPRINTF(("AUDIO_GETENC\n"));
1695
1696 ((struct audio_encoding *)addr)->flags = sc->sc_open;
1697 error = hw->query_encoding(sc->hw_hdl, (struct audio_encoding *)addr);
1698 break;
1699
1700 case AUDIO_GETFD:
1701 DPRINTF(("AUDIO_GETFD\n"));
1702 *(int *)addr = sc->sc_full_duplex;
1703 break;
1704
1705 case AUDIO_SETFD:
1706 DPRINTF(("AUDIO_SETFD\n"));
1707 fd = *(int *)addr;
1708 if (hw->get_props(sc->hw_hdl) & AUDIO_PROP_FULLDUPLEX) {
1709 if (hw->setfd)
1710 error = hw->setfd(sc->hw_hdl, fd);
1711 else
1712 error = 0;
1713 if (!error)
1714 sc->sc_full_duplex = fd;
1715 } else {
1716 if (fd)
1717 error = ENOTTY;
1718 else
1719 error = 0;
1720 }
1721 break;
1722
1723 case AUDIO_GETPROPS:
1724 DPRINTF(("AUDIO_GETPROPS\n"));
1725 *(int *)addr = hw->get_props(sc->hw_hdl);
1726 break;
1727
1728 default:
1729 DPRINTF(("audio_ioctl: unknown ioctl\n"));
1730 error = ENOTTY;
1731 break;
1732 }
1733 DPRINTF(("audio_ioctl(%d,'%c',%d) result %d\n",
1734 IOCPARM_LEN(cmd), IOCGROUP(cmd), cmd&0xff, error));
1735 return (error);
1736 }
1737
1738 void
1739 audio_selwakeup(struct audio_softc *sc, int play)
1740 {
1741 struct selinfo *si;
1742
1743 si = play? &sc->sc_wsel : &sc->sc_rsel;
1744
1745 audio_wakeup(play? &sc->sc_wchan : &sc->sc_rchan);
1746 selwakeup(si);
1747 if (sc->sc_async_audio)
1748 psignal(sc->sc_async_audio, SIGIO);
1749 KNOTE(&si->si_note, 0);
1750 }
1751
1752 #define AUDIO_FILTREAD(sc) ( \
1753 (!sc->sc_full_duplex && (sc->sc_mode & AUMODE_PLAY)) ? \
1754 sc->sc_pr.stamp > sc->sc_wstamp : sc->sc_rr.used > sc->sc_rr.usedlow)
1755
1756 #define AUDIO_FILTWRITE(sc) ( \
1757 (!sc->sc_full_duplex && (sc->sc_mode & AUMODE_RECORD)) || \
1758 (!(sc->sc_mode & AUMODE_PLAY_ALL) && sc->sc_playdrop > 0) || \
1759 (sc->sc_pr.used <= sc->sc_pr.usedlow))
1760
1761 int
1762 audio_poll(dev_t dev, int events, struct proc *p)
1763 {
1764 int unit = AUDIOUNIT(dev);
1765 struct audio_softc *sc = audio_cd.cd_devs[unit];
1766 int revents = 0, s = splaudio();
1767
1768 DPRINTF(("audio_poll: events=0x%x mode=%d\n", events, sc->sc_mode));
1769
1770 if (events & (POLLIN | POLLRDNORM)) {
1771 if (AUDIO_FILTREAD(sc))
1772 revents |= events & (POLLIN | POLLRDNORM);
1773 }
1774 if (events & (POLLOUT | POLLWRNORM)) {
1775 if (AUDIO_FILTWRITE(sc))
1776 revents |= events & (POLLOUT | POLLWRNORM);
1777 }
1778 if (revents == 0) {
1779 if (events & (POLLIN | POLLRDNORM))
1780 selrecord(p, &sc->sc_rsel);
1781 if (events & (POLLOUT | POLLWRNORM))
1782 selrecord(p, &sc->sc_wsel);
1783 }
1784 splx(s);
1785 return (revents);
1786 }
1787
1788 paddr_t
1789 audio_mmap(dev_t dev, off_t off, int prot)
1790 {
1791 int s;
1792 int unit = AUDIOUNIT(dev);
1793 struct audio_softc *sc = audio_cd.cd_devs[unit];
1794 struct audio_hw_if *hw = sc->hw_if;
1795 struct audio_ringbuffer *cb;
1796
1797 DPRINTF(("audio_mmap: off=%d, prot=%d\n", off, prot));
1798
1799 if (!(hw->get_props(sc->hw_hdl) & AUDIO_PROP_MMAP) || !hw->mappage)
1800 return -1;
1801 #if 0
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814 if (prot == (VM_PROT_READ|VM_PROT_WRITE) ||
1815 prot == VM_PROT_WRITE)
1816 cb = &sc->sc_pr;
1817 else if (prot == VM_PROT_READ)
1818 cb = &sc->sc_rr;
1819 else
1820 return -1;
1821 #else
1822 cb = &sc->sc_pr;
1823 #endif
1824
1825 if ((u_int)off >= cb->bufsize)
1826 return -1;
1827 if (!cb->mmapped) {
1828 cb->mmapped = 1;
1829 if (cb == &sc->sc_pr) {
1830 audio_fill_silence(&sc->sc_pparams, cb->start, cb->bufsize);
1831 s = splaudio();
1832 if (!sc->sc_pbus && !sc->sc_pr.pause)
1833 (void)audiostartp(sc);
1834 splx(s);
1835 } else {
1836 s = splaudio();
1837 if (!sc->sc_rbus && !sc->sc_rr.pause)
1838 (void)audiostartr(sc);
1839 splx(s);
1840 }
1841 }
1842
1843 return hw->mappage(sc->hw_hdl, cb->start, off, prot);
1844 }
1845
1846 int
1847 audiostartr(struct audio_softc *sc)
1848 {
1849 int error;
1850
1851 DPRINTF(("audiostartr: start=%p used=%d(hi=%d) mmapped=%d\n",
1852 sc->sc_rr.start, sc->sc_rr.used, sc->sc_rr.usedhigh,
1853 sc->sc_rr.mmapped));
1854
1855 if (sc->hw_if->trigger_input)
1856 error = sc->hw_if->trigger_input(sc->hw_hdl, sc->sc_rr.start,
1857 sc->sc_rr.end, sc->sc_rr.blksize,
1858 audio_rint, (void *)sc, &sc->sc_rparams);
1859 else
1860 error = sc->hw_if->start_input(sc->hw_hdl, sc->sc_rr.start,
1861 sc->sc_rr.blksize, audio_rint, (void *)sc);
1862 if (error) {
1863 DPRINTF(("audiostartr failed: %d\n", error));
1864 return error;
1865 }
1866 sc->sc_rbus = 1;
1867 return 0;
1868 }
1869
1870 int
1871 audiostartp(struct audio_softc *sc)
1872 {
1873 int error;
1874
1875 DPRINTF(("audiostartp: start=%p used=%d(hi=%d) mmapped=%d\n",
1876 sc->sc_pr.start, sc->sc_pr.used, sc->sc_pr.usedhigh,
1877 sc->sc_pr.mmapped));
1878
1879 if (!sc->sc_pr.mmapped && sc->sc_pr.used < sc->sc_pr.blksize)
1880 return 0;
1881
1882 if (sc->hw_if->trigger_output)
1883 error = sc->hw_if->trigger_output(sc->hw_hdl, sc->sc_pr.start,
1884 sc->sc_pr.end, sc->sc_pr.blksize,
1885 audio_pint, (void *)sc, &sc->sc_pparams);
1886 else
1887 error = sc->hw_if->start_output(sc->hw_hdl, sc->sc_pr.outp,
1888 sc->sc_pr.blksize, audio_pint, (void *)sc);
1889 if (error) {
1890 DPRINTF(("audiostartp failed: %d\n", error));
1891 return error;
1892 }
1893 sc->sc_pbus = 1;
1894 return 0;
1895 }
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911 static __inline void
1912 audio_pint_silence(struct audio_softc *sc, struct audio_ringbuffer *cb,
1913 u_char *inp, int cc)
1914 {
1915 u_char *s, *e, *p, *q;
1916
1917 if (sc->sc_sil_count > 0) {
1918 s = sc->sc_sil_start;
1919 e = s + sc->sc_sil_count;
1920 p = inp;
1921 if (p < s)
1922 p += cb->end - cb->start;
1923 q = p+cc;
1924
1925 if (!(s <= p && p < e &&
1926 s <= q && q <= e)) {
1927 if (s <= p)
1928 sc->sc_sil_count = max(sc->sc_sil_count, q-s);
1929 DPRINTFN(5, ("audio_pint_silence: fill cc=%d inp=%p, count=%d size=%d\n",
1930 cc, inp, sc->sc_sil_count, (int)(cb->end - cb->start)));
1931
1932 if (sc->sc_pparams.sw_code) {
1933 int ncc = cc / sc->sc_pparams.factor;
1934 audio_fill_silence(&sc->sc_pparams, inp, ncc);
1935 sc->sc_pparams.sw_code(sc->hw_hdl, inp, ncc);
1936 } else
1937 audio_fill_silence(&sc->sc_pparams, inp, cc);
1938
1939 } else {
1940 DPRINTFN(5, ("audio_pint_silence: already silent cc=%d inp=%p\n", cc, inp));
1941
1942 }
1943 } else {
1944 sc->sc_sil_start = inp;
1945 sc->sc_sil_count = cc;
1946 DPRINTFN(5, ("audio_pint_silence: start fill %p %d\n",
1947 inp, cc));
1948
1949 if (sc->sc_pparams.sw_code) {
1950 int ncc = cc / sc->sc_pparams.factor;
1951 audio_fill_silence(&sc->sc_pparams, inp, ncc);
1952 sc->sc_pparams.sw_code(sc->hw_hdl, inp, ncc);
1953 } else
1954 audio_fill_silence(&sc->sc_pparams, inp, cc);
1955
1956 }
1957 }
1958
1959
1960
1961
1962
1963
1964
1965 void
1966 audio_pint(void *v)
1967 {
1968 struct audio_softc *sc = v;
1969 struct audio_hw_if *hw = sc->hw_if;
1970 struct audio_ringbuffer *cb = &sc->sc_pr;
1971 u_char *inp;
1972 int cc;
1973 int blksize;
1974 int error;
1975
1976 if (!sc->sc_open)
1977 return;
1978
1979 blksize = cb->blksize;
1980
1981 add_audio_randomness((long)cb);
1982
1983 cb->outp += blksize;
1984 if (cb->outp >= cb->end)
1985 cb->outp = cb->start;
1986 cb->stamp += blksize;
1987 if (cb->mmapped) {
1988 DPRINTFN(5, ("audio_pint: mmapped outp=%p cc=%d inp=%p\n",
1989 cb->outp, blksize, cb->inp));
1990 if (!hw->trigger_output)
1991 (void)hw->start_output(sc->hw_hdl, cb->outp,
1992 blksize, audio_pint, (void *)sc);
1993 return;
1994 }
1995
1996 #ifdef AUDIO_INTR_TIME
1997 {
1998 struct timeval tv;
1999 u_long t;
2000 microtime(&tv);
2001 t = tv.tv_usec + 1000000 * tv.tv_sec;
2002 if (sc->sc_pnintr) {
2003 long lastdelta, totdelta;
2004 lastdelta = t - sc->sc_plastintr - sc->sc_pblktime;
2005 if (lastdelta > sc->sc_pblktime / 3) {
2006 printf("audio: play interrupt(%d) off relative by %ld us (%lu)\n",
2007 sc->sc_pnintr, lastdelta, sc->sc_pblktime);
2008 }
2009 totdelta = t - sc->sc_pfirstintr - sc->sc_pblktime * sc->sc_pnintr;
2010 if (totdelta > sc->sc_pblktime) {
2011 printf("audio: play interrupt(%d) off absolute by %ld us (%lu) (LOST)\n",
2012 sc->sc_pnintr, totdelta, sc->sc_pblktime);
2013 sc->sc_pnintr++;
2014 }
2015 } else
2016 sc->sc_pfirstintr = t;
2017 sc->sc_plastintr = t;
2018 sc->sc_pnintr++;
2019 }
2020 #endif
2021
2022 cb->used -= blksize;
2023 if (cb->used < blksize) {
2024
2025 if (cb->copying) {
2026
2027 cb->needfill = 1;
2028 DPRINTFN(1, ("audio_pint: copying in progress\n"));
2029 } else {
2030 inp = cb->inp;
2031 cc = blksize - (inp - cb->start) % blksize;
2032 if (cb->pause)
2033 cb->pdrops += cc;
2034 else {
2035 cb->drops += cc;
2036 sc->sc_playdrop += cc;
2037 }
2038 audio_pint_silence(sc, cb, inp, cc);
2039 inp += cc;
2040 if (inp >= cb->end)
2041 inp = cb->start;
2042 cb->inp = inp;
2043 cb->used += cc;
2044
2045
2046 if (cb->used + cc < cb->usedhigh)
2047 audio_pint_silence(sc, cb, inp, blksize);
2048 }
2049 }
2050
2051 DPRINTFN(5, ("audio_pint: outp=%p cc=%d\n", cb->outp, blksize));
2052 if (!hw->trigger_output) {
2053 error = hw->start_output(sc->hw_hdl, cb->outp, blksize,
2054 audio_pint, (void *)sc);
2055 if (error) {
2056
2057 DPRINTF(("audio_pint restart failed: %d\n", error));
2058 audio_clear(sc);
2059 }
2060 }
2061
2062 DPRINTFN(2, ("audio_pint: mode=%d pause=%d used=%d lowat=%d\n",
2063 sc->sc_mode, cb->pause, cb->used, cb->usedlow));
2064 if ((sc->sc_mode & AUMODE_PLAY) && !cb->pause &&
2065 cb->used <= cb->usedlow)
2066 audio_selwakeup(sc, 1);
2067
2068
2069 if (!sc->sc_full_duplex && sc->sc_rchan)
2070 audio_selwakeup(sc, 0);
2071 }
2072
2073
2074
2075
2076
2077
2078 void
2079 audio_rint(void *v)
2080 {
2081 struct audio_softc *sc = v;
2082 struct audio_hw_if *hw = sc->hw_if;
2083 struct audio_ringbuffer *cb = &sc->sc_rr;
2084 int blksize;
2085 int error;
2086
2087 if (!sc->sc_open)
2088 return;
2089
2090 add_audio_randomness((long)cb);
2091
2092 blksize = cb->blksize;
2093
2094 cb->inp += blksize;
2095 if (cb->inp >= cb->end)
2096 cb->inp = cb->start;
2097 cb->stamp += blksize;
2098 if (cb->mmapped) {
2099 DPRINTFN(2, ("audio_rint: mmapped inp=%p cc=%d\n",
2100 cb->inp, blksize));
2101 if (!hw->trigger_input)
2102 (void)hw->start_input(sc->hw_hdl, cb->inp, blksize,
2103 audio_rint, (void *)sc);
2104 return;
2105 }
2106
2107 #ifdef AUDIO_INTR_TIME
2108 {
2109 struct timeval tv;
2110 u_long t;
2111 microtime(&tv);
2112 t = tv.tv_usec + 1000000 * tv.tv_sec;
2113 if (sc->sc_rnintr) {
2114 long lastdelta, totdelta;
2115 lastdelta = t - sc->sc_rlastintr - sc->sc_rblktime;
2116 if (lastdelta > sc->sc_rblktime / 5) {
2117 printf("audio: record interrupt(%d) off relative by %ld us (%lu)\n",
2118 sc->sc_rnintr, lastdelta, sc->sc_rblktime);
2119 }
2120 totdelta = t - sc->sc_rfirstintr - sc->sc_rblktime * sc->sc_rnintr;
2121 if (totdelta > sc->sc_rblktime / 2) {
2122 sc->sc_rnintr++;
2123 printf("audio: record interrupt(%d) off absolute by %ld us (%lu)\n",
2124 sc->sc_rnintr, totdelta, sc->sc_rblktime);
2125 sc->sc_rnintr++;
2126 }
2127 } else
2128 sc->sc_rfirstintr = t;
2129 sc->sc_rlastintr = t;
2130 sc->sc_rnintr++;
2131 }
2132 #endif
2133
2134 cb->used += blksize;
2135 if (cb->pause) {
2136 DPRINTFN(1, ("audio_rint: pdrops %lu\n", cb->pdrops));
2137 cb->pdrops += blksize;
2138 cb->outp += blksize;
2139 cb->used -= blksize;
2140 } else if (cb->used + blksize >= cb->usedhigh && !cb->copying) {
2141 DPRINTFN(1, ("audio_rint: drops %lu\n", cb->drops));
2142 cb->drops += blksize;
2143 cb->outp += blksize;
2144 cb->used -= blksize;
2145 }
2146
2147 DPRINTFN(2, ("audio_rint: inp=%p cc=%d used=%d\n",
2148 cb->inp, blksize, cb->used));
2149 if (!hw->trigger_input) {
2150 error = hw->start_input(sc->hw_hdl, cb->inp, blksize,
2151 audio_rint, (void *)sc);
2152 if (error) {
2153
2154 DPRINTF(("audio_rint: restart failed: %d\n", error));
2155 audio_clear(sc);
2156 }
2157 }
2158
2159 audio_selwakeup(sc, 0);
2160 }
2161
2162 int
2163 audio_check_params(struct audio_params *p)
2164 {
2165 if (p->encoding == AUDIO_ENCODING_PCM16) {
2166 if (p->precision == 8)
2167 p->encoding = AUDIO_ENCODING_ULINEAR;
2168 else
2169 p->encoding = AUDIO_ENCODING_SLINEAR;
2170 } else if (p->encoding == AUDIO_ENCODING_PCM8) {
2171 if (p->precision == 8)
2172 p->encoding = AUDIO_ENCODING_ULINEAR;
2173 else
2174 return EINVAL;
2175 }
2176
2177 if (p->encoding == AUDIO_ENCODING_SLINEAR)
2178 #if BYTE_ORDER == LITTLE_ENDIAN
2179 p->encoding = AUDIO_ENCODING_SLINEAR_LE;
2180 #else
2181 p->encoding = AUDIO_ENCODING_SLINEAR_BE;
2182 #endif
2183 if (p->encoding == AUDIO_ENCODING_ULINEAR)
2184 #if BYTE_ORDER == LITTLE_ENDIAN
2185 p->encoding = AUDIO_ENCODING_ULINEAR_LE;
2186 #else
2187 p->encoding = AUDIO_ENCODING_ULINEAR_BE;
2188 #endif
2189
2190 switch (p->encoding) {
2191 case AUDIO_ENCODING_ULAW:
2192 case AUDIO_ENCODING_ALAW:
2193 case AUDIO_ENCODING_ADPCM:
2194 if (p->precision != 8)
2195 return (EINVAL);
2196 break;
2197 case AUDIO_ENCODING_SLINEAR_LE:
2198 case AUDIO_ENCODING_SLINEAR_BE:
2199 case AUDIO_ENCODING_ULINEAR_LE:
2200 case AUDIO_ENCODING_ULINEAR_BE:
2201 if (p->precision != 8 && p->precision != 16)
2202 return (EINVAL);
2203 break;
2204 case AUDIO_ENCODING_MPEG_L1_STREAM:
2205 case AUDIO_ENCODING_MPEG_L1_PACKETS:
2206 case AUDIO_ENCODING_MPEG_L1_SYSTEM:
2207 case AUDIO_ENCODING_MPEG_L2_STREAM:
2208 case AUDIO_ENCODING_MPEG_L2_PACKETS:
2209 case AUDIO_ENCODING_MPEG_L2_SYSTEM:
2210 break;
2211 default:
2212 return (EINVAL);
2213 }
2214
2215 if (p->channels < 1 || p->channels > 8)
2216 return (EINVAL);
2217
2218 return (0);
2219 }
2220
2221 int
2222 au_set_lr_value(struct audio_softc *sc, mixer_ctrl_t *ct, int l, int r)
2223 {
2224 ct->type = AUDIO_MIXER_VALUE;
2225 ct->un.value.num_channels = 2;
2226 ct->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
2227 ct->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
2228 if (sc->hw_if->set_port(sc->hw_hdl, ct) == 0)
2229 return 0;
2230 ct->un.value.num_channels = 1;
2231 ct->un.value.level[AUDIO_MIXER_LEVEL_MONO] = (l+r)/2;
2232 return sc->hw_if->set_port(sc->hw_hdl, ct);
2233 }
2234
2235 int
2236 au_set_gain(struct audio_softc *sc, struct au_mixer_ports *ports, int gain,
2237 int balance)
2238 {
2239 mixer_ctrl_t ct;
2240 int i, error;
2241 int l, r;
2242 u_int mask;
2243 int nset;
2244
2245 if (balance == AUDIO_MID_BALANCE) {
2246 l = r = gain;
2247 } else if (balance < AUDIO_MID_BALANCE) {
2248 r = gain;
2249 l = (balance * gain) / AUDIO_MID_BALANCE;
2250 } else {
2251 l = gain;
2252 r = ((AUDIO_RIGHT_BALANCE - balance) * gain)
2253 / AUDIO_MID_BALANCE;
2254 }
2255 DPRINTF(("au_set_gain: gain=%d balance=%d, l=%d r=%d\n",
2256 gain, balance, l, r));
2257
2258 if (ports->index == -1) {
2259 usemaster:
2260 if (ports->master == -1)
2261 return 0;
2262 ct.dev = ports->master;
2263 error = au_set_lr_value(sc, &ct, l, r);
2264 } else {
2265 ct.dev = ports->index;
2266 if (ports->isenum) {
2267 ct.type = AUDIO_MIXER_ENUM;
2268 error = sc->hw_if->get_port(sc->hw_hdl, &ct);
2269 if (error)
2270 return error;
2271 for(i = 0; i < ports->nports; i++) {
2272 if (ports->misel[i] == ct.un.ord) {
2273 ct.dev = ports->miport[i];
2274 if (ct.dev == -1 ||
2275 au_set_lr_value(sc, &ct, l, r))
2276 goto usemaster;
2277 else
2278 break;
2279 }
2280 }
2281 } else {
2282 ct.type = AUDIO_MIXER_SET;
2283 error = sc->hw_if->get_port(sc->hw_hdl, &ct);
2284 if (error)
2285 return error;
2286 mask = ct.un.mask;
2287 nset = 0;
2288 for(i = 0; i < ports->nports; i++) {
2289 if (ports->misel[i] & mask) {
2290 ct.dev = ports->miport[i];
2291 if (ct.dev != -1 &&
2292 au_set_lr_value(sc, &ct, l, r) == 0)
2293 nset++;
2294 }
2295 }
2296 if (nset == 0)
2297 goto usemaster;
2298 }
2299 }
2300 if (!error)
2301 mixer_signal(sc);
2302 return error;
2303 }
2304
2305 int
2306 au_get_lr_value(struct audio_softc *sc, mixer_ctrl_t *ct, int *l, int *r)
2307 {
2308 int error;
2309
2310 ct->un.value.num_channels = 2;
2311 if (sc->hw_if->get_port(sc->hw_hdl, ct) == 0) {
2312 *l = ct->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
2313 *r = ct->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
2314 } else {
2315 ct->un.value.num_channels = 1;
2316 error = sc->hw_if->get_port(sc->hw_hdl, ct);
2317 if (error)
2318 return error;
2319 *r = *l = ct->un.value.level[AUDIO_MIXER_LEVEL_MONO];
2320 }
2321 return 0;
2322 }
2323
2324 void
2325 au_get_gain(struct audio_softc *sc, struct au_mixer_ports *ports, u_int *pgain,
2326 u_char *pbalance)
2327 {
2328 mixer_ctrl_t ct;
2329 int i, l, r, n;
2330 int lgain = AUDIO_MAX_GAIN/2, rgain = AUDIO_MAX_GAIN/2;
2331
2332 if (ports->index == -1) {
2333 usemaster:
2334 if (ports->master == -1)
2335 goto bad;
2336 ct.dev = ports->master;
2337 ct.type = AUDIO_MIXER_VALUE;
2338 if (au_get_lr_value(sc, &ct, &lgain, &rgain))
2339 goto bad;
2340 } else {
2341 ct.dev = ports->index;
2342 if (ports->isenum) {
2343 ct.type = AUDIO_MIXER_ENUM;
2344 if (sc->hw_if->get_port(sc->hw_hdl, &ct))
2345 goto bad;
2346 ct.type = AUDIO_MIXER_VALUE;
2347 for(i = 0; i < ports->nports; i++) {
2348 if (ports->misel[i] == ct.un.ord) {
2349 ct.dev = ports->miport[i];
2350 if (ct.dev == -1 ||
2351 au_get_lr_value(sc, &ct,
2352 &lgain, &rgain))
2353 goto usemaster;
2354 else
2355 break;
2356 }
2357 }
2358 } else {
2359 ct.type = AUDIO_MIXER_SET;
2360 if (sc->hw_if->get_port(sc->hw_hdl, &ct))
2361 goto bad;
2362 ct.type = AUDIO_MIXER_VALUE;
2363 lgain = rgain = n = 0;
2364 for(i = 0; i < ports->nports; i++) {
2365 if (ports->misel[i] & ct.un.mask) {
2366 ct.dev = ports->miport[i];
2367 if (ct.dev == -1 ||
2368 au_get_lr_value(sc, &ct, &l, &r))
2369 goto usemaster;
2370 else {
2371 lgain += l;
2372 rgain += r;
2373 n++;
2374 }
2375 }
2376 }
2377 if (n != 0) {
2378 lgain /= n;
2379 rgain /= n;
2380 }
2381 }
2382 }
2383 bad:
2384 if (lgain == rgain) {
2385 *pgain = lgain;
2386 *pbalance = AUDIO_MID_BALANCE;
2387 } else if (lgain < rgain) {
2388 *pgain = rgain;
2389 *pbalance = (AUDIO_MID_BALANCE * lgain) / rgain;
2390 } else {
2391 *pgain = lgain;
2392 *pbalance = AUDIO_RIGHT_BALANCE -
2393 (AUDIO_MID_BALANCE * rgain) / lgain;
2394 }
2395 }
2396
2397 int
2398 au_set_port(struct audio_softc *sc, struct au_mixer_ports *ports, u_int port)
2399 {
2400 mixer_ctrl_t ct;
2401 int i, error;
2402
2403 if (port == 0)
2404 return 0;
2405
2406 if (ports->index == -1)
2407 return EINVAL;
2408 ct.dev = ports->index;
2409 if (ports->isenum) {
2410 if (port & (port-1))
2411 return EINVAL;
2412 ct.type = AUDIO_MIXER_ENUM;
2413 error = EINVAL;
2414 for(i = 0; i < ports->nports; i++)
2415 if (ports->aumask[i] == port) {
2416 ct.un.ord = ports->misel[i];
2417 error = sc->hw_if->set_port(sc->hw_hdl, &ct);
2418 break;
2419 }
2420 } else {
2421 ct.type = AUDIO_MIXER_SET;
2422 ct.un.mask = 0;
2423 for(i = 0; i < ports->nports; i++)
2424 if (ports->aumask[i] & port)
2425 ct.un.mask |= ports->misel[i];
2426 if (port != 0 && ct.un.mask == 0)
2427 error = EINVAL;
2428 else
2429 error = sc->hw_if->set_port(sc->hw_hdl, &ct);
2430 }
2431 if (!error)
2432 mixer_signal(sc);
2433 return error;
2434 }
2435
2436 int
2437 au_get_port(struct audio_softc *sc, struct au_mixer_ports *ports)
2438 {
2439 mixer_ctrl_t ct;
2440 int i, aumask;
2441
2442 if (ports->index == -1)
2443 return 0;
2444 ct.dev = ports->index;
2445 ct.type = ports->isenum ? AUDIO_MIXER_ENUM : AUDIO_MIXER_SET;
2446 if (sc->hw_if->get_port(sc->hw_hdl, &ct))
2447 return 0;
2448 aumask = 0;
2449 if (ports->isenum) {
2450 for(i = 0; i < ports->nports; i++)
2451 if (ct.un.ord == ports->misel[i])
2452 aumask = ports->aumask[i];
2453 } else {
2454 for(i = 0; i < ports->nports; i++)
2455 if (ct.un.mask & ports->misel[i])
2456 aumask |= ports->aumask[i];
2457 }
2458 return aumask;
2459 }
2460
2461 int
2462 audiosetinfo(struct audio_softc *sc, struct audio_info *ai)
2463 {
2464 struct audio_prinfo *r = &ai->record, *p = &ai->play;
2465 int cleared;
2466 int s, setmode, modechange = 0;
2467 int error;
2468 struct audio_hw_if *hw = sc->hw_if;
2469 struct audio_params pp, rp;
2470 int np, nr;
2471 unsigned int blks;
2472 int oldpblksize, oldrblksize;
2473 int rbus, pbus;
2474 u_int gain;
2475 u_char balance;
2476
2477 if (hw == 0)
2478 return(ENXIO);
2479
2480 rbus = sc->sc_rbus;
2481 pbus = sc->sc_pbus;
2482 error = 0;
2483 cleared = 0;
2484
2485 pp = sc->sc_pparams;
2486 rp = sc->sc_rparams;
2487 nr = np = 0;
2488
2489 if (p->sample_rate != ~0) {
2490 pp.sample_rate = p->sample_rate;
2491 np++;
2492 }
2493 if (r->sample_rate != ~0) {
2494 rp.sample_rate = r->sample_rate;
2495 nr++;
2496 }
2497 if (p->encoding != ~0) {
2498 pp.encoding = p->encoding;
2499 np++;
2500 }
2501 if (r->encoding != ~0) {
2502 rp.encoding = r->encoding;
2503 nr++;
2504 }
2505 if (p->precision != ~0) {
2506 pp.precision = p->precision;
2507 np++;
2508 }
2509 if (r->precision != ~0) {
2510 rp.precision = r->precision;
2511 nr++;
2512 }
2513 if (p->channels != ~0) {
2514 pp.channels = p->channels;
2515 np++;
2516 }
2517 if (r->channels != ~0) {
2518 rp.channels = r->channels;
2519 nr++;
2520 }
2521 #ifdef AUDIO_DEBUG
2522 if (audiodebug && nr)
2523 audio_print_params("Setting record params", &rp);
2524 if (audiodebug && np)
2525 audio_print_params("Setting play params", &pp);
2526 #endif
2527 if (nr && (error = audio_check_params(&rp)))
2528 return error;
2529 if (np && (error = audio_check_params(&pp)))
2530 return error;
2531 setmode = 0;
2532 if (nr) {
2533 if (!cleared)
2534 audio_clear(sc);
2535 modechange = cleared = 1;
2536 rp.sw_code = 0;
2537 rp.factor = 1;
2538 setmode |= AUMODE_RECORD;
2539 }
2540 if (np) {
2541 if (!cleared)
2542 audio_clear(sc);
2543 modechange = cleared = 1;
2544 pp.sw_code = 0;
2545 pp.factor = 1;
2546 setmode |= AUMODE_PLAY;
2547 }
2548
2549 if (ai->mode != ~0) {
2550 if (!cleared)
2551 audio_clear(sc);
2552 modechange = cleared = 1;
2553 sc->sc_mode = ai->mode;
2554 if (sc->sc_mode & AUMODE_PLAY_ALL)
2555 sc->sc_mode |= AUMODE_PLAY;
2556 if ((sc->sc_mode & AUMODE_PLAY) && !sc->sc_full_duplex)
2557
2558 sc->sc_mode &= ~AUMODE_RECORD;
2559 }
2560
2561 if (modechange) {
2562 int indep = hw->get_props(sc->hw_hdl) & AUDIO_PROP_INDEPENDENT;
2563 if (!indep) {
2564 if (setmode == AUMODE_RECORD)
2565 pp = rp;
2566 else if (setmode == AUMODE_PLAY)
2567 rp = pp;
2568 }
2569 error = hw->set_params(sc->hw_hdl, setmode,
2570 sc->sc_mode & (AUMODE_PLAY | AUMODE_RECORD), &pp, &rp);
2571 if (error)
2572 return (error);
2573 if (!indep) {
2574 if (setmode == AUMODE_RECORD) {
2575 pp.sample_rate = rp.sample_rate;
2576 pp.encoding = rp.encoding;
2577 pp.channels = rp.channels;
2578 pp.precision = rp.precision;
2579 } else if (setmode == AUMODE_PLAY) {
2580 rp.sample_rate = pp.sample_rate;
2581 rp.encoding = pp.encoding;
2582 rp.channels = pp.channels;
2583 rp.precision = pp.precision;
2584 }
2585 }
2586 sc->sc_rparams = rp;
2587 sc->sc_pparams = pp;
2588 }
2589
2590 oldpblksize = sc->sc_pr.blksize;
2591 oldrblksize = sc->sc_rr.blksize;
2592
2593 if (nr || np) {
2594 audio_calc_blksize(sc, AUMODE_RECORD);
2595 audio_calc_blksize(sc, AUMODE_PLAY);
2596 }
2597 #ifdef AUDIO_DEBUG
2598 if (audiodebug > 1 && nr)
2599 audio_print_params("After setting record params", &sc->sc_rparams);
2600 if (audiodebug > 1 && np)
2601 audio_print_params("After setting play params", &sc->sc_pparams);
2602 #endif
2603
2604 if (p->port != ~0) {
2605 if (!cleared)
2606 audio_clear(sc);
2607 cleared = 1;
2608
2609 error = au_set_port(sc, &sc->sc_outports, p->port);
2610 if (error)
2611 return(error);
2612 }
2613 if (r->port != ~0) {
2614 if (!cleared)
2615 audio_clear(sc);
2616 cleared = 1;
2617
2618 error = au_set_port(sc, &sc->sc_inports, r->port);
2619 if (error)
2620 return(error);
2621 }
2622 if (p->gain != ~0) {
2623 au_get_gain(sc, &sc->sc_outports, &gain, &balance);
2624 error = au_set_gain(sc, &sc->sc_outports, p->gain, balance);
2625 if (error)
2626 return(error);
2627 }
2628 if (r->gain != ~0) {
2629 au_get_gain(sc, &sc->sc_inports, &gain, &balance);
2630 error = au_set_gain(sc, &sc->sc_inports, r->gain, balance);
2631 if (error)
2632 return(error);
2633 }
2634
2635 if (p->balance != (u_char)~0) {
2636 au_get_gain(sc, &sc->sc_outports, &gain, &balance);
2637 error = au_set_gain(sc, &sc->sc_outports, gain, p->balance);
2638 if (error)
2639 return(error);
2640 }
2641 if (r->balance != (u_char)~0) {
2642 au_get_gain(sc, &sc->sc_inports, &gain, &balance);
2643 error = au_set_gain(sc, &sc->sc_inports, gain, r->balance);
2644 if (error)
2645 return(error);
2646 }
2647
2648 if (ai->monitor_gain != ~0 &&
2649 sc->sc_monitor_port != -1) {
2650 mixer_ctrl_t ct;
2651
2652 ct.dev = sc->sc_monitor_port;
2653 ct.type = AUDIO_MIXER_VALUE;
2654 ct.un.value.num_channels = 1;
2655 ct.un.value.level[AUDIO_MIXER_LEVEL_MONO] = ai->monitor_gain;
2656 error = sc->hw_if->set_port(sc->hw_hdl, &ct);
2657 if (error)
2658 return(error);
2659 }
2660
2661 if (ai->blocksize != ~0) {
2662
2663 if (!cleared)
2664 audio_clear(sc);
2665 cleared = 1;
2666
2667 if (ai->blocksize == 0) {
2668 audio_calc_blksize(sc, AUMODE_RECORD);
2669 audio_calc_blksize(sc, AUMODE_PLAY);
2670 sc->sc_blkset = 0;
2671 } else {
2672 int rbs = ai->blocksize * sc->sc_rparams.factor;
2673 int pbs = ai->blocksize * sc->sc_pparams.factor;
2674 if (hw->round_blocksize) {
2675 rbs = hw->round_blocksize(sc->hw_hdl, rbs);
2676 pbs = hw->round_blocksize(sc->hw_hdl, pbs);
2677 }
2678 sc->sc_rr.blksize = rbs;
2679 sc->sc_pr.blksize = pbs;
2680 sc->sc_blkset = 1;
2681 }
2682 }
2683
2684 if (ai->mode != ~0) {
2685 if (sc->sc_mode & AUMODE_PLAY)
2686 audio_init_play(sc);
2687 if (sc->sc_mode & AUMODE_RECORD)
2688 audio_init_record(sc);
2689 }
2690
2691 if (hw->commit_settings) {
2692 error = hw->commit_settings(sc->hw_hdl);
2693 if (error)
2694 return (error);
2695 }
2696
2697 if (cleared) {
2698 s = splaudio();
2699 error = audio_initbufs(sc);
2700 if (error) goto err;
2701 if (sc->sc_pr.blksize != oldpblksize ||
2702 sc->sc_rr.blksize != oldrblksize)
2703 audio_calcwater(sc);
2704 if ((sc->sc_mode & AUMODE_PLAY) &&
2705 pbus && !sc->sc_pbus && !sc->sc_pr.pause)
2706 error = audiostartp(sc);
2707 if (!error &&
2708 (sc->sc_mode & AUMODE_RECORD) &&
2709 rbus && !sc->sc_rbus && !sc->sc_rr.pause)
2710 error = audiostartr(sc);
2711 err:
2712 splx(s);
2713 if (error)
2714 return error;
2715 }
2716
2717
2718 if (ai->hiwat != ~0) {
2719 blks = ai->hiwat;
2720 if (blks > sc->sc_pr.maxblks)
2721 blks = sc->sc_pr.maxblks;
2722 if (blks < 2)
2723 blks = 2;
2724 sc->sc_pr.usedhigh = blks * sc->sc_pr.blksize;
2725 }
2726 if (ai->lowat != ~0) {
2727 blks = ai->lowat;
2728 if (blks > sc->sc_pr.maxblks - 1)
2729 blks = sc->sc_pr.maxblks - 1;
2730 sc->sc_pr.usedlow = blks * sc->sc_pr.blksize;
2731 }
2732 if (ai->hiwat != ~0 || ai->lowat != ~0) {
2733 if (sc->sc_pr.usedlow > sc->sc_pr.usedhigh - sc->sc_pr.blksize)
2734 sc->sc_pr.usedlow = sc->sc_pr.usedhigh - sc->sc_pr.blksize;
2735 }
2736
2737 if (p->pause != (u_char)~0) {
2738 sc->sc_pr.pause = p->pause;
2739 if (!p->pause && !sc->sc_pbus && (sc->sc_mode & AUMODE_PLAY)) {
2740 s = splaudio();
2741 error = audiostartp(sc);
2742 splx(s);
2743 if (error)
2744 return error;
2745 }
2746 }
2747 if (r->pause != (u_char)~0) {
2748 sc->sc_rr.pause = r->pause;
2749 if (!r->pause && !sc->sc_rbus && (sc->sc_mode & AUMODE_RECORD)) {
2750 s = splaudio();
2751 error = audiostartr(sc);
2752 splx(s);
2753 if (error)
2754 return error;
2755 }
2756 }
2757
2758 return (0);
2759 }
2760
2761 int
2762 audiogetinfo(struct audio_softc *sc, struct audio_info *ai)
2763 {
2764 struct audio_prinfo *r = &ai->record, *p = &ai->play;
2765 struct audio_hw_if *hw = sc->hw_if;
2766
2767 if (hw == 0)
2768 return(ENXIO);
2769
2770 p->sample_rate = sc->sc_pparams.sample_rate;
2771 r->sample_rate = sc->sc_rparams.sample_rate;
2772 p->channels = sc->sc_pparams.channels;
2773 r->channels = sc->sc_rparams.channels;
2774 p->precision = sc->sc_pparams.precision;
2775 r->precision = sc->sc_rparams.precision;
2776 p->encoding = sc->sc_pparams.encoding;
2777 r->encoding = sc->sc_rparams.encoding;
2778
2779 r->port = au_get_port(sc, &sc->sc_inports);
2780 p->port = au_get_port(sc, &sc->sc_outports);
2781
2782 r->avail_ports = sc->sc_inports.allports;
2783 p->avail_ports = sc->sc_outports.allports;
2784
2785 au_get_gain(sc, &sc->sc_inports, &r->gain, &r->balance);
2786 au_get_gain(sc, &sc->sc_outports, &p->gain, &p->balance);
2787
2788 if (sc->sc_monitor_port != -1) {
2789 mixer_ctrl_t ct;
2790
2791 ct.dev = sc->sc_monitor_port;
2792 ct.type = AUDIO_MIXER_VALUE;
2793 ct.un.value.num_channels = 1;
2794 if (sc->hw_if->get_port(sc->hw_hdl, &ct))
2795 ai->monitor_gain = 0;
2796 else
2797 ai->monitor_gain =
2798 ct.un.value.level[AUDIO_MIXER_LEVEL_MONO];
2799 } else
2800 ai->monitor_gain = 0;
2801
2802 p->seek = sc->sc_pr.used / sc->sc_pparams.factor;
2803 r->seek = sc->sc_rr.used / sc->sc_rparams.factor;
2804
2805 p->samples = sc->sc_pr.stamp - sc->sc_pr.drops;
2806 r->samples = sc->sc_rr.stamp - sc->sc_rr.drops;
2807
2808 p->eof = sc->sc_eof;
2809 r->eof = 0;
2810
2811 p->pause = sc->sc_pr.pause;
2812 r->pause = sc->sc_rr.pause;
2813
2814 p->error = sc->sc_pr.drops != 0;
2815 r->error = sc->sc_rr.drops != 0;
2816
2817 p->waiting = r->waiting = 0;
2818
2819 p->open = (sc->sc_open & AUOPEN_WRITE) != 0;
2820 r->open = (sc->sc_open & AUOPEN_READ) != 0;
2821
2822 p->active = sc->sc_pbus;
2823 r->active = sc->sc_rbus;
2824
2825 p->buffer_size = sc->sc_pr.bufsize / sc->sc_pparams.factor;
2826 r->buffer_size = sc->sc_rr.bufsize / sc->sc_rparams.factor;
2827
2828 if ((ai->blocksize = sc->sc_pr.blksize / sc->sc_pparams.factor) != 0) {
2829 ai->hiwat = sc->sc_pr.usedhigh / sc->sc_pr.blksize;
2830 ai->lowat = sc->sc_pr.usedlow / sc->sc_pr.blksize;
2831 } else {
2832 ai->hiwat = ai->lowat = 0;
2833 }
2834 ai->mode = sc->sc_mode;
2835
2836 return (0);
2837 }
2838
2839
2840
2841
2842 int
2843 mixer_open(dev_t dev, struct audio_softc *sc, int flags, int ifmt,
2844 struct proc *p)
2845 {
2846 DPRINTF(("mixer_open: dev=0x%x flags=0x%x sc=%p\n", dev, flags, sc));
2847
2848 return (0);
2849 }
2850
2851
2852
2853
2854 static void
2855 mixer_remove(struct audio_softc *sc, struct proc *p)
2856 {
2857 struct mixer_asyncs **pm, *m;
2858
2859 for(pm = &sc->sc_async_mixer; *pm; pm = &(*pm)->next) {
2860 if ((*pm)->proc == p) {
2861 m = *pm;
2862 *pm = m->next;
2863 free(m, M_DEVBUF);
2864 return;
2865 }
2866 }
2867 }
2868
2869
2870
2871
2872 static void
2873 mixer_signal(struct audio_softc *sc)
2874 {
2875 struct mixer_asyncs *m;
2876
2877 for(m = sc->sc_async_mixer; m; m = m->next)
2878 psignal(m->proc, SIGIO);
2879 }
2880
2881
2882
2883
2884
2885 int
2886 mixer_close(dev_t dev, int flags, int ifmt, struct proc *p)
2887 {
2888 int unit = AUDIOUNIT(dev);
2889 struct audio_softc *sc = audio_cd.cd_devs[unit];
2890
2891 DPRINTF(("mixer_close: unit %d\n", AUDIOUNIT(dev)));
2892
2893 mixer_remove(sc, p);
2894
2895 return (0);
2896 }
2897
2898 int
2899 mixer_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
2900 {
2901 int unit = AUDIOUNIT(dev);
2902 struct audio_softc *sc = audio_cd.cd_devs[unit];
2903 struct audio_hw_if *hw = sc->hw_if;
2904 int error = EINVAL;
2905
2906 DPRINTF(("mixer_ioctl(%d,'%c',%d)\n",
2907 IOCPARM_LEN(cmd), IOCGROUP(cmd), cmd&0xff));
2908
2909 switch (cmd) {
2910 case FIOASYNC:
2911 mixer_remove(sc, p);
2912 if (*(int *)addr) {
2913 struct mixer_asyncs *ma;
2914 ma = malloc(sizeof (struct mixer_asyncs),
2915 M_DEVBUF, M_WAITOK);
2916 ma->next = sc->sc_async_mixer;
2917 ma->proc = p;
2918 sc->sc_async_mixer = ma;
2919 }
2920 error = 0;
2921 break;
2922
2923 case AUDIO_GETDEV:
2924 DPRINTF(("AUDIO_GETDEV\n"));
2925 error = hw->getdev(sc->hw_hdl, (audio_device_t *)addr);
2926 break;
2927
2928 case AUDIO_MIXER_DEVINFO:
2929 DPRINTF(("AUDIO_MIXER_DEVINFO\n"));
2930 ((mixer_devinfo_t *)addr)->un.v.delta = 0;
2931 error = hw->query_devinfo(sc->hw_hdl, (mixer_devinfo_t *)addr);
2932 break;
2933
2934 case AUDIO_MIXER_READ:
2935 DPRINTF(("AUDIO_MIXER_READ\n"));
2936 error = hw->get_port(sc->hw_hdl, (mixer_ctrl_t *)addr);
2937 break;
2938
2939 case AUDIO_MIXER_WRITE:
2940 if (!(flag & FWRITE))
2941 return (EACCES);
2942 DPRINTF(("AUDIO_MIXER_WRITE\n"));
2943 error = hw->set_port(sc->hw_hdl, (mixer_ctrl_t *)addr);
2944 if (!error && hw->commit_settings)
2945 error = hw->commit_settings(sc->hw_hdl);
2946 if (!error)
2947 mixer_signal(sc);
2948 break;
2949
2950 default:
2951 error = ENOTTY;
2952 break;
2953 }
2954 DPRINTF(("mixer_ioctl(%d,'%c',%d) result %d\n",
2955 IOCPARM_LEN(cmd), IOCGROUP(cmd), cmd&0xff, error));
2956 return (error);
2957 }
2958 #endif
2959
2960 int
2961 audiokqfilter(dev_t dev, struct knote *kn)
2962 {
2963 int unit = AUDIOUNIT(dev);
2964 struct audio_softc *sc = audio_cd.cd_devs[unit];
2965 struct klist *klist;
2966 int s;
2967
2968 switch (kn->kn_filter) {
2969 case EVFILT_READ:
2970 klist = &sc->sc_rsel.si_note;
2971 kn->kn_fop = &audioread_filtops;
2972 break;
2973 case EVFILT_WRITE:
2974 klist = &sc->sc_wsel.si_note;
2975 kn->kn_fop = &audiowrite_filtops;
2976 break;
2977 default:
2978 return (1);
2979 }
2980 kn->kn_hook = (void *)sc;
2981
2982 s = splaudio();
2983 SLIST_INSERT_HEAD(klist, kn, kn_selnext);
2984 splx(s);
2985
2986 return (0);
2987 }
2988
2989 void
2990 filt_audiordetach(struct knote *kn)
2991 {
2992 struct audio_softc *sc = (struct audio_softc *)kn->kn_hook;
2993 int s = splaudio();
2994
2995 SLIST_REMOVE(&sc->sc_rsel.si_note, kn, knote, kn_selnext);
2996 splx(s);
2997 }
2998
2999 int
3000 filt_audioread(struct knote *kn, long hint)
3001 {
3002 struct audio_softc *sc = (struct audio_softc *)kn->kn_hook;
3003
3004 return AUDIO_FILTREAD(sc);
3005 }
3006
3007 void
3008 filt_audiowdetach(struct knote *kn)
3009 {
3010 struct audio_softc *sc = (struct audio_softc *)kn->kn_hook;
3011 int s = splaudio();
3012
3013 SLIST_REMOVE(&sc->sc_wsel.si_note, kn, knote, kn_selnext);
3014 splx(s);
3015 }
3016
3017 int
3018 filt_audiowrite(struct knote *kn, long hint)
3019 {
3020 struct audio_softc *sc = (struct audio_softc *)kn->kn_hook;
3021
3022 return AUDIO_FILTWRITE(sc);
3023 }
3024
3025 #if NAUDIO > 0 && NWSKBD > 0
3026 int
3027 wskbd_get_mixerdev(struct audio_softc *sc, int dir, int *index)
3028 {
3029 mixer_devinfo_t mi;
3030 int mixer_class;
3031 int error;
3032
3033
3034 for (mi.index = 0; ; mi.index++) {
3035 error = sc->hw_if->query_devinfo(sc->hw_hdl, &mi);
3036 if (error != 0)
3037 return (-1);
3038
3039 if (mi.type == AUDIO_MIXER_CLASS &&
3040 strcmp(mi.label.name, AudioCoutputs) == 0) {
3041 mixer_class = mi.mixer_class;
3042 break;
3043 }
3044 }
3045
3046
3047
3048
3049
3050
3051 for (mi.index = 0; ; mi.index++) {
3052 error = sc->hw_if->query_devinfo(sc->hw_hdl, &mi);
3053 if (error != 0)
3054 return (-1);
3055
3056 if (mi.type == AUDIO_MIXER_VALUE &&
3057 mi.mixer_class == mixer_class &&
3058 strcmp(mi.label.name, AudioNmaster) == 0) {
3059 if (dir == 0) {
3060
3061 if (mi.next < 0)
3062 return (-1);
3063
3064 mi.index = mi.next;
3065 error = sc->hw_if->query_devinfo(sc->hw_hdl,
3066 &mi);
3067 if (error != 0)
3068 return (-1);
3069
3070 if (mi.type != AUDIO_MIXER_ENUM ||
3071 strcmp(mi.label.name, AudioNmute) != 0)
3072 return (-1);
3073 }
3074
3075 *index = mi.index;
3076 return (0);
3077 }
3078 }
3079
3080 return (-1);
3081 }
3082
3083 int
3084 wskbd_set_mixervolume(long dir)
3085 {
3086 struct audio_softc *sc;
3087 mixer_devinfo_t mi;
3088 mixer_ctrl_t ct;
3089 int l, r;
3090 int error;
3091
3092 if (audio_cd.cd_ndevs == 0 || (sc = audio_cd.cd_devs[0]) == NULL) {
3093 DPRINTF(("wskbd_set_mixervolume: audio_cd\n"));
3094 return (ENXIO);
3095 }
3096
3097 error = wskbd_get_mixerdev(sc, dir, &ct.dev);
3098 if (error == -1) {
3099 DPRINTF(("wskbd_set_mixervolume: wskbd_get_mixerdev\n"));
3100 return (ENXIO);
3101 }
3102
3103 if (dir == 0) {
3104
3105
3106
3107
3108 ct.type = AUDIO_MIXER_ENUM;
3109 error = sc->hw_if->get_port(sc->hw_hdl, &ct);
3110 if (error != 0) {
3111 DPRINTF(("wskbd_set_mixervolume:"
3112 " get_port: %d\n", error));
3113 return (error);
3114 }
3115
3116 ct.un.ord = !ct.un.ord;
3117
3118 error = mixer_ioctl(MIXER_DEVICE,
3119 AUDIO_MIXER_WRITE, (caddr_t)&ct, FWRITE, curproc);
3120 if (error != 0) {
3121 DPRINTF(("wskbd_set_mixervolume:"
3122 " mixer_ioctl: %d\n", error));
3123 return (error);
3124 }
3125 } else {
3126 mi.index = ct.dev;
3127 error = sc->hw_if->query_devinfo(sc->hw_hdl, &mi);
3128 if (error != 0) {
3129 DPRINTF(("wskbd_set_mixervolume:"
3130 " query_devinfo: %d\n", error));
3131 return (error);
3132 }
3133
3134 ct.type = AUDIO_MIXER_VALUE;
3135
3136 error = au_get_lr_value(sc, &ct, &l, &r);
3137 if (error != 0) {
3138 DPRINTF(("wskbd_set_mixervolume:"
3139 " au_get_lr_value: %d\n", error));
3140 return (error);
3141 }
3142
3143 if (dir > 0) {
3144
3145
3146
3147 if (l > AUDIO_MAX_GAIN - mi.un.v.delta)
3148 l = AUDIO_MAX_GAIN;
3149 else
3150 l += mi.un.v.delta;
3151
3152 if (r > AUDIO_MAX_GAIN - mi.un.v.delta)
3153 r = AUDIO_MAX_GAIN;
3154 else
3155 r += mi.un.v.delta;
3156
3157 } else {
3158
3159
3160
3161 if (l < AUDIO_MIN_GAIN + mi.un.v.delta)
3162 l = AUDIO_MIN_GAIN;
3163 else
3164 l -= mi.un.v.delta;
3165
3166 if (r < AUDIO_MIN_GAIN + mi.un.v.delta)
3167 r = AUDIO_MIN_GAIN;
3168 else
3169 r -= mi.un.v.delta;
3170 }
3171
3172 error = au_set_lr_value(sc, &ct, l, r);
3173 if (error != 0) {
3174 DPRINTF(("wskbd_set_mixervolume:"
3175 " au_set_lr_value: %d\n", error));
3176 return (error);
3177 }
3178 }
3179
3180 return (0);
3181 }
3182 #endif