root/drivers/sound/soundcard.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. snd_ioctl_return
  2. sound_read
  3. sound_write
  4. sound_lseek
  5. sound_open
  6. sound_release
  7. sound_ioctl
  8. sound_select
  9. soundcard_init
  10. free_all_irqs
  11. init_module
  12. cleanup_module
  13. tenmicrosec
  14. snd_set_irq_handler
  15. snd_release_irq
  16. request_sound_timer
  17. sound_stop_timer
  18. valid_dma_page
  19. add_to_dma_list
  20. module_sound_mem_init
  21. module_sound_mem_release
  22. sound_mem_init
  23. soundcard_init
  24. sound_mem_init
  25. module_sound_mem_init

   1 /*
   2  * linux/kernel/chr_drv/sound/soundcard.c
   3  *
   4  * Soundcard driver for Linux
   5  *
   6  * Copyright by Hannu Savolainen 1993
   7  *
   8  * Redistribution and use in source and binary forms, with or without
   9  * modification, are permitted provided that the following conditions are
  10  * met: 1. Redistributions of source code must retain the above copyright
  11  * notice, this list of conditions and the following disclaimer. 2.
  12  * Redistributions in binary form must reproduce the above copyright notice,
  13  * this list of conditions and the following disclaimer in the documentation
  14  * and/or other materials provided with the distribution.
  15  *
  16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  23  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26  * SUCH DAMAGE.
  27  *
  28  */
  29 /*
  30  * Created modular version by Peter Trattler (peter@sbox.tu-graz.ac.at)
  31  */
  32 
  33 #include "sound_config.h"
  34 
  35 #ifdef CONFIGURE_SOUNDCARD
  36 
  37 #include <linux/major.h>
  38 
  39 static int      soundcards_installed = 0;       /* Number of installed
  40 
  41                                                  * soundcards */
  42 static int      soundcard_configured = 0;
  43 
  44 static struct fileinfo files[SND_NDEVS];
  45 
  46 int
  47 snd_ioctl_return (int *addr, int value)
     /* [previous][next][first][last][top][bottom][index][help] */
  48 {
  49   if (value < 0)
  50     return value;
  51 
  52   PUT_WORD_TO_USER (addr, 0, value);
  53   return 0;
  54 }
  55 
  56 static int
  57 sound_read (struct inode *inode, struct file *file, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  58 {
  59   int             dev;
  60 
  61   dev = inode->i_rdev;
  62   dev = MINOR (dev);
  63 
  64   return sound_read_sw (dev, &files[dev], buf, count);
  65 }
  66 
  67 static int
  68 sound_write (struct inode *inode, struct file *file, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  69 {
  70   int             dev;
  71 
  72 #ifdef MODULE
  73   int             err;
  74 
  75 #endif
  76 
  77   dev = inode->i_rdev;
  78   dev = MINOR (dev);
  79 
  80   return sound_write_sw (dev, &files[dev], buf, count);
  81 }
  82 
  83 static int
  84 sound_lseek (struct inode *inode, struct file *file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
  85 {
  86   return RET_ERROR (EPERM);
  87 }
  88 
  89 static int
  90 sound_open (struct inode *inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
  91 {
  92   int             dev, retval;
  93   struct fileinfo tmp_file;
  94 
  95   dev = inode->i_rdev;
  96   dev = MINOR (dev);
  97 
  98   if (!soundcard_configured && dev != SND_DEV_CTL && dev != SND_DEV_STATUS)
  99     {
 100       printk ("SoundCard Error: The soundcard system has not been configured\n");
 101       return RET_ERROR (ENXIO);
 102     }
 103 
 104   tmp_file.mode = 0;
 105   tmp_file.filp = file;
 106 
 107   if ((file->f_flags & O_ACCMODE) == O_RDWR)
 108     tmp_file.mode = OPEN_READWRITE;
 109   if ((file->f_flags & O_ACCMODE) == O_RDONLY)
 110     tmp_file.mode = OPEN_READ;
 111   if ((file->f_flags & O_ACCMODE) == O_WRONLY)
 112     tmp_file.mode = OPEN_WRITE;
 113 
 114   if ((retval = sound_open_sw (dev, &tmp_file)) < 0)
 115     return retval;
 116 
 117 #ifdef MODULE
 118   MOD_INC_USE_COUNT;
 119 #endif
 120 
 121   memcpy ((char *) &files[dev], (char *) &tmp_file, sizeof (tmp_file));
 122   return retval;
 123 }
 124 
 125 static void
 126 sound_release (struct inode *inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 127 {
 128   int             dev;
 129 
 130   dev = inode->i_rdev;
 131   dev = MINOR (dev);
 132 
 133   sound_release_sw (dev, &files[dev]);
 134 #ifdef MODULE
 135   MOD_DEC_USE_COUNT;
 136 #endif
 137 }
 138 
 139 static int
 140 sound_ioctl (struct inode *inode, struct file *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 141              unsigned int cmd, unsigned long arg)
 142 {
 143   int             dev;
 144 
 145   dev = inode->i_rdev;
 146   dev = MINOR (dev);
 147 
 148   if (cmd & IOC_INOUT)
 149     {
 150       /*
 151          * Have to validate the address given by the process.
 152        */
 153       int             len, err;
 154 
 155       len = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
 156 
 157       if (cmd & IOC_IN)
 158         {
 159           if ((err = verify_area (VERIFY_READ, (void *) arg, len)) < 0)
 160             return err;
 161         }
 162 
 163       if (cmd & IOC_OUT)
 164         {
 165           if ((err = verify_area (VERIFY_WRITE, (void *) arg, len)) < 0)
 166             return err;
 167         }
 168 
 169     }
 170 
 171   return sound_ioctl_sw (dev, &files[dev], cmd, arg);
 172 }
 173 
 174 static int
 175 sound_select (struct inode *inode, struct file *file, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 176 {
 177   int             dev;
 178 
 179   dev = inode->i_rdev;
 180   dev = MINOR (dev);
 181 
 182   DEB (printk ("sound_select(dev=%d, type=0x%x)\n", dev, sel_type));
 183 
 184   switch (dev & 0x0f)
 185     {
 186 #ifndef EXCLUDE_SEQUENCER
 187     case SND_DEV_SEQ:
 188     case SND_DEV_SEQ2:
 189       return sequencer_select (dev, &files[dev], sel_type, wait);
 190       break;
 191 #endif
 192 
 193 #ifndef EXCLUDE_MIDI
 194     case SND_DEV_MIDIN:
 195       return MIDIbuf_select (dev, &files[dev], sel_type, wait);
 196       break;
 197 #endif
 198 
 199 #ifndef EXCLUDE_AUDIO
 200     case SND_DEV_DSP:
 201     case SND_DEV_DSP16:
 202     case SND_DEV_AUDIO:
 203       return audio_select (dev, &files[dev], sel_type, wait);
 204       break;
 205 #endif
 206 
 207     default:
 208       return 0;
 209     }
 210 
 211   return 0;
 212 }
 213 
 214 static struct file_operations sound_fops =
 215 {
 216   sound_lseek,
 217   sound_read,
 218   sound_write,
 219   NULL,                         /* sound_readdir */
 220   sound_select,
 221   sound_ioctl,
 222   NULL,
 223   sound_open,
 224   sound_release
 225 };
 226 
 227 long
 228 soundcard_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 229 {
 230 #ifndef MODULE
 231   register_chrdev (SOUND_MAJOR, "sound", &sound_fops);
 232 #endif
 233 
 234   soundcard_configured = 1;
 235 
 236   mem_start = sndtable_init (mem_start);        /* Initialize call tables and
 237                                                  * detect cards */
 238 
 239   if (!(soundcards_installed = sndtable_get_cardcount ()))
 240     return mem_start;           /* No cards detected */
 241 
 242 #ifndef EXCLUDE_AUDIO
 243   if (num_audiodevs)            /* Audio devices present */
 244     {
 245       mem_start = DMAbuf_init (mem_start);
 246       mem_start = audio_init (mem_start);
 247     }
 248 #endif
 249 
 250 #ifndef EXCLUDE_MIDI
 251   if (num_midis)
 252     mem_start = MIDIbuf_init (mem_start);
 253 #endif
 254 
 255 #ifndef EXCLUDE_SEQUENCER
 256   if (num_midis + num_synths)
 257     mem_start = sequencer_init (mem_start);
 258 #endif
 259 
 260   return mem_start;
 261 }
 262 
 263 #ifdef MODULE
 264 static unsigned long irqs = 0;
 265 void            snd_release_irq (int);
 266 static int      module_sound_mem_init (void);
 267 static void     module_sound_mem_release (void);
 268 
 269 static void
 270 free_all_irqs (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 271 {
 272   int             i;
 273 
 274   for (i = 0; i < 31; i++)
 275     if (irqs & (1ul << i))
 276       snd_release_irq (i);
 277   irqs = 0;
 278 }
 279 
 280 char            kernel_version[] = UTS_RELEASE;
 281 
 282 static long     memory_pool = 0;
 283 static int      memsize = 70 * 1024;
 284 static int      debugmem = 0;   /* switched off by default */
 285 
 286 int
 287 init_module (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 288 {
 289   long            lastbyte;
 290   int             err;
 291 
 292   printk ("sound: made modular by Peter Trattler (peter@sbox.tu-graz.ac.at)\n");
 293   err = register_chrdev (SOUND_MAJOR, "sound", &sound_fops);
 294   if (err)
 295     {
 296       printk ("sound: driver already loaded/included in kernel\n");
 297       return err;
 298     }
 299   memory_pool = (long) kmalloc (memsize, GFP_KERNEL);
 300   if (memory_pool == 0l)
 301     {
 302       unregister_chrdev (SOUND_MAJOR, "sound");
 303       return -ENOMEM;
 304     }
 305   lastbyte = soundcard_init (memory_pool);
 306   if (lastbyte > memory_pool + memsize)
 307     {
 308       printk ("sound: Not enough memory; use : 'insmod sound.o memsize=%ld'\n",
 309               lastbyte - memory_pool);
 310       kfree ((void *) memory_pool);
 311       unregister_chrdev (SOUND_MAJOR, "sound");
 312       free_all_irqs ();
 313       return -ENOMEM;
 314     }
 315   err = module_sound_mem_init ();
 316   if (err)
 317     {
 318       module_sound_mem_release ();
 319       kfree ((void *) memory_pool);
 320       unregister_chrdev (SOUND_MAJOR, "sound");
 321       free_all_irqs ();
 322       return err;
 323     }
 324   if (lastbyte < memory_pool + memsize)
 325     printk ("sound: (Suggestion) too much memory; use : 'insmod sound.o memsize=%ld'\n",
 326             lastbyte - memory_pool);
 327   return 0;
 328 }
 329 
 330 void
 331 cleanup_module (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 332 {
 333   if (MOD_IN_USE)
 334     printk ("sound: module busy -- remove delayed\n");
 335   else
 336     {
 337       kfree ((void *) memory_pool);
 338       unregister_chrdev (SOUND_MAJOR, "sound");
 339       free_all_irqs ();
 340       module_sound_mem_release ();
 341     }
 342 }
 343 
 344 #endif
 345 
 346 void
 347 tenmicrosec (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 348 {
 349   int             i;
 350 
 351   for (i = 0; i < 16; i++)
 352     inb (0x80);
 353 }
 354 
 355 int
 356 snd_set_irq_handler (int interrupt_level, INT_HANDLER_PROTO (), char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 357 {
 358   int             retcode;
 359 
 360   retcode = request_irq (interrupt_level, hndlr, SA_INTERRUPT, name);
 361   if (retcode < 0)
 362     {
 363       printk ("Sound: IRQ%d already in use\n", interrupt_level);
 364     }
 365 #ifdef MODULE
 366   else
 367     irqs |= (1ul << interrupt_level);
 368 #endif
 369 
 370   return retcode;
 371 }
 372 
 373 void
 374 snd_release_irq (int vect)
     /* [previous][next][first][last][top][bottom][index][help] */
 375 {
 376 #ifdef MODULE
 377   irqs &= ~(1ul << vect);
 378 #endif
 379   free_irq (vect);
 380 }
 381 
 382 #ifndef EXCLUDE_SEQUENCER
 383 void
 384 request_sound_timer (int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 385 {
 386   extern unsigned long seq_time;
 387 
 388 #if 1
 389   if (count < 0)
 390     count = jiffies + (-count);
 391   else
 392     count += seq_time;
 393   timer_table[SOUND_TIMER].fn = sequencer_timer;
 394   timer_table[SOUND_TIMER].expires = count;
 395   timer_active |= 1 << SOUND_TIMER;
 396 #endif
 397 }
 398 
 399 #endif
 400 
 401 void
 402 sound_stop_timer (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 403 {
 404 #if 1
 405   timer_table[SOUND_TIMER].expires = 0;
 406   timer_active &= ~(1 << SOUND_TIMER);
 407 #endif
 408 }
 409 
 410 #ifndef EXCLUDE_AUDIO
 411 static int
 412 valid_dma_page (unsigned long addr, unsigned long dev_buffsize, unsigned long dma_pagesize)
     /* [previous][next][first][last][top][bottom][index][help] */
 413 {
 414   if (((addr & (dma_pagesize - 1)) + dev_buffsize) <= dma_pagesize)
 415     return 1;
 416   else
 417     return 0;
 418 }
 419 
 420 #ifdef MODULE
 421 
 422 #ifdef KMALLOC_DMA_BROKEN
 423 #define KMALLOC_MEM_REGIONS 20
 424 
 425 static char    *dma_list[KMALLOC_MEM_REGIONS];
 426 static int      dma_last = 0;
 427 inline void
 428 add_to_dma_list (char *adr)
     /* [previous][next][first][last][top][bottom][index][help] */
 429 {
 430   dma_list[dma_last++] = adr;
 431 }
 432 
 433 #endif
 434 
 435 static int
 436 module_sound_mem_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 437 {
 438   int             dev, ret = 0;
 439   unsigned long   dma_pagesize;
 440   char           *start_addr, *end_addr;
 441   struct dma_buffparms *dmap;
 442 
 443   for (dev = 0; dev < num_audiodevs; dev++)
 444     if (audio_devs[dev]->buffcount > 0 && audio_devs[dev]->dmachan >= 0)
 445       {
 446         dmap = audio_devs[dev]->dmap;
 447         if (audio_devs[dev]->flags & DMA_AUTOMODE)
 448           audio_devs[dev]->buffcount = 1;
 449 
 450         if (audio_devs[dev]->dmachan > 3)
 451           dma_pagesize = 131072;        /* 16bit dma: 128k */
 452         else
 453           dma_pagesize = 65536; /* 8bit dma: 64k */
 454         if (debugmem)
 455           printk ("sound: dma-page-size %lu\n", dma_pagesize);
 456         /* More sanity checks */
 457 
 458         if (audio_devs[dev]->buffsize > dma_pagesize)
 459           audio_devs[dev]->buffsize = dma_pagesize;
 460         audio_devs[dev]->buffsize &= 0xfffff000;        /* Truncate to n*4k */
 461         if (audio_devs[dev]->buffsize < 4096)
 462           audio_devs[dev]->buffsize = 4096;
 463         if (debugmem)
 464           printk ("sound: buffsize %lu\n", audio_devs[dev]->buffsize);
 465         /* Now allocate the buffers */
 466         for (dmap->raw_count = 0; dmap->raw_count < audio_devs[dev]->buffcount;
 467              dmap->raw_count++)
 468           {
 469 #ifdef KMALLOC_DMA_BROKEN
 470             start_addr = kmalloc (audio_devs[dev]->buffsize, GFP_KERNEL);
 471             if (start_addr)
 472               {
 473                 if (debugmem)
 474                   printk ("sound: trying 0x%lx for DMA\n", (long) start_addr);
 475                 if (valid_dma_page ((unsigned long) start_addr,
 476                                     audio_devs[dev]->buffsize,
 477                                     dma_pagesize))
 478                   add_to_dma_list (start_addr);
 479                 else
 480                   {
 481                     kfree (start_addr);
 482                     start_addr = kmalloc (audio_devs[dev]->buffsize * 2,
 483                                           GFP_KERNEL);  /* what a waste :-( */
 484                     if (start_addr)
 485                       {
 486                         if (debugmem)
 487                           printk ("sound: failed; trying 0x%lx aligned to",
 488                                   (long) start_addr);
 489                         add_to_dma_list (start_addr);
 490                         /* now align it to the next dma-page boundary */
 491                         start_addr = (char *) (((long) start_addr
 492                                                 + dma_pagesize - 1)
 493                                                & ~(dma_pagesize - 1));
 494                         if (debugmem)
 495                           printk (" 0x%lx\n", (long) start_addr);
 496                       }
 497                   }
 498               }
 499 #else
 500             start_addr = kmalloc (audio_devs[dev]->buffsize,
 501                                   GFP_DMA | GFP_KERNEL);
 502 #endif
 503             if (start_addr == NULL)
 504               ret = -ENOMEM;    /* Can't stop the loop in this case, because
 505                                    * ...->raw_buf [...] must be initilized
 506                                    * to valid values (at least to NULL)
 507                                  */
 508             else
 509               {
 510                 /* make some checks */
 511                 end_addr = start_addr + audio_devs[dev]->buffsize - 1;
 512                 if (debugmem)
 513                   printk ("sound: start 0x%lx, end 0x%lx\n",
 514                           (long) start_addr, (long) end_addr);
 515                 /* now check if it fits into the same dma-pagesize */
 516                 if (((long) start_addr & ~(dma_pagesize - 1))
 517                     != ((long) end_addr & ~(dma_pagesize - 1))
 518                     || end_addr >= (char *) (16 * 1024 * 1024))
 519                   {
 520                     printk (
 521                              "sound: kmalloc returned invalid address 0x%lx for %ld Bytes DMA-buffer\n",
 522                              (long) start_addr,
 523                              audio_devs[dev]->buffsize);
 524                     ret = -EFAULT;
 525                   }
 526               }
 527             dmap->raw_buf[dmap->raw_count] = start_addr;
 528             dmap->raw_buf_phys[dmap->raw_count] = (unsigned long) start_addr;
 529           }
 530       }
 531   return ret;
 532 }
 533 
 534 static void
 535 module_sound_mem_release (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 536 {
 537 #ifdef KMALLOC_DMA_BROKEN
 538   int             i;
 539 
 540   for (i = 0; i < dma_last; i++)
 541     {
 542       if (debugmem)
 543         printk ("sound: freeing 0x%lx\n", (long) dma_list[i]);
 544       kfree (dma_list[i]);
 545     }
 546 #else
 547   int             dev, i;
 548 
 549   for (dev = 0; dev < num_audiodevs; dev++)
 550     if (audio_devs[dev]->buffcount > 0 && audio_devs[dev]->dmachan >= 0)
 551       {
 552         for (i = 0; i < audio_devs[dev]->buffcount; i++)
 553           if (audio_devs[dev]->dmap->raw_buf[i])
 554             {
 555               if (debugmem)
 556                 printk ("sound: freeing 0x%lx\n",
 557                         (long) (audio_devs[dev]->dmap->raw_buf[i]));
 558               kfree (audio_devs[dev]->dmap->raw_buf[i]);
 559             }
 560       }
 561 #endif
 562 }
 563 
 564 #else /* !MODULE */
 565 
 566 void
 567 sound_mem_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 568 {
 569   int             i, dev;
 570   unsigned long   start_addr, end_addr, mem_ptr, dma_pagesize;
 571   struct dma_buffparms *dmap;
 572 
 573   mem_ptr = high_memory;
 574 
 575   /* Some sanity checks */
 576 
 577   if (mem_ptr > (16 * 1024 * 1024))
 578     mem_ptr = 16 * 1024 * 1024; /* Limit to 16M */
 579 
 580   for (dev = 0; dev < num_audiodevs; dev++)     /* Enumerate devices */
 581     if (audio_devs[dev]->buffcount > 0 && audio_devs[dev]->dmachan >= 0)
 582       {
 583         dmap = audio_devs[dev]->dmap;
 584 
 585         if (audio_devs[dev]->flags & DMA_AUTOMODE)
 586           audio_devs[dev]->buffcount = 1;
 587 
 588         if (audio_devs[dev]->dmachan > 3 && audio_devs[dev]->buffsize > 65536)
 589           dma_pagesize = 131072;        /* 128k */
 590         else
 591           dma_pagesize = 65536;
 592 
 593         /* More sanity checks */
 594 
 595         if (audio_devs[dev]->buffsize > dma_pagesize)
 596           audio_devs[dev]->buffsize = dma_pagesize;
 597         audio_devs[dev]->buffsize &= 0xfffff000;        /* Truncate to n*4k */
 598         if (audio_devs[dev]->buffsize < 4096)
 599           audio_devs[dev]->buffsize = 4096;
 600 
 601         /* Now allocate the buffers */
 602 
 603         for (dmap->raw_count = 0; dmap->raw_count < audio_devs[dev]->buffcount; dmap->raw_count++)
 604           {
 605             start_addr = mem_ptr - audio_devs[dev]->buffsize;
 606             if (!valid_dma_page (start_addr, audio_devs[dev]->buffsize, dma_pagesize))
 607               start_addr &= ~(dma_pagesize - 1);        /* Align address to
 608                                                          * dma_pagesize */
 609 
 610             end_addr = start_addr + audio_devs[dev]->buffsize - 1;
 611 
 612             dmap->raw_buf[dmap->raw_count] = (char *) start_addr;
 613             dmap->raw_buf_phys[dmap->raw_count] = start_addr;
 614             mem_ptr = start_addr;
 615 
 616             for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++)
 617               {
 618                 if (mem_map[i])
 619                   panic ("sound_mem_init: Page not free (driver incompatible with kernel).\n");
 620 
 621                 mem_map[i] = MAP_PAGE_RESERVED;
 622               }
 623           }
 624       }                         /* for dev */
 625 }
 626 
 627 #endif /* !MODULE */
 628 
 629 #endif
 630 
 631 #else
 632 
 633 long
 634 soundcard_init (long mem_start) /* Dummy version */
     /* [previous][next][first][last][top][bottom][index][help] */
 635 {
 636   return mem_start;
 637 }
 638 
 639 #endif
 640 
 641 #if !defined(CONFIGURE_SOUNDCARD) || defined(EXCLUDE_AUDIO)
 642 void
 643 sound_mem_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 644 {
 645   /* Dummy version */
 646 }
 647 
 648 #ifdef MODULE
 649 static int
 650 module_sound_mem_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 651 {
 652   return 0;                     /* no error */
 653 }
 654 
 655 #endif
 656 
 657 #endif

/* [previous][next][first][last][top][bottom][index][help] */