linux/sound/sound_core.c
<<
>>
Prefs
   1/*
   2 *      Sound core.  This file is composed of two parts.  sound_class
   3 *      which is common to both OSS and ALSA and OSS sound core which
   4 *      is used OSS or emulation of it.
   5 */
   6
   7/*
   8 * First, the common part.
   9 */
  10#include <linux/module.h>
  11#include <linux/device.h>
  12#include <linux/err.h>
  13#include <linux/kdev_t.h>
  14#include <linux/major.h>
  15#include <sound/core.h>
  16
  17#ifdef CONFIG_SOUND_OSS_CORE
  18static int __init init_oss_soundcore(void);
  19static void cleanup_oss_soundcore(void);
  20#else
  21static inline int init_oss_soundcore(void)      { return 0; }
  22static inline void cleanup_oss_soundcore(void)  { }
  23#endif
  24
  25struct class *sound_class;
  26EXPORT_SYMBOL(sound_class);
  27
  28MODULE_DESCRIPTION("Core sound module");
  29MODULE_AUTHOR("Alan Cox");
  30MODULE_LICENSE("GPL");
  31
  32static char *sound_devnode(struct device *dev, umode_t *mode)
  33{
  34        if (MAJOR(dev->devt) == SOUND_MAJOR)
  35                return NULL;
  36        return kasprintf(GFP_KERNEL, "snd/%s", dev_name(dev));
  37}
  38
  39static int __init init_soundcore(void)
  40{
  41        int rc;
  42
  43        rc = init_oss_soundcore();
  44        if (rc)
  45                return rc;
  46
  47        sound_class = class_create(THIS_MODULE, "sound");
  48        if (IS_ERR(sound_class)) {
  49                cleanup_oss_soundcore();
  50                return PTR_ERR(sound_class);
  51        }
  52
  53        sound_class->devnode = sound_devnode;
  54
  55        return 0;
  56}
  57
  58static void __exit cleanup_soundcore(void)
  59{
  60        cleanup_oss_soundcore();
  61        class_destroy(sound_class);
  62}
  63
  64subsys_initcall(init_soundcore);
  65module_exit(cleanup_soundcore);
  66
  67
  68#ifdef CONFIG_SOUND_OSS_CORE
  69/*
  70 *      OSS sound core handling. Breaks out sound functions to submodules
  71 *      
  72 *      Author:         Alan Cox <alan@lxorguk.ukuu.org.uk>
  73 *
  74 *      Fixes:
  75 *
  76 *
  77 *      This program is free software; you can redistribute it and/or
  78 *      modify it under the terms of the GNU General Public License
  79 *      as published by the Free Software Foundation; either version
  80 *      2 of the License, or (at your option) any later version.
  81 *
  82 *                         --------------------
  83 * 
  84 *      Top level handler for the sound subsystem. Various devices can
  85 *      plug into this. The fact they don't all go via OSS doesn't mean 
  86 *      they don't have to implement the OSS API. There is a lot of logic
  87 *      to keeping much of the OSS weight out of the code in a compatibility
  88 *      module, but it's up to the driver to rember to load it...
  89 *
  90 *      The code provides a set of functions for registration of devices
  91 *      by type. This is done rather than providing a single call so that
  92 *      we can hide any future changes in the internals (eg when we go to
  93 *      32bit dev_t) from the modules and their interface.
  94 *
  95 *      Secondly we need to allocate the dsp, dsp16 and audio devices as
  96 *      one. Thus we misuse the chains a bit to simplify this.
  97 *
  98 *      Thirdly to make it more fun and for 2.3.x and above we do all
  99 *      of this using fine grained locking.
 100 *
 101 *      FIXME: we have to resolve modules and fine grained load/unload
 102 *      locking at some point in 2.3.x.
 103 */
 104
 105#include <linux/init.h>
 106#include <linux/slab.h>
 107#include <linux/types.h>
 108#include <linux/kernel.h>
 109#include <linux/sound.h>
 110#include <linux/kmod.h>
 111
 112#define SOUND_STEP 16
 113
 114struct sound_unit
 115{
 116        int unit_minor;
 117        const struct file_operations *unit_fops;
 118        struct sound_unit *next;
 119        char name[32];
 120};
 121
 122#ifdef CONFIG_SOUND_MSNDCLAS
 123extern int msnd_classic_init(void);
 124#endif
 125#ifdef CONFIG_SOUND_MSNDPIN
 126extern int msnd_pinnacle_init(void);
 127#endif
 128
 129/*
 130 * By default, OSS sound_core claims full legacy minor range (0-255)
 131 * of SOUND_MAJOR to trap open attempts to any sound minor and
 132 * requests modules using custom sound-slot/service-* module aliases.
 133 * The only benefit of doing this is allowing use of custom module
 134 * aliases instead of the standard char-major-* ones.  This behavior
 135 * prevents alternative OSS implementation and is scheduled to be
 136 * removed.
 137 *
 138 * CONFIG_SOUND_OSS_CORE_PRECLAIM and soundcore.preclaim_oss kernel
 139 * parameter are added to allow distros and developers to try and
 140 * switch to alternative implementations without needing to rebuild
 141 * the kernel in the meantime.  If preclaim_oss is non-zero, the
 142 * kernel will behave the same as before.  All SOUND_MAJOR minors are
 143 * preclaimed and the custom module aliases along with standard chrdev
 144 * ones are emitted if a missing device is opened.  If preclaim_oss is
 145 * zero, sound_core only grabs what's actually in use and for missing
 146 * devices only the standard chrdev aliases are requested.
 147 *
 148 * All these clutters are scheduled to be removed along with
 149 * sound-slot/service-* module aliases.  Please take a look at
 150 * feature-removal-schedule.txt for details.
 151 */
 152#ifdef CONFIG_SOUND_OSS_CORE_PRECLAIM
 153static int preclaim_oss = 1;
 154#else
 155static int preclaim_oss = 0;
 156#endif
 157
 158module_param(preclaim_oss, int, 0444);
 159
 160static int soundcore_open(struct inode *, struct file *);
 161
 162static const struct file_operations soundcore_fops =
 163{
 164        /* We must have an owner or the module locking fails */
 165        .owner  = THIS_MODULE,
 166        .open   = soundcore_open,
 167        .llseek = noop_llseek,
 168};
 169
 170/*
 171 *      Low level list operator. Scan the ordered list, find a hole and
 172 *      join into it. Called with the lock asserted
 173 */
 174
 175static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, const struct file_operations *fops, int index, int low, int top)
 176{
 177        int n=low;
 178
 179        if (index < 0) {        /* first free */
 180
 181                while (*list && (*list)->unit_minor<n)
 182                        list=&((*list)->next);
 183
 184                while(n<top)
 185                {
 186                        /* Found a hole ? */
 187                        if(*list==NULL || (*list)->unit_minor>n)
 188                                break;
 189                        list=&((*list)->next);
 190                        n+=SOUND_STEP;
 191                }
 192
 193                if(n>=top)
 194                        return -ENOENT;
 195        } else {
 196                n = low+(index*16);
 197                while (*list) {
 198                        if ((*list)->unit_minor==n)
 199                                return -EBUSY;
 200                        if ((*list)->unit_minor>n)
 201                                break;
 202                        list=&((*list)->next);
 203                }
 204        }       
 205                
 206        /*
 207         *      Fill it in
 208         */
 209         
 210        s->unit_minor=n;
 211        s->unit_fops=fops;
 212        
 213        /*
 214         *      Link it
 215         */
 216         
 217        s->next=*list;
 218        *list=s;
 219        
 220        
 221        return n;
 222}
 223
 224/*
 225 *      Remove a node from the chain. Called with the lock asserted
 226 */
 227 
 228static struct sound_unit *__sound_remove_unit(struct sound_unit **list, int unit)
 229{
 230        while(*list)
 231        {
 232                struct sound_unit *p=*list;
 233                if(p->unit_minor==unit)
 234                {
 235                        *list=p->next;
 236                        return p;
 237                }
 238                list=&(p->next);
 239        }
 240        printk(KERN_ERR "Sound device %d went missing!\n", unit);
 241        return NULL;
 242}
 243
 244/*
 245 *      This lock guards the sound loader list.
 246 */
 247
 248static DEFINE_SPINLOCK(sound_loader_lock);
 249
 250/*
 251 *      Allocate the controlling structure and add it to the sound driver
 252 *      list. Acquires locks as needed
 253 */
 254
 255static int sound_insert_unit(struct sound_unit **list, const struct file_operations *fops, int index, int low, int top, const char *name, umode_t mode, struct device *dev)
 256{
 257        struct sound_unit *s = kmalloc(sizeof(*s), GFP_KERNEL);
 258        int r;
 259
 260        if (!s)
 261                return -ENOMEM;
 262
 263        spin_lock(&sound_loader_lock);
 264retry:
 265        r = __sound_insert_unit(s, list, fops, index, low, top);
 266        spin_unlock(&sound_loader_lock);
 267        
 268        if (r < 0)
 269                goto fail;
 270        else if (r < SOUND_STEP)
 271                sprintf(s->name, "sound/%s", name);
 272        else
 273                sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
 274
 275        if (!preclaim_oss) {
 276                /*
 277                 * Something else might have grabbed the minor.  If
 278                 * first free slot is requested, rescan with @low set
 279                 * to the next unit; otherwise, -EBUSY.
 280                 */
 281                r = __register_chrdev(SOUND_MAJOR, s->unit_minor, 1, s->name,
 282                                      &soundcore_fops);
 283                if (r < 0) {
 284                        spin_lock(&sound_loader_lock);
 285                        __sound_remove_unit(list, s->unit_minor);
 286                        if (index < 0) {
 287                                low = s->unit_minor + SOUND_STEP;
 288                                goto retry;
 289                        }
 290                        spin_unlock(&sound_loader_lock);
 291                        return -EBUSY;
 292                }
 293        }
 294
 295        device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
 296                      NULL, s->name+6);
 297        return s->unit_minor;
 298
 299fail:
 300        kfree(s);
 301        return r;
 302}
 303
 304/*
 305 *      Remove a unit. Acquires locks as needed. The drivers MUST have
 306 *      completed the removal before their file operations become
 307 *      invalid.
 308 */
 309        
 310static void sound_remove_unit(struct sound_unit **list, int unit)
 311{
 312        struct sound_unit *p;
 313
 314        spin_lock(&sound_loader_lock);
 315        p = __sound_remove_unit(list, unit);
 316        spin_unlock(&sound_loader_lock);
 317        if (p) {
 318                if (!preclaim_oss)
 319                        __unregister_chrdev(SOUND_MAJOR, p->unit_minor, 1,
 320                                            p->name);
 321                device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor));
 322                kfree(p);
 323        }
 324}
 325
 326/*
 327 *      Allocations
 328 *
 329 *      0       *16             Mixers
 330 *      1       *8              Sequencers
 331 *      2       *16             Midi
 332 *      3       *16             DSP
 333 *      4       *16             SunDSP
 334 *      5       *16             DSP16
 335 *      6       --              sndstat (obsolete)
 336 *      7       *16             unused
 337 *      8       --              alternate sequencer (see above)
 338 *      9       *16             raw synthesizer access
 339 *      10      *16             unused
 340 *      11      *16             unused
 341 *      12      *16             unused
 342 *      13      *16             unused
 343 *      14      *16             unused
 344 *      15      *16             unused
 345 */
 346
 347static struct sound_unit *chains[SOUND_STEP];
 348
 349/**
 350 *      register_sound_special_device - register a special sound node
 351 *      @fops: File operations for the driver
 352 *      @unit: Unit number to allocate
 353 *      @dev: device pointer
 354 *
 355 *      Allocate a special sound device by minor number from the sound
 356 *      subsystem. The allocated number is returned on success. On failure
 357 *      a negative error code is returned.
 358 */
 359 
 360int register_sound_special_device(const struct file_operations *fops, int unit,
 361                                  struct device *dev)
 362{
 363        const int chain = unit % SOUND_STEP;
 364        int max_unit = 256;
 365        const char *name;
 366        char _name[16];
 367
 368        switch (chain) {
 369            case 0:
 370                name = "mixer";
 371                break;
 372            ="L262d="L371"2nd_core.c#L371" idL371"> 371                break;
      e                name = "miquencer (uot;;
 2737/a>                   (unit =SOUND_STEP)
 2737/a>                        chunreknow a>;
 273                max_unit = 25 href="+code=p"it" class="sref">unit &#+ 1 2737/a>                  eak;
 2737/a>              L262d2"L371"2nd_core.c#L371" idL371"> 3 id="L369" class="line" name="L273"> 2737/a>                   href="+code=name" class="sref">name = "mixediuot;;
 2838/a>                 283              L262d3"L371"2nd_core.c#L371" idL371"> " id="L283" class="line" name="L283"> 283                   href="+code=name" class="sref">name = "midspuot;;
   " class="line" name="L283"> 283                ifeak;
 283              L262d4"L371"2nd_core.c#L371" idL371"> " id="L273" class="line" name="L283"> 283                   href="+code=name" class="sref">name = "miaudiouot;;
 283                  eak;
 283              L262d5"L371"2nd_core.c#L371" idL371"> " id="L368" class="line" name="L283"> 283                   href="+code=name" class="sref">name = "midspWuot;;
 283                  eak;
 293              L262d8"L371"2nd_core.c#L371" idL371"> " id="L293" class="line" name="L293"> 293                   href="+code=spme" class="sref">name = "miquencer (2uot;;
 293                }
 (unit =SOUND_STEP)
 293                ifffffffffto chunreknow a>;
 293                  phref="+code=max_unit" class="sref">max_unit = 25 href="+code=p"it" class="sref">unit &#+ 1 2939/a>                  eak;
 293              L262d9"L371"2nd_core.c#L371" idL371"> " id="L367" class="line" name="L293"> 293                wh href="+code=name" class="sref">name = "midmxediuot;;
 293                  eak;
 293              L262d=
 304                   href="+code=name" class="sref">name = "midmfmuot;;
 304                  eak;
 304              L262d=2"L371"2nd_core.c#L371" idL371">4" id="L304" class="line" name="L304"> 304                }
 href="+code=name" class="sref">name = "miadspuot;;
 3040/a>                  eak;
 304              L262d=3"L371"2nd_core.c#L371" idL371">4" id="L304" class="line" name="L304"> 3040/a>                name = "miaxediuot;;
 3040/a>                  eak;
 3040/a>              L262d14"L371"2nd_core.c#L371" idL371">4" id="L304" class="line" name="L304"> 3040/a>                   href="+code=name" class="sref">name = "miadmxediuot;;
 3141/a>                 3141/a>              default"L371"2nd_core.c#L371" idL371">4" id="L314" class="line" name="L314"> 3141/a>                }
 3141/a>                ifffff href="+code=reunreknow class="sref">chunreknow a>;
"L371"2nd_core.c#L371" idL371">4" id="L304" class="line" name="L314"> 3141/a>                    ifffff href="+code=rerintf" class="sref">sprintf(_name[1"soreknow 37;d", chain) { 3141/a>                        unit =SOUND_STEP)
 3141/a>                        if  ifffff href="+code=rertrca class="sref">soutrca a>(_name[1"so-uot;, { 3141/a>                           href="+code=name" class="sref">name = _name[1 314                if 314                  eak;
 324           324        return sound_insert_unit(stmp;chains[chain) ]fops, unit,
< phref="+code=max_unit" class="sref">max_unit = 324                name =< phref="+code=maS_IRUS class="sref">SOU_IRUS a>   | phref="+code=maS_IWUS class="sref">SOU_IWUS a>  dev, { 324   324}
 324NUEXPORT_SYMBO a>(register_sound_special_device(c{ 3242/a>
 324register_sound_special_da>(const struct file_operations *fops, int unit,
 324 32429a>        return register_sound_special_device(co href="+code=fops" class="sref">fops, in href="+code=s"it" class="sref">unit,
< phref="+code=maLL" class="sref">NULL, { 334 334 334NUEXPORT_SYMBO a>(register_sound_special_da>(c{ 3343/a>
 334 **
 334 *      6 gister_sound_spxer&q register a spxer&q vicean>
 334 *      7 ops: File operations for the driver
 334 *      8 ev: deit number to allocate
 334 *  span>
 334 *      10locate a spxer&q vice
 344 *      11Ps="a- o alquestedhe next unee slnor&q it. AcOsuccess. he nelocated nspan>
 344 *      12mber is returned o,n suilure
 344 *  /span>
 344
 344register_sound_spnor&qa>(const struct file_operations *fops, int dev)
 344 34446a>        return sound_insert_unit(stmp;chains[fops, dev)
, 0, 128 3444/a>                                "mixer";
< phref="+code=maS_IRUS class="sref">SOU_IRUS a>   | phref="+code=maS_IWUS class="sref">SOU_IWUS a>  NULL, { 344
< 344
 354NUEXPORT_SYMBO a>(register_sound_spnor&qa>(c{ 3545/a> 354 **
 354 *      @dgister_sound_spnodi register a spxedi vicean>
 354 *
 354 *      Alev: deit number to allocate
 354 *  span>
 354 *      a locate a spxedi vice
 354 */<    11Ps="a- o alquestedhe next unee slnodi it. AcOsuccess. he nelocated nspan>
 3545/a> *      10mber is returned o,n suilure
 3646/a> *  /span>
 3646/a> 364{
t register_sound_spnofile_operations *fops, int dev)
 364   364        inturn sound_insert_unit(stmp;chains[fops, dev)
, 2, 130 3646/a>                        "mixediuot;;
< phref="+code=maS_IRUS class="sref">SOU_IRUS a>   | phref="+code=maS_IWUS class="sref">SOU_IWUS a>  NULL, { 364   364
 364  phref="+code=deEXPORT_SYMBO class="sref">NUEXPORT_SYMBO a>(register_sound_spno 3646/a>
 3747/a> *
 3747/a> *      12DSP's areegister aeds nea ingpl/.eRister a only on/ nnd chea/span>
 3747/a> *      @uinperan ree abbelow/span>
 *  /span>
 2747/a>}
 2747/a> **
 2747/a> *      7 gister_sound_spdsp register a spDSP vicean>
 274   /    7 ops: File operations for the driver
 274        Alev: deit number to allocate
 274   /span>
 284        a locate a spDSP vice
 2848/a> *      12Ps="a- o alquestedhe next unee slDSP it. AcOsuccess. he nelocated nspan>
 2848/a> *      @umber is returned o,n suilure
  4" class="line" name="L284"> 2848/a> *  span>
 2848/a> *ri s togeerwispan>
 2848/a> *      Alnnd willelowayselocated he nms nea matcng elpaiq reeg dsp3/ludio3span>
 2848/a> *  /span>
 2848/a>
 284  t register_sound_spdspsp(const struct file_operations *fops, int dev)
 284   294          turn sound_insert_unit(stmp;chains[fops, dev)
, 3, 13
 294                        re      "midspuot;;
< phref="+code=maS_IWUS class="sref">SOU_IWUS a>   | phref="+code=maS_IRUS class="sref">SOU_IRUS a>  NULL, { 2949/a>}
 2949/a>
 294  phref="+code=deEXPORT_SYMBO class="sref">NUEXPORT_SYMBO a>(register_sound_spdspsp(c{ 2949/a>
 2949/a>/*
 2949/a>   /    7 register_chund_coecial so- register_c special sound device bspan>
 2949/a>        Aleit: Unut number to allocate
 2949/a>   /span>
 3050/a>        a Rele262daound device bythat wasllocated nuwithspan>
 3050/a> *      12gister_chund_coecial s()The alut nups=" nuithe soturn 
 3050/a> *      @ue sotuster_c funcons /span>
 3050/a> *  /span>
 3050/a>
 3050/a>
 3050/a>  id unitgister_sound_special_da>(cot unit,
 3050/a>   3050/a>           href="+code=n"und_comove_unit" class="sref">sound_remove_unit(stmp;chains[unit % SOUND_STEP;
]unit);
 3050/a>   3151/a>   a href="sound/sound_core.c#L305"1id="L305" class="line" name="L315"> 3151/a>  phref="+code=deEXPORT_SYMBO class="sref">NUEXPORT_SYMBO a>(unitgister_sound_special_da>(c
 3151/a>  a href="sound/sound_core.c#L315" id="L305" class="line" name="L315"> 3151/a> *
 3151/a> *an>
 3151/a> *      Aleit: Unut number to allocate
 3151/a> *  span>
 3151/a>   /    7 Rele262daound device bythat wasllocated nuwith gister_sound_spxer&q()Tspan>
 3151/a>        Ale alut nups=" nuithe soturn 
 3151/a>   //span>
 325  a href="sound/sound_core.c#L355"1id="L305" class="line" name="L325"> 325  id reregister_chund_conor&qa>(cot unit,
 3252/a>{
 325        }
 href="+code=n"und_comove_unit" class="sref">sound_remove_unit(stmp;chains[unit);
 325}
 325
 325NUEXPORT_SYMBO a>(reregister_chund_conor&qa>(c
 3252/a>
 325 *
 325 *      0 register_chund_conodi reregister_c spnodi vicean>
 335 *      1 eit: Unut number to allocate
 335 *  span>
 335 *      3 Rele262daound device bythat wasllocated nuwith gister_sound_spxedi()Tspan>
 335 *      4 e alut nups=" nuithe soturn 
 335 *  /span>
 3353/a>
 3353/a>  id reregister_chund_conodia>(cot unit,
 3353/a>   3353/a>           href="+code=n"und_comove_unit" class="sref">sound_remove_unit(stmp;chains[unit);
 3353/a>   3454/a>  a href="sound/sound_core.c#L355" id="L335" class="line" name="L345"> 3454/a>  phref="+code=deEXPORT_SYMBO class="sref">NUEXPORT_SYMBO a>(reregister_chund_conodia>(c
 3454/a>  a href="sound/sound_core.c#L315" id="L345" class="line" name="L345"> 345 *
 345 *      15register_chund_codsp reregister_c spDSP vicean>
 345 */<    1 eit: Unut number to allocate
 3454/a> *  span>
 3454/a>   /    7 Rele262daound device bythat wasllocated nuwith gister_sound_spdsp()Tspan>
 3454/a>        Ale alut nups=" nuithe soturn 
 345/*  span>
 355 *      reBothhofhe milocated nuut ns areegile262d togeerwi automic slocy/span>
 355 *  /span>
 3555/a>  a href="sound/sound_core.c#L315" id="L355" class="line" name="L355"> 355reregister_chund_codspa>(cot unit,
 355 35555a>           href="+code=n"und_comove_unit" class="sref">sound_remove_unit(stmp;chains[unit);
 3555/a>   3555/a>
 3555/a>
 3555/a>NUEXPORT_SYMBO a>(reregister_chund_codspa>(c
 3656/a>  a href="sound/sound_core.c#L355" id="L365" class="line" name="L365"> 3656/a>sound_unit *so__look_fornit" a>(cot chain) int unit,
 365{
 365        coruct sound_unit *ch/a>[< 365        ina href="sound/sound_core.c#L315" id="L355" class="line" name="L365"> 36565a>           href="+code=n"uclass="sref">ch/a>[<= href="+code=soains" class="sref">chains[chain) ] 365        chwhilea href="+code=s"uclass="sref">ch/a>[< mp;ch/a>[<-3;=< href="+code=unit" _nor nclass="sref">unit[< ml=unit,
 3656/a>           3656/a>                ififa href="+code=s"uclass="sref">ch/a>[<-3;=< href="+code=unit" _nor nclass="sref">unit[<== href="+code=soit" class="sref">unit,
 365            caaaaaaaaaaaaaturn ch/a>[< 375                ch/a>[<= href="+code=souclass="sref">ch/a>[<-3;=< href="+code=unxt uclass="sref">chxt ua>[< 375           375          turn NULL,  2757/a>
 2757/a>chund_cre.cpera a>(coruct chor dea> *chor dea> *,truct chle_oa> *chle_oa> * 2757/a> 2757/a>          t chain)  2757/a>          t unit,
 uninor na>[chor dea> *
 2757/a>          ruct sound_unit *ch/a>[< 2858/a>          nst struct file_operations *fonew_ps" a>,
 NULL,  2858/a> 285           href="+code=unain" class="sref">chain) = href="+code=soit" class="sref">unit,
mp; 285          ifa href="+code=s"ain" class="sref">chain) ==4 || phref="+code=maain" class="sref">chain) ==5)         an class="comment"> *
 285           285                   href="+code=nait" class="sref">unit,
mp; 285                   href="+code=nait" class="sref">unit,
|=3 285                   href="+code=unain" class="sref">chain) =3 285           285          a href="sound/sound_core.c#L325" id="L295" class="line" name="L295"> 295           href="+code=ch pin_lockclass="sref">ch/pin_locka>(stmp;ch/nd_coloader_locka> *
 295           href="+code=s"uclass="sref">ch/a>[< so__look_fornit" a>(co href="+code=unain" class="sref">chain) in href="+code=foit" class="sref">unit);
 295           (ch/a>[< 295                if href="+code=fonew_ps" class="sref">fonew_ps" a>,
 unps" _ge a>(co href="+code=unuclass="sref">ch/a>[<-3;=< href="+code=unit" _ps" class="sref">foit" _ps" a>);
 295           (fopreassim_os a>[< mp;fonew_ps" a>,
)  2959/a>                   href="+code=ch pin_unlockclass="sref">ch/pin_unlocka>(stmp;ch/nd_coloader_locka> *
 2959/a>
 295                wh an class="comment"> *
 2959/a>                   *  Ple262, don't ainngbythis ord toorode i/span>
 2959/a>                   *  ForoALSA slot meansound dcardlnnd OSS emulions
 3060/a>                   *  mmeess neadd-s
 3060/a> *                 *  ALSA toplevelomodulessr thund dcards,ythusswnext nspan>
 3060/a> *                 *  loadhe nms t first.   [Jaroslav Kysela ml=
 3060/a> *                 */span>
 3060/a>                   href="+code=soquested_moduleclass="sref">chquested_modulea>(co an class="string">"miund_c-slot-37; ;
< phref="+code=mait" class="sref">unit,
m;= 306                   href="+code=soquested_moduleclass="sref">chquested_modulea>(co an class="string">"miund_c-serce b-37; ;
< phref="+code=mait" class="sref">unit,
m;=chain) { 3060/a>
 3060/a>                   an class="comment"> *
 3060/a>                   * und_c-slot/serce b-*omodule ali262s areeschedulenspan>
 3060/a>                   * r thmove_aluinpfavotoofhe mistnndardlainr-major-/span>
 3161/a>                   * module ali262s.  Foroe mitimabbeg">, genatioe bothspan>
 3161/a> *                 * e milegacylnnd stnndardlmodule ali262s to e262span>
 3161/a> *                 * transions /span>
 3161/a> *                 */span>
 3161/a>                   (chquested_modulea>(co an class="string">"miainr-major-37;d&q-37;d", SOUND_STMAJO a>) in href="+code=foit" class="sref">unit);
#3;=< 0 3161/a>                        chquested_modulea>(co an class="string">"miainr-major-37;d", SOUND_STMAJO a>) { 3161/a>
 3161/a>                   href="+code=ch pin_lockclass="sref">ch/pin_locka>(stmp;ch/nd_coloader_locka> *
 316                if href="+code=s"uclass="sref">ch/a>[< so__look_fornit" a>(co href="+code=unain" class="sref">chain) in href="+code=foit" class="sref">unit);
 316                   (ch/a>[< 3262/a>                fonew_ps" a>,
 unps" _ge a>(co href="+code=unuclass="sref">ch/a>[<-3;=< href="+code=unit" _ps" class="sref">foit" _ps" a>);
 3262/a>           3262/a>           (fonew_ps" a>,
)  3262/a>                if an class="comment"> *
 3262/a> *                 * Weegily upon e mifactythat we can't balutloadedhwhile e mspan>
 3262/a> */                * subiver
 3262/a> *                 * safily dropue sotufsrence cnd_r_c snd  (< nuithnot we canspan>
 3262/a>                   * rer
 326 *                 * switcng el-3;=
 326 *                 */span>
 3363/a>                unerna>,
  3363/a>                  nst struct file_operations *foold_ps" a>,
 chle_oa> *-3;=< href="+code=unf_opclass="sref">chl_opa>,  33632a>                if href="+code=s"pe_oclass="sref">chle_oa> *-3;=< href="+code=unf_opclass="sref">chl_opa>,  fonew_ps" a>,
 3363/a>                if href="+code=fo pin_unlockclass="sref">ch/pin_unlocka>(stmp;ch/nd_coloader_locka> *
 3363/a>
 3363/a>                   (chle_oa> *-3;=< href="+code=unf_opclass="sref">chl_opa>, -3;=< href="+code=unera class="sref">chera a>(c 3363/a>                        if href="+code=foernclass="sref">unerna>,
 chle_oa> *-3;=< href="+code=unf_opclass="sref">chl_opa>, -3;=< href="+code=unera class="sref">chera a>(ca href="+code=s"or declass="sref">chor dea> *, href="+code=p"pe_oclass="sref">chle_oa> *
 3363/a>
 3363/a>                ififunerna>,
)  3363/a>            caaaaaaaaaaaaaphref="+code=s"ps" _pu class="sref">unps" _pu a>(ca href="+code=s"pe_oclass="sref">chle_oa> *-3;=< href="+code=unf_opclass="sref">chl_opa>, 
 3464/a>                chle_oa> *-3;=< href="+code=unf_opclass="sref">chl_opa>,  unps" _ge a>(co href="+code=unold_ps" class="sref">foold_ps" a>,

 3464/a>                   3464/a>  a href="sound/sound_core.c#L316" id="L346" class="line" name="L346"> 3464/a>                if href="+code=fops" _pu class="sref">unps" _pu a>(ca href="+code=s"old_ps" class="sref">foold_ps" a>,

 3464/a>                  turn unerna>,
 3464/a>           34646a>        re href="+code=fo pin_unlockclass="sref">ch/pin_unlocka>(stmp;ch/nd_coloader_locka> *
 3464/a>          turn chENODEVa>,
 346
< 346
 356SOMODULE_ALIAS_CHARDEVTMAJO a>(ca href="+code=s"UND_STMAJO class="sref">SOUND_STMAJO a>) { 3565/a> 3565/a>  atic stid chaleanup_os hund_cre.ca>(caid < 3565/a>   3565/a>           an class="comment"> *
 356 *           empty */span>
 35656a>        re href="+code=foregister_chchrv" class="sref">deregister_chchrv" a>(ca href="+code=s"UND_STMAJO class="sref">SOUND_STMAJO a>) ,span class="string">"miund_cuot;, { 3565/a>
< 3565/a>
 3565/a>so__it *< href="+code=s"orit_os hund_cre.cclass="sref">chorit_os hund_cre.ca>(caid < 3666/a>   3666/a>           (fopreassim_os a>[< mp; 36662a>               href="+code=p"quster_chchrv" class="sref">degister_chchrv" a>(ca href="+code=s"UND_STMAJO class="sref">SOUND_STMAJO a>) ,span class="string">"miund_cuot;, , mp;found_cre.cpps" a>,
) == -1)  3666/a>                if href="+code=fopng"tkclass="sref">chpng"tka>(ca href="+code=s"KERN_ER class="sref">SOKERN_ER a> *< an class="string">"miund_cre.c:ound device byalquldyuinpuse.\nuot;, { 3666/a>                  turn chEBUSYa>,
 3666/a>           3666/a>
 3666/a>          turn  3666/a>
< 3666/a>
 376  #end (< an class="comment"> *
 3767/a>


p/div>


e aloriginal LXRounftwareeby e mi href="sohttp:/oundrceforge.net/projects/lxc">LXRommenit" ya>) ,sthis experint">al versnslxc@ne"ux.noa>) .
p/div>

lxc.ne"ux.no kindcy hoed, oby  href="sohttp:/owww.redpill-ne"pro.no">Redpill Le"pro ASa>) ,sprovid toofhLe"ux nst ultg elsnd erations foserce bfosince 1995.
p/div>