diff --git a/sys/dev/sound/pcm/feeder.h b/sys/dev/sound/pcm/feeder.h index 60b8280e59ef..bd0d9dcb8f9c 100644 --- a/sys/dev/sound/pcm/feeder.h +++ b/sys/dev/sound/pcm/feeder.h @@ -1,186 +1,193 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2005-2009 Ariff Abdullah * Copyright (c) 1999 Cameron Grant * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ struct pcm_feederdesc { u_int32_t type; u_int32_t in, out; u_int32_t flags; int idx; }; struct feeder_class { KOBJ_CLASS_FIELDS; struct pcm_feederdesc *desc; void *data; }; struct pcm_feeder { KOBJ_FIELDS; int align; struct pcm_feederdesc *desc, desc_static; void *data; struct feeder_class *class; struct pcm_feeder *source, *parent; }; void feeder_register(void *p); struct feeder_class *feeder_getclass(struct pcm_feederdesc *desc); u_int32_t snd_fmtscore(u_int32_t fmt); u_int32_t snd_fmtbestbit(u_int32_t fmt, u_int32_t *fmts); u_int32_t snd_fmtbestchannel(u_int32_t fmt, u_int32_t *fmts); u_int32_t snd_fmtbest(u_int32_t fmt, u_int32_t *fmts); int feeder_add(struct pcm_channel *c, struct feeder_class *fc, struct pcm_feederdesc *desc); void feeder_remove(struct pcm_channel *c); struct pcm_feeder *feeder_find(struct pcm_channel *c, u_int32_t type); void feeder_printchain(struct pcm_feeder *head); int feeder_chain(struct pcm_channel *); #define FEEDER_DECLARE(feeder, pdata) \ static struct feeder_class feeder ## _class = { \ .name = #feeder, \ .methods = feeder ## _methods, \ .size = sizeof(struct pcm_feeder), \ .desc = feeder ## _desc, \ .data = pdata, \ }; \ SYSINIT(feeder, SI_SUB_DRIVERS, SI_ORDER_ANY, feeder_register, \ &feeder ## _class) enum { FEEDER_ROOT, FEEDER_FORMAT, FEEDER_MIXER, FEEDER_RATE, FEEDER_EQ, FEEDER_VOLUME, FEEDER_MATRIX, FEEDER_LAST, }; /* feeder_format */ enum { FEEDFORMAT_CHANNELS }; /* feeder_mixer */ enum { FEEDMIXER_CHANNELS }; /* feeder_rate */ enum { FEEDRATE_SRC, FEEDRATE_DST, FEEDRATE_QUALITY, FEEDRATE_CHANNELS }; #define FEEDRATE_RATEMIN 1 #define FEEDRATE_RATEMAX 2016000 /* 48000 * 42 */ #define FEEDRATE_MIN 1 #define FEEDRATE_MAX 0x7fffff /* sign 24bit ~ 8ghz ! */ #define FEEDRATE_ROUNDHZ 25 #define FEEDRATE_ROUNDHZ_MIN 0 #define FEEDRATE_ROUNDHZ_MAX 500 extern int feeder_rate_min; extern int feeder_rate_max; extern int feeder_rate_round; extern int feeder_rate_quality; /* feeder_eq */ enum { FEEDEQ_CHANNELS, FEEDEQ_RATE, FEEDEQ_TREBLE, FEEDEQ_BASS, FEEDEQ_PREAMP, FEEDEQ_STATE, FEEDEQ_DISABLE, FEEDEQ_ENABLE, FEEDEQ_BYPASS, FEEDEQ_UNKNOWN }; int feeder_eq_validrate(uint32_t); void feeder_eq_initsys(device_t); /* feeder_volume */ enum { FEEDVOLUME_CLASS, FEEDVOLUME_CHANNELS, FEEDVOLUME_STATE, FEEDVOLUME_ENABLE, FEEDVOLUME_BYPASS }; int feeder_volume_apply_matrix(struct pcm_feeder *, struct pcmchan_matrix *); /* feeder_matrix */ int feeder_matrix_default_id(uint32_t); struct pcmchan_matrix *feeder_matrix_default_channel_map(uint32_t); uint32_t feeder_matrix_default_format(uint32_t); int feeder_matrix_format_id(uint32_t); struct pcmchan_matrix *feeder_matrix_format_map(uint32_t); struct pcmchan_matrix *feeder_matrix_id_map(int); int feeder_matrix_setup(struct pcm_feeder *, struct pcmchan_matrix *, struct pcmchan_matrix *); int feeder_matrix_compare(struct pcmchan_matrix *, struct pcmchan_matrix *); +/* feeder_format */ +typedef intpcm_t intpcm_read_t(uint8_t *); +typedef void intpcm_write_t(uint8_t *, intpcm_t); + +intpcm_read_t *feeder_format_read_op(uint32_t); +intpcm_write_t *feeder_format_write_op(uint32_t); + /* 4Front OSS stuffs */ int feeder_matrix_oss_get_channel_order(struct pcmchan_matrix *, unsigned long long *); int feeder_matrix_oss_set_channel_order(struct pcmchan_matrix *, unsigned long long *); /* * By default, various feeders only deal with sign 16/32 bit native-endian * since it should provide the fastest processing path. Processing 8bit samples * is too noisy due to limited dynamic range, while 24bit is quite slow due to * unnatural per-byte read/write. However, for debugging purposes, ensuring * implementation correctness and torture test, the following can be defined: * * SND_FEEDER_MULTIFORMAT - Compile all type of converters, but force * 8bit samples to be converted to 16bit * native-endian for better dynamic range. * Process 24bit samples natively. * SND_FEEDER_FULL_MULTIFORMAT - Ditto, but process 8bit samples natively. */ #ifdef SND_FEEDER_FULL_MULTIFORMAT #undef SND_FEEDER_MULTIFORMAT #define SND_FEEDER_MULTIFORMAT 1 #endif diff --git a/sys/dev/sound/pcm/feeder_format.c b/sys/dev/sound/pcm/feeder_format.c index 3bdd808df0ee..53c7d3768a32 100644 --- a/sys/dev/sound/pcm/feeder_format.c +++ b/sys/dev/sound/pcm/feeder_format.c @@ -1,297 +1,393 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2008-2009 Ariff Abdullah * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * feeder_format: New generation of generic, any-to-any format converter, as * long as the sample values can be read _and_ write. */ #ifdef _KERNEL #ifdef HAVE_KERNEL_OPTION_HEADERS #include "opt_snd.h" #endif #include -#include #include -#include #include "feeder_if.h" #define SND_USE_FXDIV #include "snd_fxdiv_gen.h" #endif #define FEEDFORMAT_RESERVOIR (SND_CHN_MAX * PCM_32_BPS) -INTPCM_DECLARE(intpcm_conv_tables) - struct feed_format_info { uint32_t ibps, obps; uint32_t ialign, oalign, channels; intpcm_read_t *read; intpcm_write_t *write; uint8_t reservoir[FEEDFORMAT_RESERVOIR]; }; +#define INTPCM_DECLARE_OP_WRITE(SIGN, BIT, ENDIAN, SHIFT) \ +static __inline void \ +intpcm_write_##SIGN##BIT##ENDIAN(uint8_t *dst, intpcm_t v) \ +{ \ + \ + _PCM_WRITE_##SIGN##BIT##_##ENDIAN(dst, v >> SHIFT); \ +} + +#define INTPCM_DECLARE_OP_8(SIGN, ENDIAN) \ +static __inline intpcm_t \ +intpcm_read_##SIGN##8##ENDIAN(uint8_t *src) \ +{ \ + \ + return (_PCM_READ_##SIGN##8##_##ENDIAN(src) << 24); \ +} \ +INTPCM_DECLARE_OP_WRITE(SIGN, 8, ENDIAN, 24) + +#define INTPCM_DECLARE_OP_16(SIGN, ENDIAN) \ +static __inline intpcm_t \ +intpcm_read_##SIGN##16##ENDIAN(uint8_t *src) \ +{ \ + \ + return (_PCM_READ_##SIGN##16##_##ENDIAN(src) << 16); \ +} \ +INTPCM_DECLARE_OP_WRITE(SIGN, 16, ENDIAN, 16) + +#define INTPCM_DECLARE_OP_24(SIGN, ENDIAN) \ +static __inline intpcm_t \ +intpcm_read_##SIGN##24##ENDIAN(uint8_t *src) \ +{ \ + \ + return (_PCM_READ_##SIGN##24##_##ENDIAN(src) << 8); \ +} \ +INTPCM_DECLARE_OP_WRITE(SIGN, 24, ENDIAN, 8) + +#define INTPCM_DECLARE_OP_32(SIGN, ENDIAN) \ +static __inline intpcm_t \ +intpcm_read_##SIGN##32##ENDIAN(uint8_t *src) \ +{ \ + \ + return (_PCM_READ_##SIGN##32##_##ENDIAN(src)); \ +} \ + \ +static __inline void \ +intpcm_write_##SIGN##32##ENDIAN(uint8_t *dst, intpcm_t v) \ +{ \ + \ + _PCM_WRITE_##SIGN##32##_##ENDIAN(dst, v); \ +} + +INTPCM_DECLARE_OP_8(S, NE) +INTPCM_DECLARE_OP_16(S, LE) +INTPCM_DECLARE_OP_16(S, BE) +INTPCM_DECLARE_OP_24(S, LE) +INTPCM_DECLARE_OP_24(S, BE) +INTPCM_DECLARE_OP_32(S, LE) +INTPCM_DECLARE_OP_32(S, BE) +INTPCM_DECLARE_OP_8(U, NE) +INTPCM_DECLARE_OP_16(U, LE) +INTPCM_DECLARE_OP_16(U, BE) +INTPCM_DECLARE_OP_24(U, LE) +INTPCM_DECLARE_OP_24(U, BE) +INTPCM_DECLARE_OP_32(U, LE) +INTPCM_DECLARE_OP_32(U, BE) + +static const struct { + const uint8_t ulaw_to_u8[G711_TABLE_SIZE]; + const uint8_t alaw_to_u8[G711_TABLE_SIZE]; + const uint8_t u8_to_ulaw[G711_TABLE_SIZE]; + const uint8_t u8_to_alaw[G711_TABLE_SIZE]; +} xlaw_conv_tables = { + ULAW_TO_U8, + ALAW_TO_U8, + U8_TO_ULAW, + U8_TO_ALAW +}; + +static __inline intpcm_t +intpcm_read_ulaw(uint8_t *src) +{ + return (_G711_TO_INTPCM(xlaw_conv_tables.ulaw_to_u8, *src) << 24); +} + +static __inline intpcm_t +intpcm_read_alaw(uint8_t *src) +{ + return (_G711_TO_INTPCM(xlaw_conv_tables.alaw_to_u8, *src) << 24); +} + +static __inline void +intpcm_write_ulaw(uint8_t *dst, intpcm_t v) +{ + *dst = _INTPCM_TO_G711(xlaw_conv_tables.u8_to_ulaw, v >> 24); +} + +static __inline void +intpcm_write_alaw(uint8_t *dst, intpcm_t v) +{ + *dst = _INTPCM_TO_G711(xlaw_conv_tables.u8_to_alaw, v >> 24); +} + /* * dummy ac3/dts passthrough, etc. * XXX assume as s16le. */ static __inline intpcm_t intpcm_read_null(uint8_t *src __unused) { return (0); } static __inline void intpcm_write_null(uint8_t *dst, intpcm_t v __unused) { _PCM_WRITE_S16_LE(dst, 0); } #define FEEDFORMAT_ENTRY(SIGN, BIT, ENDIAN) \ { \ AFMT_##SIGN##BIT##_##ENDIAN, \ intpcm_read_##SIGN##BIT##ENDIAN, \ intpcm_write_##SIGN##BIT##ENDIAN \ } static const struct { uint32_t format; intpcm_read_t *read; intpcm_write_t *write; } feed_format_ops[] = { FEEDFORMAT_ENTRY(S, 8, NE), FEEDFORMAT_ENTRY(S, 16, LE), FEEDFORMAT_ENTRY(S, 24, LE), FEEDFORMAT_ENTRY(S, 32, LE), FEEDFORMAT_ENTRY(S, 16, BE), FEEDFORMAT_ENTRY(S, 24, BE), FEEDFORMAT_ENTRY(S, 32, BE), FEEDFORMAT_ENTRY(U, 8, NE), FEEDFORMAT_ENTRY(U, 16, LE), FEEDFORMAT_ENTRY(U, 24, LE), FEEDFORMAT_ENTRY(U, 32, LE), FEEDFORMAT_ENTRY(U, 16, BE), FEEDFORMAT_ENTRY(U, 24, BE), FEEDFORMAT_ENTRY(U, 32, BE), { AFMT_MU_LAW, intpcm_read_ulaw, intpcm_write_ulaw }, { AFMT_A_LAW, intpcm_read_alaw, intpcm_write_alaw }, { AFMT_AC3, intpcm_read_null, intpcm_write_null } }; static int feed_format_init(struct pcm_feeder *f) { struct feed_format_info *info; intpcm_read_t *rd_op; intpcm_write_t *wr_op; size_t i; if (f->desc->in == f->desc->out || AFMT_CHANNEL(f->desc->in) != AFMT_CHANNEL(f->desc->out)) return (EINVAL); rd_op = NULL; wr_op = NULL; for (i = 0; i < nitems(feed_format_ops) && (rd_op == NULL || wr_op == NULL); i++) { if (rd_op == NULL && AFMT_ENCODING(f->desc->in) == feed_format_ops[i].format) rd_op = feed_format_ops[i].read; if (wr_op == NULL && AFMT_ENCODING(f->desc->out) == feed_format_ops[i].format) wr_op = feed_format_ops[i].write; } if (rd_op == NULL || wr_op == NULL) { printf("%s(): failed to initialize io ops " "in=0x%08x out=0x%08x\n", __func__, f->desc->in, f->desc->out); return (EINVAL); } info = malloc(sizeof(*info), M_DEVBUF, M_NOWAIT | M_ZERO); if (info == NULL) return (ENOMEM); info->channels = AFMT_CHANNEL(f->desc->in); info->ibps = AFMT_BPS(f->desc->in); info->ialign = info->ibps * info->channels; info->read = rd_op; info->obps = AFMT_BPS(f->desc->out); info->oalign = info->obps * info->channels; info->write = wr_op; f->data = info; return (0); } static int feed_format_free(struct pcm_feeder *f) { struct feed_format_info *info; info = f->data; if (info != NULL) free(info, M_DEVBUF); f->data = NULL; return (0); } static int feed_format_set(struct pcm_feeder *f, int what, int value) { struct feed_format_info *info; info = f->data; switch (what) { case FEEDFORMAT_CHANNELS: if (value < SND_CHN_MIN || value > SND_CHN_MAX) return (EINVAL); info->channels = (uint32_t)value; info->ialign = info->ibps * info->channels; info->oalign = info->obps * info->channels; break; default: return (EINVAL); break; } return (0); } static int feed_format_feed(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b, uint32_t count, void *source) { struct feed_format_info *info; intpcm_t v; uint32_t j; uint8_t *src, *dst; info = f->data; dst = b; count = SND_FXROUND(count, info->oalign); do { if (count < info->oalign) break; if (count < info->ialign) { src = info->reservoir; j = info->ialign; } else { if (info->ialign == info->oalign) j = count; else if (info->ialign > info->oalign) j = SND_FXROUND(count, info->ialign); else j = SND_FXDIV(count, info->oalign) * info->ialign; src = dst + count - j; } j = SND_FXDIV(FEEDER_FEED(f->source, c, src, j, source), info->ialign); if (j == 0) break; j *= info->channels; count -= j * info->obps; do { v = info->read(src); info->write(dst, v); dst += info->obps; src += info->ibps; } while (--j != 0); } while (count != 0); return (dst - b); } static struct pcm_feederdesc feeder_format_desc[] = { { FEEDER_FORMAT, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 } }; static kobj_method_t feeder_format_methods[] = { KOBJMETHOD(feeder_init, feed_format_init), KOBJMETHOD(feeder_free, feed_format_free), KOBJMETHOD(feeder_set, feed_format_set), KOBJMETHOD(feeder_feed, feed_format_feed), KOBJMETHOD_END }; FEEDER_DECLARE(feeder_format, NULL); -/* Extern */ intpcm_read_t * feeder_format_read_op(uint32_t format) { size_t i; for (i = 0; i < nitems(feed_format_ops); i++) { if (AFMT_ENCODING(format) == feed_format_ops[i].format) return (feed_format_ops[i].read); } return (NULL); } intpcm_write_t * feeder_format_write_op(uint32_t format) { size_t i; for (i = 0; i < nitems(feed_format_ops); i++) { if (AFMT_ENCODING(format) == feed_format_ops[i].format) return (feed_format_ops[i].write); } return (NULL); } diff --git a/sys/dev/sound/pcm/g711.h b/sys/dev/sound/pcm/g711.h index b7a57dd17a6b..481ef368e144 100644 --- a/sys/dev/sound/pcm/g711.h +++ b/sys/dev/sound/pcm/g711.h @@ -1,190 +1,179 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2008-2009 Ariff Abdullah * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _SND_G711_H_ #define _SND_G711_H_ #define G711_TABLE_SIZE 256 #define ULAW_TO_U8 { \ 3, 7, 11, 15, 19, 23, 27, 31, \ 35, 39, 43, 47, 51, 55, 59, 63, \ 66, 68, 70, 72, 74, 76, 78, 80, \ 82, 84, 86, 88, 90, 92, 94, 96, \ 98, 99, 100, 101, 102, 103, 104, 105, \ 106, 107, 108, 109, 110, 111, 112, 113, \ 113, 114, 114, 115, 115, 116, 116, 117, \ 117, 118, 118, 119, 119, 120, 120, 121, \ 121, 121, 122, 122, 122, 122, 123, 123, \ 123, 123, 124, 124, 124, 124, 125, 125, \ 125, 125, 125, 125, 126, 126, 126, 126, \ 126, 126, 126, 126, 127, 127, 127, 127, \ 127, 127, 127, 127, 127, 127, 127, 127, \ 128, 128, 128, 128, 128, 128, 128, 128, \ 128, 128, 128, 128, 128, 128, 128, 128, \ 128, 128, 128, 128, 128, 128, 128, 128, \ 253, 249, 245, 241, 237, 233, 229, 225, \ 221, 217, 213, 209, 205, 201, 197, 193, \ 190, 188, 186, 184, 182, 180, 178, 176, \ 174, 172, 170, 168, 166, 164, 162, 160, \ 158, 157, 156, 155, 154, 153, 152, 151, \ 150, 149, 148, 147, 146, 145, 144, 143, \ 143, 142, 142, 141, 141, 140, 140, 139, \ 139, 138, 138, 137, 137, 136, 136, 135, \ 135, 135, 134, 134, 134, 134, 133, 133, \ 133, 133, 132, 132, 132, 132, 131, 131, \ 131, 131, 131, 131, 130, 130, 130, 130, \ 130, 130, 130, 130, 129, 129, 129, 129, \ 129, 129, 129, 129, 129, 129, 129, 129, \ 128, 128, 128, 128, 128, 128, 128, 128, \ 128, 128, 128, 128, 128, 128, 128, 128, \ 128, 128, 128, 128, 128, 128, 128, 128, \ } #define ALAW_TO_U8 { \ 108, 109, 106, 107, 112, 113, 110, 111, \ 100, 101, 98, 99, 104, 105, 102, 103, \ 118, 118, 117, 117, 120, 120, 119, 119, \ 114, 114, 113, 113, 116, 116, 115, 115, \ 43, 47, 35, 39, 59, 63, 51, 55, \ 11, 15, 3, 7, 27, 31, 19, 23, \ 86, 88, 82, 84, 94, 96, 90, 92, \ 70, 72, 66, 68, 78, 80, 74, 76, \ 127, 127, 127, 127, 127, 127, 127, 127, \ 127, 127, 127, 127, 127, 127, 127, 127, \ 128, 128, 128, 128, 128, 128, 128, 128, \ 128, 128, 128, 128, 128, 128, 128, 128, \ 123, 123, 123, 123, 124, 124, 124, 124, \ 121, 121, 121, 121, 122, 122, 122, 122, \ 126, 126, 126, 126, 126, 126, 126, 126, \ 125, 125, 125, 125, 125, 125, 125, 125, \ 148, 147, 150, 149, 144, 143, 146, 145, \ 156, 155, 158, 157, 152, 151, 154, 153, \ 138, 138, 139, 139, 136, 136, 137, 137, \ 142, 142, 143, 143, 140, 140, 141, 141, \ 213, 209, 221, 217, 197, 193, 205, 201, \ 245, 241, 253, 249, 229, 225, 237, 233, \ 170, 168, 174, 172, 162, 160, 166, 164, \ 186, 184, 190, 188, 178, 176, 182, 180, \ 129, 129, 129, 129, 129, 129, 129, 129, \ 129, 129, 129, 129, 129, 129, 129, 129, \ 128, 128, 128, 128, 128, 128, 128, 128, \ 128, 128, 128, 128, 128, 128, 128, 128, \ 133, 133, 133, 133, 132, 132, 132, 132, \ 135, 135, 135, 135, 134, 134, 134, 134, \ 130, 130, 130, 130, 130, 130, 130, 130, \ 131, 131, 131, 131, 131, 131, 131, 131, \ } #define U8_TO_ULAW { \ 0, 0, 0, 0, 0, 1, 1, 1, \ 1, 2, 2, 2, 2, 3, 3, 3, \ 3, 4, 4, 4, 4, 5, 5, 5, \ 5, 6, 6, 6, 6, 7, 7, 7, \ 7, 8, 8, 8, 8, 9, 9, 9, \ 9, 10, 10, 10, 10, 11, 11, 11, \ 11, 12, 12, 12, 12, 13, 13, 13, \ 13, 14, 14, 14, 14, 15, 15, 15, \ 15, 16, 16, 17, 17, 18, 18, 19, \ 19, 20, 20, 21, 21, 22, 22, 23, \ 23, 24, 24, 25, 25, 26, 26, 27, \ 27, 28, 28, 29, 29, 30, 30, 31, \ 31, 32, 33, 34, 35, 36, 37, 38, \ 39, 40, 41, 42, 43, 44, 45, 46, \ 47, 49, 51, 53, 55, 57, 59, 61, \ 63, 66, 70, 74, 78, 84, 92, 104, \ 254, 231, 219, 211, 205, 201, 197, 193, \ 190, 188, 186, 184, 182, 180, 178, 176, \ 175, 174, 173, 172, 171, 170, 169, 168, \ 167, 166, 165, 164, 163, 162, 161, 160, \ 159, 159, 158, 158, 157, 157, 156, 156, \ 155, 155, 154, 154, 153, 153, 152, 152, \ 151, 151, 150, 150, 149, 149, 148, 148, \ 147, 147, 146, 146, 145, 145, 144, 144, \ 143, 143, 143, 143, 142, 142, 142, 142, \ 141, 141, 141, 141, 140, 140, 140, 140, \ 139, 139, 139, 139, 138, 138, 138, 138, \ 137, 137, 137, 137, 136, 136, 136, 136, \ 135, 135, 135, 135, 134, 134, 134, 134, \ 133, 133, 133, 133, 132, 132, 132, 132, \ 131, 131, 131, 131, 130, 130, 130, 130, \ 129, 129, 129, 129, 128, 128, 128, 128, \ } #define U8_TO_ALAW { \ 42, 42, 42, 42, 42, 43, 43, 43, \ 43, 40, 40, 40, 40, 41, 41, 41, \ 41, 46, 46, 46, 46, 47, 47, 47, \ 47, 44, 44, 44, 44, 45, 45, 45, \ 45, 34, 34, 34, 34, 35, 35, 35, \ 35, 32, 32, 32, 32, 33, 33, 33, \ 33, 38, 38, 38, 38, 39, 39, 39, \ 39, 36, 36, 36, 36, 37, 37, 37, \ 37, 58, 58, 59, 59, 56, 56, 57, \ 57, 62, 62, 63, 63, 60, 60, 61, \ 61, 50, 50, 51, 51, 48, 48, 49, \ 49, 54, 54, 55, 55, 52, 52, 53, \ 53, 10, 11, 8, 9, 14, 15, 12, \ 13, 2, 3, 0, 1, 6, 7, 4, \ 5, 24, 30, 28, 18, 16, 22, 20, \ 106, 110, 98, 102, 122, 114, 75, 90, \ 213, 197, 245, 253, 229, 225, 237, 233, \ 149, 151, 145, 147, 157, 159, 153, 155, \ 133, 132, 135, 134, 129, 128, 131, 130, \ 141, 140, 143, 142, 137, 136, 139, 138, \ 181, 181, 180, 180, 183, 183, 182, 182, \ 177, 177, 176, 176, 179, 179, 178, 178, \ 189, 189, 188, 188, 191, 191, 190, 190, \ 185, 185, 184, 184, 187, 187, 186, 186, \ 165, 165, 165, 165, 164, 164, 164, 164, \ 167, 167, 167, 167, 166, 166, 166, 166, \ 161, 161, 161, 161, 160, 160, 160, 160, \ 163, 163, 163, 163, 162, 162, 162, 162, \ 173, 173, 173, 173, 172, 172, 172, 172, \ 175, 175, 175, 175, 174, 174, 174, 174, \ 169, 169, 169, 169, 168, 168, 168, 168, \ 171, 171, 171, 171, 170, 170, 170, 170, \ } #define _G711_TO_INTPCM(t, v) ((intpcm_t) \ ((int8_t)((t)[(uint8_t)(v)] ^ 0x80))) #define _INTPCM_TO_G711(t, v) ((t)[(uint8_t)((v) ^ 0x80)]) -#define G711_DECLARE_TABLE(t) \ -static const struct { \ - const uint8_t ulaw_to_u8[G711_TABLE_SIZE]; \ - const uint8_t alaw_to_u8[G711_TABLE_SIZE]; \ - const uint8_t u8_to_ulaw[G711_TABLE_SIZE]; \ - const uint8_t u8_to_alaw[G711_TABLE_SIZE]; \ -} t = { \ - ULAW_TO_U8, ALAW_TO_U8, \ - U8_TO_ULAW, U8_TO_ALAW \ -} - #endif /* !_SND_G711_H_ */ diff --git a/sys/dev/sound/pcm/intpcm.h b/sys/dev/sound/pcm/intpcm.h deleted file mode 100644 index 1e85535feec1..000000000000 --- a/sys/dev/sound/pcm/intpcm.h +++ /dev/null @@ -1,135 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2008-2009 Ariff Abdullah - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _SND_INTPCM_H_ -#define _SND_INTPCM_H_ - -typedef intpcm_t intpcm_read_t(uint8_t *); -typedef void intpcm_write_t(uint8_t *, intpcm_t); - -extern intpcm_read_t *feeder_format_read_op(uint32_t); -extern intpcm_write_t *feeder_format_write_op(uint32_t); - -#define INTPCM_DECLARE_OP_WRITE(SIGN, BIT, ENDIAN, SHIFT) \ -static __inline void \ -intpcm_write_##SIGN##BIT##ENDIAN(uint8_t *dst, intpcm_t v) \ -{ \ - \ - _PCM_WRITE_##SIGN##BIT##_##ENDIAN(dst, v >> SHIFT); \ -} - -#define INTPCM_DECLARE_OP_8(SIGN, ENDIAN) \ -static __inline intpcm_t \ -intpcm_read_##SIGN##8##ENDIAN(uint8_t *src) \ -{ \ - \ - return (_PCM_READ_##SIGN##8##_##ENDIAN(src) << 24); \ -} \ -INTPCM_DECLARE_OP_WRITE(SIGN, 8, ENDIAN, 24) - -#define INTPCM_DECLARE_OP_16(SIGN, ENDIAN) \ -static __inline intpcm_t \ -intpcm_read_##SIGN##16##ENDIAN(uint8_t *src) \ -{ \ - \ - return (_PCM_READ_##SIGN##16##_##ENDIAN(src) << 16); \ -} \ -INTPCM_DECLARE_OP_WRITE(SIGN, 16, ENDIAN, 16) - -#define INTPCM_DECLARE_OP_24(SIGN, ENDIAN) \ -static __inline intpcm_t \ -intpcm_read_##SIGN##24##ENDIAN(uint8_t *src) \ -{ \ - \ - return (_PCM_READ_##SIGN##24##_##ENDIAN(src) << 8); \ -} \ -INTPCM_DECLARE_OP_WRITE(SIGN, 24, ENDIAN, 8) - -#define INTPCM_DECLARE_OP_32(SIGN, ENDIAN) \ -static __inline intpcm_t \ -intpcm_read_##SIGN##32##ENDIAN(uint8_t *src) \ -{ \ - \ - return (_PCM_READ_##SIGN##32##_##ENDIAN(src)); \ -} \ - \ -static __inline void \ -intpcm_write_##SIGN##32##ENDIAN(uint8_t *dst, intpcm_t v) \ -{ \ - \ - _PCM_WRITE_##SIGN##32##_##ENDIAN(dst, v); \ -} - -#define INTPCM_DECLARE(t) \ - \ -G711_DECLARE_TABLE(t); \ - \ -static __inline intpcm_t \ -intpcm_read_ulaw(uint8_t *src) \ -{ \ - \ - return (_G711_TO_INTPCM((t).ulaw_to_u8, *src) << 24); \ -} \ - \ -static __inline intpcm_t \ -intpcm_read_alaw(uint8_t *src) \ -{ \ - \ - return (_G711_TO_INTPCM((t).alaw_to_u8, *src) << 24); \ -} \ - \ -static __inline void \ -intpcm_write_ulaw(uint8_t *dst, intpcm_t v) \ -{ \ - \ - *dst = _INTPCM_TO_G711((t).u8_to_ulaw, v >> 24); \ -} \ - \ -static __inline void \ -intpcm_write_alaw(uint8_t *dst, intpcm_t v) \ -{ \ - \ - *dst = _INTPCM_TO_G711((t).u8_to_alaw, v >> 24); \ -} \ - \ -INTPCM_DECLARE_OP_8(S, NE) \ -INTPCM_DECLARE_OP_16(S, LE) \ -INTPCM_DECLARE_OP_16(S, BE) \ -INTPCM_DECLARE_OP_24(S, LE) \ -INTPCM_DECLARE_OP_24(S, BE) \ -INTPCM_DECLARE_OP_32(S, LE) \ -INTPCM_DECLARE_OP_32(S, BE) \ -INTPCM_DECLARE_OP_8(U, NE) \ -INTPCM_DECLARE_OP_16(U, LE) \ -INTPCM_DECLARE_OP_16(U, BE) \ -INTPCM_DECLARE_OP_24(U, LE) \ -INTPCM_DECLARE_OP_24(U, BE) \ -INTPCM_DECLARE_OP_32(U, LE) \ -INTPCM_DECLARE_OP_32(U, BE) - -#endif /* !_SND_INTPCM_H_ */ diff --git a/sys/dev/sound/pcm/sound.h b/sys/dev/sound/pcm/sound.h index f1d435369d36..ff2b618adff8 100644 --- a/sys/dev/sound/pcm/sound.h +++ b/sys/dev/sound/pcm/sound.h @@ -1,520 +1,521 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2005-2009 Ariff Abdullah * Copyright (c) 1999 Cameron Grant * Copyright (c) 1995 Hannu Savolainen * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * first, include kernel header files. */ #ifndef _OS_H_ #define _OS_H_ #ifdef _KERNEL #include #include #include #include #include #include #include #include #include #include /* for DATA_SET */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef KOBJMETHOD_END #define KOBJMETHOD_END { NULL, NULL } #endif struct pcm_channel; struct pcm_feeder; struct snd_dbuf; struct snd_mixer; #include #include #include #include +#include #include #include #include #define PCM_SOFTC_SIZE (sizeof(struct snddev_info)) #define SND_STATUSLEN 64 #define SOUND_MODVER 5 #define SOUND_MINVER SOUND_MODVER #define SOUND_PREFVER SOUND_MODVER #define SOUND_MAXVER SOUND_MODVER #define SND_MAXVCHANS 256 #define SD_F_SIMPLEX 0x00000001 #define SD_F_AUTOVCHAN 0x00000002 #define SD_F_SOFTPCMVOL 0x00000004 #define SD_F_BUSY 0x00000008 #define SD_F_MPSAFE 0x00000010 #define SD_F_REGISTERED 0x00000020 #define SD_F_BITPERFECT 0x00000040 #define SD_F_VPC 0x00000080 /* volume-per-channel */ #define SD_F_EQ 0x00000100 /* EQ */ #define SD_F_EQ_ENABLED 0x00000200 /* EQ enabled */ #define SD_F_EQ_BYPASSED 0x00000400 /* EQ bypassed */ #define SD_F_EQ_PC 0x00000800 /* EQ per-channel */ #define SD_F_EQ_DEFAULT (SD_F_EQ | SD_F_EQ_ENABLED) #define SD_F_EQ_MASK (SD_F_EQ | SD_F_EQ_ENABLED | \ SD_F_EQ_BYPASSED | SD_F_EQ_PC) #define SD_F_PRIO_RD 0x10000000 #define SD_F_PRIO_WR 0x20000000 #define SD_F_BITS "\020" \ "\001SIMPLEX" \ "\002AUTOVCHAN" \ "\003SOFTPCMVOL" \ "\004BUSY" \ "\005MPSAFE" \ "\006REGISTERED" \ "\007BITPERFECT" \ "\010VPC" \ "\011EQ" \ "\012EQ_ENABLED" \ "\013EQ_BYPASSED" \ "\014EQ_PC" \ "\035PRIO_RD" \ "\036PRIO_WR" #define PCM_ALIVE(x) ((x) != NULL && (x)->lock != NULL) #define PCM_REGISTERED(x) (PCM_ALIVE(x) && ((x)->flags & SD_F_REGISTERED)) #define PCM_CHANCOUNT(d) \ (d->playcount + d->pvchancount + d->reccount + d->rvchancount) /* many variables should be reduced to a range. Here define a macro */ #define RANGE(var, low, high) (var) = \ (((var)<(low))? (low) : ((var)>(high))? (high) : (var)) /* make figuring out what a format is easier. got AFMT_STEREO already */ #define AFMT_32BIT (AFMT_S32_LE | AFMT_S32_BE | AFMT_U32_LE | AFMT_U32_BE) #define AFMT_24BIT (AFMT_S24_LE | AFMT_S24_BE | AFMT_U24_LE | AFMT_U24_BE) #define AFMT_16BIT (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE) #define AFMT_G711 (AFMT_MU_LAW | AFMT_A_LAW) #define AFMT_8BIT (AFMT_G711 | AFMT_U8 | AFMT_S8) #define AFMT_SIGNED (AFMT_S32_LE | AFMT_S32_BE | AFMT_S24_LE | AFMT_S24_BE | \ AFMT_S16_LE | AFMT_S16_BE | AFMT_S8) #define AFMT_BIGENDIAN (AFMT_S32_BE | AFMT_U32_BE | AFMT_S24_BE | AFMT_U24_BE | \ AFMT_S16_BE | AFMT_U16_BE) #define AFMT_CONVERTIBLE (AFMT_8BIT | AFMT_16BIT | AFMT_24BIT | \ AFMT_32BIT) /* Supported vchan mixing formats */ #define AFMT_VCHAN (AFMT_CONVERTIBLE & ~AFMT_G711) #define AFMT_PASSTHROUGH AFMT_AC3 #define AFMT_PASSTHROUGH_RATE 48000 #define AFMT_PASSTHROUGH_CHANNEL 2 #define AFMT_PASSTHROUGH_EXTCHANNEL 0 /* * We're simply using unused, contiguous bits from various AFMT_ definitions. * ~(0xb00ff7ff) */ #define AFMT_ENCODING_MASK 0xf00fffff #define AFMT_CHANNEL_MASK 0x07f00000 #define AFMT_CHANNEL_SHIFT 20 #define AFMT_CHANNEL_MAX 0x7f #define AFMT_EXTCHANNEL_MASK 0x08000000 #define AFMT_EXTCHANNEL_SHIFT 27 #define AFMT_EXTCHANNEL_MAX 1 #define AFMT_ENCODING(v) ((v) & AFMT_ENCODING_MASK) #define AFMT_EXTCHANNEL(v) (((v) & AFMT_EXTCHANNEL_MASK) >> \ AFMT_EXTCHANNEL_SHIFT) #define AFMT_CHANNEL(v) (((v) & AFMT_CHANNEL_MASK) >> \ AFMT_CHANNEL_SHIFT) #define AFMT_BIT(v) (((v) & AFMT_32BIT) ? 32 : \ (((v) & AFMT_24BIT) ? 24 : \ ((((v) & AFMT_16BIT) || \ ((v) & AFMT_PASSTHROUGH)) ? 16 : 8))) #define AFMT_BPS(v) (AFMT_BIT(v) >> 3) #define AFMT_ALIGN(v) (AFMT_BPS(v) * AFMT_CHANNEL(v)) #define SND_FORMAT(f, c, e) (AFMT_ENCODING(f) | \ (((c) << AFMT_CHANNEL_SHIFT) & \ AFMT_CHANNEL_MASK) | \ (((e) << AFMT_EXTCHANNEL_SHIFT) & \ AFMT_EXTCHANNEL_MASK)) #define AFMT_U8_NE AFMT_U8 #define AFMT_S8_NE AFMT_S8 #define AFMT_SIGNED_NE (AFMT_S8_NE | AFMT_S16_NE | AFMT_S24_NE | AFMT_S32_NE) #define AFMT_NE (AFMT_SIGNED_NE | AFMT_U8_NE | AFMT_U16_NE | \ AFMT_U24_NE | AFMT_U32_NE) enum { SND_DEV_CTL = 0, /* Control port /dev/mixer */ SND_DEV_SEQ, /* Sequencer /dev/sequencer */ SND_DEV_MIDIN, /* Raw midi access */ SND_DEV_DSP, /* Digitized voice /dev/dsp */ SND_DEV_STATUS, /* /dev/sndstat */ }; #define DSP_DEFAULT_SPEED 8000 extern int snd_unit; extern int snd_verbose; extern devclass_t pcm_devclass; extern struct unrhdr *pcmsg_unrhdr; #ifndef DEB #define DEB(x) #endif SYSCTL_DECL(_hw_snd); int pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction, pid_t pid, char *comm); int pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo); unsigned int pcm_getbuffersize(device_t dev, unsigned int minbufsz, unsigned int deflt, unsigned int maxbufsz); void pcm_init(device_t dev, void *devinfo); int pcm_register(device_t dev, char *str); int pcm_unregister(device_t dev); u_int32_t pcm_getflags(device_t dev); void pcm_setflags(device_t dev, u_int32_t val); void *pcm_getdevinfo(device_t dev); int snd_setup_intr(device_t dev, struct resource *res, int flags, driver_intr_t hand, void *param, void **cookiep); void *snd_mtxcreate(const char *desc, const char *type); void snd_mtxfree(void *m); void snd_mtxassert(void *m); #define snd_mtxlock(m) mtx_lock(m) #define snd_mtxunlock(m) mtx_unlock(m) int sndstat_register(device_t dev, char *str); int sndstat_unregister(device_t dev); /* These are the function codes assigned to the children of sound cards. */ enum { SCF_PCM, SCF_MIDI, SCF_SYNTH, }; /* * This is the device information struct, used by a bridge device to pass the * device function code to the children. */ struct sndcard_func { int func; /* The function code. */ void *varinfo; /* Bridge-specific information. */ }; /* * this is rather kludgey- we need to duplicate these struct def'ns from sound.c * so that the macro versions of pcm_{,un}lock can dereference them. * we also have to do this now makedev() has gone away. */ struct snddev_info { struct { struct { SLIST_HEAD(, pcm_channel) head; struct { SLIST_HEAD(, pcm_channel) head; } busy; struct { SLIST_HEAD(, pcm_channel) head; } opened; } pcm; } channels; unsigned playcount, reccount, pvchancount, rvchancount; unsigned flags; unsigned int bufsz; void *devinfo; device_t dev; char status[SND_STATUSLEN]; struct mtx *lock; struct cdev *mixer_dev; struct cdev *dsp_dev; uint32_t pvchanrate, pvchanformat; uint32_t rvchanrate, rvchanformat; int32_t eqpreamp; struct sysctl_ctx_list play_sysctl_ctx, rec_sysctl_ctx; struct sysctl_oid *play_sysctl_tree, *rec_sysctl_tree; struct cv cv; struct unrhdr *p_unr; struct unrhdr *vp_unr; struct unrhdr *r_unr; struct unrhdr *vr_unr; }; void sound_oss_sysinfo(oss_sysinfo *); int sound_oss_card_info(oss_card_info *); #define PCM_MODE_MIXER 0x01 #define PCM_MODE_PLAY 0x02 #define PCM_MODE_REC 0x04 #define PCM_LOCKOWNED(d) mtx_owned((d)->lock) #define PCM_LOCK(d) mtx_lock((d)->lock) #define PCM_UNLOCK(d) mtx_unlock((d)->lock) #define PCM_TRYLOCK(d) mtx_trylock((d)->lock) #define PCM_LOCKASSERT(d) mtx_assert((d)->lock, MA_OWNED) #define PCM_UNLOCKASSERT(d) mtx_assert((d)->lock, MA_NOTOWNED) /* * For PCM_[WAIT | ACQUIRE | RELEASE], be sure to surround these * with PCM_LOCK/UNLOCK() sequence, or I'll come to gnaw upon you! */ #ifdef SND_DIAGNOSTIC #define PCM_WAIT(x) do { \ if (!PCM_LOCKOWNED(x)) \ panic("%s(%d): [PCM WAIT] Mutex not owned!", \ __func__, __LINE__); \ while ((x)->flags & SD_F_BUSY) { \ if (snd_verbose > 3) \ device_printf((x)->dev, \ "%s(%d): [PCM WAIT] calling cv_wait().\n", \ __func__, __LINE__); \ cv_wait(&(x)->cv, (x)->lock); \ } \ } while (0) #define PCM_ACQUIRE(x) do { \ if (!PCM_LOCKOWNED(x)) \ panic("%s(%d): [PCM ACQUIRE] Mutex not owned!", \ __func__, __LINE__); \ if ((x)->flags & SD_F_BUSY) \ panic("%s(%d): [PCM ACQUIRE] " \ "Trying to acquire BUSY cv!", __func__, __LINE__); \ (x)->flags |= SD_F_BUSY; \ } while (0) #define PCM_RELEASE(x) do { \ if (!PCM_LOCKOWNED(x)) \ panic("%s(%d): [PCM RELEASE] Mutex not owned!", \ __func__, __LINE__); \ if ((x)->flags & SD_F_BUSY) { \ (x)->flags &= ~SD_F_BUSY; \ if ((x)->cv.cv_waiters != 0) { \ if ((x)->cv.cv_waiters > 1 && snd_verbose > 3) \ device_printf((x)->dev, \ "%s(%d): [PCM RELEASE] " \ "cv_waiters=%d > 1!\n", \ __func__, __LINE__, \ (x)->cv.cv_waiters); \ cv_broadcast(&(x)->cv); \ } \ } else \ panic("%s(%d): [PCM RELEASE] Releasing non-BUSY cv!", \ __func__, __LINE__); \ } while (0) /* Quick version, for shorter path. */ #define PCM_ACQUIRE_QUICK(x) do { \ if (PCM_LOCKOWNED(x)) \ panic("%s(%d): [PCM ACQUIRE QUICK] Mutex owned!", \ __func__, __LINE__); \ PCM_LOCK(x); \ PCM_WAIT(x); \ PCM_ACQUIRE(x); \ PCM_UNLOCK(x); \ } while (0) #define PCM_RELEASE_QUICK(x) do { \ if (PCM_LOCKOWNED(x)) \ panic("%s(%d): [PCM RELEASE QUICK] Mutex owned!", \ __func__, __LINE__); \ PCM_LOCK(x); \ PCM_RELEASE(x); \ PCM_UNLOCK(x); \ } while (0) #define PCM_BUSYASSERT(x) do { \ if (!((x) != NULL && ((x)->flags & SD_F_BUSY))) \ panic("%s(%d): [PCM BUSYASSERT] " \ "Failed, snddev_info=%p", __func__, __LINE__, x); \ } while (0) #define PCM_GIANT_ENTER(x) do { \ int _pcm_giant = 0; \ if (PCM_LOCKOWNED(x)) \ panic("%s(%d): [GIANT ENTER] PCM lock owned!", \ __func__, __LINE__); \ if (mtx_owned(&Giant) != 0 && snd_verbose > 3) \ device_printf((x)->dev, \ "%s(%d): [GIANT ENTER] Giant owned!\n", \ __func__, __LINE__); \ if (!((x)->flags & SD_F_MPSAFE) && mtx_owned(&Giant) == 0) \ do { \ mtx_lock(&Giant); \ _pcm_giant = 1; \ } while (0) #define PCM_GIANT_EXIT(x) do { \ if (PCM_LOCKOWNED(x)) \ panic("%s(%d): [GIANT EXIT] PCM lock owned!", \ __func__, __LINE__); \ if (!(_pcm_giant == 0 || _pcm_giant == 1)) \ panic("%s(%d): [GIANT EXIT] _pcm_giant screwed!", \ __func__, __LINE__); \ if ((x)->flags & SD_F_MPSAFE) { \ if (_pcm_giant == 1) \ panic("%s(%d): [GIANT EXIT] MPSAFE Giant?", \ __func__, __LINE__); \ if (mtx_owned(&Giant) != 0 && snd_verbose > 3) \ device_printf((x)->dev, \ "%s(%d): [GIANT EXIT] Giant owned!\n", \ __func__, __LINE__); \ } \ if (_pcm_giant != 0) { \ if (mtx_owned(&Giant) == 0) \ panic("%s(%d): [GIANT EXIT] Giant not owned!", \ __func__, __LINE__); \ _pcm_giant = 0; \ mtx_unlock(&Giant); \ } \ } while (0) #else /* !SND_DIAGNOSTIC */ #define PCM_WAIT(x) do { \ PCM_LOCKASSERT(x); \ while ((x)->flags & SD_F_BUSY) \ cv_wait(&(x)->cv, (x)->lock); \ } while (0) #define PCM_ACQUIRE(x) do { \ PCM_LOCKASSERT(x); \ KASSERT(!((x)->flags & SD_F_BUSY), \ ("%s(%d): [PCM ACQUIRE] Trying to acquire BUSY cv!", \ __func__, __LINE__)); \ (x)->flags |= SD_F_BUSY; \ } while (0) #define PCM_RELEASE(x) do { \ PCM_LOCKASSERT(x); \ KASSERT((x)->flags & SD_F_BUSY, \ ("%s(%d): [PCM RELEASE] Releasing non-BUSY cv!", \ __func__, __LINE__)); \ (x)->flags &= ~SD_F_BUSY; \ if ((x)->cv.cv_waiters != 0) \ cv_broadcast(&(x)->cv); \ } while (0) /* Quick version, for shorter path. */ #define PCM_ACQUIRE_QUICK(x) do { \ PCM_UNLOCKASSERT(x); \ PCM_LOCK(x); \ PCM_WAIT(x); \ PCM_ACQUIRE(x); \ PCM_UNLOCK(x); \ } while (0) #define PCM_RELEASE_QUICK(x) do { \ PCM_UNLOCKASSERT(x); \ PCM_LOCK(x); \ PCM_RELEASE(x); \ PCM_UNLOCK(x); \ } while (0) #define PCM_BUSYASSERT(x) KASSERT(x != NULL && \ ((x)->flags & SD_F_BUSY), \ ("%s(%d): [PCM BUSYASSERT] " \ "Failed, snddev_info=%p", \ __func__, __LINE__, x)) #define PCM_GIANT_ENTER(x) do { \ int _pcm_giant = 0; \ PCM_UNLOCKASSERT(x); \ if (!((x)->flags & SD_F_MPSAFE) && mtx_owned(&Giant) == 0) \ do { \ mtx_lock(&Giant); \ _pcm_giant = 1; \ } while (0) #define PCM_GIANT_EXIT(x) do { \ PCM_UNLOCKASSERT(x); \ KASSERT(_pcm_giant == 0 || _pcm_giant == 1, \ ("%s(%d): [GIANT EXIT] _pcm_giant screwed!", \ __func__, __LINE__)); \ KASSERT(!((x)->flags & SD_F_MPSAFE) || \ (((x)->flags & SD_F_MPSAFE) && _pcm_giant == 0), \ ("%s(%d): [GIANT EXIT] MPSAFE Giant?", \ __func__, __LINE__)); \ if (_pcm_giant != 0) { \ mtx_assert(&Giant, MA_OWNED); \ _pcm_giant = 0; \ mtx_unlock(&Giant); \ } \ } while (0) #endif /* SND_DIAGNOSTIC */ #define PCM_GIANT_LEAVE(x) \ PCM_GIANT_EXIT(x); \ } while (0) #endif /* _KERNEL */ #endif /* _OS_H_ */