Bug Summary

File:dev/audio.c
Warning:line 2297, column 2
1st function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name audio.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/audio.c
1/* $OpenBSD: audio.c,v 1.194 2022/01/09 05:42:36 jsg Exp $ */
2/*
3 * Copyright (c) 2015 Alexandre Ratchov <alex@caoua.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17#include <sys/param.h>
18#include <sys/fcntl.h>
19#include <sys/systm.h>
20#include <sys/ioctl.h>
21#include <sys/conf.h>
22#include <sys/poll.h>
23#include <sys/kernel.h>
24#include <sys/task.h>
25#include <sys/vnode.h>
26#include <sys/malloc.h>
27#include <sys/device.h>
28#include <sys/audioio.h>
29#include <dev/audio_if.h>
30#include <dev/mulaw.h>
31#include "audio.h"
32#include "wskbd.h"
33
34#ifdef AUDIO_DEBUG
35#define DPRINTF(...)do {} while(0) \
36 do { \
37 if (audio_debug) \
38 printf(__VA_ARGS__); \
39 } while(0)
40#define DPRINTFN(n, ...)do {} while(0) \
41 do { \
42 if (audio_debug > (n)) \
43 printf(__VA_ARGS__); \
44 } while(0)
45#else
46#define DPRINTF(...)do {} while(0) do {} while(0)
47#define DPRINTFN(n, ...)do {} while(0) do {} while(0)
48#endif
49
50#define IPL_SOFTAUDIO0x5 IPL_SOFTNET0x5
51
52#define DEVNAME(sc)((sc)->dev.dv_xname) ((sc)->dev.dv_xname)
53#define AUDIO_UNIT(n)(((unsigned)((n) & 0xff) | (((n) & 0xffff0000) >>
8)) & 0x0f)
(minor(n)((unsigned)((n) & 0xff) | (((n) & 0xffff0000) >>
8))
& 0x0f)
54#define AUDIO_DEV(n)(((unsigned)((n) & 0xff) | (((n) & 0xffff0000) >>
8)) & 0xf0)
(minor(n)((unsigned)((n) & 0xff) | (((n) & 0xffff0000) >>
8))
& 0xf0)
55#define AUDIO_DEV_AUDIO0 0 /* minor of /dev/audio0 */
56#define AUDIO_DEV_AUDIOCTL0xc0 0xc0 /* minor of /dev/audioctl */
57#define AUDIO_BUFSZ65536 65536 /* buffer size in bytes */
58
59/*
60 * mixer entries added by the audio(4) layer
61 */
62#define MIXER_RECORD0 0 /* record class */
63#define MIXER_RECORD_ENABLE1 1 /* record.enable control */
64#define MIXER_RECORD_ENABLE_OFF0 0 /* record.enable=off value */
65#define MIXER_RECORD_ENABLE_ON1 1 /* record.enable=on value */
66#define MIXER_RECORD_ENABLE_SYSCTL2 2 /* record.enable=sysctl val */
67
68/*
69 * dma buffer
70 */
71struct audio_buf {
72 unsigned char *data; /* DMA memory block */
73 size_t datalen; /* size of DMA memory block */
74 size_t len; /* size of DMA FIFO */
75 size_t start; /* first byte used in the FIFO */
76 size_t used; /* bytes used in the FIFO */
77 size_t blksz; /* DMA block size */
78 unsigned int nblks; /* number of blocks */
79 struct selinfo sel; /* to record & wakeup poll(2) */
80 void *softintr; /* context to call selwakeup() */
81 unsigned int pos; /* bytes transferred */
82 unsigned int xrun; /* bytes lost by xruns */
83 int blocking; /* read/write blocking */
84};
85
86#if NWSKBD1 > 0
87struct wskbd_vol
88{
89 int val; /* index of the value control */
90 int mute; /* index of the mute control */
91 int step; /* increment/decrement step */
92 int nch; /* channels in the value control */
93 int val_pending; /* pending change of val */
94 int mute_pending; /* pending change of mute */
95#define WSKBD_MUTE_TOGGLE1 1
96#define WSKBD_MUTE_DISABLE2 2
97#define WSKBD_MUTE_ENABLE3 3
98};
99#endif
100
101/*
102 * event indicating that a control was changed
103 */
104struct mixer_ev {
105 struct mixer_ev *next;
106 int pending;
107};
108
109/*
110 * device structure
111 */
112struct audio_softc {
113 struct device dev;
114 struct audio_hw_if *ops; /* driver funcs */
115 void *arg; /* first arg to driver funcs */
116 int mode; /* bitmask of AUMODE_* */
117 int quiesce; /* device suspended */
118 struct audio_buf play, rec;
119 unsigned int sw_enc; /* user exposed AUDIO_ENCODING_* */
120 unsigned int hw_enc; /* hardware AUDIO_ENCODING_* */
121 unsigned int bits; /* bits per sample */
122 unsigned int bps; /* bytes-per-sample */
123 unsigned int msb; /* sample are MSB aligned */
124 unsigned int rate; /* rate in Hz */
125 unsigned int round; /* block size in frames */
126 unsigned int pchan, rchan; /* number of channels */
127 unsigned char silence[4]; /* a sample of silence */
128 int pause; /* not trying to start DMA */
129 int active; /* DMA in process */
130 int offs; /* offset between play & rec dir */
131 void (*conv_enc)(unsigned char *, int); /* encode to native */
132 void (*conv_dec)(unsigned char *, int); /* decode to user */
133 struct mixer_ctrl *mix_ents; /* mixer state for suspend/resume */
134 int mix_nent; /* size of mixer state */
135 int mix_isopen; /* mixer open for reading */
136 int mix_blocking; /* read() blocking */
137 struct selinfo mix_sel; /* wakeup poll(2) */
138 struct mixer_ev *mix_evbuf; /* per mixer-control event */
139 struct mixer_ev *mix_pending; /* list of changed controls */
140 void *mix_softintr; /* context to call selwakeup() */
141#if NWSKBD1 > 0
142 struct wskbd_vol spkr, mic;
143 struct task wskbd_task;
144#endif
145 int record_enable; /* mixer record.enable value */
146};
147
148int audio_match(struct device *, void *, void *);
149void audio_attach(struct device *, struct device *, void *);
150int audio_activate(struct device *, int);
151int audio_detach(struct device *, int);
152void audio_pintr(void *);
153void audio_rintr(void *);
154#if NWSKBD1 > 0
155void wskbd_mixer_init(struct audio_softc *);
156void wskbd_mixer_cb(void *);
157#endif
158
159const struct cfattach audio_ca = {
160 sizeof(struct audio_softc), audio_match, audio_attach,
161 audio_detach, audio_activate
162};
163
164struct cfdriver audio_cd = {
165 NULL((void *)0), "audio", DV_DULL
166};
167
168void filt_audioctlrdetach(struct knote *);
169int filt_audioctlread(struct knote *, long);
170
171const struct filterops audioctlread_filtops = {
172 .f_flags = FILTEROP_ISFD0x00000001,
173 .f_attach = NULL((void *)0),
174 .f_detach = filt_audioctlrdetach,
175 .f_event = filt_audioctlread,
176};
177
178void filt_audiowdetach(struct knote *);
179int filt_audiowrite(struct knote *, long);
180
181const struct filterops audiowrite_filtops = {
182 .f_flags = FILTEROP_ISFD0x00000001,
183 .f_attach = NULL((void *)0),
184 .f_detach = filt_audiowdetach,
185 .f_event = filt_audiowrite,
186};
187
188void filt_audiordetach(struct knote *);
189int filt_audioread(struct knote *, long);
190
191const struct filterops audioread_filtops = {
192 .f_flags = FILTEROP_ISFD0x00000001,
193 .f_attach = NULL((void *)0),
194 .f_detach = filt_audiordetach,
195 .f_event = filt_audioread,
196};
197
198/*
199 * This mutex protects data structures (including registers on the
200 * sound-card) that are manipulated by both the interrupt handler and
201 * syscall code-paths.
202 *
203 * Note that driver methods may sleep (e.g. in malloc); consequently the
204 * audio layer calls them with the mutex unlocked. Driver methods are
205 * responsible for locking the mutex when they manipulate data used by
206 * the interrupt handler and interrupts may occur.
207 *
208 * Similarly, the driver is responsible for locking the mutex in its
209 * interrupt handler and to call the audio layer call-backs (i.e.
210 * audio_{p,r}int()) with the mutex locked.
211 */
212struct mutex audio_lock = MUTEX_INITIALIZER(IPL_AUDIO){ ((void *)0), ((((0xb)) > 0x0 && ((0xb)) < 0x9
) ? 0x9 : ((0xb))), 0x0 }
;
213
214/*
215 * Global flag to control if audio recording is enabled when the
216 * mixerctl setting is record.enable=sysctl
217 */
218int audio_record_enable = 0;
219
220#ifdef AUDIO_DEBUG
221/*
222 * 0 - nothing, as if AUDIO_DEBUG isn't defined
223 * 1 - initialisations & setup
224 * 2 - blocks & interrupts
225 */
226int audio_debug = 1;
227#endif
228
229unsigned int
230audio_gcd(unsigned int a, unsigned int b)
231{
232 unsigned int r;
233
234 while (b > 0) {
235 r = a % b;
236 a = b;
237 b = r;
238 }
239 return a;
240}
241
242/*
243 * Calculate the least block size (in frames) such that both the
244 * corresponding play and/or record block sizes (in bytes) are multiple
245 * of the given number of bytes.
246 */
247int
248audio_blksz_bytes(int mode,
249 struct audio_params *p, struct audio_params *r, int bytes)
250{
251 unsigned int np, nr;
252
253 if (mode & AUMODE_PLAY0x01) {
254 np = bytes / audio_gcd(p->bps * p->channels, bytes);
255 if (!(mode & AUMODE_RECORD0x02))
256 nr = np;
257 }
258 if (mode & AUMODE_RECORD0x02) {
259 nr = bytes / audio_gcd(r->bps * r->channels, bytes);
260 if (!(mode & AUMODE_PLAY0x01))
261 np = nr;
262 }
263
264 return nr * np / audio_gcd(nr, np);
265}
266
267void
268audio_mixer_wakeup(void *addr)
269{
270 struct audio_softc *sc = addr;
271
272 if (sc->mix_blocking) {
273 wakeup(&sc->mix_blocking);
274 sc->mix_blocking = 0;
275 }
276 /*
277 * As long as selwakeup() grabs the KERNEL_LOCK() make sure it is
278 * already held here to avoid lock ordering problems with `audio_lock'
279 */
280 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/audio.c"
, 280, "_kernel_lock_held()"))
;
281 mtx_enter(&audio_lock);
282 selwakeup(&sc->mix_sel);
283 mtx_leave(&audio_lock);
284}
285
286void
287audio_buf_wakeup(void *addr)
288{
289 struct audio_buf *buf = addr;
290
291 if (buf->blocking) {
292 wakeup(&buf->blocking);
293 buf->blocking = 0;
294 }
295 /*
296 * As long as selwakeup() grabs the KERNEL_LOCK() make sure it is
297 * already held here to avoid lock ordering problems with `audio_lock'
298 */
299 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/audio.c"
, 299, "_kernel_lock_held()"))
;
300 mtx_enter(&audio_lock);
301 selwakeup(&buf->sel);
302 mtx_leave(&audio_lock);
303}
304
305int
306audio_buf_init(struct audio_softc *sc, struct audio_buf *buf, int dir)
307{
308 buf->softintr = softintr_establish(IPL_SOFTAUDIO0x5,
309 audio_buf_wakeup, buf);
310 if (buf->softintr == NULL((void *)0)) {
311 printf("%s: can't establish softintr\n", DEVNAME(sc)((sc)->dev.dv_xname));
312 return ENOMEM12;
313 }
314 if (sc->ops->round_buffersize) {
315 buf->datalen = sc->ops->round_buffersize(sc->arg,
316 dir, AUDIO_BUFSZ65536);
317 } else
318 buf->datalen = AUDIO_BUFSZ65536;
319 if (sc->ops->allocm) {
320 buf->data = sc->ops->allocm(sc->arg, dir, buf->datalen,
321 M_DEVBUF2, M_WAITOK0x0001);
322 } else
323 buf->data = malloc(buf->datalen, M_DEVBUF2, M_WAITOK0x0001);
324 if (buf->data == NULL((void *)0)) {
325 softintr_disestablish(buf->softintr);
326 return ENOMEM12;
327 }
328 return 0;
329}
330
331void
332audio_buf_done(struct audio_softc *sc, struct audio_buf *buf)
333{
334 if (sc->ops->freem)
335 sc->ops->freem(sc->arg, buf->data, M_DEVBUF2);
336 else
337 free(buf->data, M_DEVBUF2, buf->datalen);
338 softintr_disestablish(buf->softintr);
339}
340
341/*
342 * return the reader pointer and the number of bytes available
343 */
344unsigned char *
345audio_buf_rgetblk(struct audio_buf *buf, size_t *rsize)
346{
347 size_t count;
348
349 count = buf->len - buf->start;
350 if (count > buf->used)
351 count = buf->used;
352 *rsize = count;
353 return buf->data + buf->start;
354}
355
356/*
357 * discard "count" bytes at the start position.
358 */
359void
360audio_buf_rdiscard(struct audio_buf *buf, size_t count)
361{
362#ifdef AUDIO_DEBUG
363 if (count > buf->used) {
364 panic("audio_buf_rdiscard: bad count = %zu, "
365 "start = %zu, used = %zu", count, buf->start, buf->used);
366 }
367#endif
368 buf->used -= count;
369 buf->start += count;
370 if (buf->start >= buf->len)
371 buf->start -= buf->len;
372}
373
374/*
375 * advance the writer pointer by "count" bytes
376 */
377void
378audio_buf_wcommit(struct audio_buf *buf, size_t count)
379{
380#ifdef AUDIO_DEBUG
381 if (count > (buf->len - buf->used)) {
382 panic("audio_buf_wcommit: bad count = %zu, "
383 "start = %zu, used = %zu", count, buf->start, buf->used);
384 }
385#endif
386 buf->used += count;
387}
388
389/*
390 * get writer pointer and the number of bytes writable
391 */
392unsigned char *
393audio_buf_wgetblk(struct audio_buf *buf, size_t *rsize)
394{
395 size_t end, avail, count;
396
397 end = buf->start + buf->used;
398 if (end >= buf->len)
399 end -= buf->len;
400 avail = buf->len - buf->used;
401 count = buf->len - end;
402 if (count > avail)
403 count = avail;
404 *rsize = count;
405 return buf->data + end;
406}
407
408void
409audio_calc_sil(struct audio_softc *sc)
410{
411 unsigned char *q;
412 unsigned int s, i;
413 int d, e;
414
415 e = sc->sw_enc;
416#ifdef AUDIO_DEBUG
417 switch (e) {
418 case AUDIO_ENCODING_SLINEAR_LE6:
419 case AUDIO_ENCODING_ULINEAR_LE8:
420 case AUDIO_ENCODING_SLINEAR_BE7:
421 case AUDIO_ENCODING_ULINEAR_BE9:
422 break;
423 default:
424 printf("%s: unhandled play encoding %d\n", DEVNAME(sc)((sc)->dev.dv_xname), e);
425 memset(sc->silence, 0, sc->bps)__builtin_memset((sc->silence), (0), (sc->bps));
426 return;
427 }
428#endif
429 if (e == AUDIO_ENCODING_SLINEAR_BE7 || e == AUDIO_ENCODING_ULINEAR_BE9) {
430 d = -1;
431 q = sc->silence + sc->bps - 1;
432 } else {
433 d = 1;
434 q = sc->silence;
435 }
436 if (e == AUDIO_ENCODING_SLINEAR_LE6 || e == AUDIO_ENCODING_SLINEAR_BE7) {
437 s = 0;
438 } else {
439 s = 0x80000000;
440 if (sc->msb)
441 s >>= 32 - 8 * sc->bps;
442 else
443 s >>= 32 - sc->bits;
444 }
445 for (i = 0; i < sc->bps; i++) {
446 *q = s;
447 q += d;
448 s >>= 8;
449 }
450 if (sc->conv_enc)
451 sc->conv_enc(sc->silence, sc->bps);
452}
453
454void
455audio_fill_sil(struct audio_softc *sc, unsigned char *ptr, size_t count)
456{
457 unsigned char *q, *p;
458 size_t i, j;
459
460 q = ptr;
461 for (j = count / sc->bps; j > 0; j--) {
462 p = sc->silence;
463 for (i = sc->bps; i > 0; i--)
464 *q++ = *p++;
465 }
466}
467
468void
469audio_clear(struct audio_softc *sc)
470{
471 if (sc->mode & AUMODE_PLAY0x01) {
472 sc->play.used = sc->play.start = 0;
473 sc->play.pos = sc->play.xrun = 0;
474 audio_fill_sil(sc, sc->play.data, sc->play.len);
475 }
476 if (sc->mode & AUMODE_RECORD0x02) {
477 sc->rec.used = sc->rec.start = 0;
478 sc->rec.pos = sc->rec.xrun = 0;
479 audio_fill_sil(sc, sc->rec.data, sc->rec.len);
480 }
481}
482
483/*
484 * called whenever a block is consumed by the driver
485 */
486void
487audio_pintr(void *addr)
488{
489 struct audio_softc *sc = addr;
490 unsigned char *ptr;
491 size_t count;
492 int error, nblk, todo;
493
494 MUTEX_ASSERT_LOCKED(&audio_lock)do { if (((&audio_lock)->mtx_owner != ({struct cpu_info
*__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof
(struct cpu_info, ci_self))); __ci;})) && !(panicstr ||
db_active)) panic("mutex %p not held in %s", (&audio_lock
), __func__); } while (0)
;
495 if (!(sc->mode & AUMODE_PLAY0x01) || !sc->active) {
496 printf("%s: play interrupt but not playing\n", DEVNAME(sc)((sc)->dev.dv_xname));
497 return;
498 }
499 if (sc->quiesce) {
500 DPRINTF("%s: quiesced, skipping play intr\n", DEVNAME(sc))do {} while(0);
501 return;
502 }
503
504 /*
505 * check if record pointer wrapped, see explanation
506 * in audio_rintr()
507 */
508 if ((sc->mode & AUMODE_RECORD0x02) && sc->ops->underrun == NULL((void *)0)) {
509 sc->offs--;
510 nblk = sc->rec.len / sc->rec.blksz;
511 todo = -sc->offs;
512 if (todo >= nblk) {
513 todo -= todo % nblk;
514 DPRINTFN(1, "%s: rec ptr wrapped, moving %d blocks\n",do {} while(0)
515 DEVNAME(sc), todo)do {} while(0);
516 while (todo-- > 0)
517 audio_rintr(sc);
518 }
519 }
520
521 sc->play.pos += sc->play.blksz;
522 if (!sc->ops->underrun) {
523 audio_fill_sil(sc, sc->play.data + sc->play.start,
524 sc->play.blksz);
525 }
526 audio_buf_rdiscard(&sc->play, sc->play.blksz);
527 if (sc->play.used < sc->play.blksz) {
528 DPRINTFN(1, "%s: play underrun\n", DEVNAME(sc))do {} while(0);
529 sc->play.xrun += sc->play.blksz;
530 audio_buf_wcommit(&sc->play, sc->play.blksz);
531 if (sc->ops->underrun)
532 sc->ops->underrun(sc->arg);
533 }
534
535 DPRINTFN(1, "%s: play intr, used -> %zu, start -> %zu\n",do {} while(0)
536 DEVNAME(sc), sc->play.used, sc->play.start)do {} while(0);
537
538 if (!sc->ops->trigger_output) {
539 ptr = audio_buf_rgetblk(&sc->play, &count);
540 error = sc->ops->start_output(sc->arg,
541 ptr, sc->play.blksz, audio_pintr, sc);
542 if (error) {
543 printf("%s: play restart failed: %d\n",
544 DEVNAME(sc)((sc)->dev.dv_xname), error);
545 }
546 }
547
548 if (sc->play.used < sc->play.len) {
549 DPRINTFN(1, "%s: play wakeup, chan = %d\n",do {} while(0)
550 DEVNAME(sc), sc->play.blocking)do {} while(0);
551 /*
552 * As long as selwakeup() needs to be protected by the
553 * KERNEL_LOCK() we have to delay the wakeup to another
554 * context to keep the interrupt context KERNEL_LOCK()
555 * free.
556 */
557 softintr_schedule(sc->play.softintr)do { struct x86_soft_intrhand *__sih = (sc->play.softintr)
; struct x86_soft_intr *__si = __sih->sih_intrhead; mtx_enter
(&__si->softintr_lock); if (__sih->sih_pending == 0
) { do { (__sih)->sih_q.tqe_next = ((void *)0); (__sih)->
sih_q.tqe_prev = (&__si->softintr_q)->tqh_last; *(&
__si->softintr_q)->tqh_last = (__sih); (&__si->softintr_q
)->tqh_last = &(__sih)->sih_q.tqe_next; } while (0)
; __sih->sih_pending = 1; softintr(__si->softintr_ssir)
; } mtx_leave(&__si->softintr_lock); } while ( 0)
;
558 }
559}
560
561/*
562 * called whenever a block is produced by the driver
563 */
564void
565audio_rintr(void *addr)
566{
567 struct audio_softc *sc = addr;
568 unsigned char *ptr;
569 size_t count;
570 int error, nblk, todo;
571
572 MUTEX_ASSERT_LOCKED(&audio_lock)do { if (((&audio_lock)->mtx_owner != ({struct cpu_info
*__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof
(struct cpu_info, ci_self))); __ci;})) && !(panicstr ||
db_active)) panic("mutex %p not held in %s", (&audio_lock
), __func__); } while (0)
;
573 if (!(sc->mode & AUMODE_RECORD0x02) || !sc->active) {
574 printf("%s: rec interrupt but not recording\n", DEVNAME(sc)((sc)->dev.dv_xname));
575 return;
576 }
577 if (sc->quiesce) {
578 DPRINTF("%s: quiesced, skipping rec intr\n", DEVNAME(sc))do {} while(0);
579 return;
580 }
581
582 /*
583 * Interrupts may be masked by other sub-systems during 320ms
584 * and more. During such a delay the hardware doesn't stop
585 * playing and the play buffer pointers may wrap, this can't be
586 * detected and corrected by low level drivers. This makes the
587 * record stream ahead of the play stream; this is detected as a
588 * hardware anomaly by userland and cause programs to misbehave.
589 *
590 * We fix this by advancing play position by an integer count of
591 * full buffers, so it reaches the record position.
592 */
593 if ((sc->mode & AUMODE_PLAY0x01) && sc->ops->underrun == NULL((void *)0)) {
594 sc->offs++;
595 nblk = sc->play.len / sc->play.blksz;
596 todo = sc->offs;
597 if (todo >= nblk) {
598 todo -= todo % nblk;
599 DPRINTFN(1, "%s: play ptr wrapped, moving %d blocks\n",do {} while(0)
600 DEVNAME(sc), todo)do {} while(0);
601 while (todo-- > 0)
602 audio_pintr(sc);
603 }
604 }
605
606 sc->rec.pos += sc->rec.blksz;
607 if ((sc->record_enable == MIXER_RECORD_ENABLE_SYSCTL2 &&
608 !audio_record_enable) ||
609 sc->record_enable == MIXER_RECORD_ENABLE_OFF0) {
610 ptr = audio_buf_wgetblk(&sc->rec, &count);
611 audio_fill_sil(sc, ptr, sc->rec.blksz);
612 }
613 audio_buf_wcommit(&sc->rec, sc->rec.blksz);
614 if (sc->rec.used > sc->rec.len - sc->rec.blksz) {
615 DPRINTFN(1, "%s: rec overrun\n", DEVNAME(sc))do {} while(0);
616 sc->rec.xrun += sc->rec.blksz;
617 audio_buf_rdiscard(&sc->rec, sc->rec.blksz);
618 }
619 DPRINTFN(1, "%s: rec intr, used -> %zu\n", DEVNAME(sc), sc->rec.used)do {} while(0);
620
621 if (!sc->ops->trigger_input) {
622 ptr = audio_buf_wgetblk(&sc->rec, &count);
623 error = sc->ops->start_input(sc->arg,
624 ptr, sc->rec.blksz, audio_rintr, sc);
625 if (error) {
626 printf("%s: rec restart failed: %d\n",
627 DEVNAME(sc)((sc)->dev.dv_xname), error);
628 }
629 }
630
631 if (sc->rec.used > 0) {
632 DPRINTFN(1, "%s: rec wakeup, chan = %d\n",do {} while(0)
633 DEVNAME(sc), sc->rec.blocking)do {} while(0);
634 /*
635 * As long as selwakeup() needs to be protected by the
636 * KERNEL_LOCK() we have to delay the wakeup to another
637 * context to keep the interrupt context KERNEL_LOCK()
638 * free.
639 */
640 softintr_schedule(sc->rec.softintr)do { struct x86_soft_intrhand *__sih = (sc->rec.softintr);
struct x86_soft_intr *__si = __sih->sih_intrhead; mtx_enter
(&__si->softintr_lock); if (__sih->sih_pending == 0
) { do { (__sih)->sih_q.tqe_next = ((void *)0); (__sih)->
sih_q.tqe_prev = (&__si->softintr_q)->tqh_last; *(&
__si->softintr_q)->tqh_last = (__sih); (&__si->softintr_q
)->tqh_last = &(__sih)->sih_q.tqe_next; } while (0)
; __sih->sih_pending = 1; softintr(__si->softintr_ssir)
; } mtx_leave(&__si->softintr_lock); } while ( 0)
;
641 }
642}
643
644int
645audio_start_do(struct audio_softc *sc)
646{
647 int error;
648 struct audio_params p;
649 unsigned char *ptr;
650 size_t count;
651
652 DPRINTF("%s: starting\n", DEVNAME(sc))do {} while(0);
653
654 error = 0;
655 sc->offs = 0;
656 if (sc->mode & AUMODE_PLAY0x01) {
657 if (sc->ops->trigger_output) {
658 p.encoding = sc->hw_enc;
659 p.precision = sc->bits;
660 p.bps = sc->bps;
661 p.msb = sc->msb;
662 p.sample_rate = sc->rate;
663 p.channels = sc->pchan;
664 error = sc->ops->trigger_output(sc->arg,
665 sc->play.data,
666 sc->play.data + sc->play.len,
667 sc->play.blksz,
668 audio_pintr, sc, &p);
669 } else {
670 mtx_enter(&audio_lock);
671 ptr = audio_buf_rgetblk(&sc->play, &count);
672 error = sc->ops->start_output(sc->arg,
673 ptr, sc->play.blksz, audio_pintr, sc);
674 mtx_leave(&audio_lock);
675 }
676 if (error)
677 printf("%s: failed to start playback\n", DEVNAME(sc)((sc)->dev.dv_xname));
678 }
679 if (sc->mode & AUMODE_RECORD0x02) {
680 if (sc->ops->trigger_input) {
681 p.encoding = sc->hw_enc;
682 p.precision = sc->bits;
683 p.bps = sc->bps;
684 p.msb = sc->msb;
685 p.sample_rate = sc->rate;
686 p.channels = sc->rchan;
687 error = sc->ops->trigger_input(sc->arg,
688 sc->rec.data,
689 sc->rec.data + sc->rec.len,
690 sc->rec.blksz,
691 audio_rintr, sc, &p);
692 } else {
693 mtx_enter(&audio_lock);
694 ptr = audio_buf_wgetblk(&sc->rec, &count);
695 error = sc->ops->start_input(sc->arg,
696 ptr, sc->rec.blksz, audio_rintr, sc);
697 mtx_leave(&audio_lock);
698 }
699 if (error)
700 printf("%s: failed to start recording\n", DEVNAME(sc)((sc)->dev.dv_xname));
701 }
702 return error;
703}
704
705int
706audio_stop_do(struct audio_softc *sc)
707{
708 if (sc->mode & AUMODE_PLAY0x01)
709 sc->ops->halt_output(sc->arg);
710 if (sc->mode & AUMODE_RECORD0x02)
711 sc->ops->halt_input(sc->arg);
712 DPRINTF("%s: stopped\n", DEVNAME(sc))do {} while(0);
713 return 0;
714}
715
716int
717audio_start(struct audio_softc *sc)
718{
719 sc->active = 1;
720 sc->play.xrun = sc->play.pos = sc->rec.xrun = sc->rec.pos = 0;
721 return audio_start_do(sc);
722}
723
724int
725audio_stop(struct audio_softc *sc)
726{
727 int error;
728
729 error = audio_stop_do(sc);
730 if (error)
731 return error;
732 audio_clear(sc);
733 sc->active = 0;
734 return 0;
735}
736
737int
738audio_canstart(struct audio_softc *sc)
739{
740 if (sc->active || sc->pause)
741 return 0;
742 if ((sc->mode & AUMODE_RECORD0x02) && sc->rec.used != 0)
743 return 0;
744 if ((sc->mode & AUMODE_PLAY0x01) && sc->play.used != sc->play.len)
745 return 0;
746 return 1;
747}
748
749int
750audio_setpar_blksz(struct audio_softc *sc,
751 struct audio_params *p, struct audio_params *r)
752{
753 unsigned int nr, np, max, min, mult;
754 unsigned int blk_mult, blk_max;
755
756 if (sc->ops->set_blksz) {
757 /*
758 * Don't allow block size of exceed half the buffer size
759 */
760 if (sc->mode & AUMODE_PLAY0x01) {
761 max = sc->play.datalen / 2 / (sc->pchan * sc->bps);
762 if (sc->round > max)
763 sc->round = max;
764 }
765 if (sc->mode & AUMODE_RECORD0x02) {
766 max = sc->rec.datalen / 2 / (sc->rchan * sc->bps);
767 if (sc->round > max)
768 sc->round = max;
769 }
770
771 sc->round = sc->ops->set_blksz(sc->arg, sc->mode,
772 p, r, sc->round);
773
774 DPRINTF("%s: block size set to: %u\n", DEVNAME(sc), sc->round)do {} while(0);
775 return 0;
776 }
777
778 /*
779 * get least multiplier of the number of frames per block
780 */
781 if (sc->ops->round_blocksize) {
782 blk_mult = sc->ops->round_blocksize(sc->arg, 1);
783 if (blk_mult == 0) {
784 printf("%s: 0x%x: bad block size multiplier\n",
785 DEVNAME(sc)((sc)->dev.dv_xname), blk_mult);
786 return ENODEV19;
787 }
788 } else
789 blk_mult = 1;
790 DPRINTF("%s: hw block size multiplier: %u\n", DEVNAME(sc), blk_mult)do {} while(0);
791 if (sc->mode & AUMODE_PLAY0x01) {
792 np = blk_mult / audio_gcd(sc->pchan * sc->bps, blk_mult);
793 if (!(sc->mode & AUMODE_RECORD0x02))
794 nr = np;
795 DPRINTF("%s: play number of frames multiplier: %u\n",do {} while(0)
796 DEVNAME(sc), np)do {} while(0);
797 }
798 if (sc->mode & AUMODE_RECORD0x02) {
799 nr = blk_mult / audio_gcd(sc->rchan * sc->bps, blk_mult);
800 if (!(sc->mode & AUMODE_PLAY0x01))
801 np = nr;
802 DPRINTF("%s: record number of frames multiplier: %u\n",do {} while(0)
803 DEVNAME(sc), nr)do {} while(0);
804 }
805 mult = nr * np / audio_gcd(nr, np);
806 DPRINTF("%s: least common number of frames multiplier: %u\n",do {} while(0)
807 DEVNAME(sc), mult)do {} while(0);
808
809 /*
810 * get minimum and maximum frames per block
811 */
812 if (sc->ops->round_blocksize)
813 blk_max = sc->ops->round_blocksize(sc->arg, AUDIO_BUFSZ65536);
814 else
815 blk_max = AUDIO_BUFSZ65536;
816 if ((sc->mode & AUMODE_PLAY0x01) && blk_max > sc->play.datalen / 2)
817 blk_max = sc->play.datalen / 2;
818 if ((sc->mode & AUMODE_RECORD0x02) && blk_max > sc->rec.datalen / 2)
819 blk_max = sc->rec.datalen / 2;
820 if (sc->mode & AUMODE_PLAY0x01) {
821 np = blk_max / (sc->pchan * sc->bps);
822 if (!(sc->mode & AUMODE_RECORD0x02))
823 nr = np;
824 }
825 if (sc->mode & AUMODE_RECORD0x02) {
826 nr = blk_max / (sc->rchan * sc->bps);
827 if (!(sc->mode & AUMODE_PLAY0x01))
828 np = nr;
829 }
830 max = np < nr ? np : nr;
831 max -= max % mult;
832 min = sc->rate / 1000 + mult - 1;
833 min -= min % mult;
834 DPRINTF("%s: frame number range: %u..%u\n", DEVNAME(sc), min, max)do {} while(0);
835 if (max < min) {
836 printf("%s: %u: bad max frame number\n", DEVNAME(sc)((sc)->dev.dv_xname), max);
837 return EIO5;
838 }
839
840 /*
841 * adjust the frame per block to match our constraints
842 */
843 sc->round += mult / 2;
844 sc->round -= sc->round % mult;
845 if (sc->round > max)
846 sc->round = max;
847 else if (sc->round < min)
848 sc->round = min;
849
850 return 0;
851}
852
853int
854audio_setpar_nblks(struct audio_softc *sc,
855 struct audio_params *p, struct audio_params *r)
856{
857 unsigned int max;
858
859 /*
860 * set buffer size (number of blocks)
861 */
862 if (sc->mode & AUMODE_PLAY0x01) {
863 max = sc->play.datalen / (sc->round * sc->pchan * sc->bps);
864 if (sc->play.nblks > max)
865 sc->play.nblks = max;
866 else if (sc->play.nblks < 2)
867 sc->play.nblks = 2;
868 if (sc->ops->set_nblks) {
869 sc->play.nblks = sc->ops->set_nblks(sc->arg, sc->mode,
870 p, sc->round, sc->play.nblks);
871 DPRINTF("%s: play nblks -> %u\n", DEVNAME(sc),do {} while(0)
872 sc->play.nblks)do {} while(0);
873 }
874 }
875 if (sc->mode & AUMODE_RECORD0x02) {
876 /*
877 * for recording, buffer size is not the latency (it's
878 * exactly one block), so let's get the maximum buffer
879 * size of maximum reliability during xruns
880 */
881 max = sc->rec.datalen / (sc->round * sc->rchan * sc->bps);
882 if (sc->ops->set_nblks) {
883 max = sc->ops->set_nblks(sc->arg, sc->mode,
884 r, sc->round, max);
885 DPRINTF("%s: rec nblks -> %u\n", DEVNAME(sc), max)do {} while(0);
886 }
887 sc->rec.nblks = max;
888 }
889 return 0;
890}
891
892int
893audio_setpar(struct audio_softc *sc)
894{
895 struct audio_params p, r;
896 int error;
897
898 DPRINTF("%s: setpar: req enc=%d bits=%d, bps=%d, msb=%d "do {} while(0)
899 "rate=%d, pchan=%d, rchan=%d, round=%u, nblks=%d\n",do {} while(0)
900 DEVNAME(sc), sc->sw_enc, sc->bits, sc->bps, sc->msb,do {} while(0)
901 sc->rate, sc->pchan, sc->rchan, sc->round, sc->play.nblks)do {} while(0);
902
903 /*
904 * check if requested parameters are in the allowed ranges
905 */
906 if (sc->mode & AUMODE_PLAY0x01) {
907 if (sc->pchan < 1)
908 sc->pchan = 1;
909 else if (sc->pchan > 64)
910 sc->pchan = 64;
911 }
912 if (sc->mode & AUMODE_RECORD0x02) {
913 if (sc->rchan < 1)
914 sc->rchan = 1;
915 else if (sc->rchan > 64)
916 sc->rchan = 64;
917 }
918 switch (sc->sw_enc) {
919 case AUDIO_ENCODING_ULAW1:
920 case AUDIO_ENCODING_ALAW2:
921 case AUDIO_ENCODING_SLINEAR_LE6:
922 case AUDIO_ENCODING_SLINEAR_BE7:
923 case AUDIO_ENCODING_ULINEAR_LE8:
924 case AUDIO_ENCODING_ULINEAR_BE9:
925 break;
926 default:
927 sc->sw_enc = AUDIO_ENCODING_SLINEAR_LE6;
928 }
929 if (sc->bits < 8)
930 sc->bits = 8;
931 else if (sc->bits > 32)
932 sc->bits = 32;
933 if (sc->bps < 1)
934 sc->bps = 1;
935 else if (sc->bps > 4)
936 sc->bps = 4;
937 if (sc->rate < 4000)
938 sc->rate = 4000;
939 else if (sc->rate > 192000)
940 sc->rate = 192000;
941
942 /*
943 * copy into struct audio_params, required by drivers
944 */
945 p.encoding = r.encoding = sc->sw_enc;
946 p.precision = r.precision = sc->bits;
947 p.bps = r.bps = sc->bps;
948 p.msb = r.msb = sc->msb;
949 p.sample_rate = r.sample_rate = sc->rate;
950 p.channels = sc->pchan;
951 r.channels = sc->rchan;
952
953 /*
954 * set parameters
955 */
956 error = sc->ops->set_params(sc->arg, sc->mode, sc->mode, &p, &r);
957 if (error)
958 return error;
959 if (sc->mode == (AUMODE_PLAY0x01 | AUMODE_RECORD0x02)) {
960 if (p.encoding != r.encoding ||
961 p.precision != r.precision ||
962 p.bps != r.bps ||
963 p.msb != r.msb ||
964 p.sample_rate != r.sample_rate) {
965 printf("%s: different play and record parameters "
966 "returned by hardware\n", DEVNAME(sc)((sc)->dev.dv_xname));
967 return ENODEV19;
968 }
969 }
970 if (sc->mode & AUMODE_PLAY0x01) {
971 sc->hw_enc = p.encoding;
972 sc->bits = p.precision;
973 sc->bps = p.bps;
974 sc->msb = p.msb;
975 sc->rate = p.sample_rate;
976 sc->pchan = p.channels;
977 }
978 if (sc->mode & AUMODE_RECORD0x02) {
979 sc->hw_enc = r.encoding;
980 sc->bits = r.precision;
981 sc->bps = r.bps;
982 sc->msb = r.msb;
983 sc->rate = r.sample_rate;
984 sc->rchan = r.channels;
985 }
986 if (sc->rate == 0 || sc->bps == 0 || sc->bits == 0) {
987 printf("%s: invalid parameters returned by hardware\n",
988 DEVNAME(sc)((sc)->dev.dv_xname));
989 return ENODEV19;
990 }
991 if (sc->ops->commit_settings) {
992 error = sc->ops->commit_settings(sc->arg);
993 if (error)
994 return error;
995 }
996
997 /*
998 * conversion from/to exotic/dead encoding, for drivers not supporting
999 * linear
1000 */
1001 switch (sc->hw_enc) {
1002 case AUDIO_ENCODING_SLINEAR_LE6:
1003 case AUDIO_ENCODING_SLINEAR_BE7:
1004 case AUDIO_ENCODING_ULINEAR_LE8:
1005 case AUDIO_ENCODING_ULINEAR_BE9:
1006 sc->sw_enc = sc->hw_enc;
1007 sc->conv_dec = sc->conv_enc = NULL((void *)0);
1008 break;
1009 case AUDIO_ENCODING_ULAW1:
1010#if BYTE_ORDER1234 == LITTLE_ENDIAN1234
1011 sc->sw_enc = AUDIO_ENCODING_SLINEAR_LE6;
1012#else
1013 sc->sw_enc = AUDIO_ENCODING_SLINEAR_BE7;
1014#endif
1015 if (sc->bits == 8) {
1016 sc->conv_enc = slinear8_to_mulaw;
1017 sc->conv_dec = mulaw_to_slinear8;
1018 } else if (sc->bits == 24) {
1019 sc->conv_enc = slinear24_to_mulaw24;
1020 sc->conv_dec = mulaw24_to_slinear24;
1021 } else {
1022 sc->sw_enc = sc->hw_enc;
1023 sc->conv_dec = sc->conv_enc = NULL((void *)0);
1024 }
1025 break;
1026 default:
1027 printf("%s: setpar: enc = %d, bits = %d: emulation skipped\n",
1028 DEVNAME(sc)((sc)->dev.dv_xname), sc->hw_enc, sc->bits);
1029 sc->sw_enc = sc->hw_enc;
1030 sc->conv_dec = sc->conv_enc = NULL((void *)0);
1031 }
1032 audio_calc_sil(sc);
1033
1034 error = audio_setpar_blksz(sc, &p, &r);
1035 if (error)
1036 return error;
1037
1038 error = audio_setpar_nblks(sc, &p, &r);
1039 if (error)
1040 return error;
1041
1042 /*
1043 * set buffer
1044 */
1045 if (sc->mode & AUMODE_PLAY0x01) {
1046 sc->play.blksz = sc->round * sc->pchan * sc->bps;
1047 sc->play.len = sc->play.nblks * sc->play.blksz;
1048 }
1049 if (sc->mode & AUMODE_RECORD0x02) {
1050 sc->rec.blksz = sc->round * sc->rchan * sc->bps;
1051 sc->rec.len = sc->rec.nblks * sc->rec.blksz;
1052 }
1053
1054 DPRINTF("%s: setpar: new enc=%d bits=%d, bps=%d, msb=%d "do {} while(0)
1055 "rate=%d, pchan=%d, rchan=%d, round=%u, nblks=%d\n",do {} while(0)
1056 DEVNAME(sc), sc->sw_enc, sc->bits, sc->bps, sc->msb,do {} while(0)
1057 sc->rate, sc->pchan, sc->rchan, sc->round, sc->play.nblks)do {} while(0);
1058 return 0;
1059}
1060
1061int
1062audio_ioc_start(struct audio_softc *sc)
1063{
1064 if (!sc->pause) {
1065 DPRINTF("%s: can't start: already started\n", DEVNAME(sc))do {} while(0);
1066 return EBUSY16;
1067 }
1068 if ((sc->mode & AUMODE_PLAY0x01) && sc->play.used != sc->play.len) {
1069 DPRINTF("%s: play buffer not ready\n", DEVNAME(sc))do {} while(0);
1070 return EBUSY16;
1071 }
1072 if ((sc->mode & AUMODE_RECORD0x02) && sc->rec.used != 0) {
1073 DPRINTF("%s: record buffer not ready\n", DEVNAME(sc))do {} while(0);
1074 return EBUSY16;
1075 }
1076 sc->pause = 0;
1077 return audio_start(sc);
1078}
1079
1080int
1081audio_ioc_stop(struct audio_softc *sc)
1082{
1083 if (sc->pause) {
1084 DPRINTF("%s: can't stop: not started\n", DEVNAME(sc))do {} while(0);
1085 return EBUSY16;
1086 }
1087 sc->pause = 1;
1088 if (sc->active)
1089 return audio_stop(sc);
1090 return 0;
1091}
1092
1093int
1094audio_ioc_getpar(struct audio_softc *sc, struct audio_swpar *p)
1095{
1096 p->rate = sc->rate;
1097 p->sig = sc->sw_enc == AUDIO_ENCODING_SLINEAR_LE6 ||
1098 sc->sw_enc == AUDIO_ENCODING_SLINEAR_BE7;
1099 p->le = sc->sw_enc == AUDIO_ENCODING_SLINEAR_LE6 ||
1100 sc->sw_enc == AUDIO_ENCODING_ULINEAR_LE8;
1101 p->bits = sc->bits;
1102 p->bps = sc->bps;
1103 p->msb = sc->msb;
1104 p->pchan = sc->pchan;
1105 p->rchan = sc->rchan;
1106 p->nblks = sc->play.nblks;
1107 p->round = sc->round;
1108 return 0;
1109}
1110
1111int
1112audio_ioc_setpar(struct audio_softc *sc, struct audio_swpar *p)
1113{
1114 int error, le, sig;
1115
1116 if (sc->active) {
1117 DPRINTF("%s: can't change params during dma\n",do {} while(0)
1118 DEVNAME(sc))do {} while(0);
1119 return EBUSY16;
1120 }
1121
1122 /*
1123 * copy desired parameters into the softc structure
1124 */
1125 if (p->sig != ~0U || p->le != ~0U || p->bits != ~0U) {
1126 sig = 1;
1127 le = (BYTE_ORDER1234 == LITTLE_ENDIAN1234);
1128 sc->bits = 16;
1129 sc->bps = 2;
1130 sc->msb = 1;
1131 if (p->sig != ~0U)
1132 sig = p->sig;
1133 if (p->le != ~0U)
1134 le = p->le;
1135 if (p->bits != ~0U) {
1136 sc->bits = p->bits;
1137 sc->bps = sc->bits <= 8 ?
1138 1 : (sc->bits <= 16 ? 2 : 4);
1139 if (p->bps != ~0U)
1140 sc->bps = p->bps;
1141 if (p->msb != ~0U)
1142 sc->msb = p->msb ? 1 : 0;
1143 }
1144 sc->sw_enc = (sig) ?
1145 (le ? AUDIO_ENCODING_SLINEAR_LE6 :
1146 AUDIO_ENCODING_SLINEAR_BE7) :
1147 (le ? AUDIO_ENCODING_ULINEAR_LE8 :
1148 AUDIO_ENCODING_ULINEAR_BE9);
1149 }
1150 if (p->rate != ~0)
1151 sc->rate = p->rate;
1152 if (p->pchan != ~0)
1153 sc->pchan = p->pchan;
1154 if (p->rchan != ~0)
1155 sc->rchan = p->rchan;
1156 if (p->round != ~0)
1157 sc->round = p->round;
1158 if (p->nblks != ~0)
1159 sc->play.nblks = p->nblks;
1160
1161 /*
1162 * if the device is not opened for playback or recording don't
1163 * touch the hardware yet (ex. if this is /dev/audioctlN)
1164 */
1165 if (sc->mode == 0)
1166 return 0;
1167
1168 /*
1169 * negotiate parameters with the hardware
1170 */
1171 error = audio_setpar(sc);
1172 if (error)
1173 return error;
1174 audio_clear(sc);
1175 if ((sc->mode & AUMODE_PLAY0x01) && sc->ops->init_output) {
1176 error = sc->ops->init_output(sc->arg,
1177 sc->play.data, sc->play.len);
1178 if (error)
1179 return error;
1180 }
1181 if ((sc->mode & AUMODE_RECORD0x02) && sc->ops->init_input) {
1182 error = sc->ops->init_input(sc->arg,
1183 sc->rec.data, sc->rec.len);
1184 if (error)
1185 return error;
1186 }
1187 return 0;
1188}
1189
1190int
1191audio_ioc_getstatus(struct audio_softc *sc, struct audio_status *p)
1192{
1193 p->mode = sc->mode;
1194 p->pause = sc->pause;
1195 p->active = sc->active;
1196 return 0;
1197}
1198
1199int
1200audio_match(struct device *parent, void *match, void *aux)
1201{
1202 struct audio_attach_args *sa = aux;
1203
1204 return (sa->type == AUDIODEV_TYPE_AUDIO0) ? 1 : 0;
1205}
1206
1207void
1208audio_attach(struct device *parent, struct device *self, void *aux)
1209{
1210 struct audio_softc *sc = (void *)self;
1211 struct audio_attach_args *sa = aux;
1212 struct audio_hw_if *ops = sa->hwif;
1213 struct mixer_devinfo *mi;
1214 struct mixer_ctrl *ent;
1215 void *arg = sa->hdl;
1216 int error;
1217
1218 printf("\n");
1219
1220#ifdef DIAGNOSTIC1
1221 if (ops == 0 ||
1222 ops->open == 0 ||
1223 ops->close == 0 ||
1224 ops->set_params == 0 ||
1225 (ops->start_output == 0 && ops->trigger_output == 0) ||
1226 (ops->start_input == 0 && ops->trigger_input == 0) ||
1227 ops->halt_output == 0 ||
1228 ops->halt_input == 0 ||
1229 ops->set_port == 0 ||
1230 ops->get_port == 0 ||
1231 ops->query_devinfo == 0 ||
1232 ops->get_props == 0) {
1233 printf("%s: missing method\n", DEVNAME(sc)((sc)->dev.dv_xname));
1234 sc->ops = 0;
1235 return;
1236 }
1237#endif
1238 sc->ops = ops;
1239 sc->arg = arg;
1240
1241#if NWSKBD1 > 0
1242 wskbd_mixer_init(sc);
1243#endif /* NWSKBD > 0 */
1244
1245 error = audio_buf_init(sc, &sc->play, AUMODE_PLAY0x01);
1246 if (error) {
1247 sc->ops = 0;
1248 printf("%s: could not allocate play buffer\n", DEVNAME(sc)((sc)->dev.dv_xname));
1249 return;
1250 }
1251 error = audio_buf_init(sc, &sc->rec, AUMODE_RECORD0x02);
1252 if (error) {
1253 audio_buf_done(sc, &sc->play);
1254 sc->ops = 0;
1255 printf("%s: could not allocate record buffer\n", DEVNAME(sc)((sc)->dev.dv_xname));
1256 return;
1257 }
1258
1259 sc->mix_softintr = softintr_establish(IPL_SOFTAUDIO0x5,
1260 audio_mixer_wakeup, sc);
1261 if (sc->mix_softintr == NULL((void *)0)) {
1262 audio_buf_done(sc, &sc->rec);
1263 audio_buf_done(sc, &sc->play);
1264 sc->ops = 0;
1265 printf("%s: can't establish softintr\n", DEVNAME(sc)((sc)->dev.dv_xname));
1266 return;
1267 }
1268
1269 /* set defaults */
1270#if BYTE_ORDER1234 == LITTLE_ENDIAN1234
1271 sc->sw_enc = AUDIO_ENCODING_SLINEAR_LE6;
1272#else
1273 sc->sw_enc = AUDIO_ENCODING_SLINEAR_BE7;
1274#endif
1275 sc->bits = 16;
1276 sc->bps = 2;
1277 sc->msb = 1;
1278 sc->rate = 48000;
1279 sc->pchan = 2;
1280 sc->rchan = 2;
1281 sc->round = 960;
1282 sc->play.nblks = 2;
1283 sc->play.pos = sc->play.xrun = sc->rec.pos = sc->rec.xrun = 0;
1284 sc->record_enable = MIXER_RECORD_ENABLE_SYSCTL2;
1285
1286 /*
1287 * allocate an array of mixer_ctrl structures to save the
1288 * mixer state and prefill them.
1289 */
1290
1291 mi = malloc(sizeof(struct mixer_devinfo), M_TEMP127, M_WAITOK0x0001);
1292
1293 mi->index = 0;
1294 while (1) {
1295 if (sc->ops->query_devinfo(sc->arg, mi) != 0)
1296 break;
1297 mi->index++;
1298 }
1299 sc->mix_nent = mi->index;
1300 sc->mix_ents = mallocarray(sc->mix_nent,
1301 sizeof(struct mixer_ctrl), M_DEVBUF2, M_WAITOK0x0001);
1302 sc->mix_evbuf = mallocarray(sc->mix_nent,
1303 sizeof(struct mixer_ev), M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008);
1304
1305 ent = sc->mix_ents;
1306 mi->index = 0;
1307 while (1) {
1308 if (sc->ops->query_devinfo(sc->arg, mi) != 0)
1309 break;
1310 switch (mi->type) {
1311 case AUDIO_MIXER_VALUE3:
1312 ent->un.value.num_channels = mi->un.v.num_channels;
1313 /* FALLTHROUGH */
1314 case AUDIO_MIXER_SET2:
1315 case AUDIO_MIXER_ENUM1:
1316 ent->dev = mi->index;
1317 ent->type = mi->type;
1318 }
1319 mi->index++;
1320 ent++;
1321 }
1322
1323 free(mi, M_TEMP127, sizeof(struct mixer_devinfo));
1324}
1325
1326int
1327audio_activate(struct device *self, int act)
1328{
1329 struct audio_softc *sc = (struct audio_softc *)self;
1330 int i;
1331
1332 switch (act) {
1333 case DVACT_QUIESCE2:
1334 /*
1335 * good drivers run play and rec handlers in a single
1336 * interrupt. Grab the lock to ensure we expose the same
1337 * sc->quiesce value to both play and rec handlers
1338 */
1339 mtx_enter(&audio_lock);
1340 sc->quiesce = 1;
1341 mtx_leave(&audio_lock);
1342
1343 /*
1344 * once sc->quiesce is set, interrupts may occur, but
1345 * counters are not advanced and consequently processes
1346 * keep sleeping.
1347 *
1348 * XXX: ensure read/write/ioctl don't start/stop
1349 * DMA at the same time, this needs a "ready" condvar
1350 */
1351 if (sc->mode != 0 && sc->active)
1352 audio_stop_do(sc);
1353
1354 /*
1355 * save mixer state
1356 */
1357 for (i = 0; i != sc->mix_nent; i++)
1358 sc->ops->get_port(sc->arg, sc->mix_ents + i);
1359
1360 DPRINTF("%s: quiesce: active = %d\n", DEVNAME(sc), sc->active)do {} while(0);
1361 break;
1362 case DVACT_WAKEUP5:
1363 DPRINTF("%s: wakeup: active = %d\n", DEVNAME(sc), sc->active)do {} while(0);
1364
1365 /*
1366 * restore mixer state
1367 */
1368 for (i = 0; i != sc->mix_nent; i++)
1369 sc->ops->set_port(sc->arg, sc->mix_ents + i);
1370
1371 /*
1372 * keep buffer usage the same, but set start pointer to
1373 * the beginning of the buffer.
1374 *
1375 * No need to grab the audio_lock as DMA is stopped and
1376 * this is the only thread running (caller ensures this)
1377 */
1378 sc->quiesce = 0;
1379 wakeup(&sc->quiesce);
1380
1381 if (sc->mode != 0) {
1382 if (audio_setpar(sc) != 0)
1383 break;
1384 if (sc->mode & AUMODE_PLAY0x01) {
1385 sc->play.start = 0;
1386 audio_fill_sil(sc, sc->play.data, sc->play.len);
1387 }
1388 if (sc->mode & AUMODE_RECORD0x02) {
1389 sc->rec.start = sc->rec.len - sc->rec.used;
1390 audio_fill_sil(sc, sc->rec.data, sc->rec.len);
1391 }
1392 if (sc->active)
1393 audio_start_do(sc);
1394 }
1395 break;
1396 }
1397 return 0;
1398}
1399
1400int
1401audio_detach(struct device *self, int flags)
1402{
1403 struct audio_softc *sc = (struct audio_softc *)self;
1404 int maj, mn;
1405
1406 DPRINTF("%s: audio_detach: flags = %d\n", DEVNAME(sc), flags)do {} while(0);
1407
1408 wakeup(&sc->quiesce);
1409
1410 /* locate the major number */
1411 for (maj = 0; maj < nchrdev; maj++)
1412 if (cdevsw[maj].d_open == audioopen)
1413 break;
1414 /*
1415 * Nuke the vnodes for any open instances, calls close but as
1416 * close uses device_lookup, it returns EXIO and does nothing
1417 */
1418 mn = self->dv_unit;
1419 vdevgone(maj, mn | AUDIO_DEV_AUDIO0, mn | AUDIO_DEV_AUDIO0, VCHR);
1420 vdevgone(maj, mn | AUDIO_DEV_AUDIOCTL0xc0, mn | AUDIO_DEV_AUDIOCTL0xc0, VCHR);
1421
1422 /*
1423 * The close() method did nothing, quickly halt DMA (normally
1424 * parent is already gone, and code below is no-op), and wake-up
1425 * user-land blocked in read/write/ioctl, which return EIO.
1426 */
1427 if (sc->mode != 0) {
1428 if (sc->active) {
1429 wakeup(&sc->play.blocking);
1430 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/audio.c"
, 1430, "_kernel_lock_held()"))
;
1431 mtx_enter(&audio_lock);
1432 wakeup(&sc->rec.blocking);
1433 selwakeup(&sc->play.sel);
1434 selwakeup(&sc->rec.sel);
1435 mtx_leave(&audio_lock);
1436 audio_stop(sc);
1437 }
1438 sc->ops->close(sc->arg);
1439 sc->mode = 0;
1440 }
1441 if (sc->mix_isopen) {
1442 wakeup(&sc->mix_blocking);
1443 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/audio.c"
, 1443, "_kernel_lock_held()"))
;
1444 mtx_enter(&audio_lock);
1445 selwakeup(&sc->mix_sel);
1446 mtx_leave(&audio_lock);
1447 }
1448 klist_invalidate(&sc->play.sel.si_note);
1449 klist_invalidate(&sc->rec.sel.si_note);
1450 klist_invalidate(&sc->mix_sel.si_note);
1451
1452 /* free resources */
1453 softintr_disestablish(sc->mix_softintr);
1454 free(sc->mix_evbuf, M_DEVBUF2, sc->mix_nent * sizeof(struct mixer_ev));
1455 free(sc->mix_ents, M_DEVBUF2, sc->mix_nent * sizeof(struct mixer_ctrl));
1456 audio_buf_done(sc, &sc->play);
1457 audio_buf_done(sc, &sc->rec);
1458 return 0;
1459}
1460
1461int
1462audio_submatch(struct device *parent, void *match, void *aux)
1463{
1464 struct cfdata *cf = match;
1465
1466 return (cf->cf_driver == &audio_cd);
1467}
1468
1469struct device *
1470audio_attach_mi(struct audio_hw_if *ops, void *arg, struct device *dev)
1471{
1472 struct audio_attach_args aa;
1473
1474 aa.type = AUDIODEV_TYPE_AUDIO0;
1475 aa.hwif = ops;
1476 aa.hdl = arg;
1477
1478 /*
1479 * attach this driver to the caller (hardware driver), this
1480 * checks the kernel config and possibly calls audio_attach()
1481 */
1482 return config_found_sm(dev, &aa, audioprint, audio_submatch);
1483}
1484
1485int
1486audioprint(void *aux, const char *pnp)
1487{
1488 struct audio_attach_args *arg = aux;
1489 const char *type;
1490
1491 if (pnp != NULL((void *)0)) {
1492 switch (arg->type) {
1493 case AUDIODEV_TYPE_AUDIO0:
1494 type = "audio";
1495 break;
1496 case AUDIODEV_TYPE_OPL2:
1497 type = "opl";
1498 break;
1499 case AUDIODEV_TYPE_MPU3:
1500 type = "mpu";
1501 break;
1502 default:
1503 panic("audioprint: unknown type %d", arg->type);
1504 }
1505 printf("%s at %s", type, pnp);
1506 }
1507 return UNCONF1;
1508}
1509
1510int
1511audio_open(struct audio_softc *sc, int flags)
1512{
1513 int error;
1514 int props;
1515
1516 if (sc->mode)
1517 return EBUSY16;
1518 error = sc->ops->open(sc->arg, flags);
1519 if (error)
1520 return error;
1521 sc->active = 0;
1522 sc->pause = 1;
1523 sc->rec.blocking = 0;
1524 sc->play.blocking = 0;
1525 sc->mode = 0;
1526 if (flags & FWRITE0x0002)
1527 sc->mode |= AUMODE_PLAY0x01;
1528 if (flags & FREAD0x0001)
1529 sc->mode |= AUMODE_RECORD0x02;
1530 props = sc->ops->get_props(sc->arg);
1531 if (sc->mode == (AUMODE_PLAY0x01 | AUMODE_RECORD0x02)) {
1532 if (!(props & AUDIO_PROP_FULLDUPLEX0x01)) {
1533 error = ENOTTY25;
1534 goto bad;
1535 }
1536 if (sc->ops->setfd) {
1537 error = sc->ops->setfd(sc->arg, 1);
1538 if (error)
1539 goto bad;
1540 }
1541 }
1542
1543 if (sc->ops->speaker_ctl) {
1544 /*
1545 * XXX: what is this used for?
1546 */
1547 sc->ops->speaker_ctl(sc->arg,
1548 (sc->mode & AUMODE_PLAY0x01) ? SPKR_ON1 : SPKR_OFF0);
1549 }
1550
1551 error = audio_setpar(sc);
1552 if (error)
1553 goto bad;
1554 audio_clear(sc);
1555
1556 /*
1557 * allow read(2)/write(2) to automatically start DMA, without
1558 * the need for ioctl(), to make /dev/audio usable in scripts
1559 */
1560 sc->pause = 0;
1561 return 0;
1562bad:
1563 sc->ops->close(sc->arg);
1564 sc->mode = 0;
1565 return error;
1566}
1567
1568int
1569audio_drain(struct audio_softc *sc)
1570{
1571 int error, xrun;
1572 unsigned char *ptr;
1573 size_t count, bpf;
1574
1575 DPRINTF("%s: drain: mode = %d, pause = %d, active = %d, used = %zu\n",do {} while(0)
1576 DEVNAME(sc), sc->mode, sc->pause, sc->active, sc->play.used)do {} while(0);
1577 if (!(sc->mode & AUMODE_PLAY0x01) || sc->pause)
1578 return 0;
1579
1580 /* discard partial samples, required by audio_fill_sil() */
1581 mtx_enter(&audio_lock);
1582 bpf = sc->pchan * sc->bps;
1583 sc->play.used -= sc->play.used % bpf;
1584 if (sc->play.used == 0) {
1585 mtx_leave(&audio_lock);
1586 return 0;
1587 }
1588
1589 if (!sc->active) {
1590 /*
1591 * dma not started yet because buffer was not full
1592 * enough to start automatically. Pad it and start now.
1593 */
1594 for (;;) {
1595 ptr = audio_buf_wgetblk(&sc->play, &count);
1596 if (count == 0)
1597 break;
1598 audio_fill_sil(sc, ptr, count);
1599 audio_buf_wcommit(&sc->play, count);
1600 }
1601 mtx_leave(&audio_lock);
1602 error = audio_start(sc);
1603 if (error)
1604 return error;
1605 mtx_enter(&audio_lock);
1606 }
1607
1608 xrun = sc->play.xrun;
1609 while (sc->play.xrun == xrun) {
1610 DPRINTF("%s: drain: used = %zu, xrun = %d\n",do {} while(0)
1611 DEVNAME(sc), sc->play.used, sc->play.xrun)do {} while(0);
1612
1613 /*
1614 * set a 5 second timeout, in case interrupts don't
1615 * work, useful only for debugging drivers
1616 */
1617 sc->play.blocking = 1;
1618 error = msleep_nsec(&sc->play.blocking, &audio_lock,
1619 PWAIT32 | PCATCH0x100, "au_dr", SEC_TO_NSEC(5));
1620 if (!(sc->dev.dv_flags & DVF_ACTIVE0x0001))
1621 error = EIO5;
1622 if (error) {
1623 DPRINTF("%s: drain, err = %d\n", DEVNAME(sc), error)do {} while(0);
1624 break;
1625 }
1626 }
1627 mtx_leave(&audio_lock);
1628 return error;
1629}
1630
1631int
1632audio_close(struct audio_softc *sc)
1633{
1634 audio_drain(sc);
1635 if (sc->active)
1636 audio_stop(sc);
1637 sc->ops->close(sc->arg);
1638 sc->mode = 0;
1639 DPRINTF("%s: close: done\n", DEVNAME(sc))do {} while(0);
1640 return 0;
1641}
1642
1643int
1644audio_read(struct audio_softc *sc, struct uio *uio, int ioflag)
1645{
1646 unsigned char *ptr;
1647 size_t count;
1648 int error;
1649
1650 DPRINTFN(1, "%s: read: resid = %zd\n", DEVNAME(sc), uio->uio_resid)do {} while(0);
1651
1652 /* block if quiesced */
1653 while (sc->quiesce)
1654 tsleep_nsec(&sc->quiesce, 0, "au_qrd", INFSLP0xffffffffffffffffULL);
1655
1656 /* start automatically if audio_ioc_start() was never called */
1657 if (audio_canstart(sc)) {
1658 error = audio_start(sc);
1659 if (error)
1660 return error;
1661 }
1662
1663 mtx_enter(&audio_lock);
1664
1665 /* if there is no data then sleep */
1666 while (sc->rec.used == 0) {
1667 if (ioflag & IO_NDELAY0x10) {
1668 mtx_leave(&audio_lock);
1669 return EWOULDBLOCK35;
1670 }
1671 DPRINTFN(1, "%s: read sleep\n", DEVNAME(sc))do {} while(0);
1672 sc->rec.blocking = 1;
1673 error = msleep_nsec(&sc->rec.blocking,
1674 &audio_lock, PWAIT32 | PCATCH0x100, "au_rd", INFSLP0xffffffffffffffffULL);
1675 if (!(sc->dev.dv_flags & DVF_ACTIVE0x0001))
1676 error = EIO5;
1677 if (error) {
1678 DPRINTF("%s: read woke up error = %d\n",do {} while(0)
1679 DEVNAME(sc), error)do {} while(0);
1680 mtx_leave(&audio_lock);
1681 return error;
1682 }
1683 }
1684
1685 /* at this stage, there is data to transfer */
1686 while (uio->uio_resid > 0 && sc->rec.used > 0) {
1687 ptr = audio_buf_rgetblk(&sc->rec, &count);
1688 if (count > uio->uio_resid)
1689 count = uio->uio_resid;
1690 mtx_leave(&audio_lock);
1691 DPRINTFN(1, "%s: read: start = %zu, count = %zu\n",do {} while(0)
1692 DEVNAME(sc), ptr - sc->rec.data, count)do {} while(0);
1693 if (sc->conv_dec)
1694 sc->conv_dec(ptr, count);
1695 error = uiomove(ptr, count, uio);
1696 if (error)
1697 return error;
1698 mtx_enter(&audio_lock);
1699 audio_buf_rdiscard(&sc->rec, count);
1700 }
1701 mtx_leave(&audio_lock);
1702 return 0;
1703}
1704
1705int
1706audio_write(struct audio_softc *sc, struct uio *uio, int ioflag)
1707{
1708 unsigned char *ptr;
1709 size_t count;
1710 int error;
1711
1712 DPRINTFN(1, "%s: write: resid = %zd\n", DEVNAME(sc), uio->uio_resid)do {} while(0);
1713
1714 /* block if quiesced */
1715 while (sc->quiesce)
1716 tsleep_nsec(&sc->quiesce, 0, "au_qwr", INFSLP0xffffffffffffffffULL);
1717
1718 /*
1719 * if IO_NDELAY flag is set then check if there is enough room
1720 * in the buffer to store at least one byte. If not then don't
1721 * start the write process.
1722 */
1723 mtx_enter(&audio_lock);
1724 if (uio->uio_resid > 0 && (ioflag & IO_NDELAY0x10)) {
1725 if (sc->play.used == sc->play.len) {
1726 mtx_leave(&audio_lock);
1727 return EWOULDBLOCK35;
1728 }
1729 }
1730
1731 while (uio->uio_resid > 0) {
1732 while (1) {
1733 ptr = audio_buf_wgetblk(&sc->play, &count);
1734 if (count > 0)
1735 break;
1736 if (ioflag & IO_NDELAY0x10) {
1737 /*
1738 * At this stage at least one byte is already
1739 * moved so we do not return EWOULDBLOCK
1740 */
1741 mtx_leave(&audio_lock);
1742 return 0;
1743 }
1744 DPRINTFN(1, "%s: write sleep\n", DEVNAME(sc))do {} while(0);
1745 sc->play.blocking = 1;
1746 error = msleep_nsec(&sc->play.blocking,
1747 &audio_lock, PWAIT32 | PCATCH0x100, "au_wr", INFSLP0xffffffffffffffffULL);
1748 if (!(sc->dev.dv_flags & DVF_ACTIVE0x0001))
1749 error = EIO5;
1750 if (error) {
1751 DPRINTF("%s: write woke up error = %d\n",do {} while(0)
1752 DEVNAME(sc), error)do {} while(0);
1753 mtx_leave(&audio_lock);
1754 return error;
1755 }
1756 }
1757 if (count > uio->uio_resid)
1758 count = uio->uio_resid;
1759 mtx_leave(&audio_lock);
1760 error = uiomove(ptr, count, uio);
1761 if (error)
1762 return 0;
1763 if (sc->conv_enc) {
1764 sc->conv_enc(ptr, count);
1765 DPRINTFN(1, "audio_write: converted count = %zu\n",do {} while(0)
1766 count)do {} while(0);
1767 }
1768 if (sc->ops->copy_output)
1769 sc->ops->copy_output(sc->arg, count);
1770
1771 mtx_enter(&audio_lock);
1772 audio_buf_wcommit(&sc->play, count);
1773
1774 /* start automatically if audio_ioc_start() was never called */
1775 if (audio_canstart(sc)) {
1776 mtx_leave(&audio_lock);
1777 error = audio_start(sc);
1778 if (error)
1779 return error;
1780 mtx_enter(&audio_lock);
1781 }
1782 }
1783 mtx_leave(&audio_lock);
1784 return 0;
1785}
1786
1787int
1788audio_getdev(struct audio_softc *sc, struct audio_device *adev)
1789{
1790 memset(adev, 0, sizeof(struct audio_device))__builtin_memset((adev), (0), (sizeof(struct audio_device)));
1791 if (sc->dev.dv_parent == NULL((void *)0))
1792 return EIO5;
1793 strlcpy(adev->name, sc->dev.dv_parent->dv_xname, MAX_AUDIO_DEV_LEN16);
1794 return 0;
1795}
1796
1797int
1798audio_ioctl(struct audio_softc *sc, unsigned long cmd, void *addr)
1799{
1800 struct audio_pos *ap;
1801 int error = 0;
1802
1803 /* block if quiesced */
1804 while (sc->quiesce)
1805 tsleep_nsec(&sc->quiesce, 0, "au_qio", INFSLP0xffffffffffffffffULL);
1806
1807 switch (cmd) {
1808 case FIONBIO((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((126)))
:
1809 /* All handled in the upper FS layer. */
1810 break;
1811 case AUDIO_GETPOS((unsigned long)0x40000000 | ((sizeof(struct audio_pos) &
0x1fff) << 16) | ((('A')) << 8) | ((35)))
:
1812 mtx_enter(&audio_lock);
1813 ap = (struct audio_pos *)addr;
1814 ap->play_pos = sc->play.pos;
1815 ap->play_xrun = sc->play.xrun;
1816 ap->rec_pos = sc->rec.pos;
1817 ap->rec_xrun = sc->rec.xrun;
1818 mtx_leave(&audio_lock);
1819 break;
1820 case AUDIO_START((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('A')) << 8) | ((38)))
:
1821 return audio_ioc_start(sc);
1822 case AUDIO_STOP((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('A')) << 8) | ((39)))
:
1823 return audio_ioc_stop(sc);
1824 case AUDIO_SETPAR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct audio_swpar) & 0x1fff) << 16) | ((('A')) <<
8) | ((37)))
:
1825 error = audio_ioc_setpar(sc, (struct audio_swpar *)addr);
1826 break;
1827 case AUDIO_GETPAR((unsigned long)0x40000000 | ((sizeof(struct audio_swpar) &
0x1fff) << 16) | ((('A')) << 8) | ((36)))
:
1828 error = audio_ioc_getpar(sc, (struct audio_swpar *)addr);
1829 break;
1830 case AUDIO_GETSTATUS((unsigned long)0x40000000 | ((sizeof(struct audio_status) &
0x1fff) << 16) | ((('A')) << 8) | ((40)))
:
1831 error = audio_ioc_getstatus(sc, (struct audio_status *)addr);
1832 break;
1833 case AUDIO_GETDEV((unsigned long)0x40000000 | ((sizeof(struct audio_device) &
0x1fff) << 16) | ((('A')) << 8) | ((27)))
:
1834 error = audio_getdev(sc, (struct audio_device *)addr);
1835 break;
1836 default:
1837 DPRINTF("%s: unknown ioctl 0x%lx\n", DEVNAME(sc), cmd)do {} while(0);
1838 error = ENOTTY25;
1839 break;
1840 }
1841 return error;
1842}
1843
1844void
1845audio_event(struct audio_softc *sc, int addr)
1846{
1847 struct mixer_ev *e;
1848
1849 mtx_enter(&audio_lock);
1850 if (sc->mix_isopen) {
1851 e = sc->mix_evbuf + addr;
1852 if (!e->pending) {
1853 e->pending = 1;
1854 e->next = sc->mix_pending;
1855 sc->mix_pending = e;
1856 }
1857 softintr_schedule(sc->mix_softintr)do { struct x86_soft_intrhand *__sih = (sc->mix_softintr);
struct x86_soft_intr *__si = __sih->sih_intrhead; mtx_enter
(&__si->softintr_lock); if (__sih->sih_pending == 0
) { do { (__sih)->sih_q.tqe_next = ((void *)0); (__sih)->
sih_q.tqe_prev = (&__si->softintr_q)->tqh_last; *(&
__si->softintr_q)->tqh_last = (__sih); (&__si->softintr_q
)->tqh_last = &(__sih)->sih_q.tqe_next; } while (0)
; __sih->sih_pending = 1; softintr(__si->softintr_ssir)
; } mtx_leave(&__si->softintr_lock); } while ( 0)
;
1858 }
1859 mtx_leave(&audio_lock);
1860}
1861
1862int
1863audio_mixer_devinfo(struct audio_softc *sc, struct mixer_devinfo *devinfo)
1864{
1865 if (devinfo->index < sc->mix_nent)
1866 return sc->ops->query_devinfo(sc->arg, devinfo);
1867
1868 devinfo->next = -1;
1869 devinfo->prev = -1;
1870 switch (devinfo->index - sc->mix_nent) {
1871 case MIXER_RECORD0:
1872 strlcpy(devinfo->label.name, AudioCrecord"record", MAX_AUDIO_DEV_LEN16);
1873 devinfo->type = AUDIO_MIXER_CLASS0;
1874 devinfo->mixer_class = -1;
1875 break;
1876 case MIXER_RECORD_ENABLE1:
1877 strlcpy(devinfo->label.name, "enable", MAX_AUDIO_DEV_LEN16);
1878 devinfo->type = AUDIO_MIXER_ENUM1;
1879 devinfo->mixer_class = MIXER_RECORD0 + sc->mix_nent;
1880 devinfo->un.e.num_mem = 3;
1881 devinfo->un.e.member[0].ord = MIXER_RECORD_ENABLE_OFF0;
1882 strlcpy(devinfo->un.e.member[0].label.name, "off",
1883 MAX_AUDIO_DEV_LEN16);
1884 devinfo->un.e.member[1].ord = MIXER_RECORD_ENABLE_ON1;
1885 strlcpy(devinfo->un.e.member[1].label.name, "on",
1886 MAX_AUDIO_DEV_LEN16);
1887 devinfo->un.e.member[2].ord = MIXER_RECORD_ENABLE_SYSCTL2;
1888 strlcpy(devinfo->un.e.member[2].label.name, "sysctl",
1889 MAX_AUDIO_DEV_LEN16);
1890 break;
1891 default:
1892 return EINVAL22;
1893 }
1894
1895 return 0;
1896}
1897
1898int
1899audio_mixer_get(struct audio_softc *sc, struct mixer_ctrl *c)
1900{
1901 if (c->dev < sc->mix_nent)
1902 return sc->ops->get_port(sc->arg, c);
1903
1904 switch (c->dev - sc->mix_nent) {
1905 case MIXER_RECORD0:
1906 return EBADF9;
1907 case MIXER_RECORD_ENABLE1:
1908 c->un.ord = sc->record_enable;
1909 break;
1910 default:
1911 return EINVAL22;
1912 }
1913
1914 return 0;
1915}
1916
1917int
1918audio_mixer_set(struct audio_softc *sc, struct mixer_ctrl *c, struct proc *p)
1919{
1920 int error;
1921
1922 if (c->dev < sc->mix_nent) {
1923 error = sc->ops->set_port(sc->arg, c);
1924 if (error)
1925 return error;
1926 if (sc->ops->commit_settings)
1927 return sc->ops->commit_settings(sc->arg);
1928 audio_event(sc, c->dev);
1929 return 0;
1930 }
1931
1932 switch (c->dev - sc->mix_nent) {
1933 case MIXER_RECORD0:
1934 return EBADF9;
1935 case MIXER_RECORD_ENABLE1:
1936 switch (c->un.ord) {
1937 case MIXER_RECORD_ENABLE_OFF0:
1938 case MIXER_RECORD_ENABLE_ON1:
1939 case MIXER_RECORD_ENABLE_SYSCTL2:
1940 break;
1941 default:
1942 return EINVAL22;
1943 }
1944 if (suser(p) == 0)
1945 sc->record_enable = c->un.ord;
1946 break;
1947 default:
1948 return EINVAL22;
1949 }
1950
1951 return 0;
1952}
1953
1954int
1955audio_ioctl_mixer(struct audio_softc *sc, unsigned long cmd, void *addr,
1956 struct proc *p)
1957{
1958 /* block if quiesced */
1959 while (sc->quiesce)
1960 tsleep_nsec(&sc->quiesce, 0, "mix_qio", INFSLP0xffffffffffffffffULL);
1961
1962 switch (cmd) {
1963 case FIONBIO((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((126)))
:
1964 /* All handled in the upper FS layer. */
1965 break;
1966 case AUDIO_MIXER_DEVINFO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(mixer_devinfo_t) & 0x1fff) << 16) | ((('M')) <<
8) | ((2)))
:
1967 return audio_mixer_devinfo(sc, addr);
1968 case AUDIO_MIXER_READ(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(mixer_ctrl_t) & 0x1fff) << 16) | ((('M')) <<
8) | ((0)))
:
1969 return audio_mixer_get(sc, addr);
1970 case AUDIO_MIXER_WRITE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(mixer_ctrl_t) & 0x1fff) << 16) | ((('M')) <<
8) | ((1)))
:
1971 return audio_mixer_set(sc, addr, p);
1972 default:
1973 return ENOTTY25;
1974 }
1975 return 0;
1976}
1977
1978int
1979audio_mixer_read(struct audio_softc *sc, struct uio *uio, int ioflag)
1980{
1981 struct mixer_ev *e;
1982 int data;
1983 int error;
1984
1985 DPRINTF("%s: mixer read: resid = %zd\n", DEVNAME(sc), uio->uio_resid)do {} while(0);
1986
1987 /* block if quiesced */
1988 while (sc->quiesce)
1989 tsleep_nsec(&sc->quiesce, 0, "mix_qrd", INFSLP0xffffffffffffffffULL);
1990
1991 mtx_enter(&audio_lock);
1992
1993 /* if there are no events then sleep */
1994 while (!sc->mix_pending) {
1995 if (ioflag & IO_NDELAY0x10) {
1996 mtx_leave(&audio_lock);
1997 return EWOULDBLOCK35;
1998 }
1999 DPRINTF("%s: mixer read sleep\n", DEVNAME(sc))do {} while(0);
2000 sc->mix_blocking = 1;
2001 error = msleep_nsec(&sc->mix_blocking,
2002 &audio_lock, PWAIT32 | PCATCH0x100, "mix_rd", INFSLP0xffffffffffffffffULL);
2003 if (!(sc->dev.dv_flags & DVF_ACTIVE0x0001))
2004 error = EIO5;
2005 if (error) {
2006 DPRINTF("%s: mixer read woke up error = %d\n",do {} while(0)
2007 DEVNAME(sc), error)do {} while(0);
2008 mtx_leave(&audio_lock);
2009 return error;
2010 }
2011 }
2012
2013 /* at this stage, there is an event to transfer */
2014 while (uio->uio_resid >= sizeof(int) && sc->mix_pending) {
2015 e = sc->mix_pending;
2016 sc->mix_pending = e->next;
2017 e->pending = 0;
2018 data = e - sc->mix_evbuf;
2019 mtx_leave(&audio_lock);
2020 DPRINTF("%s: mixer read: %u\n", DEVNAME(sc), data)do {} while(0);
2021 error = uiomove(&data, sizeof(int), uio);
2022 if (error)
2023 return error;
2024 mtx_enter(&audio_lock);
2025 }
2026
2027 mtx_leave(&audio_lock);
2028 return 0;
2029}
2030
2031int
2032audio_mixer_poll(struct audio_softc *sc, int events, struct proc *p)
2033{
2034 int revents = 0;
2035
2036 mtx_enter(&audio_lock);
2037 if (sc->mix_isopen && sc->mix_pending)
2038 revents |= events & (POLLIN0x0001 | POLLRDNORM0x0040);
2039 if (revents == 0) {
2040 if (events & (POLLIN0x0001 | POLLRDNORM0x0040))
2041 selrecord(p, &sc->mix_sel);
2042 }
2043 mtx_leave(&audio_lock);
2044 return revents;
2045}
2046
2047int
2048audio_mixer_open(struct audio_softc *sc, int flags)
2049{
2050 DPRINTF("%s: flags = 0x%x\n", __func__, flags)do {} while(0);
2051
2052 if (flags & FREAD0x0001) {
2053 if (sc->mix_isopen)
2054 return EBUSY16;
2055 sc->mix_isopen = 1;
2056 }
2057 return 0;
2058}
2059
2060int
2061audio_mixer_close(struct audio_softc *sc, int flags)
2062{
2063 int i;
2064
2065 DPRINTF("%s: flags = 0x%x\n", __func__, flags)do {} while(0);
2066
2067 if (flags & FREAD0x0001) {
2068 sc->mix_isopen = 0;
2069
2070 mtx_enter(&audio_lock);
2071 sc->mix_pending = NULL((void *)0);
2072 for (i = 0; i < sc->mix_nent; i++)
2073 sc->mix_evbuf[i].pending = 0;
2074 mtx_leave(&audio_lock);
2075 }
2076 return 0;
2077}
2078
2079int
2080audio_poll(struct audio_softc *sc, int events, struct proc *p)
2081{
2082 int revents = 0;
2083
2084 mtx_enter(&audio_lock);
2085 if ((sc->mode & AUMODE_RECORD0x02) && sc->rec.used > 0)
2086 revents |= events & (POLLIN0x0001 | POLLRDNORM0x0040);
2087 if ((sc->mode & AUMODE_PLAY0x01) && sc->play.used < sc->play.len)
2088 revents |= events & (POLLOUT0x0004 | POLLWRNORM0x0004);
2089 if (revents == 0) {
2090 if (events & (POLLIN0x0001 | POLLRDNORM0x0040))
2091 selrecord(p, &sc->rec.sel);
2092 if (events & (POLLOUT0x0004 | POLLWRNORM0x0004))
2093 selrecord(p, &sc->play.sel);
2094 }
2095 mtx_leave(&audio_lock);
2096 return revents;
2097}
2098
2099int
2100audioopen(dev_t dev, int flags, int mode, struct proc *p)
2101{
2102 struct audio_softc *sc;
2103 int error;
2104
2105 sc = (struct audio_softc *)device_lookup(&audio_cd, AUDIO_UNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0x0f)
);
2106 if (sc == NULL((void *)0))
2107 return ENXIO6;
2108 if (sc->ops == NULL((void *)0))
2109 error = ENXIO6;
2110 else {
2111 switch (AUDIO_DEV(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xf0)
) {
2112 case AUDIO_DEV_AUDIO0:
2113 error = audio_open(sc, flags);
2114 break;
2115 case AUDIO_DEV_AUDIOCTL0xc0:
2116 error = audio_mixer_open(sc, flags);
2117 break;
2118 default:
2119 error = ENXIO6;
2120 }
2121 }
2122 device_unref(&sc->dev);
2123 return error;
2124}
2125
2126int
2127audioclose(dev_t dev, int flags, int ifmt, struct proc *p)
2128{
2129 struct audio_softc *sc;
2130 int error;
2131
2132 sc = (struct audio_softc *)device_lookup(&audio_cd, AUDIO_UNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0x0f)
);
2133 if (sc == NULL((void *)0))
2134 return ENXIO6;
2135 switch (AUDIO_DEV(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xf0)
) {
2136 case AUDIO_DEV_AUDIO0:
2137 error = audio_close(sc);
2138 break;
2139 case AUDIO_DEV_AUDIOCTL0xc0:
2140 error = audio_mixer_close(sc, flags);
2141 break;
2142 default:
2143 error = ENXIO6;
2144 }
2145 device_unref(&sc->dev);
2146 return error;
2147}
2148
2149int
2150audioread(dev_t dev, struct uio *uio, int ioflag)
2151{
2152 struct audio_softc *sc;
2153 int error;
2154
2155 sc = (struct audio_softc *)device_lookup(&audio_cd, AUDIO_UNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0x0f)
);
2156 if (sc == NULL((void *)0))
2157 return ENXIO6;
2158 switch (AUDIO_DEV(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xf0)
) {
2159 case AUDIO_DEV_AUDIO0:
2160 error = audio_read(sc, uio, ioflag);
2161 break;
2162 case AUDIO_DEV_AUDIOCTL0xc0:
2163 error = audio_mixer_read(sc, uio, ioflag);
2164 break;
2165 default:
2166 error = ENXIO6;
2167 }
2168 device_unref(&sc->dev);
2169 return error;
2170}
2171
2172int
2173audiowrite(dev_t dev, struct uio *uio, int ioflag)
2174{
2175 struct audio_softc *sc;
2176 int error;
2177
2178 sc = (struct audio_softc *)device_lookup(&audio_cd, AUDIO_UNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0x0f)
);
2179 if (sc == NULL((void *)0))
2180 return ENXIO6;
2181 switch (AUDIO_DEV(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xf0)
) {
2182 case AUDIO_DEV_AUDIO0:
2183 error = audio_write(sc, uio, ioflag);
2184 break;
2185 case AUDIO_DEV_AUDIOCTL0xc0:
2186 error = ENODEV19;
2187 break;
2188 default:
2189 error = ENXIO6;
2190 }
2191 device_unref(&sc->dev);
2192 return error;
2193}
2194
2195int
2196audioioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
2197{
2198 struct audio_softc *sc;
2199 int error;
2200
2201 sc = (struct audio_softc *)device_lookup(&audio_cd, AUDIO_UNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0x0f)
);
2202 if (sc == NULL((void *)0))
2203 return ENXIO6;
2204 switch (AUDIO_DEV(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xf0)
) {
2205 case AUDIO_DEV_AUDIO0:
2206 error = audio_ioctl(sc, cmd, addr);
2207 break;
2208 case AUDIO_DEV_AUDIOCTL0xc0:
2209 if (cmd == AUDIO_SETPAR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct audio_swpar) & 0x1fff) << 16) | ((('A')) <<
8) | ((37)))
&& sc->mode != 0) {
2210 error = EBUSY16;
2211 break;
2212 }
2213 if (cmd == AUDIO_START((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('A')) << 8) | ((38)))
|| cmd == AUDIO_STOP((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('A')) << 8) | ((39)))
) {
2214 error = ENXIO6;
2215 break;
2216 }
2217 if (cmd == AUDIO_MIXER_DEVINFO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(mixer_devinfo_t) & 0x1fff) << 16) | ((('M')) <<
8) | ((2)))
||
2218 cmd == AUDIO_MIXER_READ(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(mixer_ctrl_t) & 0x1fff) << 16) | ((('M')) <<
8) | ((0)))
||
2219 cmd == AUDIO_MIXER_WRITE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(mixer_ctrl_t) & 0x1fff) << 16) | ((('M')) <<
8) | ((1)))
)
2220 error = audio_ioctl_mixer(sc, cmd, addr, p);
2221 else
2222 error = audio_ioctl(sc, cmd, addr);
2223 break;
2224 default:
2225 error = ENXIO6;
2226 }
2227 device_unref(&sc->dev);
2228 return error;
2229}
2230
2231int
2232audiopoll(dev_t dev, int events, struct proc *p)
2233{
2234 struct audio_softc *sc;
2235 int revents;
2236
2237 sc = (struct audio_softc *)device_lookup(&audio_cd, AUDIO_UNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0x0f)
);
2238 if (sc == NULL((void *)0))
2239 return POLLERR0x0008;
2240 switch (AUDIO_DEV(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xf0)
) {
2241 case AUDIO_DEV_AUDIO0:
2242 revents = audio_poll(sc, events, p);
2243 break;
2244 case AUDIO_DEV_AUDIOCTL0xc0:
2245 revents = audio_mixer_poll(sc, events, p);
2246 break;
2247 default:
2248 revents = 0;
2249 break;
2250 }
2251 device_unref(&sc->dev);
2252 return revents;
2253}
2254
2255int
2256audiokqfilter(dev_t dev, struct knote *kn)
2257{
2258 struct audio_softc *sc;
2259 struct klist *klist;
1
'klist' declared without an initial value
2260 int error;
2261
2262 sc = (struct audio_softc *)device_lookup(&audio_cd, AUDIO_UNIT(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0x0f)
);
2263 if (sc == NULL((void *)0))
2
Assuming 'sc' is not equal to NULL
3
Taking false branch
2264 return ENXIO6;
2265 error = 0;
2266 switch (AUDIO_DEV(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8)) & 0xf0)
) {
4
'Default' branch taken. Execution continues on line 2294
2267 case AUDIO_DEV_AUDIO0:
2268 switch (kn->kn_filterkn_kevent.filter) {
2269 case EVFILT_READ(-1):
2270 klist = &sc->rec.sel.si_note;
2271 kn->kn_fop = &audioread_filtops;
2272 break;
2273 case EVFILT_WRITE(-2):
2274 klist = &sc->play.sel.si_note;
2275 kn->kn_fop = &audiowrite_filtops;
2276 break;
2277 default:
2278 error = EINVAL22;
2279 goto done;
2280 }
2281 break;
2282 case AUDIO_DEV_AUDIOCTL0xc0:
2283 switch (kn->kn_filterkn_kevent.filter) {
2284 case EVFILT_READ(-1):
2285 klist = &sc->mix_sel.si_note;
2286 kn->kn_fop = &audioctlread_filtops;
2287 break;
2288 default:
2289 error = EINVAL22;
2290 goto done;
2291 }
2292 break;
2293 }
2294 kn->kn_hook = sc;
2295
2296 mtx_enter(&audio_lock);
2297 klist_insert_locked(klist, kn);
5
1st function call argument is an uninitialized value
2298 mtx_leave(&audio_lock);
2299done:
2300 device_unref(&sc->dev);
2301 return error;
2302}
2303
2304void
2305filt_audiordetach(struct knote *kn)
2306{
2307 struct audio_softc *sc = kn->kn_hook;
2308
2309 mtx_enter(&audio_lock);
2310 klist_remove_locked(&sc->rec.sel.si_note, kn);
2311 mtx_leave(&audio_lock);
2312}
2313
2314int
2315filt_audioread(struct knote *kn, long hint)
2316{
2317 struct audio_softc *sc = kn->kn_hook;
2318 int retval = 0;
2319
2320 if ((hint & NOTE_SUBMIT0x01000000) == 0)
2321 mtx_enter(&audio_lock);
2322 retval = (sc->mode & AUMODE_RECORD0x02) && (sc->rec.used > 0);
2323 if ((hint & NOTE_SUBMIT0x01000000) == 0)
2324 mtx_leave(&audio_lock);
2325
2326 return retval;
2327}
2328
2329void
2330filt_audiowdetach(struct knote *kn)
2331{
2332 struct audio_softc *sc = kn->kn_hook;
2333
2334 mtx_enter(&audio_lock);
2335 klist_remove_locked(&sc->play.sel.si_note, kn);
2336 mtx_leave(&audio_lock);
2337}
2338
2339int
2340filt_audiowrite(struct knote *kn, long hint)
2341{
2342 struct audio_softc *sc = kn->kn_hook;
2343 int retval = 0;
2344
2345 if ((hint & NOTE_SUBMIT0x01000000) == 0)
2346 mtx_enter(&audio_lock);
2347 retval = (sc->mode & AUMODE_PLAY0x01) && (sc->play.used < sc->play.len);
2348 if ((hint & NOTE_SUBMIT0x01000000) == 0)
2349 mtx_leave(&audio_lock);
2350
2351 return retval;
2352}
2353
2354void
2355filt_audioctlrdetach(struct knote *kn)
2356{
2357 struct audio_softc *sc = kn->kn_hook;
2358
2359 mtx_enter(&audio_lock);
2360 klist_remove_locked(&sc->mix_sel.si_note, kn);
2361 mtx_leave(&audio_lock);
2362}
2363
2364int
2365filt_audioctlread(struct knote *kn, long hint)
2366{
2367 struct audio_softc *sc = kn->kn_hook;
2368 int retval = 0;
2369
2370 if ((hint & NOTE_SUBMIT0x01000000) == 0)
2371 mtx_enter(&audio_lock);
2372 retval = (sc->mix_isopen && sc->mix_pending);
2373 if ((hint & NOTE_SUBMIT0x01000000) == 0)
2374 mtx_leave(&audio_lock);
2375
2376 return retval;
2377}
2378
2379#if NWSKBD1 > 0
2380int
2381wskbd_initmute(struct audio_softc *sc, struct mixer_devinfo *vol)
2382{
2383 struct mixer_devinfo *mi;
2384 int index = -1;
2385
2386 mi = malloc(sizeof(struct mixer_devinfo), M_TEMP127, M_WAITOK0x0001);
2387
2388 for (mi->index = vol->next; mi->index != -1; mi->index = mi->next) {
2389 if (sc->ops->query_devinfo(sc->arg, mi) != 0)
2390 break;
2391 if (strcmp(mi->label.name, AudioNmute"mute") == 0) {
2392 index = mi->index;
2393 break;
2394 }
2395 }
2396
2397 free(mi, M_TEMP127, sizeof(struct mixer_devinfo));
2398 return index;
2399}
2400
2401int
2402wskbd_initvol(struct audio_softc *sc, struct wskbd_vol *vol, char *cn, char *dn)
2403{
2404 struct mixer_devinfo *dev, *cls;
2405
2406 vol->val = vol->mute = -1;
2407 dev = malloc(sizeof(struct mixer_devinfo), M_TEMP127, M_WAITOK0x0001);
2408 cls = malloc(sizeof(struct mixer_devinfo), M_TEMP127, M_WAITOK0x0001);
2409
2410 for (dev->index = 0; ; dev->index++) {
2411 if (sc->ops->query_devinfo(sc->arg, dev) != 0)
2412 break;
2413 if (dev->type != AUDIO_MIXER_VALUE3)
2414 continue;
2415 cls->index = dev->mixer_class;
2416 if (sc->ops->query_devinfo(sc->arg, cls) != 0)
2417 continue;
2418 if (strcmp(cls->label.name, cn) == 0 &&
2419 strcmp(dev->label.name, dn) == 0) {
2420 vol->val = dev->index;
2421 vol->nch = dev->un.v.num_channels;
2422 vol->step = dev->un.v.delta > 8 ? dev->un.v.delta : 8;
2423 vol->mute = wskbd_initmute(sc, dev);
2424 vol->val_pending = vol->mute_pending = 0;
2425 DPRINTF("%s: wskbd using %s.%s%s\n", DEVNAME(sc),do {} while(0)
2426 cn, dn, vol->mute >= 0 ? ", mute control" : "")do {} while(0);
2427 break;
2428 }
2429 }
2430
2431 free(cls, M_TEMP127, sizeof(struct mixer_devinfo));
2432 free(dev, M_TEMP127, sizeof(struct mixer_devinfo));
2433 return (vol->val != -1);
2434}
2435
2436void
2437wskbd_mixer_init(struct audio_softc *sc)
2438{
2439 static struct {
2440 char *cn, *dn;
2441 } spkr_names[] = {
2442 {AudioCoutputs"outputs", AudioNmaster"master"},
2443 {AudioCinputs"inputs", AudioNdac"dac"},
2444 {AudioCoutputs"outputs", AudioNdac"dac"},
2445 {AudioCoutputs"outputs", AudioNoutput"output"}
2446 }, mic_names[] = {
2447 {AudioCrecord"record", AudioNrecord"record"},
2448 {AudioCrecord"record", AudioNvolume"volume"},
2449 {AudioCinputs"inputs", AudioNrecord"record"},
2450 {AudioCinputs"inputs", AudioNvolume"volume"},
2451 {AudioCinputs"inputs", AudioNinput"input"}
2452 };
2453 int i;
2454
2455 if (sc->dev.dv_unit != 0) {
2456 DPRINTF("%s: not configuring wskbd keys\n", DEVNAME(sc))do {} while(0);
2457 return;
2458 }
2459 for (i = 0; i < sizeof(spkr_names) / sizeof(spkr_names[0]); i++) {
2460 if (wskbd_initvol(sc, &sc->spkr,
2461 spkr_names[i].cn, spkr_names[i].dn))
2462 break;
2463 }
2464 for (i = 0; i < sizeof(mic_names) / sizeof(mic_names[0]); i++) {
2465 if (wskbd_initvol(sc, &sc->mic,
2466 mic_names[i].cn, mic_names[i].dn))
2467 break;
2468 }
2469 task_set(&sc->wskbd_task, wskbd_mixer_cb, sc);
2470}
2471
2472void
2473wskbd_mixer_update(struct audio_softc *sc, struct wskbd_vol *vol)
2474{
2475 struct mixer_ctrl ctrl;
2476 int val_pending, mute_pending, i, gain, error, s;
2477
2478 s = spltty()splraise(0x9);
2479 val_pending = vol->val_pending;
2480 vol->val_pending = 0;
2481 mute_pending = vol->mute_pending;
2482 vol->mute_pending = 0;
2483 splx(s)spllower(s);
2484
2485 if (sc->ops == NULL((void *)0))
2486 return;
2487 if (vol->mute >= 0 && mute_pending) {
2488 ctrl.dev = vol->mute;
2489 ctrl.type = AUDIO_MIXER_ENUM1;
2490 error = sc->ops->get_port(sc->arg, &ctrl);
2491 if (error) {
2492 DPRINTF("%s: get mute err = %d\n", DEVNAME(sc), error)do {} while(0);
2493 return;
2494 }
2495 switch (mute_pending) {
2496 case WSKBD_MUTE_TOGGLE1:
2497 ctrl.un.ord = !ctrl.un.ord;
2498 break;
2499 case WSKBD_MUTE_DISABLE2:
2500 ctrl.un.ord = 0;
2501 break;
2502 case WSKBD_MUTE_ENABLE3:
2503 ctrl.un.ord = 1;
2504 break;
2505 }
2506 DPRINTFN(1, "%s: wskbd mute setting to %d\n",do {} while(0)
2507 DEVNAME(sc), ctrl.un.ord)do {} while(0);
2508 error = sc->ops->set_port(sc->arg, &ctrl);
2509 if (error) {
2510 DPRINTF("%s: set mute err = %d\n", DEVNAME(sc), error)do {} while(0);
2511 return;
2512 }
2513 audio_event(sc, vol->mute);
2514 }
2515 if (vol->val >= 0 && val_pending) {
2516 ctrl.dev = vol->val;
2517 ctrl.type = AUDIO_MIXER_VALUE3;
2518 ctrl.un.value.num_channels = vol->nch;
2519 error = sc->ops->get_port(sc->arg, &ctrl);
2520 if (error) {
2521 DPRINTF("%s: get mute err = %d\n", DEVNAME(sc), error)do {} while(0);
2522 return;
2523 }
2524 for (i = 0; i < vol->nch; i++) {
2525 gain = ctrl.un.value.level[i] + vol->step * val_pending;
2526 if (gain > AUDIO_MAX_GAIN255)
2527 gain = AUDIO_MAX_GAIN255;
2528 else if (gain < AUDIO_MIN_GAIN0)
2529 gain = AUDIO_MIN_GAIN0;
2530 ctrl.un.value.level[i] = gain;
2531 DPRINTFN(1, "%s: wskbd level %d set to %d\n",do {} while(0)
2532 DEVNAME(sc), i, gain)do {} while(0);
2533 }
2534 error = sc->ops->set_port(sc->arg, &ctrl);
2535 if (error) {
2536 DPRINTF("%s: set vol err = %d\n", DEVNAME(sc), error)do {} while(0);
2537 return;
2538 }
2539 audio_event(sc, vol->val);
2540 }
2541}
2542
2543void
2544wskbd_mixer_cb(void *arg)
2545{
2546 struct audio_softc *sc = arg;
2547
2548 wskbd_mixer_update(sc, &sc->spkr);
2549 wskbd_mixer_update(sc, &sc->mic);
2550 device_unref(&sc->dev);
2551}
2552
2553int
2554wskbd_set_mixermute(long mute, long out)
2555{
2556 struct audio_softc *sc;
2557 struct wskbd_vol *vol;
2558
2559 sc = (struct audio_softc *)device_lookup(&audio_cd, 0);
2560 if (sc == NULL((void *)0))
2561 return ENODEV19;
2562 vol = out ? &sc->spkr : &sc->mic;
2563 vol->mute_pending = mute ? WSKBD_MUTE_ENABLE3 : WSKBD_MUTE_DISABLE2;
2564 if (!task_add(systq, &sc->wskbd_task))
2565 device_unref(&sc->dev);
2566 return 0;
2567}
2568
2569int
2570wskbd_set_mixervolume(long dir, long out)
2571{
2572 struct audio_softc *sc;
2573 struct wskbd_vol *vol;
2574
2575 sc = (struct audio_softc *)device_lookup(&audio_cd, 0);
2576 if (sc == NULL((void *)0))
2577 return ENODEV19;
2578 vol = out ? &sc->spkr : &sc->mic;
2579 if (dir == 0)
2580 vol->mute_pending ^= WSKBD_MUTE_TOGGLE1;
2581 else
2582 vol->val_pending += dir;
2583 if (!task_add(systq, &sc->wskbd_task))
2584 device_unref(&sc->dev);
2585 return 0;
2586}
2587#endif /* NWSKBD > 0 */