1170159Sariff/*- 2170159Sariff * Copyright (c) 2007 Ariff Abdullah <ariff@FreeBSD.org> 3170159Sariff * All rights reserved. 4170159Sariff * 5170159Sariff * Redistribution and use in source and binary forms, with or without 6170159Sariff * modification, are permitted provided that the following conditions 7170159Sariff * are met: 8170159Sariff * 1. Redistributions of source code must retain the above copyright 9170159Sariff * notice, this list of conditions and the following disclaimer. 10170159Sariff * 2. Redistributions in binary form must reproduce the above copyright 11170159Sariff * notice, this list of conditions and the following disclaimer in the 12170159Sariff * documentation and/or other materials provided with the distribution. 13170159Sariff * 14170159Sariff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15170159Sariff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16170159Sariff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17170159Sariff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18170159Sariff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19170159Sariff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20170159Sariff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21170159Sariff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22170159Sariff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23170159Sariff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24170159Sariff * SUCH DAMAGE. 25170159Sariff * 26170159Sariff * $FreeBSD: releng/10.2/sys/dev/sound/unit.c 193640 2009-06-07 19:12:08Z ariff $ 27170159Sariff */ 28170159Sariff 29170159Sariff#include <sys/param.h> 30170159Sariff#include <sys/systm.h> 31170159Sariff 32193640Sariff#ifdef HAVE_KERNEL_OPTION_HEADERS 33193640Sariff#include "opt_snd.h" 34193640Sariff#endif 35193640Sariff 36170159Sariff#include <dev/sound/unit.h> 37170159Sariff 38170159Sariff/* 39170159Sariff * Unit magic allocator for sound driver. 40170159Sariff * 41170159Sariff * 'u' = Unit of attached soundcards 42170159Sariff * 'd' = Device type 43170159Sariff * 'c' = Channel number 44170159Sariff * 45170159Sariff * eg: dsp0.p1 - u=0, d=p, c=1 46170159Sariff * dsp1.vp0 - u=1, d=vp, c=0 47170159Sariff * dsp0.10 - u=0, d=clone, c=allocated clone (see further explanation) 48170159Sariff * 49170159Sariff * Maximum unit of soundcards can be tuned through "hw.snd.maxunit", which 50170159Sariff * is between SND_UNIT_UMIN (16) and SND_UNIT_UMAX (2048). By design, 51170159Sariff * maximum allowable allocated channel is 256, with exception for clone 52170159Sariff * devices which doesn't have any notion of channel numbering. The use of 53170159Sariff * channel numbering in a clone device is simply to provide uniqueness among 54170159Sariff * allocated clones. This also means that the maximum allowable clonable 55170159Sariff * device is largely dependant and dynamically tuned depending on 56170159Sariff * hw.snd.maxunit. 57170159Sariff */ 58170159Sariff 59170159Sariff/* Default width */ 60170159Sariffstatic int snd_u_shift = 9; /* 0 - 0x1ff : 512 distinct soundcards */ 61170159Sariffstatic int snd_d_shift = 5; /* 0 - 0x1f : 32 distinct device types */ 62170159Sariffstatic int snd_c_shift = 10; /* 0 - 0x3ff : 1024 distinct channels 63170159Sariff (256 limit "by design", 64170159Sariff except for clone devices) */ 65170159Sariff 66170159Sariffstatic int snd_unit_initialized = 0; 67170159Sariff 68170159Sariff#ifdef SND_DIAGNOSTIC 69170159Sariff#define SND_UNIT_ASSERT() do { \ 70170159Sariff if (snd_unit_initialized == 0) \ 71170159Sariff panic("%s(): Uninitialized sound unit!", __func__); \ 72193640Sariff} while (0) 73170159Sariff#else 74170159Sariff#define SND_UNIT_ASSERT() KASSERT(snd_unit_initialized != 0, \ 75170159Sariff ("%s(): Uninitialized sound unit!", \ 76170159Sariff __func__)) 77170159Sariff#endif 78170159Sariff 79170159Sariff#define MKMASK(x) ((1 << snd_##x##_shift) - 1) 80170159Sariff 81170159Sariffint 82170159Sariffsnd_max_u(void) 83170159Sariff{ 84170159Sariff SND_UNIT_ASSERT(); 85170159Sariff 86170159Sariff return (MKMASK(u)); 87170159Sariff} 88170159Sariff 89170159Sariffint 90170159Sariffsnd_max_d(void) 91170159Sariff{ 92170159Sariff SND_UNIT_ASSERT(); 93170159Sariff 94170159Sariff return (MKMASK(d)); 95170159Sariff} 96170159Sariff 97170159Sariffint 98170159Sariffsnd_max_c(void) 99170159Sariff{ 100170159Sariff SND_UNIT_ASSERT(); 101170159Sariff 102170159Sariff return (MKMASK(c)); 103170159Sariff} 104170159Sariff 105170159Sariffint 106170159Sariffsnd_unit2u(int unit) 107170159Sariff{ 108170159Sariff SND_UNIT_ASSERT(); 109170159Sariff 110170159Sariff return ((unit >> (snd_c_shift + snd_d_shift)) & MKMASK(u)); 111170159Sariff} 112170159Sariff 113170159Sariffint 114170159Sariffsnd_unit2d(int unit) 115170159Sariff{ 116170159Sariff SND_UNIT_ASSERT(); 117170159Sariff 118170159Sariff return ((unit >> snd_c_shift) & MKMASK(d)); 119170159Sariff} 120170159Sariff 121170159Sariffint 122170159Sariffsnd_unit2c(int unit) 123170159Sariff{ 124170159Sariff SND_UNIT_ASSERT(); 125170159Sariff 126170159Sariff return (unit & MKMASK(c)); 127170159Sariff} 128170159Sariff 129170159Sariffint 130170159Sariffsnd_u2unit(int u) 131170159Sariff{ 132170159Sariff SND_UNIT_ASSERT(); 133170159Sariff 134170159Sariff return ((u & MKMASK(u)) << (snd_c_shift + snd_d_shift)); 135170159Sariff} 136170159Sariff 137170159Sariffint 138170159Sariffsnd_d2unit(int d) 139170159Sariff{ 140170159Sariff SND_UNIT_ASSERT(); 141170159Sariff 142170159Sariff return ((d & MKMASK(d)) << snd_c_shift); 143170159Sariff} 144170159Sariff 145170159Sariffint 146170159Sariffsnd_c2unit(int c) 147170159Sariff{ 148170159Sariff SND_UNIT_ASSERT(); 149170159Sariff 150170159Sariff return (c & MKMASK(c)); 151170159Sariff} 152170159Sariff 153170159Sariffint 154170159Sariffsnd_mkunit(int u, int d, int c) 155170159Sariff{ 156170159Sariff SND_UNIT_ASSERT(); 157170159Sariff 158170159Sariff return ((c & MKMASK(c)) | ((d & MKMASK(d)) << snd_c_shift) | 159170159Sariff ((u & MKMASK(u)) << (snd_c_shift + snd_d_shift))); 160170159Sariff} 161170159Sariff 162170159Sariff/* 163170159Sariff * This *must* be called first before any of the functions above!!! 164170159Sariff */ 165170159Sariffvoid 166170159Sariffsnd_unit_init(void) 167170159Sariff{ 168170159Sariff int i; 169170159Sariff 170170159Sariff if (snd_unit_initialized != 0) 171170159Sariff return; 172170159Sariff 173170159Sariff snd_unit_initialized = 1; 174170159Sariff 175170159Sariff if (getenv_int("hw.snd.maxunit", &i) != 0) { 176170159Sariff if (i < SND_UNIT_UMIN) 177170159Sariff i = SND_UNIT_UMIN; 178170159Sariff else if (i > SND_UNIT_UMAX) 179170159Sariff i = SND_UNIT_UMAX; 180170159Sariff else 181170159Sariff i = roundup2(i, 2); 182170159Sariff 183170159Sariff for (snd_u_shift = 0; (i >> (snd_u_shift + 1)) != 0; 184170159Sariff snd_u_shift++) 185170159Sariff ; 186170159Sariff 187170159Sariff /* 188170159Sariff * Make room for channels/clones allocation unit 189170159Sariff * to fit within 24bit MAXMINOR limit. 190170159Sariff */ 191170159Sariff snd_c_shift = 24 - snd_u_shift - snd_d_shift; 192170159Sariff } 193170159Sariff 194170159Sariff if (bootverbose != 0) 195170159Sariff printf("%s() u=0x%08x [%d] d=0x%08x [%d] c=0x%08x [%d]\n", 196170159Sariff __func__, SND_U_MASK, snd_max_u() + 1, 197170159Sariff SND_D_MASK, snd_max_d() + 1, SND_C_MASK, snd_max_c() + 1); 198170159Sariff} 199