sound.c (192920) | sound.c (193640) |
---|---|
1/*- | 1/*- |
2 * Copyright (c) 1999 Cameron Grant <cg@freebsd.org> | 2 * Copyright (c) 2005-2009 Ariff Abdullah <ariff@FreeBSD.org> 3 * Portions Copyright (c) Ryan Beasley <ryan.beasley@gmail.com> - GSoC 2006 4 * Copyright (c) 1999 Cameron Grant <cg@FreeBSD.org> |
3 * Copyright (c) 1997 Luigi Rizzo 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. --- 9 unchanged lines hidden (view full) --- 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 | 5 * Copyright (c) 1997 Luigi Rizzo 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. --- 9 unchanged lines hidden (view full) --- 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 |
30#ifdef HAVE_KERNEL_OPTION_HEADERS 31#include "opt_snd.h" 32#endif 33 |
|
28#include <dev/sound/pcm/sound.h> 29#include <dev/sound/pcm/ac97.h> 30#include <dev/sound/pcm/vchan.h> 31#include <dev/sound/pcm/dsp.h> | 34#include <dev/sound/pcm/sound.h> 35#include <dev/sound/pcm/ac97.h> 36#include <dev/sound/pcm/vchan.h> 37#include <dev/sound/pcm/dsp.h> |
38#include <dev/sound/pcm/sndstat.h> |
|
32#include <dev/sound/version.h> 33#include <sys/limits.h> 34#include <sys/sysctl.h> 35 36#include "feeder_if.h" 37 | 39#include <dev/sound/version.h> 40#include <sys/limits.h> 41#include <sys/sysctl.h> 42 43#include "feeder_if.h" 44 |
38SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pcm/sound.c 192920 2009-05-27 18:16:53Z joel $"); | 45SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pcm/sound.c 193640 2009-06-07 19:12:08Z ariff $"); |
39 40devclass_t pcm_devclass; 41 42int pcm_veto_load = 1; 43 | 46 47devclass_t pcm_devclass; 48 49int pcm_veto_load = 1; 50 |
44#ifdef USING_DEVFS | |
45int snd_unit = -1; 46TUNABLE_INT("hw.snd.default_unit", &snd_unit); | 51int snd_unit = -1; 52TUNABLE_INT("hw.snd.default_unit", &snd_unit); |
47#endif | |
48 49static int snd_unit_auto = 0; 50TUNABLE_INT("hw.snd.default_auto", &snd_unit_auto); 51SYSCTL_INT(_hw_snd, OID_AUTO, default_auto, CTLFLAG_RW, 52 &snd_unit_auto, 0, "assign default unit to a newly attached device"); 53 54int snd_maxautovchans = 16; 55/* XXX: a tunable implies that we may need more than one sound channel before --- 5 unchanged lines hidden (view full) --- 61 62/* 63 * XXX I've had enough with people not telling proper version/arch 64 * while reporting problems, not after 387397913213th questions/requests. 65 */ 66static const char snd_driver_version[] = 67 __XSTRING(SND_DRV_VERSION)"/"MACHINE_ARCH; 68SYSCTL_STRING(_hw_snd, OID_AUTO, version, CTLFLAG_RD, &snd_driver_version, | 53 54static int snd_unit_auto = 0; 55TUNABLE_INT("hw.snd.default_auto", &snd_unit_auto); 56SYSCTL_INT(_hw_snd, OID_AUTO, default_auto, CTLFLAG_RW, 57 &snd_unit_auto, 0, "assign default unit to a newly attached device"); 58 59int snd_maxautovchans = 16; 60/* XXX: a tunable implies that we may need more than one sound channel before --- 5 unchanged lines hidden (view full) --- 66 67/* 68 * XXX I've had enough with people not telling proper version/arch 69 * while reporting problems, not after 387397913213th questions/requests. 70 */ 71static const char snd_driver_version[] = 72 __XSTRING(SND_DRV_VERSION)"/"MACHINE_ARCH; 73SYSCTL_STRING(_hw_snd, OID_AUTO, version, CTLFLAG_RD, &snd_driver_version, |
69 0, "Driver version/arch"); | 74 0, "driver version/arch"); |
70 71/** 72 * @brief Unit number allocator for syncgroup IDs 73 */ 74struct unrhdr *pcmsg_unrhdr = NULL; 75 | 75 76/** 77 * @brief Unit number allocator for syncgroup IDs 78 */ 79struct unrhdr *pcmsg_unrhdr = NULL; 80 |
76static int sndstat_prepare_pcm(struct sbuf *s, device_t dev, int verbose); | 81static int 82sndstat_prepare_pcm(SNDSTAT_PREPARE_PCM_ARGS) 83{ 84 SNDSTAT_PREPARE_PCM_BEGIN(); 85 SNDSTAT_PREPARE_PCM_END(); 86} |
77 78void * 79snd_mtxcreate(const char *desc, const char *type) 80{ | 87 88void * 89snd_mtxcreate(const char *desc, const char *type) 90{ |
81#ifdef USING_MUTEX | |
82 struct mtx *m; 83 84 m = malloc(sizeof(*m), M_DEVBUF, M_WAITOK | M_ZERO); 85 mtx_init(m, desc, type, MTX_DEF); 86 return m; | 91 struct mtx *m; 92 93 m = malloc(sizeof(*m), M_DEVBUF, M_WAITOK | M_ZERO); 94 mtx_init(m, desc, type, MTX_DEF); 95 return m; |
87#else 88 return (void *)0xcafebabe; 89#endif | |
90} 91 92void 93snd_mtxfree(void *m) 94{ | 96} 97 98void 99snd_mtxfree(void *m) 100{ |
95#ifdef USING_MUTEX | |
96 struct mtx *mtx = m; 97 | 101 struct mtx *mtx = m; 102 |
98 /* mtx_assert(mtx, MA_OWNED); */ | |
99 mtx_destroy(mtx); 100 free(mtx, M_DEVBUF); | 103 mtx_destroy(mtx); 104 free(mtx, M_DEVBUF); |
101#endif | |
102} 103 104void 105snd_mtxassert(void *m) 106{ | 105} 106 107void 108snd_mtxassert(void *m) 109{ |
107#ifdef USING_MUTEX | |
108#ifdef INVARIANTS 109 struct mtx *mtx = m; 110 111 mtx_assert(mtx, MA_OWNED); 112#endif | 110#ifdef INVARIANTS 111 struct mtx *mtx = m; 112 113 mtx_assert(mtx, MA_OWNED); 114#endif |
113#endif | |
114} | 115} |
115/* 116void 117snd_mtxlock(void *m) 118{ 119#ifdef USING_MUTEX 120 struct mtx *mtx = m; | |
121 | 116 |
122 mtx_lock(mtx); 123#endif 124} 125 126void 127snd_mtxunlock(void *m) 128{ 129#ifdef USING_MUTEX 130 struct mtx *mtx = m; 131 132 mtx_unlock(mtx); 133#endif 134} 135*/ | |
136int 137snd_setup_intr(device_t dev, struct resource *res, int flags, driver_intr_t hand, void *param, void **cookiep) 138{ 139 struct snddev_info *d; | 117int 118snd_setup_intr(device_t dev, struct resource *res, int flags, driver_intr_t hand, void *param, void **cookiep) 119{ 120 struct snddev_info *d; |
140#ifdef USING_MUTEX | 121 |
141 flags &= INTR_MPSAFE; 142 flags |= INTR_TYPE_AV; | 122 flags &= INTR_MPSAFE; 123 flags |= INTR_TYPE_AV; |
143#else 144 flags = INTR_TYPE_AV; 145#endif | |
146 d = device_get_softc(dev); 147 if (d != NULL && (flags & INTR_MPSAFE)) 148 d->flags |= SD_F_MPSAFE; 149 150 return bus_setup_intr(dev, res, flags, 151#if __FreeBSD_version >= 700031 152 NULL, 153#endif 154 hand, param, cookiep); 155} 156 | 124 d = device_get_softc(dev); 125 if (d != NULL && (flags & INTR_MPSAFE)) 126 d->flags |= SD_F_MPSAFE; 127 128 return bus_setup_intr(dev, res, flags, 129#if __FreeBSD_version >= 700031 130 NULL, 131#endif 132 hand, param, cookiep); 133} 134 |
157#ifndef PCM_DEBUG_MTX 158void 159pcm_lock(struct snddev_info *d) 160{ 161 snd_mtxlock(d->lock); 162} 163 164void 165pcm_unlock(struct snddev_info *d) 166{ 167 snd_mtxunlock(d->lock); 168} 169#endif 170 171struct pcm_channel * 172pcm_getfakechan(struct snddev_info *d) 173{ 174 return d->fakechan; 175} 176 | |
177static void 178pcm_clonereset(struct snddev_info *d) 179{ 180 int cmax; 181 182 PCM_BUSYASSERT(d); 183 184 cmax = d->playcount + d->reccount - 1; 185 if (d->pvchancount > 0) | 135static void 136pcm_clonereset(struct snddev_info *d) 137{ 138 int cmax; 139 140 PCM_BUSYASSERT(d); 141 142 cmax = d->playcount + d->reccount - 1; 143 if (d->pvchancount > 0) |
186 cmax += MAX(d->pvchancount, snd_maxautovchans) - 1; | 144 cmax += max(d->pvchancount, snd_maxautovchans) - 1; |
187 if (d->rvchancount > 0) | 145 if (d->rvchancount > 0) |
188 cmax += MAX(d->rvchancount, snd_maxautovchans) - 1; | 146 cmax += max(d->rvchancount, snd_maxautovchans) - 1; |
189 if (cmax > PCMMAXCLONE) 190 cmax = PCMMAXCLONE; 191 (void)snd_clone_gc(d->clones); 192 (void)snd_clone_setmaxunit(d->clones, cmax); 193} 194 | 147 if (cmax > PCMMAXCLONE) 148 cmax = PCMMAXCLONE; 149 (void)snd_clone_gc(d->clones); 150 (void)snd_clone_setmaxunit(d->clones, cmax); 151} 152 |
195static int | 153int |
196pcm_setvchans(struct snddev_info *d, int direction, int newcnt, int num) 197{ 198 struct pcm_channel *c, *ch, *nch; | 154pcm_setvchans(struct snddev_info *d, int direction, int newcnt, int num) 155{ 156 struct pcm_channel *c, *ch, *nch; |
199 int err, vcnt; | 157 struct pcmchan_caps *caps; 158 int i, err, vcnt; |
200 201 PCM_BUSYASSERT(d); 202 203 if ((direction == PCMDIR_PLAY && d->playcount < 1) || 204 (direction == PCMDIR_REC && d->reccount < 1)) 205 return (ENODEV); 206 207 if (!(d->flags & SD_F_AUTOVCHAN)) --- 15 unchanged lines hidden (view full) --- 223 ("bogus vchan_create() request num=%d newcnt=%d vcnt=%d", 224 num, newcnt, vcnt)); 225 /* add new vchans - find a parent channel first */ 226 ch = NULL; 227 CHN_FOREACH(c, d, channels.pcm) { 228 CHN_LOCK(c); 229 if (c->direction == direction && 230 ((c->flags & CHN_F_HAS_VCHAN) || (vcnt == 0 && | 159 160 PCM_BUSYASSERT(d); 161 162 if ((direction == PCMDIR_PLAY && d->playcount < 1) || 163 (direction == PCMDIR_REC && d->reccount < 1)) 164 return (ENODEV); 165 166 if (!(d->flags & SD_F_AUTOVCHAN)) --- 15 unchanged lines hidden (view full) --- 182 ("bogus vchan_create() request num=%d newcnt=%d vcnt=%d", 183 num, newcnt, vcnt)); 184 /* add new vchans - find a parent channel first */ 185 ch = NULL; 186 CHN_FOREACH(c, d, channels.pcm) { 187 CHN_LOCK(c); 188 if (c->direction == direction && 189 ((c->flags & CHN_F_HAS_VCHAN) || (vcnt == 0 && |
190 c->refcount < 1 && |
|
231 !(c->flags & (CHN_F_BUSY | CHN_F_VIRTUAL))))) { | 191 !(c->flags & (CHN_F_BUSY | CHN_F_VIRTUAL))))) { |
232 ch = c; 233 break; | 192 /* 193 * Reuse hw channel with vchans already 194 * created. 195 */ 196 if (c->flags & CHN_F_HAS_VCHAN) { 197 ch = c; 198 break; 199 } 200 /* 201 * No vchans ever created, look for 202 * channels with supported formats. 203 */ 204 caps = chn_getcaps(c); 205 if (caps == NULL) { 206 CHN_UNLOCK(c); 207 continue; 208 } 209 for (i = 0; caps->fmtlist[i] != 0; i++) { 210 if (caps->fmtlist[i] & AFMT_CONVERTIBLE) 211 break; 212 } 213 if (caps->fmtlist[i] != 0) { 214 ch = c; 215 break; 216 } |
234 } 235 CHN_UNLOCK(c); 236 } 237 if (ch == NULL) 238 return (EBUSY); 239 ch->flags |= CHN_F_BUSY; 240 err = 0; 241 while (err == 0 && newcnt > vcnt) { --- 20 unchanged lines hidden (view full) --- 262 if (c->direction != direction || 263 CHN_EMPTY(c, children) || 264 !(c->flags & CHN_F_HAS_VCHAN)) { 265 CHN_UNLOCK(c); 266 continue; 267 } 268 CHN_FOREACH_SAFE(ch, c, nch, children) { 269 CHN_LOCK(ch); | 217 } 218 CHN_UNLOCK(c); 219 } 220 if (ch == NULL) 221 return (EBUSY); 222 ch->flags |= CHN_F_BUSY; 223 err = 0; 224 while (err == 0 && newcnt > vcnt) { --- 20 unchanged lines hidden (view full) --- 245 if (c->direction != direction || 246 CHN_EMPTY(c, children) || 247 !(c->flags & CHN_F_HAS_VCHAN)) { 248 CHN_UNLOCK(c); 249 continue; 250 } 251 CHN_FOREACH_SAFE(ch, c, nch, children) { 252 CHN_LOCK(ch); |
270 if (!(ch->flags & CHN_F_BUSY)) { | 253 if (vcnt == 1 && c->refcount > 0) { |
271 CHN_UNLOCK(ch); | 254 CHN_UNLOCK(ch); |
272 CHN_UNLOCK(c); | 255 break; 256 } 257 if (!(ch->flags & CHN_F_BUSY) && 258 ch->refcount < 1) { |
273 err = vchan_destroy(ch); | 259 err = vchan_destroy(ch); |
274 CHN_LOCK(c); | |
275 if (err == 0) 276 vcnt--; 277 } else 278 CHN_UNLOCK(ch); 279 if (vcnt == newcnt) 280 break; 281 } 282 CHN_UNLOCK(c); 283 break; 284 } 285 pcm_clonereset(d); 286 } 287 288 return (0); 289} 290 291/* return error status and a locked channel */ 292int 293pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction, | 260 if (err == 0) 261 vcnt--; 262 } else 263 CHN_UNLOCK(ch); 264 if (vcnt == newcnt) 265 break; 266 } 267 CHN_UNLOCK(c); 268 break; 269 } 270 pcm_clonereset(d); 271 } 272 273 return (0); 274} 275 276/* return error status and a locked channel */ 277int 278pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction, |
294 pid_t pid, int devunit) | 279 pid_t pid, char *comm, int devunit) |
295{ 296 struct pcm_channel *c; | 280{ 281 struct pcm_channel *c; |
297 int err, vchancount; | 282 int err, vchancount, vchan_num; |
298 299 KASSERT(d != NULL && ch != NULL && (devunit == -1 || 300 !(devunit & ~(SND_U_MASK | SND_D_MASK | SND_C_MASK))) && 301 (direction == PCMDIR_PLAY || direction == PCMDIR_REC), 302 ("%s(): invalid d=%p ch=%p direction=%d pid=%d devunit=%d", 303 __func__, d, ch, direction, pid, devunit)); 304 PCM_BUSYASSERT(d); 305 306 /* Double check again. */ 307 if (devunit != -1) { 308 switch (snd_unit2d(devunit)) { 309 case SND_DEV_DSPHW_PLAY: 310 case SND_DEV_DSPHW_VPLAY: 311 if (direction != PCMDIR_PLAY) | 283 284 KASSERT(d != NULL && ch != NULL && (devunit == -1 || 285 !(devunit & ~(SND_U_MASK | SND_D_MASK | SND_C_MASK))) && 286 (direction == PCMDIR_PLAY || direction == PCMDIR_REC), 287 ("%s(): invalid d=%p ch=%p direction=%d pid=%d devunit=%d", 288 __func__, d, ch, direction, pid, devunit)); 289 PCM_BUSYASSERT(d); 290 291 /* Double check again. */ 292 if (devunit != -1) { 293 switch (snd_unit2d(devunit)) { 294 case SND_DEV_DSPHW_PLAY: 295 case SND_DEV_DSPHW_VPLAY: 296 if (direction != PCMDIR_PLAY) |
312 return (EOPNOTSUPP); | 297 return (ENOTSUP); |
313 break; 314 case SND_DEV_DSPHW_REC: 315 case SND_DEV_DSPHW_VREC: 316 if (direction != PCMDIR_REC) | 298 break; 299 case SND_DEV_DSPHW_REC: 300 case SND_DEV_DSPHW_VREC: 301 if (direction != PCMDIR_REC) |
317 return (EOPNOTSUPP); | 302 return (ENOTSUP); |
318 break; 319 default: 320 if (!(direction == PCMDIR_PLAY || 321 direction == PCMDIR_REC)) | 303 break; 304 default: 305 if (!(direction == PCMDIR_PLAY || 306 direction == PCMDIR_REC)) |
322 return (EOPNOTSUPP); | 307 return (ENOTSUP); |
323 break; 324 } 325 } 326 | 308 break; 309 } 310 } 311 |
312 *ch = NULL; 313 vchan_num = 0; 314 vchancount = (direction == PCMDIR_PLAY) ? d->pvchancount : 315 d->rvchancount; 316 |
|
327retry_chnalloc: | 317retry_chnalloc: |
328 err = EOPNOTSUPP; | 318 err = ENOTSUP; |
329 /* scan for a free channel */ 330 CHN_FOREACH(c, d, channels.pcm) { 331 CHN_LOCK(c); | 319 /* scan for a free channel */ 320 CHN_FOREACH(c, d, channels.pcm) { 321 CHN_LOCK(c); |
322 if (devunit == -1 && c->direction == direction && 323 (c->flags & CHN_F_VIRTUAL)) { 324 if (vchancount < snd_maxautovchans && 325 vchan_num < CHN_CHAN(c)) { 326 CHN_UNLOCK(c); 327 goto vchan_alloc; 328 } 329 vchan_num++; 330 } |
|
332 if (c->direction == direction && !(c->flags & CHN_F_BUSY) && 333 (devunit == -1 || devunit == -2 || c->unit == devunit)) { 334 c->flags |= CHN_F_BUSY; 335 c->pid = pid; | 331 if (c->direction == direction && !(c->flags & CHN_F_BUSY) && 332 (devunit == -1 || devunit == -2 || c->unit == devunit)) { 333 c->flags |= CHN_F_BUSY; 334 c->pid = pid; |
335 strlcpy(c->comm, (comm != NULL) ? comm : 336 CHN_COMM_UNKNOWN, sizeof(c->comm)); |
|
336 *ch = c; 337 return (0); 338 } else if (c->unit == devunit) { 339 if (c->direction != direction) | 337 *ch = c; 338 return (0); 339 } else if (c->unit == devunit) { 340 if (c->direction != direction) |
340 err = EOPNOTSUPP; | 341 err = ENOTSUP; |
341 else if (c->flags & CHN_F_BUSY) 342 err = EBUSY; 343 else 344 err = EINVAL; 345 CHN_UNLOCK(c); 346 return (err); 347 } else if ((devunit == -1 || devunit == -2) && 348 c->direction == direction && (c->flags & CHN_F_BUSY)) 349 err = EBUSY; 350 CHN_UNLOCK(c); 351 } 352 353 if (devunit == -2) 354 return (err); 355 | 342 else if (c->flags & CHN_F_BUSY) 343 err = EBUSY; 344 else 345 err = EINVAL; 346 CHN_UNLOCK(c); 347 return (err); 348 } else if ((devunit == -1 || devunit == -2) && 349 c->direction == direction && (c->flags & CHN_F_BUSY)) 350 err = EBUSY; 351 CHN_UNLOCK(c); 352 } 353 354 if (devunit == -2) 355 return (err); 356 |
357vchan_alloc: |
|
356 /* no channel available */ 357 if (devunit == -1 || snd_unit2d(devunit) == SND_DEV_DSPHW_VPLAY || 358 snd_unit2d(devunit) == SND_DEV_DSPHW_VREC) { | 358 /* no channel available */ 359 if (devunit == -1 || snd_unit2d(devunit) == SND_DEV_DSPHW_VPLAY || 360 snd_unit2d(devunit) == SND_DEV_DSPHW_VREC) { |
359 if (direction == PCMDIR_PLAY) 360 vchancount = d->pvchancount; 361 else 362 vchancount = d->rvchancount; | |
363 if (!(vchancount > 0 && vchancount < snd_maxautovchans) && 364 (devunit == -1 || snd_unit2c(devunit) < snd_maxautovchans)) 365 return (err); 366 err = pcm_setvchans(d, direction, vchancount + 1, 367 (devunit == -1) ? -1 : snd_unit2c(devunit)); 368 if (err == 0) { 369 if (devunit == -1) 370 devunit = -2; --- 8 unchanged lines hidden (view full) --- 379int 380pcm_chnrelease(struct pcm_channel *c) 381{ 382 PCM_BUSYASSERT(c->parentsnddev); 383 CHN_LOCKASSERT(c); 384 385 c->flags &= ~CHN_F_BUSY; 386 c->pid = -1; | 361 if (!(vchancount > 0 && vchancount < snd_maxautovchans) && 362 (devunit == -1 || snd_unit2c(devunit) < snd_maxautovchans)) 363 return (err); 364 err = pcm_setvchans(d, direction, vchancount + 1, 365 (devunit == -1) ? -1 : snd_unit2c(devunit)); 366 if (err == 0) { 367 if (devunit == -1) 368 devunit = -2; --- 8 unchanged lines hidden (view full) --- 377int 378pcm_chnrelease(struct pcm_channel *c) 379{ 380 PCM_BUSYASSERT(c->parentsnddev); 381 CHN_LOCKASSERT(c); 382 383 c->flags &= ~CHN_F_BUSY; 384 c->pid = -1; |
385 strlcpy(c->comm, CHN_COMM_UNUSED, sizeof(c->comm)); |
|
387 CHN_UNLOCK(c); 388 389 return (0); 390} 391 392int 393pcm_chnref(struct pcm_channel *c, int ref) 394{ 395 PCM_BUSYASSERT(c->parentsnddev); 396 CHN_LOCKASSERT(c); 397 398 c->refcount += ref; 399 400 return (c->refcount); 401} 402 403int 404pcm_inprog(struct snddev_info *d, int delta) 405{ | 386 CHN_UNLOCK(c); 387 388 return (0); 389} 390 391int 392pcm_chnref(struct pcm_channel *c, int ref) 393{ 394 PCM_BUSYASSERT(c->parentsnddev); 395 CHN_LOCKASSERT(c); 396 397 c->refcount += ref; 398 399 return (c->refcount); 400} 401 402int 403pcm_inprog(struct snddev_info *d, int delta) 404{ |
406 snd_mtxassert(d->lock); | 405 PCM_LOCKASSERT(d); |
407 408 d->inprog += delta; 409 410 return (d->inprog); 411} 412 413static void 414pcm_setmaxautovchans(struct snddev_info *d, int num) --- 11 unchanged lines hidden (view full) --- 426 if (num >= 0 && d->rvchancount > num) 427 (void)pcm_setvchans(d, PCMDIR_REC, num, -1); 428 else if (num > 0 && d->rvchancount == 0) 429 (void)pcm_setvchans(d, PCMDIR_REC, 1, -1); 430 431 pcm_clonereset(d); 432} 433 | 406 407 d->inprog += delta; 408 409 return (d->inprog); 410} 411 412static void 413pcm_setmaxautovchans(struct snddev_info *d, int num) --- 11 unchanged lines hidden (view full) --- 425 if (num >= 0 && d->rvchancount > num) 426 (void)pcm_setvchans(d, PCMDIR_REC, num, -1); 427 else if (num > 0 && d->rvchancount == 0) 428 (void)pcm_setvchans(d, PCMDIR_REC, 1, -1); 429 430 pcm_clonereset(d); 431} 432 |
434#ifdef USING_DEVFS | |
435static int 436sysctl_hw_snd_default_unit(SYSCTL_HANDLER_ARGS) 437{ 438 struct snddev_info *d; 439 int error, unit; 440 441 unit = snd_unit; 442 error = sysctl_handle_int(oidp, &unit, 0, req); 443 if (error == 0 && req->newptr != NULL) { 444 d = devclass_get_softc(pcm_devclass, unit); 445 if (!PCM_REGISTERED(d) || CHN_EMPTY(d, channels.pcm)) 446 return EINVAL; 447 snd_unit = unit; 448 } 449 return (error); 450} 451/* XXX: do we need a way to let the user change the default unit? */ 452SYSCTL_PROC(_hw_snd, OID_AUTO, default_unit, CTLTYPE_INT | CTLFLAG_RW, 453 0, sizeof(int), sysctl_hw_snd_default_unit, "I", "default sound device"); | 433static int 434sysctl_hw_snd_default_unit(SYSCTL_HANDLER_ARGS) 435{ 436 struct snddev_info *d; 437 int error, unit; 438 439 unit = snd_unit; 440 error = sysctl_handle_int(oidp, &unit, 0, req); 441 if (error == 0 && req->newptr != NULL) { 442 d = devclass_get_softc(pcm_devclass, unit); 443 if (!PCM_REGISTERED(d) || CHN_EMPTY(d, channels.pcm)) 444 return EINVAL; 445 snd_unit = unit; 446 } 447 return (error); 448} 449/* XXX: do we need a way to let the user change the default unit? */ 450SYSCTL_PROC(_hw_snd, OID_AUTO, default_unit, CTLTYPE_INT | CTLFLAG_RW, 451 0, sizeof(int), sysctl_hw_snd_default_unit, "I", "default sound device"); |
454#endif | |
455 456static int 457sysctl_hw_snd_maxautovchans(SYSCTL_HANDLER_ARGS) 458{ 459 struct snddev_info *d; 460 int i, v, error; 461 462 v = snd_maxautovchans; --- 23 unchanged lines hidden (view full) --- 486pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, int dir, int num, void *devinfo) 487{ 488 struct pcm_channel *ch; 489 int direction, err, rpnum, *pnum, max; 490 int udc, device, chan; 491 char *dirs, *devname, buf[CHN_NAMELEN]; 492 493 PCM_BUSYASSERT(d); | 452 453static int 454sysctl_hw_snd_maxautovchans(SYSCTL_HANDLER_ARGS) 455{ 456 struct snddev_info *d; 457 int i, v, error; 458 459 v = snd_maxautovchans; --- 23 unchanged lines hidden (view full) --- 483pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, int dir, int num, void *devinfo) 484{ 485 struct pcm_channel *ch; 486 int direction, err, rpnum, *pnum, max; 487 int udc, device, chan; 488 char *dirs, *devname, buf[CHN_NAMELEN]; 489 490 PCM_BUSYASSERT(d); |
494 snd_mtxassert(d->lock); | 491 PCM_LOCKASSERT(d); |
495 KASSERT(num >= -1, ("invalid num=%d", num)); 496 497 498 switch (dir) { 499 case PCMDIR_PLAY: 500 dirs = "play"; 501 direction = PCMDIR_PLAY; 502 pnum = &d->playcount; --- 62 unchanged lines hidden (view full) --- 565 devname = dsp_unit2name(buf, sizeof(buf), udc); 566 567 if (devname == NULL) { 568 device_printf(d->dev, 569 "Failed to query device name udc=0x%08x\n", udc); 570 return (NULL); 571 } 572 | 492 KASSERT(num >= -1, ("invalid num=%d", num)); 493 494 495 switch (dir) { 496 case PCMDIR_PLAY: 497 dirs = "play"; 498 direction = PCMDIR_PLAY; 499 pnum = &d->playcount; --- 62 unchanged lines hidden (view full) --- 562 devname = dsp_unit2name(buf, sizeof(buf), udc); 563 564 if (devname == NULL) { 565 device_printf(d->dev, 566 "Failed to query device name udc=0x%08x\n", udc); 567 return (NULL); 568 } 569 |
573 pcm_unlock(d); | 570 PCM_UNLOCK(d); |
574 ch = malloc(sizeof(*ch), M_DEVBUF, M_WAITOK | M_ZERO); 575 ch->methods = kobj_create(cls, M_DEVBUF, M_WAITOK | M_ZERO); 576 ch->unit = udc; 577 ch->pid = -1; | 571 ch = malloc(sizeof(*ch), M_DEVBUF, M_WAITOK | M_ZERO); 572 ch->methods = kobj_create(cls, M_DEVBUF, M_WAITOK | M_ZERO); 573 ch->unit = udc; 574 ch->pid = -1; |
575 strlcpy(ch->comm, CHN_COMM_UNUSED, sizeof(ch->comm)); |
|
578 ch->parentsnddev = d; 579 ch->parentchannel = parent; 580 ch->dev = d->dev; 581 ch->trigger = PCMTRIG_STOP; 582 snprintf(ch->name, sizeof(ch->name), "%s:%s:%s", 583 device_get_nameunit(ch->dev), dirs, devname); 584 585 err = chn_init(ch, devinfo, dir, direction); | 576 ch->parentsnddev = d; 577 ch->parentchannel = parent; 578 ch->dev = d->dev; 579 ch->trigger = PCMTRIG_STOP; 580 snprintf(ch->name, sizeof(ch->name), "%s:%s:%s", 581 device_get_nameunit(ch->dev), dirs, devname); 582 583 err = chn_init(ch, devinfo, dir, direction); |
586 pcm_lock(d); | 584 PCM_LOCK(d); |
587 if (err) { 588 device_printf(d->dev, "chn_init(%s) failed: err = %d\n", 589 ch->name, err); 590 kobj_delete(ch->methods, M_DEVBUF); 591 free(ch, M_DEVBUF); 592 return (NULL); 593 } 594 --- 20 unchanged lines hidden (view full) --- 615 free(ch, M_DEVBUF); 616 617 return (0); 618} 619 620int 621pcm_chn_add(struct snddev_info *d, struct pcm_channel *ch) 622{ | 585 if (err) { 586 device_printf(d->dev, "chn_init(%s) failed: err = %d\n", 587 ch->name, err); 588 kobj_delete(ch->methods, M_DEVBUF); 589 free(ch, M_DEVBUF); 590 return (NULL); 591 } 592 --- 20 unchanged lines hidden (view full) --- 613 free(ch, M_DEVBUF); 614 615 return (0); 616} 617 618int 619pcm_chn_add(struct snddev_info *d, struct pcm_channel *ch) 620{ |
623 struct pcm_channel *tmp, *after; 624 int num; 625 | |
626 PCM_BUSYASSERT(d); | 621 PCM_BUSYASSERT(d); |
627 snd_mtxassert(d->lock); | 622 PCM_LOCKASSERT(d); |
628 KASSERT(ch != NULL && (ch->direction == PCMDIR_PLAY || 629 ch->direction == PCMDIR_REC), ("Invalid pcm channel")); 630 | 623 KASSERT(ch != NULL && (ch->direction == PCMDIR_PLAY || 624 ch->direction == PCMDIR_REC), ("Invalid pcm channel")); 625 |
631 after = NULL; 632 tmp = NULL; 633 num = 0; | 626 CHN_INSERT_SORT_ASCEND(d, ch, channels.pcm); |
634 | 627 |
635 /* 636 * Look for possible device collision. 637 */ 638 CHN_FOREACH(tmp, d, channels.pcm) { 639 if (tmp->unit == ch->unit) { 640 device_printf(d->dev, "%s(): Device collision " 641 "old=%p new=%p devunit=0x%08x\n", 642 __func__, tmp, ch, ch->unit); 643 return (ENODEV); 644 } 645 if (CHN_DEV(tmp) < CHN_DEV(ch)) { 646 if (num == 0) 647 after = tmp; 648 continue; 649 } else if (CHN_DEV(tmp) > CHN_DEV(ch)) 650 break; 651 num++; 652 if (CHN_CHAN(tmp) < CHN_CHAN(ch)) 653 after = tmp; 654 else if (CHN_CHAN(tmp) > CHN_CHAN(ch)) 655 break; 656 } 657 658 if (after != NULL) { 659 CHN_INSERT_AFTER(after, ch, channels.pcm); 660 } else { 661 CHN_INSERT_HEAD(d, ch, channels.pcm); 662 } 663 | |
664 switch (CHN_DEV(ch)) { 665 case SND_DEV_DSPHW_PLAY: 666 d->playcount++; 667 break; 668 case SND_DEV_DSPHW_VPLAY: 669 d->pvchancount++; 670 break; 671 case SND_DEV_DSPHW_REC: --- 12 unchanged lines hidden (view full) --- 684} 685 686int 687pcm_chn_remove(struct snddev_info *d, struct pcm_channel *ch) 688{ 689 struct pcm_channel *tmp; 690 691 PCM_BUSYASSERT(d); | 628 switch (CHN_DEV(ch)) { 629 case SND_DEV_DSPHW_PLAY: 630 d->playcount++; 631 break; 632 case SND_DEV_DSPHW_VPLAY: 633 d->pvchancount++; 634 break; 635 case SND_DEV_DSPHW_REC: --- 12 unchanged lines hidden (view full) --- 648} 649 650int 651pcm_chn_remove(struct snddev_info *d, struct pcm_channel *ch) 652{ 653 struct pcm_channel *tmp; 654 655 PCM_BUSYASSERT(d); |
692 snd_mtxassert(d->lock); | 656 PCM_LOCKASSERT(d); |
693 694 tmp = NULL; 695 696 CHN_FOREACH(tmp, d, channels.pcm) { 697 if (tmp == ch) 698 break; 699 } 700 --- 28 unchanged lines hidden (view full) --- 729pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo) 730{ 731 struct snddev_info *d = device_get_softc(dev); 732 struct pcm_channel *ch; 733 int err; 734 735 PCM_BUSYASSERT(d); 736 | 657 658 tmp = NULL; 659 660 CHN_FOREACH(tmp, d, channels.pcm) { 661 if (tmp == ch) 662 break; 663 } 664 --- 28 unchanged lines hidden (view full) --- 693pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo) 694{ 695 struct snddev_info *d = device_get_softc(dev); 696 struct pcm_channel *ch; 697 int err; 698 699 PCM_BUSYASSERT(d); 700 |
737 pcm_lock(d); | 701 PCM_LOCK(d); |
738 ch = pcm_chn_create(d, NULL, cls, dir, -1, devinfo); 739 if (!ch) { 740 device_printf(d->dev, "pcm_chn_create(%s, %d, %p) failed\n", 741 cls->name, dir, devinfo); | 702 ch = pcm_chn_create(d, NULL, cls, dir, -1, devinfo); 703 if (!ch) { 704 device_printf(d->dev, "pcm_chn_create(%s, %d, %p) failed\n", 705 cls->name, dir, devinfo); |
742 pcm_unlock(d); | 706 PCM_UNLOCK(d); |
743 return (ENODEV); 744 } 745 746 err = pcm_chn_add(d, ch); | 707 return (ENODEV); 708 } 709 710 err = pcm_chn_add(d, ch); |
747 pcm_unlock(d); | 711 PCM_UNLOCK(d); |
748 if (err) { 749 device_printf(d->dev, "pcm_chn_add(%s) failed, err=%d\n", 750 ch->name, err); 751 pcm_chn_destroy(ch); 752 } 753 754 return (err); 755} --- 4 unchanged lines hidden (view full) --- 760 struct snddev_info *d = device_get_softc(dev); 761 struct pcm_channel *ch; 762 int error; 763 764 PCM_BUSYASSERT(d); 765 766 ch = CHN_FIRST(d, channels.pcm); 767 | 712 if (err) { 713 device_printf(d->dev, "pcm_chn_add(%s) failed, err=%d\n", 714 ch->name, err); 715 pcm_chn_destroy(ch); 716 } 717 718 return (err); 719} --- 4 unchanged lines hidden (view full) --- 724 struct snddev_info *d = device_get_softc(dev); 725 struct pcm_channel *ch; 726 int error; 727 728 PCM_BUSYASSERT(d); 729 730 ch = CHN_FIRST(d, channels.pcm); 731 |
768 pcm_lock(d); | 732 PCM_LOCK(d); |
769 error = pcm_chn_remove(d, ch); | 733 error = pcm_chn_remove(d, ch); |
770 pcm_unlock(d); | 734 PCM_UNLOCK(d); |
771 if (error) 772 return (error); 773 return (pcm_chn_destroy(ch)); 774} 775 776int 777pcm_setstatus(device_t dev, char *str) 778{ --- 9 unchanged lines hidden (view full) --- 788 d->flags |= SD_F_AUTOVCHAN; 789 vchan_initsys(dev); 790 } 791 792 pcm_setmaxautovchans(d, snd_maxautovchans); 793 794 strlcpy(d->status, str, SND_STATUSLEN); 795 | 735 if (error) 736 return (error); 737 return (pcm_chn_destroy(ch)); 738} 739 740int 741pcm_setstatus(device_t dev, char *str) 742{ --- 9 unchanged lines hidden (view full) --- 752 d->flags |= SD_F_AUTOVCHAN; 753 vchan_initsys(dev); 754 } 755 756 pcm_setmaxautovchans(d, snd_maxautovchans); 757 758 strlcpy(d->status, str, SND_STATUSLEN); 759 |
796 pcm_lock(d); | 760 PCM_LOCK(d); |
797 798 /* Last stage, enable cloning. */ 799 if (d->clones != NULL) 800 (void)snd_clone_enable(d->clones); 801 802 /* Done, we're ready.. */ 803 d->flags |= SD_F_REGISTERED; 804 805 PCM_RELEASE(d); 806 | 761 762 /* Last stage, enable cloning. */ 763 if (d->clones != NULL) 764 (void)snd_clone_enable(d->clones); 765 766 /* Done, we're ready.. */ 767 d->flags |= SD_F_REGISTERED; 768 769 PCM_RELEASE(d); 770 |
807 pcm_unlock(d); | 771 PCM_UNLOCK(d); |
808 809 if (snd_unit < 0 || snd_unit_auto != 0) 810 snd_unit = device_get_unit(dev); 811 812 return (0); 813} 814 815uint32_t --- 45 unchanged lines hidden (view full) --- 861 sz = deflt; 862 } 863 864 d->bufsz = sz; 865 866 return sz; 867} 868 | 772 773 if (snd_unit < 0 || snd_unit_auto != 0) 774 snd_unit = device_get_unit(dev); 775 776 return (0); 777} 778 779uint32_t --- 45 unchanged lines hidden (view full) --- 825 sz = deflt; 826 } 827 828 d->bufsz = sz; 829 830 return sz; 831} 832 |
869#if defined(SND_DYNSYSCTL) && defined(SND_DEBUG) | |
870static int | 833static int |
834sysctl_dev_pcm_bitperfect(SYSCTL_HANDLER_ARGS) 835{ 836 struct snddev_info *d; 837 int err, val; 838 839 d = oidp->oid_arg1; 840 if (!PCM_REGISTERED(d)) 841 return (ENODEV); 842 843 PCM_LOCK(d); 844 PCM_WAIT(d); 845 val = (d->flags & SD_F_BITPERFECT) ? 1 : 0; 846 PCM_ACQUIRE(d); 847 PCM_UNLOCK(d); 848 849 err = sysctl_handle_int(oidp, &val, 0, req); 850 851 if (err == 0 && req->newptr != NULL) { 852 if (!(val == 0 || val == 1)) { 853 PCM_RELEASE_QUICK(d); 854 return (EINVAL); 855 } 856 857 PCM_LOCK(d); 858 859 d->flags &= ~SD_F_BITPERFECT; 860 d->flags |= (val != 0) ? SD_F_BITPERFECT : 0; 861 862 PCM_RELEASE(d); 863 PCM_UNLOCK(d); 864 } else 865 PCM_RELEASE_QUICK(d); 866 867 return (err); 868} 869 870#ifdef SND_DEBUG 871static int |
|
871sysctl_dev_pcm_clone_flags(SYSCTL_HANDLER_ARGS) 872{ 873 struct snddev_info *d; 874 uint32_t flags; 875 int err; 876 877 d = oidp->oid_arg1; 878 if (!PCM_REGISTERED(d) || d->clones == NULL) --- 97 unchanged lines hidden (view full) --- 976 0, sizeof(int), sysctl_hw_snd_clone_gc, "I", 977 "global clone garbage collector"); 978#endif 979 980int 981pcm_register(device_t dev, void *devinfo, int numplay, int numrec) 982{ 983 struct snddev_info *d; | 872sysctl_dev_pcm_clone_flags(SYSCTL_HANDLER_ARGS) 873{ 874 struct snddev_info *d; 875 uint32_t flags; 876 int err; 877 878 d = oidp->oid_arg1; 879 if (!PCM_REGISTERED(d) || d->clones == NULL) --- 97 unchanged lines hidden (view full) --- 977 0, sizeof(int), sysctl_hw_snd_clone_gc, "I", 978 "global clone garbage collector"); 979#endif 980 981int 982pcm_register(device_t dev, void *devinfo, int numplay, int numrec) 983{ 984 struct snddev_info *d; |
985 int i; |
|
984 985 if (pcm_veto_load) { 986 device_printf(dev, "disabled due to an error while initialising: %d\n", pcm_veto_load); 987 988 return EINVAL; 989 } 990 991 if (device_get_unit(dev) > PCMMAXUNIT) { --- 13 unchanged lines hidden (view full) --- 1005#if 0 1006 /* 1007 * d->flags should be cleared by the allocator of the softc. 1008 * We cannot clear this field here because several devices set 1009 * this flag before calling pcm_register(). 1010 */ 1011 d->flags = 0; 1012#endif | 986 987 if (pcm_veto_load) { 988 device_printf(dev, "disabled due to an error while initialising: %d\n", pcm_veto_load); 989 990 return EINVAL; 991 } 992 993 if (device_get_unit(dev) > PCMMAXUNIT) { --- 13 unchanged lines hidden (view full) --- 1007#if 0 1008 /* 1009 * d->flags should be cleared by the allocator of the softc. 1010 * We cannot clear this field here because several devices set 1011 * this flag before calling pcm_register(). 1012 */ 1013 d->flags = 0; 1014#endif |
1015 i = 0; 1016 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 1017 "vpc", &i) != 0 || i != 0) 1018 d->flags |= SD_F_VPC; 1019 1020 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 1021 "bitperfect", &i) == 0 && i != 0) 1022 d->flags |= SD_F_BITPERFECT; 1023 |
|
1013 d->devinfo = devinfo; 1014 d->devcount = 0; 1015 d->reccount = 0; 1016 d->playcount = 0; 1017 d->pvchancount = 0; 1018 d->rvchancount = 0; 1019 d->pvchanrate = 0; 1020 d->pvchanformat = 0; 1021 d->rvchanrate = 0; 1022 d->rvchanformat = 0; 1023 d->inprog = 0; 1024 1025 /* 1026 * Create clone manager, disabled by default. Cloning will be | 1024 d->devinfo = devinfo; 1025 d->devcount = 0; 1026 d->reccount = 0; 1027 d->playcount = 0; 1028 d->pvchancount = 0; 1029 d->rvchancount = 0; 1030 d->pvchanrate = 0; 1031 d->pvchanformat = 0; 1032 d->rvchanrate = 0; 1033 d->rvchanformat = 0; 1034 d->inprog = 0; 1035 1036 /* 1037 * Create clone manager, disabled by default. Cloning will be |
1027 * enabled during final stage of driver iniialization through | 1038 * enabled during final stage of driver initialization through |
1028 * pcm_setstatus(). 1029 */ 1030 d->clones = snd_clone_create(SND_U_MASK | SND_D_MASK, PCMMAXCLONE, 1031 SND_CLONE_DEADLINE_DEFAULT, SND_CLONE_WAITOK | 1032 SND_CLONE_GC_ENABLE | SND_CLONE_GC_UNREF | 1033 SND_CLONE_GC_LASTREF | SND_CLONE_GC_EXPIRED); 1034 1035 if (bootverbose != 0 || snd_verbose > 3) { 1036 device_printf(dev, 1037 "clone manager: deadline=%dms flags=0x%08x\n", 1038 snd_clone_getdeadline(d->clones), 1039 snd_clone_getflags(d->clones)); 1040 } 1041 1042 CHN_INIT(d, channels.pcm); 1043 CHN_INIT(d, channels.pcm.busy); | 1039 * pcm_setstatus(). 1040 */ 1041 d->clones = snd_clone_create(SND_U_MASK | SND_D_MASK, PCMMAXCLONE, 1042 SND_CLONE_DEADLINE_DEFAULT, SND_CLONE_WAITOK | 1043 SND_CLONE_GC_ENABLE | SND_CLONE_GC_UNREF | 1044 SND_CLONE_GC_LASTREF | SND_CLONE_GC_EXPIRED); 1045 1046 if (bootverbose != 0 || snd_verbose > 3) { 1047 device_printf(dev, 1048 "clone manager: deadline=%dms flags=0x%08x\n", 1049 snd_clone_getdeadline(d->clones), 1050 snd_clone_getflags(d->clones)); 1051 } 1052 1053 CHN_INIT(d, channels.pcm); 1054 CHN_INIT(d, channels.pcm.busy); |
1055 CHN_INIT(d, channels.pcm.opened); |
|
1044 1045 /* XXX This is incorrect, but lets play along for now. */ 1046 if ((numplay == 0 || numrec == 0) && numplay != numrec) 1047 d->flags |= SD_F_SIMPLEX; 1048 | 1056 1057 /* XXX This is incorrect, but lets play along for now. */ 1058 if ((numplay == 0 || numrec == 0) && numplay != numrec) 1059 d->flags |= SD_F_SIMPLEX; 1060 |
1049 d->fakechan = fkchan_setup(dev); 1050 chn_init(d->fakechan, NULL, 0, 0); 1051 1052#ifdef SND_DYNSYSCTL | |
1053 sysctl_ctx_init(&d->play_sysctl_ctx); 1054 d->play_sysctl_tree = SYSCTL_ADD_NODE(&d->play_sysctl_ctx, 1055 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "play", 1056 CTLFLAG_RD, 0, "playback channels node"); 1057 sysctl_ctx_init(&d->rec_sysctl_ctx); 1058 d->rec_sysctl_tree = SYSCTL_ADD_NODE(&d->rec_sysctl_ctx, 1059 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "rec", 1060 CTLFLAG_RD, 0, "record channels node"); 1061 /* XXX: an user should be able to set this with a control tool, the 1062 sysadmin then needs min+max sysctls for this */ 1063 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), 1064 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 1065 OID_AUTO, "buffersize", CTLFLAG_RD, &d->bufsz, 0, "allocated buffer size"); | 1061 sysctl_ctx_init(&d->play_sysctl_ctx); 1062 d->play_sysctl_tree = SYSCTL_ADD_NODE(&d->play_sysctl_ctx, 1063 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "play", 1064 CTLFLAG_RD, 0, "playback channels node"); 1065 sysctl_ctx_init(&d->rec_sysctl_ctx); 1066 d->rec_sysctl_tree = SYSCTL_ADD_NODE(&d->rec_sysctl_ctx, 1067 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "rec", 1068 CTLFLAG_RD, 0, "record channels node"); 1069 /* XXX: an user should be able to set this with a control tool, the 1070 sysadmin then needs min+max sysctls for this */ 1071 SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), 1072 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 1073 OID_AUTO, "buffersize", CTLFLAG_RD, &d->bufsz, 0, "allocated buffer size"); |
1074 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 1075 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 1076 "bitperfect", CTLTYPE_INT | CTLFLAG_RW, d, sizeof(d), 1077 sysctl_dev_pcm_bitperfect, "I", 1078 "bit-perfect playback/recording (0=disable, 1=enable)"); |
|
1066#ifdef SND_DEBUG 1067 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 1068 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 1069 "clone_flags", CTLTYPE_UINT | CTLFLAG_RW, d, sizeof(d), 1070 sysctl_dev_pcm_clone_flags, "IU", 1071 "clone flags"); 1072 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 1073 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 1074 "clone_deadline", CTLTYPE_INT | CTLFLAG_RW, d, sizeof(d), 1075 sysctl_dev_pcm_clone_deadline, "I", 1076 "clone expiration deadline (ms)"); 1077 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 1078 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 1079 "clone_gc", CTLTYPE_INT | CTLFLAG_RW, d, sizeof(d), 1080 sysctl_dev_pcm_clone_gc, "I", 1081 "clone garbage collector"); 1082#endif | 1079#ifdef SND_DEBUG 1080 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 1081 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 1082 "clone_flags", CTLTYPE_UINT | CTLFLAG_RW, d, sizeof(d), 1083 sysctl_dev_pcm_clone_flags, "IU", 1084 "clone flags"); 1085 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 1086 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 1087 "clone_deadline", CTLTYPE_INT | CTLFLAG_RW, d, sizeof(d), 1088 sysctl_dev_pcm_clone_deadline, "I", 1089 "clone expiration deadline (ms)"); 1090 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 1091 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 1092 "clone_gc", CTLTYPE_INT | CTLFLAG_RW, d, sizeof(d), 1093 sysctl_dev_pcm_clone_gc, "I", 1094 "clone garbage collector"); 1095#endif |
1083#endif | |
1084 1085 if (numplay > 0 || numrec > 0) { 1086 d->flags |= SD_F_AUTOVCHAN; 1087 vchan_initsys(dev); 1088 } 1089 | 1096 1097 if (numplay > 0 || numrec > 0) { 1098 d->flags |= SD_F_AUTOVCHAN; 1099 vchan_initsys(dev); 1100 } 1101 |
1102 if (d->flags & SD_F_EQ) 1103 feeder_eq_initsys(dev); 1104 |
|
1090 sndstat_register(dev, d->status, sndstat_prepare_pcm); 1091 1092 return 0; 1093} 1094 1095int 1096pcm_unregister(device_t dev) 1097{ --- 10 unchanged lines hidden (view full) --- 1108 return (0); 1109 } 1110 1111 if (sndstat_acquire(td) != 0) { 1112 device_printf(dev, "unregister: sndstat busy\n"); 1113 return (EBUSY); 1114 } 1115 | 1105 sndstat_register(dev, d->status, sndstat_prepare_pcm); 1106 1107 return 0; 1108} 1109 1110int 1111pcm_unregister(device_t dev) 1112{ --- 10 unchanged lines hidden (view full) --- 1123 return (0); 1124 } 1125 1126 if (sndstat_acquire(td) != 0) { 1127 device_printf(dev, "unregister: sndstat busy\n"); 1128 return (EBUSY); 1129 } 1130 |
1116 pcm_lock(d); | 1131 PCM_LOCK(d); |
1117 PCM_WAIT(d); 1118 1119 if (d->inprog != 0) { 1120 device_printf(dev, "unregister: operation in progress\n"); | 1132 PCM_WAIT(d); 1133 1134 if (d->inprog != 0) { 1135 device_printf(dev, "unregister: operation in progress\n"); |
1121 pcm_unlock(d); | 1136 PCM_UNLOCK(d); |
1122 sndstat_release(td); 1123 return (EBUSY); 1124 } 1125 1126 PCM_ACQUIRE(d); | 1137 sndstat_release(td); 1138 return (EBUSY); 1139 } 1140 1141 PCM_ACQUIRE(d); |
1127 pcm_unlock(d); | 1142 PCM_UNLOCK(d); |
1128 1129 CHN_FOREACH(ch, d, channels.pcm) { 1130 CHN_LOCK(ch); 1131 if (ch->refcount > 0) { 1132 device_printf(dev, 1133 "unregister: channel %s busy (pid %d)\n", 1134 ch->name, ch->pid); 1135 CHN_UNLOCK(ch); --- 6 unchanged lines hidden (view full) --- 1142 1143 if (d->clones != NULL) { 1144 if (snd_clone_busy(d->clones) != 0) { 1145 device_printf(dev, "unregister: clone busy\n"); 1146 PCM_RELEASE_QUICK(d); 1147 sndstat_release(td); 1148 return (EBUSY); 1149 } else { | 1143 1144 CHN_FOREACH(ch, d, channels.pcm) { 1145 CHN_LOCK(ch); 1146 if (ch->refcount > 0) { 1147 device_printf(dev, 1148 "unregister: channel %s busy (pid %d)\n", 1149 ch->name, ch->pid); 1150 CHN_UNLOCK(ch); --- 6 unchanged lines hidden (view full) --- 1157 1158 if (d->clones != NULL) { 1159 if (snd_clone_busy(d->clones) != 0) { 1160 device_printf(dev, "unregister: clone busy\n"); 1161 PCM_RELEASE_QUICK(d); 1162 sndstat_release(td); 1163 return (EBUSY); 1164 } else { |
1150 pcm_lock(d); | 1165 PCM_LOCK(d); |
1151 (void)snd_clone_disable(d->clones); | 1166 (void)snd_clone_disable(d->clones); |
1152 pcm_unlock(d); | 1167 PCM_UNLOCK(d); |
1153 } 1154 } 1155 1156 if (mixer_uninit(dev) == EBUSY) { 1157 device_printf(dev, "unregister: mixer busy\n"); | 1168 } 1169 } 1170 1171 if (mixer_uninit(dev) == EBUSY) { 1172 device_printf(dev, "unregister: mixer busy\n"); |
1158 pcm_lock(d); | 1173 PCM_LOCK(d); |
1159 if (d->clones != NULL) 1160 (void)snd_clone_enable(d->clones); 1161 PCM_RELEASE(d); | 1174 if (d->clones != NULL) 1175 (void)snd_clone_enable(d->clones); 1176 PCM_RELEASE(d); |
1162 pcm_unlock(d); | 1177 PCM_UNLOCK(d); |
1163 sndstat_release(td); 1164 return (EBUSY); 1165 } 1166 | 1178 sndstat_release(td); 1179 return (EBUSY); 1180 } 1181 |
1167 pcm_lock(d); | 1182 PCM_LOCK(d); |
1168 d->flags |= SD_F_DYING; 1169 d->flags &= ~SD_F_REGISTERED; | 1183 d->flags |= SD_F_DYING; 1184 d->flags &= ~SD_F_REGISTERED; |
1170 pcm_unlock(d); | 1185 PCM_UNLOCK(d); |
1171 1172 /* 1173 * No lock being held, so this thing can be flushed without 1174 * stucking into devdrn oblivion. 1175 */ 1176 if (d->clones != NULL) { 1177 snd_clone_destroy(d->clones); 1178 d->clones = NULL; 1179 } 1180 | 1186 1187 /* 1188 * No lock being held, so this thing can be flushed without 1189 * stucking into devdrn oblivion. 1190 */ 1191 if (d->clones != NULL) { 1192 snd_clone_destroy(d->clones); 1193 d->clones = NULL; 1194 } 1195 |
1181#ifdef SND_DYNSYSCTL | |
1182 if (d->play_sysctl_tree != NULL) { 1183 sysctl_ctx_free(&d->play_sysctl_ctx); 1184 d->play_sysctl_tree = NULL; 1185 } 1186 if (d->rec_sysctl_tree != NULL) { 1187 sysctl_ctx_free(&d->rec_sysctl_ctx); 1188 d->rec_sysctl_tree = NULL; 1189 } | 1196 if (d->play_sysctl_tree != NULL) { 1197 sysctl_ctx_free(&d->play_sysctl_ctx); 1198 d->play_sysctl_tree = NULL; 1199 } 1200 if (d->rec_sysctl_tree != NULL) { 1201 sysctl_ctx_free(&d->rec_sysctl_ctx); 1202 d->rec_sysctl_tree = NULL; 1203 } |
1190#endif | |
1191 1192 while (!CHN_EMPTY(d, channels.pcm)) 1193 pcm_killchan(dev); 1194 | 1204 1205 while (!CHN_EMPTY(d, channels.pcm)) 1206 pcm_killchan(dev); 1207 |
1195 chn_kill(d->fakechan); 1196 fkchan_kill(d->fakechan); 1197 | |
1198 dsp_cdevinfo_flush(d); 1199 | 1208 dsp_cdevinfo_flush(d); 1209 |
1200 pcm_lock(d); | 1210 PCM_LOCK(d); |
1201 PCM_RELEASE(d); 1202 cv_destroy(&d->cv); | 1211 PCM_RELEASE(d); 1212 cv_destroy(&d->cv); |
1203 pcm_unlock(d); | 1213 PCM_UNLOCK(d); |
1204 snd_mtxfree(d->lock); 1205 sndstat_unregister(dev); 1206 sndstat_release(td); 1207 1208 if (snd_unit == device_get_unit(dev)) { 1209 /* 1210 * Reassign default unit to the next available dev, but 1211 * first, reset snd_unit to something ridiculous. --- 11 unchanged lines hidden (view full) --- 1223 } 1224 } 1225 1226 return (0); 1227} 1228 1229/************************************************************************/ 1230 | 1214 snd_mtxfree(d->lock); 1215 sndstat_unregister(dev); 1216 sndstat_release(td); 1217 1218 if (snd_unit == device_get_unit(dev)) { 1219 /* 1220 * Reassign default unit to the next available dev, but 1221 * first, reset snd_unit to something ridiculous. --- 11 unchanged lines hidden (view full) --- 1233 } 1234 } 1235 1236 return (0); 1237} 1238 1239/************************************************************************/ 1240 |
1231static int 1232sndstat_prepare_pcm(struct sbuf *s, device_t dev, int verbose) 1233{ 1234 struct snddev_info *d; 1235 struct pcm_channel *c; 1236 struct pcm_feeder *f; 1237 1238 if (verbose < 1) 1239 return 0; 1240 1241 d = device_get_softc(dev); 1242 if (!d) 1243 return ENXIO; 1244 1245 PCM_BUSYASSERT(d); 1246 1247 if (CHN_EMPTY(d, channels.pcm)) { 1248 sbuf_printf(s, " (mixer only)"); 1249 return 0; 1250 } 1251 1252 sbuf_printf(s, " (%dp:%dv/%dr:%dv channels%s%s)", 1253 d->playcount, d->pvchancount, 1254 d->reccount, d->rvchancount, 1255 (d->flags & SD_F_SIMPLEX)? "" : " duplex", 1256#ifdef USING_DEVFS 1257 (device_get_unit(dev) == snd_unit)? " default" : "" 1258#else 1259 "" 1260#endif 1261 ); 1262 1263 if (verbose <= 1) 1264 return 0; 1265 1266 CHN_FOREACH(c, d, channels.pcm) { 1267 1268 KASSERT(c->bufhard != NULL && c->bufsoft != NULL, 1269 ("hosed pcm channel setup")); 1270 1271 sbuf_printf(s, "\n\t"); 1272 1273 /* it would be better to indent child channels */ 1274 sbuf_printf(s, "%s[%s]: ", c->parentchannel? c->parentchannel->name : "", c->name); 1275 sbuf_printf(s, "spd %d", c->speed); 1276 if (c->speed != sndbuf_getspd(c->bufhard)) 1277 sbuf_printf(s, "/%d", sndbuf_getspd(c->bufhard)); 1278 sbuf_printf(s, ", fmt 0x%08x", c->format); 1279 if (c->format != sndbuf_getfmt(c->bufhard)) 1280 sbuf_printf(s, "/0x%08x", sndbuf_getfmt(c->bufhard)); 1281 sbuf_printf(s, ", flags 0x%08x, 0x%08x", c->flags, c->feederflags); 1282 if (c->pid != -1) 1283 sbuf_printf(s, ", pid %d", c->pid); 1284 sbuf_printf(s, "\n\t"); 1285 1286 sbuf_printf(s, "interrupts %d, ", c->interrupts); 1287 if (c->direction == PCMDIR_REC) 1288 sbuf_printf(s, "overruns %d, feed %u, hfree %d, sfree %d [b:%d/%d/%d|bs:%d/%d/%d]", 1289 c->xruns, c->feedcount, sndbuf_getfree(c->bufhard), sndbuf_getfree(c->bufsoft), 1290 sndbuf_getsize(c->bufhard), sndbuf_getblksz(c->bufhard), 1291 sndbuf_getblkcnt(c->bufhard), 1292 sndbuf_getsize(c->bufsoft), sndbuf_getblksz(c->bufsoft), 1293 sndbuf_getblkcnt(c->bufsoft)); 1294 else 1295 sbuf_printf(s, "underruns %d, feed %u, ready %d [b:%d/%d/%d|bs:%d/%d/%d]", 1296 c->xruns, c->feedcount, sndbuf_getready(c->bufsoft), 1297 sndbuf_getsize(c->bufhard), sndbuf_getblksz(c->bufhard), 1298 sndbuf_getblkcnt(c->bufhard), 1299 sndbuf_getsize(c->bufsoft), sndbuf_getblksz(c->bufsoft), 1300 sndbuf_getblkcnt(c->bufsoft)); 1301 sbuf_printf(s, "\n\t"); 1302 1303 sbuf_printf(s, "{%s}", (c->direction == PCMDIR_REC)? "hardware" : "userland"); 1304 sbuf_printf(s, " -> "); 1305 f = c->feeder; 1306 while (f->source != NULL) 1307 f = f->source; 1308 while (f != NULL) { 1309 sbuf_printf(s, "%s", f->class->name); 1310 if (f->desc->type == FEEDER_FMT) 1311 sbuf_printf(s, "(0x%08x -> 0x%08x)", f->desc->in, f->desc->out); 1312 if (f->desc->type == FEEDER_RATE) 1313 sbuf_printf(s, "(%d -> %d)", FEEDER_GET(f, FEEDRATE_SRC), FEEDER_GET(f, FEEDRATE_DST)); 1314 if (f->desc->type == FEEDER_ROOT || f->desc->type == FEEDER_MIXER || 1315 f->desc->type == FEEDER_VOLUME) 1316 sbuf_printf(s, "(0x%08x)", f->desc->out); 1317 sbuf_printf(s, " -> "); 1318 f = f->parent; 1319 } 1320 sbuf_printf(s, "{%s}", (c->direction == PCMDIR_REC)? "userland" : "hardware"); 1321 } 1322 1323 return 0; 1324} 1325 1326/************************************************************************/ 1327 1328#ifdef SND_DYNSYSCTL 1329int 1330sysctl_hw_snd_vchans(SYSCTL_HANDLER_ARGS) 1331{ 1332 struct snddev_info *d; 1333 int direction, vchancount; 1334 int err, cnt; 1335 1336 d = devclass_get_softc(pcm_devclass, VCHAN_SYSCTL_UNIT(oidp->oid_arg1)); 1337 if (!PCM_REGISTERED(d) || !(d->flags & SD_F_AUTOVCHAN)) 1338 return (EINVAL); 1339 1340 pcm_lock(d); 1341 PCM_WAIT(d); 1342 1343 switch (VCHAN_SYSCTL_DIR(oidp->oid_arg1)) { 1344 case VCHAN_PLAY: 1345 direction = PCMDIR_PLAY; 1346 vchancount = d->pvchancount; 1347 cnt = d->playcount; 1348 break; 1349 case VCHAN_REC: 1350 direction = PCMDIR_REC; 1351 vchancount = d->rvchancount; 1352 cnt = d->reccount; 1353 break; 1354 default: 1355 pcm_unlock(d); 1356 return (EINVAL); 1357 break; 1358 } 1359 1360 if (cnt < 1) { 1361 pcm_unlock(d); 1362 return (ENODEV); 1363 } 1364 1365 PCM_ACQUIRE(d); 1366 pcm_unlock(d); 1367 1368 cnt = vchancount; 1369 err = sysctl_handle_int(oidp, &cnt, 0, req); 1370 1371 if (err == 0 && req->newptr != NULL && vchancount != cnt) { 1372 if (cnt < 0) 1373 cnt = 0; 1374 if (cnt > SND_MAXVCHANS) 1375 cnt = SND_MAXVCHANS; 1376 err = pcm_setvchans(d, direction, cnt, -1); 1377 } 1378 1379 PCM_RELEASE_QUICK(d); 1380 1381 return err; 1382} 1383#endif 1384 1385/************************************************************************/ 1386 | |
1387/** 1388 * @brief Handle OSSv4 SNDCTL_SYSINFO ioctl. 1389 * 1390 * @param si Pointer to oss_sysinfo struct where information about the 1391 * sound subsystem will be written/copied. 1392 * 1393 * This routine returns information about the sound system, such as the 1394 * current OSS version, number of audio, MIDI, and mixer drivers, etc. --- 38 unchanged lines hidden (view full) --- 1433 i < devclass_get_maxunit(pcm_devclass); i++) { 1434 d = devclass_get_softc(pcm_devclass, i); 1435 if (!PCM_REGISTERED(d)) 1436 continue; 1437 1438 /* XXX Need Giant magic entry ??? */ 1439 1440 /* See note in function's docblock */ | 1241/** 1242 * @brief Handle OSSv4 SNDCTL_SYSINFO ioctl. 1243 * 1244 * @param si Pointer to oss_sysinfo struct where information about the 1245 * sound subsystem will be written/copied. 1246 * 1247 * This routine returns information about the sound system, such as the 1248 * current OSS version, number of audio, MIDI, and mixer drivers, etc. --- 38 unchanged lines hidden (view full) --- 1287 i < devclass_get_maxunit(pcm_devclass); i++) { 1288 d = devclass_get_softc(pcm_devclass, i); 1289 if (!PCM_REGISTERED(d)) 1290 continue; 1291 1292 /* XXX Need Giant magic entry ??? */ 1293 1294 /* See note in function's docblock */ |
1441 mtx_assert(d->lock, MA_NOTOWNED); 1442 pcm_lock(d); | 1295 PCM_UNLOCKASSERT(d); 1296 PCM_LOCK(d); |
1443 1444 si->numaudios += d->devcount; 1445 ++ncards; 1446 1447 CHN_FOREACH(c, d, channels.pcm) { | 1297 1298 si->numaudios += d->devcount; 1299 ++ncards; 1300 1301 CHN_FOREACH(c, d, channels.pcm) { |
1448 mtx_assert(c->lock, MA_NOTOWNED); | 1302 CHN_UNLOCKASSERT(c); |
1449 CHN_LOCK(c); 1450 if (c->flags & CHN_F_BUSY) 1451 si->openedaudio[j / intnbits] |= 1452 (1 << (j % intnbits)); 1453 CHN_UNLOCK(c); 1454 j++; 1455 } 1456 | 1303 CHN_LOCK(c); 1304 if (c->flags & CHN_F_BUSY) 1305 si->openedaudio[j / intnbits] |= 1306 (1 << (j % intnbits)); 1307 CHN_UNLOCK(c); 1308 j++; 1309 } 1310 |
1457 pcm_unlock(d); | 1311 PCM_UNLOCK(d); |
1458 } 1459 si->numaudioengines = si->numaudios; 1460 1461 si->numsynths = 0; /* OSSv4 docs: this field is obsolete */ 1462 /** 1463 * @todo Collect num{midis,timers}. 1464 * 1465 * Need access to sound/midi/midi.c::midistat_lock in order --- 39 unchanged lines hidden (view full) --- 1505 i < devclass_get_maxunit(pcm_devclass); i++) { 1506 d = devclass_get_softc(pcm_devclass, i); 1507 if (!PCM_REGISTERED(d)) 1508 continue; 1509 1510 if (ncards++ != si->card) 1511 continue; 1512 | 1312 } 1313 si->numaudioengines = si->numaudios; 1314 1315 si->numsynths = 0; /* OSSv4 docs: this field is obsolete */ 1316 /** 1317 * @todo Collect num{midis,timers}. 1318 * 1319 * Need access to sound/midi/midi.c::midistat_lock in order --- 39 unchanged lines hidden (view full) --- 1359 i < devclass_get_maxunit(pcm_devclass); i++) { 1360 d = devclass_get_softc(pcm_devclass, i); 1361 if (!PCM_REGISTERED(d)) 1362 continue; 1363 1364 if (ncards++ != si->card) 1365 continue; 1366 |
1513 mtx_assert(d->lock, MA_NOTOWNED); 1514 pcm_lock(d); | 1367 PCM_UNLOCKASSERT(d); 1368 PCM_LOCK(d); |
1515 1516 strlcpy(si->shortname, device_get_nameunit(d->dev), 1517 sizeof(si->shortname)); 1518 strlcpy(si->longname, device_get_desc(d->dev), 1519 sizeof(si->longname)); 1520 strlcpy(si->hw_info, d->status, sizeof(si->hw_info)); 1521 si->intr_count = si->ack_count = 0; | 1369 1370 strlcpy(si->shortname, device_get_nameunit(d->dev), 1371 sizeof(si->shortname)); 1372 strlcpy(si->longname, device_get_desc(d->dev), 1373 sizeof(si->longname)); 1374 strlcpy(si->hw_info, d->status, sizeof(si->hw_info)); 1375 si->intr_count = si->ack_count = 0; |
1522 pcm_unlock(d); | 1376 1377 PCM_UNLOCK(d); 1378 |
1523 return (0); 1524 } 1525 return (ENXIO); 1526} 1527 1528/************************************************************************/ 1529 1530static int --- 15 unchanged lines hidden (view full) --- 1546 if (ret != 0) 1547 break; 1548 if (pcmsg_unrhdr != NULL) { 1549 delete_unrhdr(pcmsg_unrhdr); 1550 pcmsg_unrhdr = NULL; 1551 } 1552 break; 1553 default: | 1379 return (0); 1380 } 1381 return (ENXIO); 1382} 1383 1384/************************************************************************/ 1385 1386static int --- 15 unchanged lines hidden (view full) --- 1402 if (ret != 0) 1403 break; 1404 if (pcmsg_unrhdr != NULL) { 1405 delete_unrhdr(pcmsg_unrhdr); 1406 pcmsg_unrhdr = NULL; 1407 } 1408 break; 1409 default: |
1554 ret = EOPNOTSUPP; | 1410 ret = ENOTSUP; |
1555 } 1556 1557 return ret; 1558#endif 1559} 1560 1561DEV_MODULE(sound, sound_modevent, NULL); 1562MODULE_VERSION(sound, SOUND_MODVER); | 1411 } 1412 1413 return ret; 1414#endif 1415} 1416 1417DEV_MODULE(sound, sound_modevent, NULL); 1418MODULE_VERSION(sound, SOUND_MODVER); |