1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2005-2009 Ariff Abdullah <ariff@FreeBSD.org> 5 * Copyright (c) 1999 Cameron Grant <cg@FreeBSD.org> 6 * Copyright (c) 1995 Hannu Savolainen 7 * All rights reserved. 8 * Copyright (c) 2024-2025 The FreeBSD Foundation 9 * 10 * Portions of this software were developed by Christos Margiolis 11 * <christos@FreeBSD.org> under sponsorship from the FreeBSD Foundation. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 /* 36 * first, include kernel header files. 37 */ 38 39 #ifndef _OS_H_ 40 #define _OS_H_ 41 42 #ifdef _KERNEL 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/eventhandler.h> 46 #include <sys/ioccom.h> 47 #include <sys/filio.h> 48 #include <sys/sockio.h> 49 #include <sys/fcntl.h> 50 #include <sys/selinfo.h> 51 #include <sys/proc.h> 52 #include <sys/kernel.h> /* for DATA_SET */ 53 #include <sys/module.h> 54 #include <sys/conf.h> 55 #include <sys/file.h> 56 #include <sys/uio.h> 57 #include <sys/syslog.h> 58 #include <sys/errno.h> 59 #include <sys/malloc.h> 60 #include <sys/bus.h> 61 #include <machine/resource.h> 62 #include <machine/bus.h> 63 #include <sys/rman.h> 64 #include <sys/limits.h> 65 #include <sys/mman.h> 66 #include <sys/poll.h> 67 #include <sys/sbuf.h> 68 #include <sys/soundcard.h> 69 #include <sys/sysctl.h> 70 #include <sys/kobj.h> 71 #include <vm/vm.h> 72 #include <vm/pmap.h> 73 74 #include <sys/lock.h> 75 #include <sys/mutex.h> 76 #include <sys/condvar.h> 77 78 struct pcm_channel; 79 struct pcm_feeder; 80 struct snd_dbuf; 81 struct snd_mixer; 82 83 #include <dev/sound/pcm/buffer.h> 84 #include <dev/sound/pcm/matrix.h> 85 #include <dev/sound/pcm/channel.h> 86 #include <dev/sound/pcm/feeder.h> 87 #include <dev/sound/pcm/mixer.h> 88 #include <dev/sound/pcm/dsp.h> 89 90 #define PCM_SOFTC_SIZE (sizeof(struct snddev_info)) 91 92 #define SND_STATUSLEN 64 93 94 #define SD_F_SIMPLEX 0x00000001 95 /* unused 0x00000002 */ 96 #define SD_F_SOFTPCMVOL 0x00000004 97 #define SD_F_BUSY 0x00000008 98 #define SD_F_MPSAFE 0x00000010 99 #define SD_F_REGISTERED 0x00000020 100 #define SD_F_BITPERFECT 0x00000040 101 /* unused 0x00000080 */ 102 /* unused 0x00000100 */ 103 #define SD_F_EQ 0x00000200 /* EQ enabled */ 104 /* unused 0x00000400 */ 105 /* unused 0x00000800 */ 106 #define SD_F_PVCHANS 0x00001000 /* Playback vchans enabled */ 107 #define SD_F_RVCHANS 0x00002000 /* Recording vchans enabled */ 108 109 #define SD_F_BITS "\020" \ 110 "\001SIMPLEX" \ 111 /* "\002 */ \ 112 "\003SOFTPCMVOL" \ 113 "\004BUSY" \ 114 "\005MPSAFE" \ 115 "\006REGISTERED" \ 116 "\007BITPERFECT" \ 117 /* "\010 */ \ 118 /* "\011 */ \ 119 "\012EQ" \ 120 /* "\013 */ \ 121 /* "\014 */ \ 122 "\015PVCHANS" \ 123 "\016RVCHANS" 124 125 #define PCM_REGISTERED(x) \ 126 ((x) != NULL && ((x)->flags & SD_F_REGISTERED)) 127 128 #define PCM_MAXCHANS 10000 129 #define PCM_CHANCOUNT(d) \ 130 (d->playcount + d->pvchancount + d->reccount + d->rvchancount) 131 132 /* many variables should be reduced to a range. Here define a macro */ 133 #define RANGE(var, low, high) (var) = \ 134 (((var)<(low))? (low) : ((var)>(high))? (high) : (var)) 135 136 extern int snd_unit; 137 extern int snd_verbose; 138 extern devclass_t pcm_devclass; 139 extern struct unrhdr *pcmsg_unrhdr; 140 141 #ifndef DEB 142 #define DEB(x) 143 #endif 144 145 SYSCTL_DECL(_hw_snd); 146 147 int pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo); 148 unsigned int pcm_getbuffersize(device_t dev, unsigned int minbufsz, unsigned int deflt, unsigned int maxbufsz); 149 void pcm_init(device_t dev, void *devinfo); 150 int pcm_register(device_t dev, char *str); 151 int pcm_unregister(device_t dev); 152 uint32_t pcm_getflags(device_t dev); 153 void pcm_setflags(device_t dev, uint32_t val); 154 void *pcm_getdevinfo(device_t dev); 155 156 int snd_setup_intr(device_t dev, struct resource *res, int flags, 157 driver_intr_t hand, void *param, void **cookiep); 158 159 /* 160 * this is rather kludgey- we need to duplicate these struct def'ns from sound.c 161 * so that the macro versions of pcm_{,un}lock can dereference them. 162 * we also have to do this now makedev() has gone away. 163 */ 164 165 struct snddev_info { 166 struct { 167 struct { 168 SLIST_HEAD(, pcm_channel) head; 169 struct { 170 SLIST_HEAD(, pcm_channel) head; 171 } busy; 172 struct { 173 SLIST_HEAD(, pcm_channel) head; 174 } opened; 175 struct { 176 SLIST_HEAD(, pcm_channel) head; 177 } primary; 178 } pcm; 179 } channels; 180 unsigned playcount, reccount, pvchancount, rvchancount; 181 unsigned flags; 182 void *devinfo; 183 device_t dev; 184 char status[SND_STATUSLEN]; 185 struct mtx lock; 186 struct cdev *dsp_dev; 187 struct snd_mixer *mixer; 188 uint32_t pvchanrate, pvchanformat, pvchanmode; 189 uint32_t rvchanrate, rvchanformat, rvchanmode; 190 int32_t eqpreamp; 191 struct sysctl_ctx_list play_sysctl_ctx, rec_sysctl_ctx; 192 struct sysctl_oid *play_sysctl_tree, *rec_sysctl_tree; 193 struct cv cv; 194 struct unrhdr *p_unr; 195 struct unrhdr *vp_unr; 196 struct unrhdr *r_unr; 197 struct unrhdr *vr_unr; 198 }; 199 200 void sound_oss_sysinfo(oss_sysinfo *); 201 int sound_oss_card_info(oss_card_info *); 202 203 #define PCM_MODE_MIXER 0x01 204 #define PCM_MODE_PLAY 0x02 205 #define PCM_MODE_REC 0x04 206 207 #define PCM_LOCKOWNED(d) mtx_owned(&(d)->lock) 208 #define PCM_LOCK(d) mtx_lock(&(d)->lock) 209 #define PCM_UNLOCK(d) mtx_unlock(&(d)->lock) 210 #define PCM_TRYLOCK(d) mtx_trylock(&(d)->lock) 211 #define PCM_LOCKASSERT(d) mtx_assert(&(d)->lock, MA_OWNED) 212 #define PCM_UNLOCKASSERT(d) mtx_assert(&(d)->lock, MA_NOTOWNED) 213 214 /* 215 * For PCM_[WAIT | ACQUIRE | RELEASE], be sure to surround these 216 * with PCM_LOCK/UNLOCK() sequence, or I'll come to gnaw upon you! 217 */ 218 #define PCM_WAIT(x) do { \ 219 PCM_LOCKASSERT(x); \ 220 while ((x)->flags & SD_F_BUSY) \ 221 cv_wait(&(x)->cv, &(x)->lock); \ 222 } while (0) 223 224 #define PCM_ACQUIRE(x) do { \ 225 PCM_LOCKASSERT(x); \ 226 KASSERT(!((x)->flags & SD_F_BUSY), \ 227 ("%s(%d): [PCM ACQUIRE] Trying to acquire BUSY cv!", \ 228 __func__, __LINE__)); \ 229 (x)->flags |= SD_F_BUSY; \ 230 } while (0) 231 232 #define PCM_RELEASE(x) do { \ 233 PCM_LOCKASSERT(x); \ 234 KASSERT((x)->flags & SD_F_BUSY, \ 235 ("%s(%d): [PCM RELEASE] Releasing non-BUSY cv!", \ 236 __func__, __LINE__)); \ 237 (x)->flags &= ~SD_F_BUSY; \ 238 cv_broadcast(&(x)->cv); \ 239 } while (0) 240 241 /* Quick version, for shorter path. */ 242 #define PCM_ACQUIRE_QUICK(x) do { \ 243 PCM_UNLOCKASSERT(x); \ 244 PCM_LOCK(x); \ 245 PCM_WAIT(x); \ 246 PCM_ACQUIRE(x); \ 247 PCM_UNLOCK(x); \ 248 } while (0) 249 250 #define PCM_RELEASE_QUICK(x) do { \ 251 PCM_UNLOCKASSERT(x); \ 252 PCM_LOCK(x); \ 253 PCM_RELEASE(x); \ 254 PCM_UNLOCK(x); \ 255 } while (0) 256 257 #define PCM_BUSYASSERT(x) KASSERT(x != NULL && \ 258 ((x)->flags & SD_F_BUSY), \ 259 ("%s(%d): [PCM BUSYASSERT] " \ 260 "Failed, snddev_info=%p", \ 261 __func__, __LINE__, x)) 262 263 #define PCM_GIANT_ENTER(x) do { \ 264 int _pcm_giant = 0; \ 265 PCM_UNLOCKASSERT(x); \ 266 if (!((x)->flags & SD_F_MPSAFE) && mtx_owned(&Giant) == 0) \ 267 do { \ 268 mtx_lock(&Giant); \ 269 _pcm_giant = 1; \ 270 } while (0) 271 272 #define PCM_GIANT_EXIT(x) do { \ 273 PCM_UNLOCKASSERT(x); \ 274 KASSERT(_pcm_giant == 0 || _pcm_giant == 1, \ 275 ("%s(%d): [GIANT EXIT] _pcm_giant screwed!", \ 276 __func__, __LINE__)); \ 277 KASSERT(!((x)->flags & SD_F_MPSAFE) || \ 278 (((x)->flags & SD_F_MPSAFE) && _pcm_giant == 0), \ 279 ("%s(%d): [GIANT EXIT] MPSAFE Giant?", \ 280 __func__, __LINE__)); \ 281 if (_pcm_giant != 0) { \ 282 mtx_assert(&Giant, MA_OWNED); \ 283 _pcm_giant = 0; \ 284 mtx_unlock(&Giant); \ 285 } \ 286 } while (0) 287 288 #define PCM_GIANT_LEAVE(x) \ 289 PCM_GIANT_EXIT(x); \ 290 } while (0) 291 292 #endif /* _KERNEL */ 293 294 /* make figuring out what a format is easier. got AFMT_STEREO already */ 295 #define AFMT_32BIT (AFMT_S32_LE | AFMT_S32_BE | AFMT_U32_LE | AFMT_U32_BE | \ 296 AFMT_F32_LE | AFMT_F32_BE) 297 #define AFMT_24BIT (AFMT_S24_LE | AFMT_S24_BE | AFMT_U24_LE | AFMT_U24_BE) 298 #define AFMT_16BIT (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE) 299 #define AFMT_G711 (AFMT_MU_LAW | AFMT_A_LAW) 300 #define AFMT_8BIT (AFMT_G711 | AFMT_U8 | AFMT_S8) 301 #define AFMT_SIGNED (AFMT_S32_LE | AFMT_S32_BE | AFMT_F32_LE | AFMT_F32_BE | \ 302 AFMT_S24_LE | AFMT_S24_BE | \ 303 AFMT_S16_LE | AFMT_S16_BE | AFMT_S8) 304 #define AFMT_BIGENDIAN (AFMT_S32_BE | AFMT_U32_BE | AFMT_F32_BE | \ 305 AFMT_S24_BE | AFMT_U24_BE | AFMT_S16_BE | AFMT_U16_BE) 306 307 #define AFMT_CONVERTIBLE (AFMT_8BIT | AFMT_16BIT | AFMT_24BIT | \ 308 AFMT_32BIT) 309 310 /* Supported vchan mixing formats */ 311 #define AFMT_VCHAN (AFMT_CONVERTIBLE & ~AFMT_G711) 312 313 #define AFMT_PASSTHROUGH AFMT_AC3 314 #define AFMT_PASSTHROUGH_RATE 48000 315 #define AFMT_PASSTHROUGH_CHANNEL 2 316 #define AFMT_PASSTHROUGH_EXTCHANNEL 0 317 318 /* 319 * We're simply using unused, contiguous bits from various AFMT_ definitions. 320 * ~(0xb00ff7ff) 321 */ 322 #define AFMT_ENCODING_MASK 0xf00fffff 323 #define AFMT_CHANNEL_MASK 0x07f00000 324 #define AFMT_CHANNEL_SHIFT 20 325 #define AFMT_CHANNEL_MAX 0x7f 326 #define AFMT_EXTCHANNEL_MASK 0x08000000 327 #define AFMT_EXTCHANNEL_SHIFT 27 328 #define AFMT_EXTCHANNEL_MAX 1 329 330 #define AFMT_ENCODING(v) ((v) & AFMT_ENCODING_MASK) 331 332 #define AFMT_EXTCHANNEL(v) (((v) & AFMT_EXTCHANNEL_MASK) >> \ 333 AFMT_EXTCHANNEL_SHIFT) 334 335 #define AFMT_CHANNEL(v) (((v) & AFMT_CHANNEL_MASK) >> \ 336 AFMT_CHANNEL_SHIFT) 337 338 #define AFMT_BIT(v) (((v) & AFMT_32BIT) ? 32 : \ 339 (((v) & AFMT_24BIT) ? 24 : \ 340 ((((v) & AFMT_16BIT) || \ 341 ((v) & AFMT_PASSTHROUGH)) ? 16 : 8))) 342 343 #define AFMT_BPS(v) (AFMT_BIT(v) >> 3) 344 #define AFMT_ALIGN(v) (AFMT_BPS(v) * AFMT_CHANNEL(v)) 345 346 #define SND_FORMAT(f, c, e) (AFMT_ENCODING(f) | \ 347 (((c) << AFMT_CHANNEL_SHIFT) & \ 348 AFMT_CHANNEL_MASK) | \ 349 (((e) << AFMT_EXTCHANNEL_SHIFT) & \ 350 AFMT_EXTCHANNEL_MASK)) 351 352 #define AFMT_U8_NE AFMT_U8 353 #define AFMT_S8_NE AFMT_S8 354 355 #define AFMT_SIGNED_NE (AFMT_S8_NE | AFMT_S16_NE | AFMT_S24_NE | \ 356 AFMT_S32_NE | AFMT_F32_NE) 357 358 #define AFMT_NE (AFMT_SIGNED_NE | AFMT_U8_NE | AFMT_U16_NE | \ 359 AFMT_U24_NE | AFMT_U32_NE) 360 361 #endif /* _OS_H_ */ 362