linux-old/drivers/sound/sound_core.c
<<
>>
Prefs
   1/*
   2 *      Sound core handling. Breaks out sound functions to submodules
   3 *      
   4 *      Author:         Alan Cox <alan.cox@linux.org>
   5 *
   6 *      Fixes:
   7 *
   8 *
   9 *      This program is free software; you can redistribute it and/or
  10 *      modify it under the terms of the GNU General Public License
  11 *      as published by the Free Software Foundation; either version
  12 *      2 of the License, or (at your option) any later version.
  13 *
  14 *                         --------------------
  15 * 
  16 *      Top level handler for the sound subsystem. Various devices can
  17 *      plug into this. The fact they dont all go via OSS doesn't mean 
  18 *      they don't have to implement the OSS API. There is a lot of logic
  19 *      to keeping much of the OSS weight out of the code in a compatibility
  20 *      module, but its up to the driver to rember to load it...
  21 *
  22 *      The code provides a set of functions for registration of devices
  23 *      by type. This is done rather than providing a single call so that
  24 *      we can hide any future changes in the internals (eg when we go to
  25 *      32bit dev_t) from the modules and their interface.
  26 *
  27 *      Secondly we need to allocate the dsp, dsp16 and audio devices as
  28 *      one. Thus we misuse the chains a bit to simplify this.
  29 *
  30 *      Thirdly to make it more fun and for 2.3.x and above we do all
  31 *      of this using fine grained locking.
  32 *
  33 *      FIXME: we have to resolve modules and fine grained load/unload
  34 *      locking at some point in 2.3.x.
  35 */
  36
  37#include <linux/config.h>
  38#include <linux/module.h>
  39#include <linux/init.h>
  40#include <linux/slab.h>
  41#include <linux/types.h>
  42#include <linux/kernel.h>
  43#include <linux/fs.h>
  44#include <linux/sound.h>
  45#include <linux/major.h>
  46#include <linux/kmod.h>
  47#include <linux/devfs_fs_kernel.h>
  48
  49#define SOUND_STEP 16
  50
  51
  52struct sound_unit
  53{
  54        int unit_minor;
  55        struct file_operations *unit_fops;
  56        struct sound_unit *next;
  57        devfs_handle_t de;
  58};
  59
  60#ifdef CONFIG_SOUND_MSNDCLAS
  61extern int msnd_classic_init(void);
  62#endif
  63#ifdef CONFIG_SOUND_MSNDPIN
  64extern int msnd_pinnacle_init(void);
  65#endif
  66
  67/*
  68 *      Low level list operator. Scan the ordered list, find a hole and
  69 *      join into it. Called with the lock asserted
  70 */
  71
  72static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, struct file_operations *fops, int index, int low, int top)
  73{
  74        int n=low;
  75
  76        if (index < 0) {        /* first free */
  77
  78                while (*list && (*list)->unit_minor<n)
  79                        list=&((*list)->next);
  80
  81                while(n<top)
  82                {
  83                        /* Found a hole ? */
  84                        if(*list==NULL || (*list)->unit_minor>n)
  85                                break;
  86                        list=&((*list)->next);
  87                        n+=SOUND_STEP;
  88                }
  89
  90                if(n>=top)
  91                        return -ENOENT;
  92        } else {
  93                n = low+(index*16);
  94                while (*list) {
  95                        if ((*list)->unit_minor==n)
  96                                return -EBUSY;
  97                        if ((*list)->unit_minor>n)
  98                                break;
  99                        list=&((*list)->next);
 100                }
 101        }       
 102                
 103        /*
 104         *      Fill it in
 105         */
 106         
 107        s->unit_minor=n;
 108        s->unit_fops=fops;
 109        
 110        /*
 111         *      Link it
 112         */
 113         
 114        s->next=*list;
 115        *list=s;
 116        
 117        
 118        MOD_INC_USE_COUNT;
 119        return n;
 120}
 121
 122/*
 123 *      Remove a node from the chain. Called with the lock asserted
 124 */
 125 
 126static void __sound_remove_unit(struct sound_unit **list, int unit)
 127{
 128        while(*list)
 129        {
 130                struct sound_unit *p=*list;
 131                if(p->unit_minor==unit)
 132                {
 133                        *list=p->next;
 134                        devfs_unregister (p->de);
 135                        kfree(p);
 136                        MOD_DEC_USE_COUNT;
 137                        return;
 138                }
 139                list=&(p->next);
 140        }
 141        printk(KERN_ERR "Sound device %d went missing!\n", unit);
 142}
 143
 144/*
 145 *      This lock guards the sound loader list.
 146 */
 147
 148static spinlock_t sound_loader_lock = SPIN_LOCK_UNLOCKED;
 149
 150/*
 151 *      Allocate the controlling structure and add it to the sound driver
 152 *      list. Acquires locks as needed
 153 */
 154
 155static devfs_handle_t devfs_handle;
 156 
 157static int sound_insert_unit(struct sound_unit **list, struct file_operations *fops, int index, int low, int top, const char *name, umode_t mode)
 158{
 159        int r;
 160        struct sound_unit *s=(struct sound_unit *)kmalloc(sizeof(struct sound_unit), GFP_KERNEL);
 161        char name_buf[16];
 162
 163        if(s==NULL)
 164                return -ENOMEM;
 165                
 166        spin_lock(&sound_loader_lock);
 167        r=__sound_insert_unit(s,list,fops,index,low,top);
 168        spin_unlock(&sound_loader_lock);
 169        
 170        if(r<0)
 171        {
 172                kfree(s);
 173                return r;
 174        }
 175        
 176        if (r == low)
 177                sprintf (name_buf, "%s", name);
 178        else
 179                sprintf (name_buf, "%s%d", name, (r - low) / SOUND_STEP);
 180        s->de = devfs_register (devfs_handle, name_buf,
 181                                DEVFS_FL_NONE, SOUND_MAJOR, s->unit_minor,
 182                                S_IFCHR | mode, fops, NULL);
 183        return r;
 184}
 185
 186/*
 187 *      Remove a unit. Acquires locks as needed. The drivers MUST have
 188 *      completed the removal before their file operations become
 189 *      invalid.
 190 */
 191        
 192static void sound_remove_unit(struct sound_unit **list, int unit)
 193{
 194        spin_lock(&sound_loader_lock);
 195        __sound_remove_unit(list, unit);
 196        spin_unlock(&sound_loader_lock);
 197}
 198
 199/*
 200 *      Allocations
 201 *
 202 *      0       *16             Mixers
 203 *      1       *8              Sequencers
 204 *      2       *16             Midi
 205 *      3       *16             DSP
 206 *      4       *16             SunDSP
 207 *      5       *16             DSP16
 208 *      6       --              sndstat (obsolete)
 209 *      7       *16             unused
 210 *      8       --              alternate sequencer (see above)
 211 *      9       *16             raw synthesizer access
 212 *      10      *16             unused
 213 *      11      *16             unused
 214 *      12      *16             unused
 215 *      13      *16             unused
 216 *      14      *16             unused
 217 *      15      *16             unused
 218 */
 219
 220static struct sound_unit *chains[16];
 221
 222/**
 223 *      register_sound_special - register a special sound node
 224 *      @fops: File operations for the driver
 225 *      @unit: Unit number to allocate
 226 *
 227 *      Allocate a special sound device by minor number from the sound
 228 *      subsystem. The allocated number is returned on succes. On failure
 229 *      a negative error code is returned.
 230 */
 231 
 232int register_sound_special(struct file_operations *fops, int unit)
 233{
 234        char *name;
 235
 236        switch (unit) {
 237            case 0:
 238                name = "mixer";
 239                break;
 240            case 1:
 241                name = "sequencer";
 242                break;
 243            case 2:
 244                name = "midi00";
 245                break;
 246            case 3:
 247                name = "dsp";
 248                break;
 249            case 4:
 250                name = "audio";
 251                break;
 252            case 5:
 253                name = "unknown5";
 254                break;
 255            case 6:             /* Was once sndstat */
 256                name = "unknown6";
 257                break;
 258            case 7:
 259                name = "unknown7";
 260                break;
 261            case 8:
 262                name = "sequencer2";
 263                break;
 264            case 9:
 265                name = "dmmidi";
 266                break;
 267            case 10:
 268                name = "dmfm";
 269                break;
 270            case 11:
 271                name = "unknown11";
 272                break;
 273            case 12:
 274                name = "adsp";
 275                break;
 276            case 13:
 277                name = "amidi";
 278                break;
 279            case 14:
 280                name = "admmidi";
 281                break;
 282            default:
 283                name = "unknown";
 284                break;
 285        }
 286        return sound_insert_unit(&chains[unit&15], fops, -1, unit, unit+1,
 287                                 name, S_IRUSR | S_IWUSR);
 288}
 289 
 290EXPORT_SYMBOL(register_sound_special);
 291
 292/**
 293 *      register_sound_mixer - register a mixer device
 294 *      @fops: File operations for the driver
 295 *      @dev: Unit number to allocate
 296 *
 297 *      Allocate a mixer device. Unit is the number of the mixer requested.
 298 *      Pass -1 to request the next free mixer unit. On success the allocated
 299 *      number is returned, on failure a negative error code is returned.
 300 */
 301
 302int register_sound_mixer(struct file_operations *fops, int dev)
 303{
 304        return sound_insert_unit(&chains[0], fops, dev, 0, 128,
 305                                 "mixer", S_IRUSR | S_IWUSR);
 306}
 307
 308EXPORT_SYMBOL(register_sound_mixer);
 309
 310/**
 311 *      register_sound_midi - register a midi device
 312 *      @fops: File operations for the driver
 313 *      @dev: Unit number to allocate
 314 *
 315 *      Allocate a midi device. Unit is the number of the midi device requested.
 316 *      Pass -1 to request the next free midi unit. On success the allocated
 317 *      number is returned, on failure a negative error code is returned.
 318 */
 319
 320int register_sound_midi(struct file_operations *fops, int dev)
 321{
 322        return sound_insert_unit(&chains[2], fops, dev, 2, 130,
 323                                 "midi", S_IRUSR | S_IWUSR);
 324}
 325
 326EXPORT_SYMBOL(register_sound_midi);
 327
 328/*
 329 *      DSP's are registered as a triple. Register only one and cheat
 330 *      in open - see below.
 331 */
 332 
 333/**
 334 *      register_sound_dsp - register a DSP device
 335 *      @fops: File operations for the driver
 336 *      @dev: Unit number to allocate
 337 *
 338 *      Allocate a DSP device. Unit is the number of the DSP requested.
 339 *      Pass -1 to request the next free DSP unit. On success the allocated
 340 *      number is returned, on failure a negative error code is returned.
 341 *
 342 *      This function allocates both the audio and dsp device entries together
 343 *      and will always allocate them as a matching pair - eg dsp3/audio3
 344 */
 345
 346int register_sound_dsp(struct file_operations *fops, int dev)
 347{
 348        return sound_insert_unit(&chains[3], fops, dev, 3, 131,
 349                                 "dsp", S_IWUSR | S_IRUSR);
 350}
 351
 352EXPORT_SYMBOL(register_sound_dsp);
 353
 354/**
 355 *      register_sound_synth - register a synth device
 356 *      @fops: File operations for the driver
 357 *      @dev: Unit number to allocate
 358 *
 359 *      Allocate a synth device. Unit is the number of the synth device requested.
 360 *      Pass -1 to request the next free synth unit. On success the allocated
 361 *      number is returned, on failure a negative error code is returned.
 362 */
 363
 364
 365int register_sound_synth(struct file_operations *fops, int dev)
 366{
 367        return sound_insert_unit(&chains[9], fops, dev, 9, 137,
 368                                 "synth", S_IRUSR | S_IWUSR);
 369}
 370
 371EXPORT_SYMBOL(register_sound_synth);
 372
 373/**
 374 *      unregister_sound_special - unregister a special sound device
 375 *      @unit: unit number to allocate
 376 *
 377 *      Release a sound device that was allocated with
 378 *      register_sound_special(). The unit passed is the return value from
 379 *      the register function.
 380 */
 381
 382
 383void unregister_sound_special(int unit)
 384{
 385        sound_remove_unit(&chains[unit&15], unit);
 386}
 387 
 388EXPORT_SYMBOL(unregister_sound_special);
 389
 390/**
 391 *      unregister_sound_mixer - unregister a mixer
 392 *      @unit: unit number to allocate
 393 *
 394 *      Release a sound device that was allocated with register_sound_mixer().
 395 *      The unit passed is the return value from the register function.
 396 */
 397
 398void unregister_sound_mixer(int unit)
 399{
 400        sound_remove_unit(&chains[0], unit);
 401}
 402
 403EXPORT_SYMBOL(unregister_sound_mixer);
 404
 405/**
 406 *      unregister_sound_midi - unregister a midi device
 407 *      @unit: unit number to allocate
 408 *
 409 *      Release a sound device that was allocated with register_sound_midi().
 410 *      The unit passed is the return value from the register function.
 411 */
 412
 413void unregister_sound_midi(int unit)
 414{
 415        return sound_remove_unit(&chains[2], unit);
 416}
 417
 418EXPORT_SYMBOL(unregister_sound_midi);
 419
 420/**
 421 *      unregister_sound_dsp - unregister a DSP device
 422 *      @unit: unit number to allocate
 423 *
 424 *      Release a sound device that was allocated with register_sound_dsp().
 425 *      The unit passed is the return value from the register function.
 426 *
 427 *      Both of the allocated units are released together automatically.
 428 */
 429
 430void unregister_sound_dsp(int unit)
 431{
 432        return sound_remove_unit(&chains[3], unit);
 433}
 434
 435
 436EXPORT_SYMBOL(unregister_sound_dsp);
 437
 438/**
 439 *      unregister_sound_synth - unregister a synth device
 440 *      @unit: unit number to allocate
 441 *
 442 *      Release a sound device that was allocated with register_sound_synth().
 443 *      The unit passed is the return value from the register function.
 444 */
 445
 446void unregister_sound_synth(int unit)
 447{
 448        return sound_remove_unit(&chains[9], unit);
 449}
 450
 451EXPORT_SYMBOL(unregister_sound_synth);
 452
 453/*
 454 *      Now our file operations
 455 */
 456
 457static int soundcore_open(struct inode *, struct file *);
 458
 459static struct file_operations soundcore_fops=
 460{
 461        /* We must have an owner or the module locking fails */
 462        owner:  THIS_MODULE,
 463        open:   soundcore_open,
 464};
 465
 466static struct sound_unit *__look_for_unit(int chain, int unit)
 467{
 468        struct sound_unit *s;
 469        
 470        s=chains[chain];
 471        while(s && s->unit_minor <= unit)
 472        {
 473                if(s->unit_minor==unit)
 474                        return s;
 475                s=s->next;
 476        }
 477        return NULL;
 478}
 479
 480int soundcore_open(struct inode *inode, struct file *file)
 481{
 482        int chain;
 483        int unit=MINOR(inode->i_rdev);
 484        struct sound_unit *s;
 485        struct file_operations *new_fops = NULL;
 486
 487        chain=unit&0x0F;
 488        if(chain==4 || chain==5)        /* dsp/audio/dsp16 */
 489        {
 490                unit&=0xF0;
 491                unit|=3;
 492                chain=3;
 493        }
 494        
 495        spin_lock(&sound_loader_lock);
 496        s = __look_for_unit(chain, unit);
 497        if (s)
 498                new_fops = fops_get(s->unit_fops);
 499        if (!new_fops) {
 500                char mod[32];
 501        
 502                spin_unlock(&sound_loader_lock);
 503                /*
 504                 *  Please, don't change this order or code.
 505                 *  For ALSA slot means soundcard and OSS emulation code
 506                 *  comes as add-on modules which aren't depend on
 507                 *  ALSA toplevel modules for soundcards, thus we need
 508                 *  load them at first.   [Jaroslav Kysela <perex@jcu.cz>]
 509                 */
 510                sprintf(mod, "sound-slot-%i", unit>>4);
 511                request_module(mod);
 512                sprintf(mod, "sound-service-%i-%i", unit>>4, chain);
 513                request_module(mod);
 514                spin_lock(&sound_loader_lock);
 515                s = __look_for_unit(chain, unit);
 516                if (s)
 517                        new_fops = fops_get(s->unit_fops);
 518        }
 519        if (new_fops) {
 520                /*
 521                 * We rely upon the fact that we can't be unloaded while the
 522                 * subdriver is there, so if ->open() is successful we can
 523                 * safely drop the reference counter and if it is not we can
 524                 * revert to old ->f_op. Ugly, indeed, but that's the cost of
 525                 * switching ->f_op in the first place.
 526                 */
 527                int err = 0;
 528                struct file_operations *old_fops = file->f_op;
 529                file->f_op = new_fops;
 530                spin_unlock(&sound_loader_lock);
 531                if(file->f_op->open)
 532                        err = file->f_op->open(inode,file);
 533                if (err) {
 534                        fops_put(file->f_op);
 535                        file->f_op = fops_get(old_fops);
 536                }
 537                fops_put(old_fops);
 538                return err;
 539        }
 540        spin_unlock(&sound_loader_lock);
 541        return -ENODEV;
 542}
 543
 544extern int mod_firmware_load(const char *, char **);
 545EXPORT_SYMBOL(mod_firmware_load);
 546
 547
 548MODULE_DESCRIPTION("Core sound module");
 549MODULE_AUTHOR("Alan Cox");
 550MODULE_LICENSE("GPL");
 551
 552static void __exit cleanup_soundcore(void)
 553{
 554        /* We have nothing to really do here - we know the lists must be
 555           empty */
 556        devfs_unregister_chrdev(SOUND_MAJOR, "sound");
 557        devfs_unregister (devfs_handle);
 558}
 559
 560static int __init init_soundcore(void)
 561{
 562        if(devfs_register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops)==-1)
 563        {
 564                printk(KERN_ERR "soundcore: sound device already in use.\n");
 565                return -EBUSY;
 566        }
 567        devfs_handle = devfs_mk_dir (NULL, "sound", NULL);
 568
 569        return 0;
 570}
 571
 572module_init(init_soundcore);
 573module_exit(cleanup_soundcore);
 574