]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/dev/sound/pcm/sound.h
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / dev / sound / pcm / sound.h
1 /*-
2  * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
3  * Copyright by Hannu Savolainen 1995
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD$
28  */
29
30 /*
31  * first, include kernel header files.
32  */
33
34 #ifndef _OS_H_
35 #define _OS_H_
36
37 #ifdef _KERNEL
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/ioccom.h>
41 #include <sys/filio.h>
42 #include <sys/sockio.h>
43 #include <sys/fcntl.h>
44 #include <sys/tty.h>
45 #include <sys/proc.h>
46 #include <sys/kernel.h> /* for DATA_SET */
47 #include <sys/module.h>
48 #include <sys/conf.h>
49 #include <sys/file.h>
50 #include <sys/uio.h>
51 #include <sys/syslog.h>
52 #include <sys/errno.h>
53 #include <sys/malloc.h>
54 #include <sys/bus.h>
55 #if __FreeBSD_version < 500000
56 #include <sys/buf.h>
57 #endif
58 #include <machine/resource.h>
59 #include <machine/bus.h>
60 #include <sys/rman.h>
61 #include <sys/limits.h>
62 #include <sys/mman.h>
63 #include <sys/poll.h>
64 #include <sys/sbuf.h>
65 #include <sys/soundcard.h>
66 #include <sys/sysctl.h>
67 #include <sys/kobj.h>
68 #include <vm/vm.h>
69 #include <vm/pmap.h>
70
71 #undef  USING_MUTEX
72 #undef  USING_DEVFS
73
74 #if __FreeBSD_version > 500000
75 #include <sys/lock.h>
76 #include <sys/mutex.h>
77 #include <sys/condvar.h>
78
79 #define USING_MUTEX
80 #define USING_DEVFS
81 #else
82 #define INTR_TYPE_AV    INTR_TYPE_TTY
83 #define INTR_MPSAFE     0
84 #endif
85
86 #define SND_DYNSYSCTL
87
88 struct pcm_channel;
89 struct pcm_feeder;
90 struct snd_dbuf;
91 struct snd_mixer;
92
93 #include <dev/sound/pcm/buffer.h>
94 #include <dev/sound/pcm/channel.h>
95 #include <dev/sound/pcm/feeder.h>
96 #include <dev/sound/pcm/mixer.h>
97 #include <dev/sound/pcm/dsp.h>
98 #include <dev/sound/clone.h>
99 #include <dev/sound/unit.h>
100
101 #define PCM_SOFTC_SIZE  512
102
103 #define SND_STATUSLEN   64
104
105 #define SOUND_MODVER    2
106
107 #define SOUND_MINVER    SOUND_MODVER
108 #define SOUND_PREFVER   SOUND_MODVER
109 #define SOUND_MAXVER    SOUND_MODVER
110
111 /*
112  * We're abusing the fact that MAXMINOR still have enough room
113  * for our bit twiddling and nobody ever need 512 unique soundcards,
114  * 32 unique device types and 1024 unique cloneable devices for the
115  * next 100 years...
116  */
117
118 #define PCMMAXUNIT              (snd_max_u())
119 #define PCMMAXDEV               (snd_max_d())
120 #define PCMMAXCHAN              (snd_max_c())
121
122 #define PCMMAXCLONE             PCMMAXCHAN
123
124 #define PCMUNIT(x)              (snd_unit2u(dev2unit(x)))
125 #define PCMDEV(x)               (snd_unit2d(dev2unit(x)))
126 #define PCMCHAN(x)              (snd_unit2c(dev2unit(x)))
127
128 /*
129  * By design, limit possible channels for each direction.
130  */
131 #define SND_MAXHWCHAN           256
132 #define SND_MAXVCHANS           SND_MAXHWCHAN
133
134 #define SD_F_SIMPLEX            0x00000001
135 #define SD_F_AUTOVCHAN          0x00000002
136 #define SD_F_SOFTPCMVOL         0x00000004
137 #define SD_F_PSWAPLR            0x00000008
138 #define SD_F_RSWAPLR            0x00000010
139 #define SD_F_DYING              0x00000020
140 #define SD_F_SUICIDE            0x00000040
141 #define SD_F_BUSY               0x00000080
142 #define SD_F_MPSAFE             0x00000100
143 #define SD_F_REGISTERED         0x00000200
144
145 #define SD_F_PRIO_RD            0x10000000
146 #define SD_F_PRIO_WR            0x20000000
147 #define SD_F_PRIO_SET           (SD_F_PRIO_RD | SD_F_PRIO_WR)
148 #define SD_F_DIR_SET            0x40000000
149 #define SD_F_TRANSIENT          0xf0000000
150
151 #define PCM_ALIVE(x)            ((x) != NULL && (x)->lock != NULL &&    \
152                                  !((x)->flags & SD_F_DYING))
153 #define PCM_REGISTERED(x)       (PCM_ALIVE(x) &&                        \
154                                  ((x)->flags & SD_F_REGISTERED))
155
156 /* many variables should be reduced to a range. Here define a macro */
157 #define RANGE(var, low, high) (var) = \
158         (((var)<(low))? (low) : ((var)>(high))? (high) : (var))
159 #define DSP_BUFFSIZE (8192)
160
161 /*
162  * Macros for reading/writing PCM sample / int values from bytes array.
163  * Since every process is done using signed integer (and to make our life
164  * less miserable), unsigned sample will be converted to its signed
165  * counterpart and restored during writing back. To avoid overflow,
166  * we truncate 32bit (and only 32bit) samples down to 24bit (see below
167  * for the reason), unless PCM_USE_64BIT_ARITH is defined.
168  */
169
170 /*
171  * Automatically turn on 64bit arithmetic on suitable archs
172  * (amd64 64bit, ia64, etc..) for wider 32bit samples / integer processing.
173  */
174 #if LONG_BIT >= 64
175 #undef PCM_USE_64BIT_ARITH
176 #define PCM_USE_64BIT_ARITH     1
177 #else
178 #if 0
179 #undef PCM_USE_64BIT_ARITH
180 #define PCM_USE_64BIT_ARITH     1
181 #endif
182 #endif
183
184 #ifdef PCM_USE_64BIT_ARITH
185 typedef int64_t intpcm_t;
186 #else
187 typedef int32_t intpcm_t;
188 #endif
189
190 /* 32bit fixed point shift */
191 #define PCM_FXSHIFT     8
192
193 #define PCM_S8_MAX        0x7f
194 #define PCM_S8_MIN       -0x80
195 #define PCM_S16_MAX       0x7fff
196 #define PCM_S16_MIN      -0x8000
197 #define PCM_S24_MAX       0x7fffff
198 #define PCM_S24_MIN      -0x800000
199 #ifdef PCM_USE_64BIT_ARITH
200 #if LONG_BIT >= 64
201 #define PCM_S32_MAX       0x7fffffffL
202 #define PCM_S32_MIN      -0x80000000L
203 #else
204 #define PCM_S32_MAX       0x7fffffffLL
205 #define PCM_S32_MIN      -0x80000000LL
206 #endif
207 #else
208 #define PCM_S32_MAX       0x7fffffff
209 #define PCM_S32_MIN     (-0x7fffffff - 1)
210 #endif
211
212 /* Bytes-per-sample definition */
213 #define PCM_8_BPS       1
214 #define PCM_16_BPS      2
215 #define PCM_24_BPS      3
216 #define PCM_32_BPS      4
217
218 #if BYTE_ORDER == LITTLE_ENDIAN
219 #define PCM_READ_S16_LE(b8)             *((int16_t *)(b8))
220 #define _PCM_READ_S32_LE(b8)            *((int32_t *)(b8))
221 #define PCM_READ_S16_BE(b8) \
222                 ((int32_t)((b8)[1] | ((int8_t)((b8)[0])) << 8))
223 #define _PCM_READ_S32_BE(b8) \
224                 ((int32_t)((b8)[3] | (b8)[2] << 8 | (b8)[1] << 16 | \
225                         ((int8_t)((b8)[0])) << 24))
226
227 #define PCM_WRITE_S16_LE(b8, val)       *((int16_t *)(b8)) = (val)
228 #define _PCM_WRITE_S32_LE(b8, val)      *((int32_t *)(b8)) = (val)
229 #define PCM_WRITE_S16_BE(bb8, vval) do { \
230                         int32_t val = (vval); \
231                         uint8_t *b8 = (bb8); \
232                         b8[1] = val; \
233                         b8[0] = val >> 8; \
234                 } while(0)
235 #define _PCM_WRITE_S32_BE(bb8, vval) do { \
236                         int32_t val = (vval); \
237                         uint8_t *b8 = (bb8); \
238                         b8[3] = val; \
239                         b8[2] = val >> 8; \
240                         b8[1] = val >> 16; \
241                         b8[0] = val >> 24; \
242                 } while(0)
243
244 #define PCM_READ_U16_LE(b8)             ((int16_t)(*((uint16_t *)(b8)) ^ 0x8000))
245 #define _PCM_READ_U32_LE(b8)            ((int32_t)(*((uint32_t *)(b8)) ^ 0x80000000))
246 #define PCM_READ_U16_BE(b8) \
247                 ((int32_t)((b8)[1] | ((int8_t)((b8)[0] ^ 0x80)) << 8))
248 #define _PCM_READ_U32_BE(b8) \
249                 ((int32_t)((b8)[3] | (b8)[2] << 8 | (b8)[1] << 16 | \
250                         ((int8_t)((b8)[0] ^ 0x80)) << 24))
251
252 #define PCM_WRITE_U16_LE(b8, val)       *((uint16_t *)(b8)) = (val) ^ 0x8000
253 #define _PCM_WRITE_U32_LE(b8, val)      *((uint32_t *)(b8)) = (val) ^ 0x80000000
254 #define PCM_WRITE_U16_BE(bb8, vval) do { \
255                         int32_t val = (vval); \
256                         uint8_t *b8 = (bb8); \
257                         b8[1] = val; \
258                         b8[0] = (val >> 8) ^ 0x80; \
259                 } while(0)
260 #define _PCM_WRITE_U32_BE(bb8, vval) do { \
261                         int32_t val = (vval); \
262                         uint8_t *b8 = (bb8); \
263                         b8[3] = val; \
264                         b8[2] = val >> 8; \
265                         b8[1] = val >> 16; \
266                         b8[0] = (val >> 24) ^ 0x80; \
267                 } while(0)
268 #else /* !LITTLE_ENDIAN */
269 #define PCM_READ_S16_LE(b8) \
270                 ((int32_t)((b8)[0] | ((int8_t)((b8)[1])) << 8))
271 #define _PCM_READ_S32_LE(b8) \
272                 ((int32_t)((b8)[0] | (b8)[1] << 8 | (b8)[2] << 16 | \
273                         ((int8_t)((b8)[3])) << 24))
274 #define PCM_READ_S16_BE(b8)             *((int16_t *)(b8))
275 #define _PCM_READ_S32_BE(b8)            *((int32_t *)(b8))
276
277 #define PCM_WRITE_S16_LE(bb8, vval) do { \
278                         int32_t val = (vval); \
279                         uint8_t *b8 = (bb8); \
280                         b8[0] = val; \
281                         b8[1] = val >> 8; \
282                 } while(0)
283 #define _PCM_WRITE_S32_LE(bb8, vval) do { \
284                         int32_t val = (vval); \
285                         uint8_t *b8 = (bb8); \
286                         b8[0] = val; \
287                         b8[1] = val >> 8; \
288                         b8[2] = val >> 16; \
289                         b8[3] = val >> 24; \
290                 } while(0)
291 #define PCM_WRITE_S16_BE(b8, val)       *((int16_t *)(b8)) = (val)
292 #define _PCM_WRITE_S32_BE(b8, val)      *((int32_t *)(b8)) = (val)
293
294 #define PCM_READ_U16_LE(b8) \
295                 ((int32_t)((b8)[0] | ((int8_t)((b8)[1] ^ 0x80)) << 8))
296 #define _PCM_READ_U32_LE(b8) \
297                 ((int32_t)((b8)[0] | (b8)[1] << 8 | (b8)[2] << 16 | \
298                         ((int8_t)((b8)[3] ^ 0x80)) << 24))
299 #define PCM_READ_U16_BE(b8) ((int16_t)(*((uint16_t *)(b8)) ^ 0x8000))
300 #define _PCM_READ_U32_BE(b8) ((int32_t)(*((uint32_t *)(b8)) ^ 0x80000000))
301
302 #define PCM_WRITE_U16_LE(bb8, vval) do { \
303                         int32_t val = (vval); \
304                         uint8_t *b8 = (bb8); \
305                         b8[0] = val; \
306                         b8[1] = (val >> 8) ^ 0x80; \
307                 } while(0)
308 #define _PCM_WRITE_U32_LE(bb8, vval) do { \
309                         int32_t val = (vval); \
310                         uint8_t *b8 = (bb8); \
311                         b8[0] = val; \
312                         b8[1] = val >> 8; \
313                         b8[2] = val >> 16; \
314                         b8[3] = (val >> 24) ^ 0x80; \
315                 } while(0)
316 #define PCM_WRITE_U16_BE(b8, val)       *((uint16_t *)(b8)) = (val) ^ 0x8000
317 #define _PCM_WRITE_U32_BE(b8, val)      *((uint32_t *)(b8)) = (val) ^ 0x80000000
318 #endif
319
320 #define PCM_READ_S24_LE(b8) \
321                 ((int32_t)((b8)[0] | (b8)[1] << 8 | ((int8_t)((b8)[2])) << 16))
322 #define PCM_READ_S24_BE(b8) \
323                 ((int32_t)((b8)[2] | (b8)[1] << 8 | ((int8_t)((b8)[0])) << 16))
324
325 #define PCM_WRITE_S24_LE(bb8, vval) do { \
326                         int32_t val = (vval); \
327                         uint8_t *b8 = (bb8); \
328                         b8[0] = val; \
329                         b8[1] = val >> 8; \
330                         b8[2] = val >> 16; \
331                 } while(0)
332 #define PCM_WRITE_S24_BE(bb8, vval) do { \
333                         int32_t val = (vval); \
334                         uint8_t *b8 = (bb8); \
335                         b8[2] = val; \
336                         b8[1] = val >> 8; \
337                         b8[0] = val >> 16; \
338                 } while(0)
339
340 #define PCM_READ_U24_LE(b8) \
341                 ((int32_t)((b8)[0] | (b8)[1] << 8 | \
342                         ((int8_t)((b8)[2] ^ 0x80)) << 16))
343 #define PCM_READ_U24_BE(b8) \
344                 ((int32_t)((b8)[2] | (b8)[1] << 8 | \
345                         ((int8_t)((b8)[0] ^ 0x80)) << 16))
346
347 #define PCM_WRITE_U24_LE(bb8, vval) do { \
348                         int32_t val = (vval); \
349                         uint8_t *b8 = (bb8); \
350                         b8[0] = val; \
351                         b8[1] = val >> 8; \
352                         b8[2] = (val >> 16) ^ 0x80; \
353                 } while(0)
354 #define PCM_WRITE_U24_BE(bb8, vval) do { \
355                         int32_t val = (vval); \
356                         uint8_t *b8 = (bb8); \
357                         b8[2] = val; \
358                         b8[1] = val >> 8; \
359                         b8[0] = (val >> 16) ^ 0x80; \
360                 } while(0)
361
362 #ifdef PCM_USE_64BIT_ARITH
363 #define PCM_READ_S32_LE(b8)             _PCM_READ_S32_LE(b8)
364 #define PCM_READ_S32_BE(b8)             _PCM_READ_S32_BE(b8)
365 #define PCM_WRITE_S32_LE(b8, val)       _PCM_WRITE_S32_LE(b8, val)
366 #define PCM_WRITE_S32_BE(b8, val)       _PCM_WRITE_S32_BE(b8, val)
367
368 #define PCM_READ_U32_LE(b8)             _PCM_READ_U32_LE(b8)
369 #define PCM_READ_U32_BE(b8)             _PCM_READ_U32_BE(b8)
370 #define PCM_WRITE_U32_LE(b8, val)       _PCM_WRITE_U32_LE(b8, val)
371 #define PCM_WRITE_U32_BE(b8, val)       _PCM_WRITE_U32_BE(b8, val)
372 #else /* !PCM_USE_64BIT_ARITH */
373 /*
374  * 24bit integer ?!? This is quite unfortunate, eh? Get the fact straight:
375  * Dynamic range for:
376  *      1) Human =~ 140db
377  *      2) 16bit = 96db (close enough)
378  *      3) 24bit = 144db (perfect)
379  *      4) 32bit = 196db (way too much)
380  *      5) Bugs Bunny = Gazillion!@%$Erbzzztt-EINVAL db
381  * Since we're not Bugs Bunny ..uh..err.. avoiding 64bit arithmetic, 24bit
382  * is pretty much sufficient for our signed integer processing.
383  */
384 #define PCM_READ_S32_LE(b8)             (_PCM_READ_S32_LE(b8) >> PCM_FXSHIFT)
385 #define PCM_READ_S32_BE(b8)             (_PCM_READ_S32_BE(b8) >> PCM_FXSHIFT)
386 #define PCM_WRITE_S32_LE(b8, val)       _PCM_WRITE_S32_LE(b8, (val) << PCM_FXSHIFT)
387 #define PCM_WRITE_S32_BE(b8, val)       _PCM_WRITE_S32_BE(b8, (val) << PCM_FXSHIFT)
388
389 #define PCM_READ_U32_LE(b8)             (_PCM_READ_U32_LE(b8) >> PCM_FXSHIFT)
390 #define PCM_READ_U32_BE(b8)             (_PCM_READ_U32_BE(b8) >> PCM_FXSHIFT)
391 #define PCM_WRITE_U32_LE(b8, val)       _PCM_WRITE_U32_LE(b8, (val) << PCM_FXSHIFT)
392 #define PCM_WRITE_U32_BE(b8, val)       _PCM_WRITE_U32_BE(b8, (val) << PCM_FXSHIFT)
393 #endif
394
395 /*
396  * 8bit sample is pretty much useless since it doesn't provide
397  * sufficient dynamic range throughout our filtering process.
398  * For the sake of completeness, declare it anyway.
399  */
400 #define PCM_READ_S8(b8)                 *((int8_t *)(b8))
401 #define PCM_READ_S8_NE(b8)              PCM_READ_S8(b8)
402 #define PCM_READ_U8(b8)                 ((int8_t)(*((uint8_t *)(b8)) ^ 0x80))
403 #define PCM_READ_U8_NE(b8)              PCM_READ_U8(b8)
404
405 #define PCM_WRITE_S8(b8, val)           *((int8_t *)(b8)) = (val)
406 #define PCM_WRITE_S8_NE(b8, val)        PCM_WRITE_S8(b8, val)
407 #define PCM_WRITE_U8(b8, val)           *((uint8_t *)(b8)) = (val) ^ 0x80
408 #define PCM_WRITE_U8_NE(b8, val)        PCM_WRITE_U8(b8, val)
409
410 #define PCM_CLAMP_S8(val) \
411                 (((val) > PCM_S8_MAX) ? PCM_S8_MAX : \
412                         (((val) < PCM_S8_MIN) ? PCM_S8_MIN : (val)))
413 #define PCM_CLAMP_S16(val) \
414                 (((val) > PCM_S16_MAX) ? PCM_S16_MAX : \
415                         (((val) < PCM_S16_MIN) ? PCM_S16_MIN : (val)))
416 #define PCM_CLAMP_S24(val) \
417                 (((val) > PCM_S24_MAX) ? PCM_S24_MAX : \
418                         (((val) < PCM_S24_MIN) ? PCM_S24_MIN : (val)))
419
420 #ifdef PCM_USE_64BIT_ARITH
421 #define PCM_CLAMP_S32(val) \
422                 (((val) > PCM_S32_MAX) ? PCM_S32_MAX : \
423                         (((val) < PCM_S32_MIN) ? PCM_S32_MIN : (val)))
424 #else
425 #define PCM_CLAMP_S32(val) \
426                 (((val) > PCM_S24_MAX) ? PCM_S32_MAX : \
427                         (((val) < PCM_S24_MIN) ? PCM_S32_MIN : \
428                         ((val) << PCM_FXSHIFT)))
429 #endif
430
431 #define PCM_CLAMP_U8(val)       PCM_CLAMP_S8(val)
432 #define PCM_CLAMP_U16(val)      PCM_CLAMP_S16(val)
433 #define PCM_CLAMP_U24(val)      PCM_CLAMP_S24(val)
434 #define PCM_CLAMP_U32(val)      PCM_CLAMP_S32(val)
435
436 /* make figuring out what a format is easier. got AFMT_STEREO already */
437 #define AFMT_32BIT (AFMT_S32_LE | AFMT_S32_BE | AFMT_U32_LE | AFMT_U32_BE)
438 #define AFMT_24BIT (AFMT_S24_LE | AFMT_S24_BE | AFMT_U24_LE | AFMT_U24_BE)
439 #define AFMT_16BIT (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE)
440 #define AFMT_8BIT (AFMT_MU_LAW | AFMT_A_LAW | AFMT_U8 | AFMT_S8)
441 #define AFMT_SIGNED (AFMT_S32_LE | AFMT_S32_BE | AFMT_S24_LE | AFMT_S24_BE | \
442                         AFMT_S16_LE | AFMT_S16_BE | AFMT_S8)
443 #define AFMT_BIGENDIAN (AFMT_S32_BE | AFMT_U32_BE | AFMT_S24_BE | AFMT_U24_BE | \
444                         AFMT_S16_BE | AFMT_U16_BE)
445
446 struct pcm_channel *fkchan_setup(device_t dev);
447 int fkchan_kill(struct pcm_channel *c);
448
449 /*
450  * Minor numbers for the sound driver.
451  *
452  * Unfortunately Creative called the codec chip of SB as a DSP. For this
453  * reason the /dev/dsp is reserved for digitized audio use. There is a
454  * device for true DSP processors but it will be called something else.
455  * In v3.0 it's /dev/sndproc but this could be a temporary solution.
456  */
457
458 #define SND_DEV_CTL     0       /* Control port /dev/mixer */
459 #define SND_DEV_SEQ     1       /* Sequencer /dev/sequencer */
460 #define SND_DEV_MIDIN   2       /* Raw midi access */
461 #define SND_DEV_DSP     3       /* Digitized voice /dev/dsp */
462 #define SND_DEV_AUDIO   4       /* Sparc compatible /dev/audio */
463 #define SND_DEV_DSP16   5       /* Like /dev/dsp but 16 bits/sample */
464 #define SND_DEV_STATUS  6       /* /dev/sndstat */
465                                 /* #7 not in use now. */
466 #define SND_DEV_SEQ2    8       /* /dev/sequencer, level 2 interface */
467 #define SND_DEV_SNDPROC 9       /* /dev/sndproc for programmable devices */
468 #define SND_DEV_PSS     SND_DEV_SNDPROC /* ? */
469 #define SND_DEV_NORESET 10
470
471 #define SND_DEV_DSPHW_PLAY      11      /* specific playback channel */
472 #define SND_DEV_DSPHW_VPLAY     12      /* specific virtual playback channel */
473 #define SND_DEV_DSPHW_REC       13      /* specific record channel */
474 #define SND_DEV_DSPHW_VREC      14      /* specific virtual record channel */
475
476 #define SND_DEV_DSPHW_CD        15      /* s16le/stereo 44100Hz CD */
477
478 #define SND_DEV_DSP_MMAP        16      /* OSSv4 compatible /dev/dsp_mmap */
479
480 #define SND_DEV_LAST            SND_DEV_DSP_MMAP
481 #define SND_DEV_MAX             PCMMAXDEV
482
483 #define DSP_DEFAULT_SPEED       8000
484
485 #define ON              1
486 #define OFF             0
487
488 extern int pcm_veto_load;
489 extern int snd_unit;
490 extern int snd_maxautovchans;
491 extern int snd_verbose;
492 extern devclass_t pcm_devclass;
493 extern struct unrhdr *pcmsg_unrhdr;
494
495 /*
496  * some macros for debugging purposes
497  * DDB/DEB to enable/disable debugging stuff
498  * BVDDB   to enable debugging when bootverbose
499  */
500 #define BVDDB(x) if (bootverbose) x
501
502 #ifndef DEB
503 #define DEB(x)
504 #endif
505
506 SYSCTL_DECL(_hw_snd);
507
508 struct pcm_channel *pcm_getfakechan(struct snddev_info *d);
509 int pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction, pid_t pid, int devunit);
510 int pcm_chnrelease(struct pcm_channel *c);
511 int pcm_chnref(struct pcm_channel *c, int ref);
512 int pcm_inprog(struct snddev_info *d, int delta);
513
514 struct pcm_channel *pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, int dir, int num, void *devinfo);
515 int pcm_chn_destroy(struct pcm_channel *ch);
516 int pcm_chn_add(struct snddev_info *d, struct pcm_channel *ch);
517 int pcm_chn_remove(struct snddev_info *d, struct pcm_channel *ch);
518
519 int pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo);
520 unsigned int pcm_getbuffersize(device_t dev, unsigned int minbufsz, unsigned int deflt, unsigned int maxbufsz);
521 int pcm_register(device_t dev, void *devinfo, int numplay, int numrec);
522 int pcm_unregister(device_t dev);
523 int pcm_setstatus(device_t dev, char *str);
524 u_int32_t pcm_getflags(device_t dev);
525 void pcm_setflags(device_t dev, u_int32_t val);
526 void *pcm_getdevinfo(device_t dev);
527
528
529 int snd_setup_intr(device_t dev, struct resource *res, int flags,
530                    driver_intr_t hand, void *param, void **cookiep);
531
532 void *snd_mtxcreate(const char *desc, const char *type);
533 void snd_mtxfree(void *m);
534 void snd_mtxassert(void *m);
535 #define snd_mtxlock(m) mtx_lock(m)
536 #define snd_mtxunlock(m) mtx_unlock(m)
537
538 int sysctl_hw_snd_vchans(SYSCTL_HANDLER_ARGS);
539
540 typedef int (*sndstat_handler)(struct sbuf *s, device_t dev, int verbose);
541 int sndstat_acquire(struct thread *td);
542 int sndstat_release(struct thread *td);
543 int sndstat_register(device_t dev, char *str, sndstat_handler handler);
544 int sndstat_registerfile(char *str);
545 int sndstat_unregister(device_t dev);
546 int sndstat_unregisterfile(char *str);
547
548 #define SND_DECLARE_FILE(version) \
549         _SND_DECLARE_FILE(__LINE__, version)
550
551 #define _SND_DECLARE_FILE(uniq, version) \
552         __SND_DECLARE_FILE(uniq, version)
553
554 #define __SND_DECLARE_FILE(uniq, version) \
555         static char sndstat_vinfo[] = version; \
556         SYSINIT(sdf_ ## uniq, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, sndstat_registerfile, sndstat_vinfo); \
557         SYSUNINIT(sdf_ ## uniq, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, sndstat_unregisterfile, sndstat_vinfo);
558
559 /* usage of flags in device config entry (config file) */
560 #define DV_F_DRQ_MASK   0x00000007      /* mask for secondary drq */
561 #define DV_F_DUAL_DMA   0x00000010      /* set to use secondary dma channel */
562
563 /* ought to be made obsolete but still used by mss */
564 #define DV_F_DEV_MASK   0x0000ff00      /* force device type/class */
565 #define DV_F_DEV_SHIFT  8               /* force device type/class */
566
567 #define PCM_DEBUG_MTX
568
569 /*
570  * this is rather kludgey- we need to duplicate these struct def'ns from sound.c
571  * so that the macro versions of pcm_{,un}lock can dereference them.
572  * we also have to do this now makedev() has gone away.
573  */
574
575 struct snddev_info {
576         struct {
577                 struct {
578                         SLIST_HEAD(, pcm_channel) head;
579                         struct {
580                                 SLIST_HEAD(, pcm_channel) head;
581                         } busy;
582                 } pcm;
583         } channels;
584         TAILQ_HEAD(dsp_cdevinfo_linkhead, dsp_cdevinfo) dsp_cdevinfo_pool;
585         struct snd_clone *clones;
586         struct pcm_channel *fakechan;
587         unsigned devcount, playcount, reccount, pvchancount, rvchancount ;
588         unsigned flags;
589         int inprog;
590         unsigned int bufsz;
591         void *devinfo;
592         device_t dev;
593         char status[SND_STATUSLEN];
594         struct mtx *lock;
595         struct cdev *mixer_dev;
596         uint32_t pvchanrate, pvchanformat;
597         uint32_t rvchanrate, rvchanformat;
598         struct sysctl_ctx_list play_sysctl_ctx, rec_sysctl_ctx;
599         struct sysctl_oid *play_sysctl_tree, *rec_sysctl_tree;
600         struct cv cv;
601 };
602
603 void    sound_oss_sysinfo(oss_sysinfo *);
604
605 #ifdef  PCM_DEBUG_MTX
606 #define pcm_lock(d) mtx_lock(((struct snddev_info *)(d))->lock)
607 #define pcm_unlock(d) mtx_unlock(((struct snddev_info *)(d))->lock)
608 #else
609 void pcm_lock(struct snddev_info *d);
610 void pcm_unlock(struct snddev_info *d);
611 #endif
612
613 /*
614  * For PCM_CV_[WAIT | ACQUIRE | RELEASE], be sure to surround these
615  * with pcm_lock/unlock() sequence, or I'll come to gnaw upon you!
616  */
617 #ifdef SND_DIAGNOSTIC
618 #define PCM_WAIT(x)             do {                                    \
619         if (mtx_owned((x)->lock) == 0)                                  \
620                 panic("%s(%d): [PCM WAIT] Mutex not owned!",            \
621                     __func__, __LINE__);                                \
622         while ((x)->flags & SD_F_BUSY) {                                \
623                 if (snd_verbose > 3)                                    \
624                         device_printf((x)->dev,                         \
625                             "%s(%d): [PCM WAIT] calling cv_wait().\n",  \
626                             __func__, __LINE__);                        \
627                 cv_wait(&(x)->cv, (x)->lock);                           \
628         }                                                               \
629 } while(0)
630
631 #define PCM_ACQUIRE(x)          do {                                    \
632         if (mtx_owned((x)->lock) == 0)                                  \
633                 panic("%s(%d): [PCM ACQUIRE] Mutex not owned!",         \
634                     __func__, __LINE__);                                \
635         if ((x)->flags & SD_F_BUSY)                                     \
636                 panic("%s(%d): [PCM ACQUIRE] "                          \
637                     "Trying to acquire BUSY cv!", __func__, __LINE__);  \
638         (x)->flags |= SD_F_BUSY;                                        \
639 } while(0)
640
641 #define PCM_RELEASE(x)          do {                                    \
642         if (mtx_owned((x)->lock) == 0)                                  \
643                 panic("%s(%d): [PCM RELEASE] Mutex not owned!",         \
644                     __func__, __LINE__);                                \
645         if ((x)->flags & SD_F_BUSY) {                                   \
646                 (x)->flags &= ~SD_F_BUSY;                               \
647                 if ((x)->cv.cv_waiters != 0) {                          \
648                         if ((x)->cv.cv_waiters > 1 && snd_verbose > 3)  \
649                                 device_printf((x)->dev,                 \
650                                     "%s(%d): [PCM RELEASE] "            \
651                                     "cv_waiters=%d > 1!\n",             \
652                                     __func__, __LINE__,                 \
653                                     (x)->cv.cv_waiters);                \
654                         cv_broadcast(&(x)->cv);                         \
655                 }                                                       \
656         } else                                                          \
657                 panic("%s(%d): [PCM RELEASE] Releasing non-BUSY cv!",   \
658                     __func__, __LINE__);                                \
659 } while(0)
660
661 /* Quick version, for shorter path. */
662 #define PCM_ACQUIRE_QUICK(x)    do {                                    \
663         if (mtx_owned((x)->lock) != 0)                                  \
664                 panic("%s(%d): [PCM ACQUIRE QUICK] Mutex owned!",       \
665                     __func__, __LINE__);                                \
666         pcm_lock(x);                                                    \
667         PCM_WAIT(x);                                                    \
668         PCM_ACQUIRE(x);                                                 \
669         pcm_unlock(x);                                                  \
670 } while(0)
671
672 #define PCM_RELEASE_QUICK(x)    do {                                    \
673         if (mtx_owned((x)->lock) != 0)                                  \
674                 panic("%s(%d): [PCM RELEASE QUICK] Mutex owned!",       \
675                     __func__, __LINE__);                                \
676         pcm_lock(x);                                                    \
677         PCM_RELEASE(x);                                                 \
678         pcm_unlock(x);                                                  \
679 } while(0)
680
681 #define PCM_BUSYASSERT(x)       do {                                    \
682         if (!((x) != NULL && ((x)->flags & SD_F_BUSY)))                 \
683                 panic("%s(%d): [PCM BUSYASSERT] "                       \
684                     "Failed, snddev_info=%p", __func__, __LINE__, x);   \
685 } while(0)
686
687 #define PCM_GIANT_ENTER(x)      do {                                    \
688         int _pcm_giant = 0;                                             \
689         if (mtx_owned((x)->lock) != 0)                                  \
690                 panic("%s(%d): [GIANT ENTER] PCM lock owned!",          \
691                     __func__, __LINE__);                                \
692         if (mtx_owned(&Giant) != 0 && snd_verbose > 3)                  \
693                 device_printf((x)->dev,                                 \
694                     "%s(%d): [GIANT ENTER] Giant owned!\n",             \
695                     __func__, __LINE__);                                \
696         if (!((x)->flags & SD_F_MPSAFE) && mtx_owned(&Giant) == 0)      \
697                 do {                                                    \
698                         mtx_lock(&Giant);                               \
699                         _pcm_giant = 1;                                 \
700                 } while(0)
701
702 #define PCM_GIANT_EXIT(x)       do {                                    \
703         if (mtx_owned((x)->lock) != 0)                                  \
704                 panic("%s(%d): [GIANT EXIT] PCM lock owned!",           \
705                     __func__, __LINE__);                                \
706         if (!(_pcm_giant == 0 || _pcm_giant == 1))                      \
707                 panic("%s(%d): [GIANT EXIT] _pcm_giant screwed!",       \
708                     __func__, __LINE__);                                \
709         if ((x)->flags & SD_F_MPSAFE) {                                 \
710                 if (_pcm_giant == 1)                                    \
711                         panic("%s(%d): [GIANT EXIT] MPSAFE Giant?",     \
712                             __func__, __LINE__);                        \
713                 if (mtx_owned(&Giant) != 0 && snd_verbose > 3)          \
714                         device_printf((x)->dev,                         \
715                             "%s(%d): [GIANT EXIT] Giant owned!\n",      \
716                             __func__, __LINE__);                        \
717         }                                                               \
718         if (_pcm_giant != 0) {                                          \
719                 if (mtx_owned(&Giant) == 0)                             \
720                         panic("%s(%d): [GIANT EXIT] Giant not owned!",  \
721                             __func__, __LINE__);                        \
722                 _pcm_giant = 0;                                         \
723                 mtx_unlock(&Giant);                                     \
724         }                                                               \
725 } while(0)
726 #else /* SND_DIAGNOSTIC */
727 #define PCM_WAIT(x)             do {                                    \
728         mtx_assert((x)->lock, MA_OWNED);                                \
729         while ((x)->flags & SD_F_BUSY)                                  \
730                 cv_wait(&(x)->cv, (x)->lock);                           \
731 } while(0)
732
733 #define PCM_ACQUIRE(x)          do {                                    \
734         mtx_assert((x)->lock, MA_OWNED);                                \
735         KASSERT(!((x)->flags & SD_F_BUSY),                              \
736             ("%s(%d): [PCM ACQUIRE] Trying to acquire BUSY cv!",        \
737             __func__, __LINE__));                                       \
738         (x)->flags |= SD_F_BUSY;                                        \
739 } while(0)
740
741 #define PCM_RELEASE(x)          do {                                    \
742         mtx_assert((x)->lock, MA_OWNED);                                \
743         KASSERT((x)->flags & SD_F_BUSY,                                 \
744             ("%s(%d): [PCM RELEASE] Releasing non-BUSY cv!",            \
745             __func__, __LINE__));                                       \
746         (x)->flags &= ~SD_F_BUSY;                                       \
747         if ((x)->cv.cv_waiters != 0)                                    \
748                 cv_broadcast(&(x)->cv);                                 \
749 } while(0)
750
751 /* Quick version, for shorter path. */
752 #define PCM_ACQUIRE_QUICK(x)    do {                                    \
753         mtx_assert((x)->lock, MA_NOTOWNED);                             \
754         pcm_lock(x);                                                    \
755         PCM_WAIT(x);                                                    \
756         PCM_ACQUIRE(x);                                                 \
757         pcm_unlock(x);                                                  \
758 } while(0)
759
760 #define PCM_RELEASE_QUICK(x)    do {                                    \
761         mtx_assert((x)->lock, MA_NOTOWNED);                             \
762         pcm_lock(x);                                                    \
763         PCM_RELEASE(x);                                                 \
764         pcm_unlock(x);                                                  \
765 } while(0)
766
767 #define PCM_BUSYASSERT(x)       KASSERT(x != NULL &&                    \
768                                     ((x)->flags & SD_F_BUSY),           \
769                                     ("%s(%d): [PCM BUSYASSERT] "        \
770                                     "Failed, snddev_info=%p",           \
771                                     __func__, __LINE__, x))
772
773 #define PCM_GIANT_ENTER(x)      do {                                    \
774         int _pcm_giant = 0;                                             \
775         mtx_assert((x)->lock, MA_NOTOWNED);                             \
776         if (!((x)->flags & SD_F_MPSAFE) && mtx_owned(&Giant) == 0)      \
777                 do {                                                    \
778                         mtx_lock(&Giant);                               \
779                         _pcm_giant = 1;                                 \
780                 } while(0)
781
782 #define PCM_GIANT_EXIT(x)       do {                                    \
783         mtx_assert((x)->lock, MA_NOTOWNED);                             \
784         KASSERT(_pcm_giant == 0 || _pcm_giant == 1,                     \
785             ("%s(%d): [GIANT EXIT] _pcm_giant screwed!",                \
786             __func__, __LINE__));                                       \
787         KASSERT(!((x)->flags & SD_F_MPSAFE) ||                          \
788             (((x)->flags & SD_F_MPSAFE) && _pcm_giant == 0),            \
789             ("%s(%d): [GIANT EXIT] MPSAFE Giant?",                      \
790             __func__, __LINE__));                                       \
791         if (_pcm_giant != 0) {                                          \
792                 mtx_assert(&Giant, MA_OWNED);                           \
793                 _pcm_giant = 0;                                         \
794                 mtx_unlock(&Giant);                                     \
795         }                                                               \
796 } while(0)
797 #endif /* !SND_DIAGNOSTIC */
798
799 #define PCM_GIANT_LEAVE(x)                                              \
800         PCM_GIANT_EXIT(x);                                              \
801 } while(0)
802
803 #ifdef KLD_MODULE
804 #define PCM_KLDSTRING(a) ("kld " # a)
805 #else
806 #define PCM_KLDSTRING(a) ""
807 #endif
808
809 #endif /* _KERNEL */
810
811 #endif  /* _OS_H_ */