xref: /dragonfly/sys/dev/sound/pcm/sound.h (revision 7d9c5de0a918cd65147f60c34857832be332ea6c)
1 /*-
2  * Copyright (c) 2005-2009 Ariff Abdullah <ariff@FreeBSD.org>
3  * Copyright (c) 1999 Cameron Grant <cg@FreeBSD.org>
4  * Copyright (c) 1995 Hannu Savolainen
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD: head/sys/dev/sound/pcm/sound.h 274035 2014-11-03 11:11:45Z bapt $
29  */
30 
31 /*
32  * first, include kernel header files.
33  */
34 
35 #ifndef _OS_H_
36 #define _OS_H_
37 
38 #ifdef _KERNEL
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/filio.h>
42 #include <sys/sockio.h>
43 #include <sys/fcntl.h>
44 #include <sys/proc.h>
45 #include <sys/kernel.h> /* for DATA_SET */
46 #include <sys/module.h>
47 #include <sys/conf.h>
48 #include <sys/file.h>
49 #include <sys/uio.h>
50 #include <sys/syslog.h>
51 #include <sys/errno.h>
52 #include <sys/malloc.h>
53 #include <sys/bus.h>
54 #include <sys/rman.h>
55 #include <sys/limits.h>
56 #include <sys/mman.h>
57 #include <sys/poll.h>
58 #include <sys/sbuf.h>
59 #include <sys/soundcard.h>
60 #include <sys/sysctl.h>
61 #include <sys/kobj.h>
62 #include <vm/vm.h>
63 #include <vm/pmap.h>
64 
65 #include <sys/lock.h>
66 #include <sys/mplock2.h>
67 #include <sys/mutex.h>
68 #include <sys/condvar.h>
69 #include <sys/taskqueue.h>
70 
71 struct pcm_channel;
72 struct pcm_feeder;
73 struct snd_dbuf;
74 struct snd_mixer;
75 
76 #include <dev/sound/pcm/buffer.h>
77 #include <dev/sound/pcm/matrix.h>
78 #include <dev/sound/pcm/matrix_map.h>
79 #include <dev/sound/pcm/channel.h>
80 #include <dev/sound/pcm/feeder.h>
81 #include <dev/sound/pcm/mixer.h>
82 #include <dev/sound/pcm/dsp.h>
83 #include <dev/sound/clone.h>
84 #include <dev/sound/unit.h>
85 
86 #define   PCM_SOFTC_SIZE      (sizeof(struct snddev_info))
87 
88 #define SND_STATUSLEN         64
89 
90 #define SOUND_MODVER          5
91 
92 #define SOUND_MINVER          SOUND_MODVER
93 #define SOUND_PREFVER         SOUND_MODVER
94 #define SOUND_MAXVER          SOUND_MODVER
95 
96 /*
97  * Minor number encoding: 0xFFFF00FF
98  *        unit                  0x000000FF
99  *        chan                  0x07FF0000
100  *        devtype               0xF8000000
101  */
102 
103 #define SND_U_MASK  0x000000FF
104 #define SND_C_MASK  0x07FF0000
105 #define SND_D_MASK  0xF8000000
106 
107 #define PCMMAXUNIT  255
108 #define PCMMAXDEV   31
109 #define PCMMAXCHAN  2047
110 #define PCMMAXCLONE PCMMAXCHAN
111 
112 /*
113  *
114  */
115 #define PCMUNIT(x)            (minor(x) & 0x00FF)
116 #define PCMSUBUNIT(x)                   ((minor(x) >> 16) & 0x07FF)
117 #define PCMDEV(x)             ((minor(x) >> 27) & 0x001F)
118 
119 #define PCMUNIT_DEFAULT                 0x00FF
120 
121 #define PCMMKMINOR(u, d, sub) (snd_u2unit(u) | snd_c2unit(sub) | snd_d2unit(d))
122 
123 #define snd_unit2u(m)                   ((m) & 0x00FF)
124 #define snd_unit2c(m)                   (((m) >> 16) & 0x07FF)
125 #define snd_unit2d(m)                   (((m) >> 27) & 0x001F)
126 
127 #define snd_u2unit(u)                   ((u) & 0x00FF)
128 #define snd_c2unit(c)                   (((c) & 0x07FF) << 16)
129 #define snd_d2unit(d)                   (((d) & 0x001F) << 27)
130 
131 #define snd_mkunit(u, d, c)   (snd_u2unit(u) | snd_d2unit(d) | snd_c2unit(c))
132 
133 /*
134  * By design, limit possible channels for each direction.
135  */
136 #define SND_MAXHWCHAN                   256
137 #define SND_MAXVCHANS                   SND_MAXHWCHAN
138 
139 #define SD_F_SIMPLEX                    0x00000001
140 #define SD_F_AUTOVCHAN                  0x00000002
141 #define SD_F_SOFTPCMVOL                 0x00000004
142 /*
143  * Obsolete due to better matrixing
144  */
145 #if 0
146 #define SD_F_PSWAPLR                    0x00000008
147 #define SD_F_RSWAPLR                    0x00000010
148 #endif
149 #define SD_F_DYING            0x00000008
150 #define SD_F_SUICIDE                    0x00000010
151 #define SD_F_BUSY             0x00000020
152 #define SD_F_MPSAFE           0x00000040
153 #define SD_F_REGISTERED                 0x00000080
154 #define SD_F_BITPERFECT                 0x00000100
155 #define SD_F_VPC              0x00000200          /* volume-per-channel */
156 #define SD_F_EQ                         0x00000400          /* EQ */
157 #define SD_F_EQ_ENABLED                 0x00000800          /* EQ enabled */
158 #define SD_F_EQ_BYPASSED      0x00001000          /* EQ bypassed */
159 #define SD_F_EQ_PC            0x00002000          /* EQ per-channel */
160 
161 #define SD_F_EQ_DEFAULT                 (SD_F_EQ | SD_F_EQ_ENABLED)
162 #define SD_F_EQ_MASK                    (SD_F_EQ | SD_F_EQ_ENABLED |            \
163                                          SD_F_EQ_BYPASSED | SD_F_EQ_PC)
164 
165 #define SD_F_PRIO_RD                    0x10000000
166 #define SD_F_PRIO_WR                    0x20000000
167 #define SD_F_PRIO_SET                   (SD_F_PRIO_RD | SD_F_PRIO_WR)
168 #define SD_F_DIR_SET                    0x40000000
169 #define SD_F_TRANSIENT                  0xf0000000
170 
171 #define SD_F_BITS             "\020"                                            \
172                                         "\001SIMPLEX"                                     \
173                                         "\002AUTOVCHAN"                                   \
174                                         "\003SOFTPCMVOL"                        \
175                                         "\004DYING"                                       \
176                                         "\005SUICIDE"                                     \
177                                         "\006BUSY"                                        \
178                                         "\007MPSAFE"                                      \
179                                         "\010REGISTERED"                        \
180                                         "\011BITPERFECT"                        \
181                                         "\012VPC"                               \
182                                         "\013EQ"                                \
183                                         "\014EQ_ENABLED"                        \
184                                         "\015EQ_BYPASSED"                       \
185                                         "\016EQ_PC"                                       \
186                                         "\035PRIO_RD"                                     \
187                                         "\036PRIO_WR"                                     \
188                                         "\037DIR_SET"
189 
190 #define PCM_ALIVE(x)                    ((x) != NULL && (x)->lock != NULL &&    \
191                                          !((x)->flags & SD_F_DYING))
192 #define PCM_REGISTERED(x)     (PCM_ALIVE(x) &&                        \
193                                          ((x)->flags & SD_F_REGISTERED))
194 
195 /* many variables should be reduced to a range. Here define a macro */
196 #define RANGE(var, low, high) (var) = \
197           (((var)<(low))? (low) : ((var)>(high))? (high) : (var))
198 #define DSP_BUFFSIZE (8192)
199 
200 /* make figuring out what a format is easier. got AFMT_STEREO already */
201 #define AFMT_32BIT (AFMT_S32_LE | AFMT_S32_BE | AFMT_U32_LE | AFMT_U32_BE)
202 #define AFMT_24BIT (AFMT_S24_LE | AFMT_S24_BE | AFMT_U24_LE | AFMT_U24_BE)
203 #define AFMT_16BIT (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE)
204 #define AFMT_G711  (AFMT_MU_LAW | AFMT_A_LAW)
205 #define AFMT_8BIT (AFMT_G711 | AFMT_U8 | AFMT_S8)
206 #define AFMT_SIGNED (AFMT_S32_LE | AFMT_S32_BE | AFMT_S24_LE | AFMT_S24_BE | \
207                               AFMT_S16_LE | AFMT_S16_BE | AFMT_S8)
208 #define AFMT_BIGENDIAN (AFMT_S32_BE | AFMT_U32_BE | AFMT_S24_BE | AFMT_U24_BE | \
209                               AFMT_S16_BE | AFMT_U16_BE)
210 
211 #define AFMT_CONVERTIBLE      (AFMT_8BIT | AFMT_16BIT | AFMT_24BIT |  \
212                                          AFMT_32BIT)
213 
214 /* Supported vchan mixing formats */
215 #define AFMT_VCHAN            (AFMT_CONVERTIBLE & ~AFMT_G711)
216 
217 #define AFMT_PASSTHROUGH                AFMT_AC3
218 #define AFMT_PASSTHROUGH_RATE           48000
219 #define AFMT_PASSTHROUGH_CHANNEL        2
220 #define AFMT_PASSTHROUGH_EXTCHANNEL     0
221 
222 /*
223  * We're simply using unused, contiguous bits from various AFMT_ definitions.
224  * ~(0xb00ff7ff)
225  */
226 #define AFMT_ENCODING_MASK    0xf00fffff
227 #define AFMT_CHANNEL_MASK     0x01f00000
228 #define AFMT_CHANNEL_SHIFT    20
229 #define AFMT_CHANNEL_MAX      0x7f
230 #define AFMT_EXTCHANNEL_MASK  0x0e000000
231 #define AFMT_EXTCHANNEL_SHIFT 25
232 
233 #define AFMT_ENCODING(v)      ((v) & AFMT_ENCODING_MASK)
234 
235 #define AFMT_EXTCHANNEL(v)    (((v) & AFMT_EXTCHANNEL_MASK) >>        \
236                                         AFMT_EXTCHANNEL_SHIFT)
237 
238 #define AFMT_CHANNEL(v)                 (((v) & AFMT_CHANNEL_MASK) >>           \
239                                         AFMT_CHANNEL_SHIFT)
240 
241 #define AFMT_BIT(v)           (((v) & AFMT_32BIT) ? 32 :              \
242                                         (((v) & AFMT_24BIT) ? 24 :              \
243                                         ((((v) & AFMT_16BIT) ||                           \
244                                         ((v) & AFMT_PASSTHROUGH)) ? 16 : 8)))
245 
246 #define AFMT_BPS(v)           (AFMT_BIT(v) >> 3)
247 #define AFMT_ALIGN(v)                   (AFMT_BPS(v) * AFMT_CHANNEL(v))
248 
249 #define SND_FORMAT(f, c, e)   (AFMT_ENCODING(f) |           \
250                                         (((c) << AFMT_CHANNEL_SHIFT) &                    \
251                                         AFMT_CHANNEL_MASK) |                              \
252                                         (((e) << AFMT_EXTCHANNEL_SHIFT) &       \
253                                         AFMT_EXTCHANNEL_MASK))
254 
255 #define AFMT_U8_NE  AFMT_U8
256 #define AFMT_S8_NE  AFMT_S8
257 
258 #define AFMT_SIGNED_NE        (AFMT_S8_NE | AFMT_S16_NE | AFMT_S24_NE | AFMT_S32_NE)
259 
260 #define AFMT_NE               (AFMT_SIGNED_NE | AFMT_U8_NE | AFMT_U16_NE |      \
261                                AFMT_U24_NE | AFMT_U32_NE)
262 
263 /*
264  * Minor numbers for the sound driver.
265  *
266  * Unfortunately Creative called the codec chip of SB as a DSP. For this
267  * reason the /dev/dsp is reserved for digitized audio use. There is a
268  * device for true DSP processors but it will be called something else.
269  * In v3.0 it's /dev/sndproc but this could be a temporary solution.
270  */
271 
272 #define SND_DEV_CTL 0         /* Control port /dev/mixer */
273 #define SND_DEV_SEQ 1         /* Sequencer /dev/sequencer */
274 #define SND_DEV_MIDIN         2         /* Raw midi access */
275 #define SND_DEV_DSP 3         /* Digitized voice /dev/dsp */
276 #define SND_DEV_AUDIO         4         /* Sparc compatible /dev/audio */
277 #define SND_DEV_DSP16         5         /* Like /dev/dsp but 16 bits/sample */
278 #define SND_DEV_STATUS        6         /* /dev/sndstat */
279                                         /* #7 not in use now. */
280 #define SND_DEV_SEQ2          8         /* /dev/sequencer, level 2 interface */
281 #define SND_DEV_SNDPROC 9     /* /dev/sndproc for programmable devices */
282 #define SND_DEV_PSS SND_DEV_SNDPROC /* ? */
283 #define SND_DEV_NORESET       10
284 
285 #define SND_DEV_DSPHW_PLAY    11        /* specific playback channel */
286 #define SND_DEV_DSPHW_VPLAY   12        /* specific virtual playback channel */
287 #define SND_DEV_DSPHW_REC     13        /* specific record channel */
288 #define SND_DEV_DSPHW_VREC    14        /* specific virtual record channel */
289 
290 #define SND_DEV_DSPHW_CD      15        /* s16le/stereo 44100Hz CD */
291 
292 /*
293  * OSSv4 compatible device. For now, it serve no purpose and
294  * the cloning itself will forward the request to ordinary /dev/dsp
295  * instead.
296  */
297 #define SND_DEV_DSP_MMAP      16        /* /dev/dsp_mmap     */
298 #define SND_DEV_DSP_AC3                 17        /* /dev/dsp_ac3      */
299 #define SND_DEV_DSP_MULTICH   18        /* /dev/dsp_multich  */
300 #define SND_DEV_DSP_SPDIFOUT  19        /* /dev/dsp_spdifout */
301 #define SND_DEV_DSP_SPDIFIN   20        /* /dev/dsp_spdifin  */
302 
303 #define SND_DEV_LAST                    SND_DEV_DSP_SPDIFIN
304 #define SND_DEV_MAX           PCMMAXDEV
305 
306 #define DSP_DEFAULT_SPEED     8000
307 
308 #define ON                    1
309 #define OFF                   0
310 
311 extern int pcm_veto_load;
312 extern int snd_unit;
313 extern int snd_maxautovchans;
314 extern int snd_verbose;
315 extern devclass_t pcm_devclass;
316 extern struct unrhdr *pcmsg_unrhdr;
317 
318 /*
319  * some macros for debugging purposes
320  * DDB/DEB to enable/disable debugging stuff
321  * BVDDB   to enable debugging when bootverbose
322  */
323 #define BVDDB(x) if (bootverbose) x
324 
325 #ifndef DEB
326 #define DEB(x)
327 #endif
328 
329 SYSCTL_DECL(_hw_snd);
330 
331 int pcm_setvchans(struct snddev_info *d, int direction, int newcnt, int num);
332 int pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction,
333     pid_t pid, char *comm, int devunit);
334 int pcm_chnrelease(struct pcm_channel *c);
335 int pcm_chnref(struct pcm_channel *c, int ref);
336 int pcm_inprog(struct snddev_info *d, int delta);
337 
338 struct pcm_channel *pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, int dir, int num, void *devinfo);
339 int pcm_chn_destroy(struct pcm_channel *ch);
340 int pcm_chn_add(struct snddev_info *d, struct pcm_channel *ch);
341 int pcm_chn_remove(struct snddev_info *d, struct pcm_channel *ch);
342 
343 int pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo);
344 unsigned int pcm_getbuffersize(device_t dev, unsigned int minbufsz, unsigned int deflt, unsigned int maxbufsz);
345 int pcm_register(device_t dev, void *devinfo, int numplay, int numrec);
346 int pcm_unregister(device_t dev);
347 int pcm_setstatus(device_t dev, char *str);
348 u_int32_t pcm_getflags(device_t dev);
349 void pcm_setflags(device_t dev, u_int32_t val);
350 void *pcm_getdevinfo(device_t dev);
351 
352 
353 int snd_setup_intr(device_t dev, struct resource *res, int flags,
354                        driver_intr_t hand, void *param, void **cookiep);
355 
356 void *snd_mtxcreate(const char *desc, const char *type);
357 void snd_mtxfree(void *m);
358 void snd_mtxassert(void *m);
359 #define   snd_mtxlock(m) lockmgr(m, LK_EXCLUSIVE)
360 #define   snd_mtxunlock(m) lockmgr(m, LK_RELEASE)
361 
362 typedef int (*sndstat_handler)(struct sbuf *s, device_t dev, int verbose);
363 int sndstat_acquire(struct thread *td);
364 int sndstat_release(struct thread *td);
365 int sndstat_register(device_t dev, char *str, sndstat_handler handler);
366 int sndstat_registerfile(char *str);
367 int sndstat_unregister(device_t dev);
368 int sndstat_unregisterfile(char *str);
369 
370 #define SND_DECLARE_FILE(version) \
371           _SND_DECLARE_FILE(__LINE__, version)
372 
373 #define _SND_DECLARE_FILE(uniq, version) \
374           __SND_DECLARE_FILE(uniq, version)
375 
376 #define __SND_DECLARE_FILE(uniq, version) \
377           static char sndstat_vinfo[] = version; \
378           SYSINIT(sdf_ ## uniq, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, sndstat_registerfile, sndstat_vinfo); \
379           SYSUNINIT(sdf_ ## uniq, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, sndstat_unregisterfile, sndstat_vinfo)
380 
381 /* usage of flags in device config entry (config file) */
382 #define DV_F_DRQ_MASK         0x00000007          /* mask for secondary drq */
383 #define   DV_F_DUAL_DMA       0x00000010          /* set to use secondary dma channel */
384 
385 /* ought to be made obsolete but still used by mss */
386 #define   DV_F_DEV_MASK       0x0000ff00          /* force device type/class */
387 #define   DV_F_DEV_SHIFT      8                   /* force device type/class */
388 
389 /*
390  * this is rather kludgey- we need to duplicate these struct def'ns from sound.c
391  * so that the macro versions of pcm_{,un}lock can dereference them.
392  * we also have to do this now makedev() has gone away.
393  */
394 
395 struct snddev_info {
396           struct {
397                     struct {
398                               SLIST_HEAD(, pcm_channel) head;
399                               struct {
400                                         SLIST_HEAD(, pcm_channel) head;
401                               } busy;
402                               struct {
403                                         SLIST_HEAD(, pcm_channel) head;
404                               } opened;
405                     } pcm;
406           } channels;
407           TAILQ_HEAD(dsp_cdevinfo_linkhead, dsp_cdevinfo) dsp_cdevinfo_pool;
408           struct snd_clone *clones;
409           unsigned devcount, playcount, reccount, pvchancount, rvchancount ;
410           unsigned flags;
411           int inprog;
412           unsigned int bufsz;
413           void *devinfo;
414           device_t dev;
415           char status[SND_STATUSLEN];
416           struct lock *lock;
417           struct cdev *mixer_dev;
418           struct cdev *dsp_clonedev;
419           uint32_t pvchanrate, pvchanformat;
420           uint32_t rvchanrate, rvchanformat;
421           int32_t eqpreamp;
422           struct sysctl_ctx_list play_sysctl_ctx, rec_sysctl_ctx;
423           struct sysctl_oid *play_sysctl_tree, *rec_sysctl_tree;
424           struct cv cv;
425 };
426 
427 void      sound_oss_sysinfo(oss_sysinfo *);
428 int       sound_oss_card_info(oss_card_info *);
429 
430 #define PCM_LOCKOWNED(d)      (lockstatus((d)->lock, curthread) == LK_EXCLUSIVE)
431 #define PCM_LOCK(d)           lockmgr((d)->lock, LK_EXCLUSIVE)
432 #define PCM_UNLOCK(d)                   lockmgr((d)->lock, LK_RELEASE)
433 #define PCM_TRYLOCK(d)                  lockmgr_try((d)->lock, LK_EXCLUSIVE)
434 #define PCM_LOCKASSERT(d)     KKASSERT(lockstatus((d)->lock, curthread) == LK_EXCLUSIVE)
435 #define PCM_UNLOCKASSERT(d)   KKASSERT(lockstatus((d)->lock, curthread) != LK_EXCLUSIVE)
436 
437 /*
438  * For PCM_[WAIT | ACQUIRE | RELEASE], be sure to surround these
439  * with PCM_LOCK/UNLOCK() sequence, or I'll come to gnaw upon you!
440  */
441 #ifdef SND_DIAGNOSTIC
442 #define PCM_WAIT(x)           do {                                              \
443           if (!PCM_LOCKOWNED(x))                                                          \
444                     panic("%s(%d): [PCM WAIT] Mutex not owned!",                \
445                         __func__, __LINE__);                                    \
446           while ((x)->flags & SD_F_BUSY) {                                      \
447                     if (snd_verbose > 3)                                                  \
448                               device_printf((x)->dev,                                     \
449                                   "%s(%d): [PCM WAIT] calling cv_wait().\n",    \
450                                   __func__, __LINE__);                          \
451                     cv_wait(&(x)->cv, (x)->lock);                               \
452           }                                                                               \
453 } while (0)
454 
455 #define PCM_ACQUIRE(x)                  do {                                              \
456           if (!PCM_LOCKOWNED(x))                                                          \
457                     panic("%s(%d): [PCM ACQUIRE] Mutex not owned!",             \
458                         __func__, __LINE__);                                    \
459           if ((x)->flags & SD_F_BUSY)                                           \
460                     panic("%s(%d): [PCM ACQUIRE] "                                        \
461                         "Trying to acquire BUSY cv!", __func__, __LINE__);      \
462           (x)->flags |= SD_F_BUSY;                                              \
463 } while (0)
464 
465 #define PCM_RELEASE(x)                  do {                                              \
466           if (!PCM_LOCKOWNED(x))                                                          \
467                     panic("%s(%d): [PCM RELEASE] Mutex not owned!",             \
468                         __func__, __LINE__);                                    \
469           if ((x)->flags & SD_F_BUSY) {                                         \
470                     (x)->flags &= ~SD_F_BUSY;                                   \
471                     if ((x)->cv.cv_waiters != 0) {                                        \
472                               if ((x)->cv.cv_waiters > 1 && snd_verbose > 3)    \
473                                         device_printf((x)->dev,                           \
474                                             "%s(%d): [PCM RELEASE] "            \
475                                             "cv_waiters=%d > 1!\n",             \
476                                             __func__, __LINE__,                           \
477                                             (x)->cv.cv_waiters);                \
478                               cv_broadcast(&(x)->cv);                                     \
479                     }                                                                     \
480           } else                                                                          \
481                     panic("%s(%d): [PCM RELEASE] Releasing non-BUSY cv!",       \
482                         __func__, __LINE__);                                    \
483 } while (0)
484 
485 /* Quick version, for shorter path. */
486 #define PCM_ACQUIRE_QUICK(x)  do {                                              \
487           if (PCM_LOCKOWNED(x))                                                           \
488                     panic("%s(%d): [PCM ACQUIRE QUICK] Mutex owned!", \
489                         __func__, __LINE__);                                    \
490           PCM_LOCK(x);                                                                    \
491           PCM_WAIT(x);                                                                    \
492           PCM_ACQUIRE(x);                                                                 \
493           PCM_UNLOCK(x);                                                                  \
494 } while (0)
495 
496 #define PCM_RELEASE_QUICK(x)  do {                                              \
497           if (PCM_LOCKOWNED(x))                                                           \
498                     panic("%s(%d): [PCM RELEASE QUICK] Mutex owned!", \
499                         __func__, __LINE__);                                    \
500           PCM_LOCK(x);                                                                    \
501           PCM_RELEASE(x);                                                                 \
502           PCM_UNLOCK(x);                                                                  \
503 } while (0)
504 
505 #define PCM_BUSYASSERT(x)     do {                                              \
506           if (!((x) != NULL && ((x)->flags & SD_F_BUSY)))                       \
507                     panic("%s(%d): [PCM BUSYASSERT] "                           \
508                         "Failed, snddev_info=%p", __func__, __LINE__, x);       \
509 } while (0)
510 
511 #define PCM_GIANT_ENTER(x)    do {                                              \
512           int _pcm_giant = 0;                                                   \
513           if (PCM_LOCKOWNED(x))                                                           \
514                     panic("%s(%d): [GIANT ENTER] PCM lock owned!",              \
515                         __func__, __LINE__);                                    \
516           if (mtx_owned(&Giant) != 0 && snd_verbose > 3)                        \
517                     device_printf((x)->dev,                                               \
518                         "%s(%d): [GIANT ENTER] Giant owned!\n",                 \
519                         __func__, __LINE__);                                    \
520           if (!((x)->flags & SD_F_MPSAFE) && mtx_owned(&Giant) == 0)  \
521                     do {                                                                  \
522                               mtx_lock(&Giant);                                 \
523                               _pcm_giant = 1;                                             \
524                     } while (0)
525 
526 #define PCM_GIANT_EXIT(x)     do {                                              \
527           if (PCM_LOCKOWNED(x))                                                           \
528                     panic("%s(%d): [GIANT EXIT] PCM lock owned!",               \
529                         __func__, __LINE__);                                    \
530           if (!(_pcm_giant == 0 || _pcm_giant == 1))                            \
531                     panic("%s(%d): [GIANT EXIT] _pcm_giant screwed!", \
532                         __func__, __LINE__);                                    \
533           if ((x)->flags & SD_F_MPSAFE) {                                                 \
534                     if (_pcm_giant == 1)                                                  \
535                               panic("%s(%d): [GIANT EXIT] MPSAFE Giant?",       \
536                                   __func__, __LINE__);                          \
537                     if (mtx_owned(&Giant) != 0 && snd_verbose > 3)              \
538                               device_printf((x)->dev,                                     \
539                                   "%s(%d): [GIANT EXIT] Giant owned!\n",        \
540                                   __func__, __LINE__);                          \
541           }                                                                               \
542           if (_pcm_giant != 0) {                                                          \
543                     if (mtx_owned(&Giant) == 0)                                 \
544                               panic("%s(%d): [GIANT EXIT] Giant not owned!",    \
545                                   __func__, __LINE__);                          \
546                     _pcm_giant = 0;                                                       \
547                     mtx_unlock(&Giant);                                         \
548           }                                                                               \
549 } while (0)
550 #else /* SND_DIAGNOSTIC */
551 #define PCM_WAIT(x)           do {                                              \
552           PCM_LOCKASSERT(x);                                                    \
553           while ((x)->flags & SD_F_BUSY)                                                  \
554                     cv_wait(&(x)->cv, (x)->lock);                               \
555 } while (0)
556 
557 #define PCM_ACQUIRE(x)                  do {                                              \
558           PCM_LOCKASSERT(x);                                                    \
559           KASSERT(!((x)->flags & SD_F_BUSY),                                    \
560               ("%s(%d): [PCM ACQUIRE] Trying to acquire BUSY cv!",    \
561               __func__, __LINE__));                                             \
562           (x)->flags |= SD_F_BUSY;                                              \
563 } while (0)
564 
565 #define PCM_RELEASE(x)                  do {                                              \
566           PCM_LOCKASSERT(x);                                                    \
567           KASSERT((x)->flags & SD_F_BUSY,                                                 \
568               ("%s(%d): [PCM RELEASE] Releasing non-BUSY cv!",                  \
569               __func__, __LINE__));                                             \
570           (x)->flags &= ~SD_F_BUSY;                                             \
571           if ((x)->cv.cv_waiters != 0)                                          \
572                     cv_broadcast(&(x)->cv);                                               \
573 } while (0)
574 
575 /* Quick version, for shorter path. */
576 #define PCM_ACQUIRE_QUICK(x)  do {                                              \
577           PCM_UNLOCKASSERT(x);                                                            \
578           PCM_LOCK(x);                                                                    \
579           PCM_WAIT(x);                                                                    \
580           PCM_ACQUIRE(x);                                                                 \
581           PCM_UNLOCK(x);                                                                  \
582 } while (0)
583 
584 #define PCM_RELEASE_QUICK(x)  do {                                              \
585           PCM_UNLOCKASSERT(x);                                                            \
586           PCM_LOCK(x);                                                                    \
587           PCM_RELEASE(x);                                                                 \
588           PCM_UNLOCK(x);                                                                  \
589 } while (0)
590 
591 #define PCM_BUSYASSERT(x)     KASSERT(x != NULL &&                              \
592                                             ((x)->flags & SD_F_BUSY),           \
593                                             ("%s(%d): [PCM BUSYASSERT] "        \
594                                             "Failed, snddev_info=%p",           \
595                                             __func__, __LINE__, x))
596 
597 #define PCM_GIANT_ENTER(x)    do {                                              \
598           if (!((x)->flags & SD_F_MPSAFE))                                      \
599                     get_mplock();                                                         \
600 } while (0)
601 
602 #define PCM_GIANT_EXIT(x)     do {                                              \
603           if (!((x)->flags & SD_F_MPSAFE))                                      \
604                     rel_mplock();                                                         \
605 } while (0)
606 #endif /* !SND_DIAGNOSTIC */
607 
608 #define PCM_GIANT_LEAVE(x)    PCM_GIANT_EXIT(x)
609 
610 #ifdef KLD_MODULE
611 #define PCM_KLDSTRING(a) ("kld " # a)
612 #else
613 #define PCM_KLDSTRING(a) ""
614 #endif
615 
616 #endif /* _KERNEL */
617 
618 #endif    /* _OS_H_ */
619