Annotation of sys/dev/audio.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: audio.c,v 1.72 2007/08/08 05:51:23 jakemsr Exp $ */
2: /* $NetBSD: audio.c,v 1.119 1999/11/09 16:50:47 augustss Exp $ */
3:
4: /*
5: * Copyright (c) 1991-1993 Regents of the University of California.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the Computer Systems
19: * Engineering Group at Lawrence Berkeley Laboratory.
20: * 4. Neither the name of the University nor of the Laboratory may be used
21: * to endorse or promote products derived from this software without
22: * specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: /*
38: * This is a (partially) SunOS-compatible /dev/audio driver for NetBSD.
39: *
40: * This code tries to do something half-way sensible with
41: * half-duplex hardware, such as with the SoundBlaster hardware. With
42: * half-duplex hardware allowing O_RDWR access doesn't really make
43: * sense. However, closing and opening the device to "turn around the
44: * line" is relatively expensive and costs a card reset (which can
45: * take some time, at least for the SoundBlaster hardware). Instead
46: * we allow O_RDWR access, and provide an ioctl to set the "mode",
47: * i.e. playing or recording.
48: *
49: * If you write to a half-duplex device in record mode, the data is
50: * tossed. If you read from the device in play mode, you get silence
51: * filled buffers at the rate at which samples are naturally
52: * generated.
53: *
54: * If you try to set both play and record mode on a half-duplex
55: * device, playing takes precedence.
56: */
57:
58: /*
59: * Todo:
60: * - Add softaudio() isr processing for wakeup, poll, signals,
61: * and silence fill.
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" /* NWSKBD (mixer tuning using keyboard) */
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 /* round to nice boundary */
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: /* The default audio mode: 8 kHz mono ulaw */
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: /* Mixer manipulation using keyboard */
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: * Set default softc params
283: */
284: sc->sc_pparams = audio_default;
285: sc->sc_rparams = audio_default;
286:
287: /* Set up some default values */
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: /* free resources */
376: audio_free_ring(sc, &sc->sc_pr);
377: audio_free_ring(sc, &sc->sc_rr);
378:
379: /* locate the major number */
380: for (maj = 0; maj < nchrdev; maj++)
381: if (cdevsw[maj].d_open == audioopen)
382: break;
383:
384: /* Nuke the vnodes for any open instances (calls close). */
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: * Called from hardware driver. This is where the MI audio driver gets
455: * probed/attached to the hardware driver.
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 /* NAUDIO > 0 */
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: * Alloc DMA play and record buffers
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: * Audio driver
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; /* set lowater at 75% */
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: /* call at splaudio() */
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; /* Block sizes not set yet */
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: /* doesn't always work right on SB.
945: (flags & (FWRITE|FREAD)) == (FWRITE|FREAD) &&
946: (sc->hw_if->get_props(sc->hw_hdl) & AUDIO_PROP_FULLDUPLEX);
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: * Multiplex device: /dev/audio (MU-Law) and /dev/sound (linear)
961: * The /dev/audio is always (re)set to 8-bit MU-Law mono
962: * For the other devices, you get what they were last set to.
963: */
964: if (ISDEVAUDIO(dev)) {
965: /* /dev/audio */
966: sc->sc_rparams = audio_default;
967: sc->sc_pparams = audio_default;
968: }
969: #ifdef DIAGNOSTIC
970: /*
971: * Sample rate and precision are supposed to be set to proper
972: * default values by the hardware driver, so that it may give
973: * us these values.
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; /* force recalculation */
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: * Must be called from task context.
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: * Must be called from task context.
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: /* We've never started playing, probably because the
1052: * block was too short. Pad it and start now.
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: * Play until a silence block has been played, then we
1077: * know all has been drained.
1078: * XXX This should be done some other way to avoid
1079: * playing silence.
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: * When the process is exiting, it ignores all signals and
1094: * we can't interrupt this sleep, so we set a timeout just in case.
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: * Close an audio chip.
1106: */
1107: /* ARGSUSED */
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: /* Stop recording. */
1120: if ((flags & FREAD) && sc->sc_rbus) {
1121: /*
1122: * XXX Some drivers (e.g. SB) use the same routine
1123: * to halt input and output so don't halt input if
1124: * in full duplex mode. These drivers should be fixed.
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: * Block until output drains, but allow ^C interrupt.
1132: */
1133: sc->sc_pr.usedlow = sc->sc_pr.blksize; /* avoid excessive wakeups */
1134: /*
1135: * If there is pending output, let it drain (unless
1136: * the output is paused).
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: * If flags has neither read nor write then reset both
1149: * directions. Encountered when someone runs revoke(2).
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: * If hardware is half-duplex and currently playing, return
1187: * silence blocks based on the number of blocks we have output.
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; /* maximum to read */
1250: n = cb->end - outp;
1251: if (n < cc)
1252: cc = n; /* don't read beyond end of buffer */
1253:
1254: /* and no more than we want */
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; /* initialize to please gcc */
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: /* is this right XXX */
1344: case AUDIO_ENCODING_SLINEAR_LE:
1345: case AUDIO_ENCODING_SLINEAR_BE:
1346: auzero0 = 0; /* fortunately this works for both 8 and 16 bits */
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; /* XXX memset */
1370: } else /* nfill must be 2 */ {
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: * If half-duplex and currently recording, throw away data.
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; /* maximum to write */
1466: n = cb->end - inp;
1467: if (sc->sc_pparams.factor != 1) {
1468: /* Compensate for software coding expansion factor. */
1469: n /= sc->sc_pparams.factor;
1470: cc /= sc->sc_pparams.factor;
1471: }
1472: if (n < cc)
1473: cc = n; /* don't write beyond end of buffer */
1474: if (uio->uio_resid < cc)
1475: cc = uio->uio_resid; /* and no more than we have */
1476:
1477: #ifdef DIAGNOSTIC
1478: /*
1479: * This should never happen since the block size and and
1480: * block pointers are always nicely aligned.
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; /* number of bytes actually moved */
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: * Continue even if uiomove() failed because we may have
1501: * gotten a partial block.
1502: */
1503:
1504: if (sc->sc_pparams.sw_code) {
1505: sc->sc_pparams.sw_code(sc->hw_hdl, inp, cc);
1506: /* Adjust count after the expansion. */
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: * This is a very suboptimal way of keeping track of
1518: * silence in the buffer, but it is simple.
1519: */
1520: sc->sc_sil_count = 0;
1521:
1522: cb->inp = einp;
1523: cb->used += cc;
1524: /* If the interrupt routine wants the last block filled AND
1525: * the copy did not fill the last block completely it needs to
1526: * be padded.
1527: */
1528: if (cb->needfill &&
1529: (inp - cb->start) / cb->blksize ==
1530: (einp - cb->start) / cb->blksize) {
1531: /* Figure out how many bytes there is to a block boundary. */
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: /* Report the first error that occurred. */
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: /* All handled in the upper FS layer. */
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: * Number of read (write) samples dropped. We don't know where or
1610: * when they were dropped.
1611: *
1612: * The audio_ringbuffer->drops count is the number of buffer
1613: * sample size bytes. Convert it to userland sample size bytes,
1614: * then convert to samples. There is no easy way to get the
1615: * buffer sample size, but the userland sample size can be
1616: * calculated with userland channels and userland precision.
1617: *
1618: * original formula:
1619: * sc->sc_rr.drops /
1620: * sc->sc_rparams.factor /
1621: * (sc->sc_rparams.channels * (sc->sc_rparams.precision / NBBY))
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: * Offsets into buffer.
1637: */
1638: case AUDIO_GETIOFFS:
1639: s = splaudio();
1640: /* figure out where next DMA will start */
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: /* figure out where next DMA will start */
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: * How many bytes will elapse until mike hears the first
1665: * sample of what we write next?
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: /* Pass read/write info down to query_encoding */
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: /* XXX
1803: * The idea here was to use the protection to determine if
1804: * we are mapping the read or write buffer, but it fails.
1805: * The VM system is broken in (at least) two ways.
1806: * 1) If you map memory VM_PROT_WRITE you SIGSEGV
1807: * when writing to it, so VM_PROT_READ|VM_PROT_WRITE
1808: * has to be used for mmapping the play buffer.
1809: * 2) Even if calling mmap() with VM_PROT_READ|VM_PROT_WRITE
1810: * audio_mmap will get called at some point with VM_PROT_READ
1811: * only.
1812: * So, alas, we always map the play buffer for now.
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: * When the play interrupt routine finds that the write isn't keeping
1899: * the buffer filled it will insert silence in the buffer to make up
1900: * for this. The part of the buffer that is filled with silence
1901: * is kept track of in a very approximate way: it starts at sc_sil_start
1902: * and extends sc_sil_count bytes. If there is already silence in
1903: * the requested area nothing is done; so when the whole buffer is
1904: * silent nothing happens. When the writer starts again sc_sil_count
1905: * is set to 0.
1906: */
1907: /* XXX
1908: * Putting silence into the output buffer should not really be done
1909: * at splaudio, but there is no softaudio level to do it at yet.
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; /* start of silence */
1919: e = s + sc->sc_sil_count; /* end of silence, may be beyond end */
1920: p = inp; /* adjusted pointer to area to fill */
1921: if (p < s)
1922: p += cb->end - cb->start;
1923: q = p+cc;
1924: /* Check if there is already silence. */
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: * Called from HW driver module on completion of dma output.
1961: * Start output of new block, wrap in ring buffer if needed.
1962: * If no more buffers to play, output zero instead.
1963: * Do a wakeup if necessary.
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; /* ignore interrupt if not open */
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++; /* avoid repeated messages */
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: /* we don't have a full block to use */
2025: if (cb->copying) {
2026: /* writer is in progress, don't disturb */
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: /* Clear next block so we keep ahead of the DMA. */
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: /* XXX does this really help? */
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: /* Possible to return one or more "phantom blocks" now. */
2069: if (!sc->sc_full_duplex && sc->sc_rchan)
2070: audio_selwakeup(sc, 0);
2071: }
2072:
2073: /*
2074: * Called from HW driver module on completion of dma input.
2075: * Mark it as input in the ring buffer (fiddle pointers).
2076: * Do a wakeup if necessary.
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; /* ignore interrupt if not open */
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++; /* avoid repeated messages */
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: /* XXX does this really help? */
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) /* sanity check # of channels */
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; /* just ignore it silently */
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) { /* handles lgain==rgain==0 */
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 /* lgain > rgain */ {
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) /* allow this special case */
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; /* Only one port allowed */
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) /* HW has not attached */
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; /* Temporary encoding storage in */
2486: rp = sc->sc_rparams; /* case setting the modes fails. */
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: /* Play takes precedence */
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: /* Play params can affect the record params, so recalculate blksize. */
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: /* Block size specified explicitly. */
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: /* Change water marks after initializing the buffers. */
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) /* HW has not attached */
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; /* open never hangs */
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: * Mixer driver
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: * Remove a process from those to be signalled on mixer activity.
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: * Signal all processes waitinf for the mixer.
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: * Close a mixer device
2883: */
2884: /* ARGSUSED */
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); /* remove old entry */
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; /* default */
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: /* looking for ``outputs'' */
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: * looking for ``outputs.master''
3048: * start mi.index from 0 because ''outputs.master'' can precede
3049: * ''outputs''.
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: /* looking for ``outputs.master.mute'' */
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: * Mute.
3106: * Use mixer_ioctl() for writing. It does many things for us.
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; /* toggle */
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: * Raise volume
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: * Lower volume
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 /* NAUDIO > 0 && NWSKBD > 0 */
CVSweb