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.
 150 */
 151#ifdef CONFIG_SOUND_OSS_CORE_PRECLAIM
 152static int preclaim_oss = 1;
 153#else
 154static int preclaim_oss = 0;
 155#endif
 156
 157module_param(preclaim_oss, int, 0444);
 158
 159static int soundcore_open(struct inode *, struct file *);
 160
 161static const struct file_operations soundcore_fops =
 162{
 163        /* We must have an owner or the module locking fails */
 164        .owner  = THIS_MODULE,
 165        .open   = soundcore_open,
 166        .llseek = noop_llseek,
 167};
 168
 169/*
 170 *      Low level list operator. Scan the ordered list, find a hole and
 171 *      join into it. Called with the lock asserted
 172 */
 173
 174static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, const struct file_operations *fops, int index, int low, int top)
 175{
 176        int n=low;
 177
 178        if (index < 0) {        /* first free */
 179
 180                while (*list && (*list)->unit_minor<n)
 181                        list=&((*list)->next);
 182
 183                while(n<top)
 184                {
 185                        /* Found a hole ? */
 186                        if(*list==NULL || (*list)->unit_minor>n)
 187                                break;
 188                        list=&((*list)->next);
 189                        n+=SOUND_STEP;
 190                }
 191
 192                if(n>=top)
 193                        return -ENOENT;
 194        } else {
 195                n = low+(index*16);
 196                while (*list) {
 197                        if ((*list)->unit_minor==n)
 198                                return -EBUSY;
 199                        if ((*list)->unit_minor>n)
 200                                break;
 201                        list=&((*list)->next);
 202                }
 203        }       
 204                
 205        /*
 206         *      Fill it in
 207         */
 208         
 209        s->unit_minor=n;
 210        s->unit_fops=fops;
 211        
 212        /*
 213         *      Link it
 214         */
 215         
 216        s->next=*list;
 217        *list=s;
 218        
 219        
 220        return n;
 221}
 222
 223/*
 224 *      Remove a node from the chain. Called with the lock asserted
 225 */
 226 
 227static struct sound_unit *__sound_remove_unit(struct sound_unit **list, int unit)
 228{
 229        while(*list)
 230        {
 231                struct sound_unit *p=*list;
 232                if(p->unit_minor==unit)
 233                {
 234                        *list=p->next;
 235                        return p;
 236                }
 237                list=&(p->next);
 238        }
 239        printk(KERN_ERR "Sound device %d went missing!\n", unit);
 240        return NULL;
 241}
 242
 243/*
 244 *      This lock guards the sound loader list.
 245 */
 246
 247static DEFINE_SPINLOCK(sound_loader_lock);
 248
 249/*
 250 *      Allocate the controlling structure and add it to the sound driver
 251 *      list. Acquires locks as needed
 252 */
 253
 254static 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)
 255{
 256        struct sound_unit *s = kmalloc(sizeof(*s), GFP_KERNEL);
 257        int r;
 258
 259        if (!s)
 260                return -ENOMEM;
 261
 262        spin_lock(&sound_loader_lock);
 263retry:
 264        r = __sound_insert_unit(s, list, fops, index, low, top);
 265        spin_unlock(&sound_loader_lock);
 266        
 267        if (r < 0)
 268                goto fail;
 269        else if (r < SOUND_STEP)
 270                sprintf(s->name, "sound/%s", name);
 271        else
 272                sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
 273
 274        if (!preclaim_oss) {
 275                /*
 276                 * Something else might have grabbed the minor.  If
 277                 * first free slot is requested, rescan with @low set
 278                 * to the next unit; otherwise, -EBUSY.
 279                 */
 280                r = __register_chrdev(SOUND_MAJOR, s->unit_minor, 1, s->name,
 281                                      &soundcore_fops);
 282                if (r < 0) {
 283                        spin_lock(&sound_loader_lock);
 284                        __sound_remove_unit(list, s->unit_minor);
 285                        if (index < 0) {
 286                                low = s->unit_minor + SOUND_STEP;
 287                                goto retry;
 288                        }
 289                        spin_unlock(&sound_loader_lock);
 290                        return -EBUSY;
 291                }
 292        }
 293
 294        device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
 295                      NULL, s->name+6);
 296        return s->unit_minor;
 297
 298fail:
 299        kfree(s);
 300        return r;
 301}
 302
 303/*
 304 *      Remove a unit. Acquires locks as needed. The drivers MUST have
 305 *      completed the removal before their file operations become
 306 *      invalid.
 307 */
 308        
 309static void sound_remove_unit(struct sound_unit **list, int unit)
 310{
 311        struct sound_unit *p;
 312
 313        spin_lock(&sound_loader_lock);
 314        p = __sound_remove_unit(list, unit);
 315        spin_unlock(&sound_loader_lock);
 316        if (p) {
 317                if (!preclaim_oss)
 318                        __unregister_chrdev(SOUND_MAJOR, p->unit_minor, 1,
 319                                            p->name);
 320                device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor));
 321                kfree(p);
 322        }
 323}
 324
 325/*
 326 *      Allocations
 327 *
 328 *      0       *16             Mixers
 329 *      1       *8              Sequencers
 330 *      2       *16             Midi
 331 *      3       *16             DSP
 332 *      4       *16             SunDSP
 333 *      5       *16             DSP16
 334 *      6       --              sndstat (obsolete)
 335 *      7       *16             unused
 336 *      8       --              alternate sequencer (see above)
 337 *      9       *16             raw synthesizer access
 338 *      10      *16             unused
 339 *      11      *16             unused
 340 *      12      *16             unused
 341 *      13      *16             unused
 342 *      14      *16             unused
 343 *      15      *16             unused
 344 */
 345
 346static struct sound_unit *chains[SOUND_STEP];
 347
 348/**
 349 *      register_sound_special_device - register a special sound node
 350 *      @fops: File operations for the driver
 351 *      @unit: Unit number to allocate
 352 *      @dev: device pointer
 353 *
 354 *      Allocate a special sound device by minor number from the sound
 355 *      subsystem. The allocated number is returned on success. On failure
 356 *      a negative error code is returned.
 357 */
 358 
 359int register_sound_special_device(const struct file_operations *fops, int unit,
 360                                  struct device *dev)
 361{
 362        const int chain = unit % SOUND_STEP;
 363        int max_unit = 256;
 364        const char *name;
 365        char _name[16];
 366
 367        switch (chain) {
 368            case 0:
 369                name = "mixer";
 370                break;
 371            case 1:
 372                name = "sequencer";
 373                if (unit >= SOUND_STEP)
 374                        goto __unknown;
 375                max_unit = unit + 1;
 376                break;
 377            case 2:
 378                name = "midi";
 379                break;
 380            case 3:
 381                name = "dsp";
 382                break;
 383            case 4:
 384                name = "audio";
 385                break;
 386            case 5:
 387                name = "dspW";
 388                break;
 389            case 8:
 390                name = "sequencer2";
 391                if (unit >= SOUND_STEP)
 392                        goto __unknown;
 393                max_unit = unit + 1;
 394                break;
 395            case 9:
 396                name = "dmmidi";
 397                break;
 398            case 10:
 399                name = "dmfm";
 400                break;
 401            case 12:
 402                name = "adsp";
 403                break;
 404            case 13:
 405                name = "amidi";
 406                break;
 407            case 14:
 408                name = "admmidi";
 409                break;
 410            default:
 411                {
 412                    __unknown:
 413                        sprintf(_name, "unknown%d", chain);
 414                        if (unit >= SOUND_STEP)
 415                                 414               usef="+code=str5="L414"> 414            class="s               {
p) {
4recla4m_oss)
u4it_mi4or, 1,
        
 254 315   tic struct (s, s *fops<4f="+code=4nit_minor" class="sref">4nit_m4nor));
, |ound/sound_core.S_IWUS_class, device_create( 414   f">kfree<4a>(p4322     pan>
/*device_crEXPORT_SYMBOd="L295" class="EXPORT_SYMBOd 415            /sound_core.c#L359" id="L359" class="line" name="L359"> 359int  414   fef="+code="L324" class="line" nam4="L3242*/
 325 359intf="+code=register_sound_special_device" class="sref">register_sound_special_device(const struct file_operations *unit >=  *      A4locat4ons 327 359int s * 414   f=  *     41       *8              4equen4ersdevice_crEXPORT_SYMBOd="L295" class="EXPORT_SYMBOd 415            /sound_core.c#L359" id class="line" name="L359"> 359intf="+ef="+code=str5="L414"> 414   comment">4*      3       *16      4     43f">p;
 * 4    4       *16         4   Su4DSP
 *4     5       *16        4    D4P16
 359     e" name="L349"     e 3504ment"> * 4    7       *16         4   un4sed
 351 351
 356 * 4    10      *16         4   un4sed
 356 * 4    11      *16         4   un4sed
 35lass="ce.c#L356" id="L356" class="line" name="L356"> 356 * 4    12      *16         4   un4sed
 * 4    13      *16         4   un4> 241}
 * 4    14      *16         4   un4sed 
 359/a   f="+code=register_sound_special_device" class="sref">register_sound_special_device(const struct fi            struct d4ment"> * 4    15      *16         4   un4sed 254 315   tic struct s, fi            struct fops<4c#L345" i4="L345" class="line" nam4="L3444< 0) {
 369                device_cr" id="L295" class="line" naef="+code=str5="L414"> 414   ef="+code4SOUND_STEP" class="sref"4SOUND4STEP);
 348device_crEXPORT_SYMBOd="L295" class="EXPORT_SYMBOd 415            /sound_core.c#L/a    class="line" name="L359"> 359/a   f="+ef="+code=str5="L414"> 414   ecial_dev4ce - register a special 4ound 45rs * 4    @unit: Unit number t4 allo4ate
 359/adie" name="L349"  die *      @dev: devi4e poi4ter
 3504name="L354"> 353 351 351
 356 *     4a negative error code is4retur4ed.
 356 357
 35lass="ce.c#L356" id="L356" class="line" name="L356"> 356
, int <4 href="+code=unit" class4"sref46rsdev 
 359/aline"+code=register_sound_special_device" class="sref">register_sound_special_device(const struct fi            struct d4#L361" id4"L361" class="line" name4"L3614> 361 254 315   tic struct s, fi            struct fops<4f="+code=4ax_unit" class="sref">ma4_unit46ain);
 369             , |ound/sound_core.S_IWUS_class, device_cr" id="L295" class="line" naef="+code=str5="L414"> 414   t char *<4 href="+code=name" class4"sref4>name<   }
_na4e[16];
 366pref">device_crEXPORT_SYMBOd="L295" class="EXPORT_SYMBOd 415            /sound_core.c#L/adi class="line" name="L359"> 359/aline"+ef="+code=str5="L414"> 414   tme="L3574f="+code=chain" class="s4ef">c46ock);
 368  4     46ed
 = "mi4er&qu47ed
                 * first4s="line" 4ame="L370"> 370     4     47er
 356 371  4     47te
"sequen4er&qu47     pan>
__u47e)
 359dspe" name="L349"DSPe = un4>/*
 3504s="line" 4ame="L376"> 376     4     4 If
 351 377  4     4set
"m4di&qu4SY.
 356 379     4     48ed
 356 380  4     48er
 35lass="ce.c#L356" id="L356" class="line" name="L356"> 356"4sp&qu48te
 356 382     4     48er
 356 383  4     48 *
 356"au4io&qu48e)
 385     4     48[16];
 386  4     4   cas/a> 
 359dspne"+code=register_sound_special_device" class="sref">register_sound_special_device(const struct fi            struct d4/a> = "d4pW&qu4t; 388     4     4    break;
 254 315   tic struct s, fi            struct p-> 389  4     4lock);
 369               , |ound/sound_core.S_IRUS_class, device_cr" id="L295" class="line" naef="+code=str5="L414"> 414   "sequenc4r2&qu49f">r;
__u4knowndevice_crEXPORT_SYMBOd="L295" class="EXPORT_SYMBOd 415            /sound_core.c#Ldsp class="line" name="L359"> 359dspne"+ef="+code=str5="L414"> 414   un49 323}
 394     4     49> 324
 356 395  4     49/*
    id="L354" class="line"me="L356"> 356"dmm4di&qu49If
 351 397     4     49et
 398   4     49Y.
 = "d5fm&qu50ed
 = "sequenc5     50er
    func" clame="L356"> 356 401   5     50te
 = "a5sp&qu50        }
 403     5     50 323}
 404   5     5  case href="sound/sound_c318     class="L354"perations * 359intf="+cns" class="sref">file_operations *unit >=  = "am5di&qu5t; 406     5     5    break;
 309 315   tic struct chain = (li5ass="line5 name="L407"> 407   5     5  case/a>;
"admm5di&qu5t;;
 409     5     5    brpref">device_crEXPORT_SYMBOd="L295" class="EXPORT_SYMBOd 415            318     class="L354"perations * 359intf="+ref="+code=list" class="sref">li5ass="line5 name="L410"> 410   5     5  defaf="+code=list" class="sref">li5ass="line5ne" name="L411"> 4115     51te
 356__u51er
 359     e" 318    id/a   f=="L356"> 35651 *
 351 351
 359     ()i" name="L351"> 351
    func" clame="L356"> 3565recla51et
u5it_mi5or#L357" id="L357" class="line" 5a>->     href="sound/sound_c318     class/a    class="line" n318     class/a   f="+cns" class="sref">file_operations *unit >= 5nit_m52>dev)
kfree<5a>(p);
 309 315   tic struct (li5ahref="+c5lass="line" name="L322">5322        }
 323}
 324device_crEXPORT_SYMBOd="L295" class="EXPORT_SYMBOd 415            318     class/a    class="line" n318     class/a   f="+ref="+code=list" class="sref">li5a        5"> 325 *      A5locat5ons
 356 327     class/adie" 318    id/adie
 351 *     51       *8              5equen5ers
 351
 359  di()i" name="L351"> 3515*      3       *16      5     5DSP
    func" clame="L356"> 356 * 5    4       *16         5   Su5DSP
 *5     5       *16        5    D53 323}
     class/adif="+cns" class="sref">file_operations *unit >=  * 5    7       *16         5   un53; 309 315   tic struct (li5 ame="L325            raw synthesi5er ac53 case/a>;
 * 5    10      *16         5   un53r#L357" id="L357" class="line" 5ment"> * 5    11      *16         5   un54   brpref">device_crEXPORT_SYMBOd="L295" class="EXPORT_SYMBOd 415            318     class/adi class="line" n318     class/adif="+ref="+code=list" class="sref">li5ment"> * 5    12      *16         5   un54 defaf="+code=list" class="sref">li5ment"> * 5    13      *16         5   un5sed
 356 * 5    14      *16         5   un5sed
    idDSPe * 5    15      *16         5   un5sed
 351 344
 351 359dsp()i" name="L351"> 351
    func" clame="L356"> 356 347
 351 * 5> 348

<55"yame="L356"> 356li5ment"> * 5    @unit: Unit number t5 allo5ate     classdspf="+cns" class="sref">file_operations *unit >=  *      @dev: devi5e poi5terfile_operatiname="L35554"> 353 309 315   tic struct  414 5 from4the5s4und
l44" cl"L351" of 276chains[ * 5    11      *16         5   un54   brpref">device_"> * 5    @unit: Unit number t5 allo5ate;

 345
__look_for#L345" id="L345" cla__look_for#L345te 254 315register_sound_special_device(const struct 5ations" c5ass="sref">fi           5struc5f">dev)
 345
cial_device 361fi            struct 5a hre56terfilial_device 254 315 tic struct filial_devicech>register_sound_spe_"commcial_device(con_"comma>);
(const struct 5a4" cl"L35f4"+code=_name" class="s5e4">_56ine" name=      ch>register_sound_spe_"commcial_device(con_"comma>(const struct ch>register_sound> 37ial_device 37a> 414 5de" na 365ple.5Rame="L34only4once.5d che5sound/sound_cond_core.c#L411" id="L4hr_IWUS_r|ound/sound_co tic struct  414 5a>  4    547te
"seque54er&q547    /span>
ref">register_sound7" clss="L3594"> 254 254 345
comde"> 254 
 254 345
nd_c"> 2545ame="L3595> 359dspe" name="L349"DS5e 254 315register_sound_special_device(const s
i"comma> 254 345
cial_device 359dspne"+code=register_snew_4"> 254 new_4"> st s
 254 315(const svice<0x0F tic struct  254 315          "L254"> 254 3155L278"5   5e.nd dspe(const svice<=0xF0 tic struct (const s|=3 tic struct 
 254 315 385   5 4   5f="sound/soundef="+code=str5="L414"> 414 5ations" c5ass="sref">fi           5struc5 414 5aa>  4   54n class="string">"54pW&q54t; 345
cpin_lockial_device loader_lockial_device loader_lockname  tic struct fi            struct 5a hre5 3, 13p" class      5   un54 lial_device 254 315 309 315   tic struct device_cr" id="L295" cl5ss="l5f="+code=name"quot;, "sequen54r2&q5=unit" class="sref">uncode=register_snew_4"> 254 new_4"> st s
 _ge309 4"> _ge3tech>register_sound_spe_4"> 254 _spe_4"> /a>   tic struct  preOUNim_os a> 254 new_4"> st s)oef="+code=device" class="sref">5ore.c#Lds5 class="line" name="L3595> 3595code=max_unit" class="L345"> 345
cpin_unlockial_device loader_lockial_device loader_lockname  tic struct 59ef="+ef="+code=str5="L414"> 4145    4    549> 324
);
 3685"L354" -e518    id="L354" clas5="lin5"me="L356"> 356 = t "> ngclasis ordi&qur 351  4   5 49et
 = t depen4 ound/sound_corePhree-s cla" name=L278" 6id="L3u i6=phress=i44" clhref="sva6ue4_core.c#L348" id="L348" classsssssssssssssss*  load3"> 383t first.sss[Jaroslav Kysela vlch59"ex@jcu.cz">ch]nd/sound_corePhree-s cla" name=L278" 6i2="L3u i6=s="string">"sequen6nc" c6ame="L356"> 356 38regis-slot-a>   ">ma4_unit46ain);
 = <6p5n class="string">"6a5sp&6sound/sound_core.ce" c/8pecial_device 4ame="_moduleial_device 38regis-ser5" c-a>   "-a>   ">ma4_unit46ain);
sprintf( 403   6 5   60ef="+ef="+code=str5="L414"> 4146+cns" cla6s="sref">file_operations6/a> *6a href="+code=name" clL/a>);
 36865a> = "a65di&q60me="L356"> 356 =  351 368659> = 
 e> 382und_core4lass="lin4" name="L368"> 36865 = "adm65di&q61_core.c#L348" id="L348" classsssssssssssssss* Y. 36865d="L3u i6ons * 36961_core.c#L348" id="L348" classsssssssssssssss* transihref="sound/sound_core="L3u id=phress=i44"6i5ass="li6e5 name="L410"> 410 6 5   6 5  defaf="+code=list" classsssssssssssssssss*="commen5ecial_dev5ce - register a spe65    651te
 412     quot;,  38 clr-major-> 413<-> 413                         309 315  f">ch 0truct  359     e" 318   6id/a 6="string">"unknown%d&;,  38 clr-major-> 413                        sprintf( 4146"sref5>SO6N51nd
 345
cpin_lockial_device loader_lockial_device loader_lockname  tic struct  3596    (6line" name=       254 315 309 315   tic struct e" clhr/a>    f6nc" c6ref="so   }
5recl651et
 254 new_4"> st s
 _ge309 4"> _ge3tech>register_sound_spe_4"> 254 _spe_4"> /a>   tic struct  414 6+cns" cla6s="sref">file_operations6/a> *62="+code=name"quot;,  254 new_4"> st s)oef="+code=device" class="sref">65f="+code65nit_minor" class="sref"65nit_62unit" class="sref">unc/a>);
 3686_0]>( 356 = t b5ef=loadedLwhile Y. 3686_ame="L3565lass="line" name="L322"65322<62f=ore.c#L348" id="L348" classsssssssssssssss* subss="srUND_STEre, re"quo-">ch3594()UND_d 3686_/sound_c6d5"L323" class="line" na6e5"L362" name="L351"> 351¬"le canund_core4lass="lin4" name="L368"> 3686_sref5>SO6ss="line" n318     c6ass/a62" name="L351"> 351chf_op. Ugly"sredeame=butlass=a> =  3686_as355" c6 5"> 325[16];
chf_oprst4Y.
 356    id/ad6eregister_soundermcial_deviceermst s
  cas/a> 
 359dspne"+code=register_sold_4"> 254 old_4"> st s
 254ch>register_soundf_op"> 254 254ch>register_soundf_op"> 254 254 new_4"> st s tic struct  356  di(63unit" class="sref">uncode=register_scpin_unlockial_device loader_lockial_device loader_lockname  tic struct e" clhr/a>    f6nc" c63_core.c#L357" id="L357" class="line6    5   S65DSP
"unknowquot;,  254ch>register_soundf_op"> 254ch>register_sound3594"> 2546*5     5       *16      6 5   63 href="+code=name" clsref">uncode=register_sermcial_deviceermst s
,  254ch>register_soundf_op"> 254ch>register_sound3594"> 254 254,  254file_operations6/a> *63 f="+ref="+code=list" class="sref">65ment"> *65    7       *16        65   u63ine" name=      , ermst s)oef="+code=device" class="sref">6_2]>( _pu309 4"> _pu3te 254ch>register_soundf_op"> 254 254ch>register_soundf_op"> 254 _ge309 4"> _ge3te 254 old_4"> st s  tic struct  6 5    10      *16       6 5   643, 13p" class="sref">ef="+code=str5="L414"> 414 6ass/adi c6ass="line" n318     6lass/6dif="+ref="+code=list" class="sref">6i5ment"> 6 5    12      *16       6 5   64unit" class="sref">uncode=register_s4"> _pu309 4"> _pu3te 254 old_4"> st s  tic struct 
 412     nd_core.c#L411" id="L4ermcial_deviceermst s tic struct     idDS6e&quoef="+code=str5="L414"> 414 6a5mment">6re.c#L351u id="L351" cla6s="li64sed loader_lockial_device loader_lockname  tic struct 
 *6class=witheame="L359"> 369dsp(6ne" naef="+code=str5="L414"> 414 6clhref="s6alue4e" clhr/a>    f6nc" c64STEP 347
sprintf( 4146ial 5ound65ode
 2546+cns" cla6s="sref">file_operations6/a> *65="L412"> 412 *      @dev: dev65e po6="L350"> 350 38regis/a>          ref">sprintf(
 414 644" cl"L361" of 276chains[register_sound__i345" id="L345" cla__ie" name=      5   un54 coit_os  t5 al 414"> 2546name4"L35645ed
,  preOUNim_os a>6nal 5ound6<4 href="+code=unit" cla6s4"sr661ne" name=      <;,  38regis/a>          , vicess="L4"> 254 414">ss="L4"> st s)o== -1)oef="+code=device" class="sref">6ations" c6ass="sref">fi           6struc66unit" class="sref">uncode=register_spe="tkial_device 38regis="sr:" i5="L345" clal 4rdyrst4use.\n/a>          ref">sprintf( 412     nd_core-/8pecial_deviceEBUSYial_devicefi            struct 6a hre66"string">&quoef="+code=str5="L414"> 414 64d/sound_6>device_cr" id="L295" cl6ss="l66ef="+ef="+code=str5="L414"> 4146 from4the64 href="+code=name" clas64"sre660, 128"+code=nd_core0 tic struct _66e" naef="+code=str5="L414"> 414 6 s" cla/a6class="line" name="L359"6 359/6line"+ef="+code=str5="L414"> 41464 nam5="L674f="+code=chain" class=6s4ef"6f="sou#endquofaf="+code=list" class=">CONFIG_ds="srOSS_COREs*="commen5ecial_dev5ce - register a spe6/a>  4   6 46ed

co5eoriginal LXR" iftwclasby Y.LXR"st" _spey5
lxr@>


lxr.>

Redpill L
  cault   4 n4<4f="+code=user5" c=usince 1995.
e/div>