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. tenmicrosec
  11. snd_set_irq_handler
  12. snd_release_irq
  13. request_sound_timer
  14. sound_stop_timer
  15. valid_dma_page
  16. sound_mem_init
  17. soundcard_init
  18. sound_mem_init

   1 
   2 /*
   3  * linux/kernel/chr_drv/sound/soundcard.c
   4  *
   5  * Soundcard driver for Linux
   6  *
   7  * Copyright by Hannu Savolainen 1993
   8  *
   9  * Redistribution and use in source and binary forms, with or without
  10  * modification, are permitted provided that the following conditions are
  11  * met: 1. Redistributions of source code must retain the above copyright
  12  * notice, this list of conditions and the following disclaimer. 2.
  13  * Redistributions in binary form must reproduce the above copyright notice,
  14  * this list of conditions and the following disclaimer in the documentation
  15  * and/or other materials provided with the distribution.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  *
  29  */
  30 
  31 #include "sound_config.h"
  32 
  33 #ifdef CONFIGURE_SOUNDCARD
  34 
  35 #include <linux/major.h>
  36 
  37 extern long     seq_time;
  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 extern char    *snd_raw_buf[MAX_DSP_DEV][DSP_BUFFCOUNT];
  47 extern unsigned long snd_raw_buf_phys[MAX_DSP_DEV][DSP_BUFFCOUNT];
  48 extern int      snd_raw_count[MAX_DSP_DEV];
  49 
  50 int
  51 snd_ioctl_return (int *addr, int value)
     /* [previous][next][first][last][top][bottom][index][help] */
  52 {
  53   if (value < 0)
  54     return value;
  55 
  56   PUT_WORD_TO_USER (addr, 0, value);
  57   return 0;
  58 }
  59 
  60 static int
  61 sound_read (struct inode *inode, struct file *file, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  62 {
  63   int             dev;
  64 
  65   dev = inode->i_rdev;
  66   dev = MINOR (dev);
  67 
  68   return sound_read_sw (dev, &files[dev], buf, count);
  69 }
  70 
  71 static int
  72 sound_write (struct inode *inode, struct file *file, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  73 {
  74   int             dev;
  75 
  76   dev = inode->i_rdev;
  77   dev = MINOR (dev);
  78 
  79   return sound_write_sw (dev, &files[dev], buf, count);
  80 }
  81 
  82 static int
  83 sound_lseek (struct inode *inode, struct file *file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
  84 {
  85   return RET_ERROR (EPERM);
  86 }
  87 
  88 static int
  89 sound_open (struct inode *inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
  90 {
  91   int             dev;
  92 
  93   dev = inode->i_rdev;
  94   dev = MINOR (dev);
  95 
  96   if (!soundcard_configured && dev != SND_DEV_CTL && dev != SND_DEV_STATUS)
  97     {
  98       printk ("SoundCard Error: The soundcard system has not been configured\n");
  99       return RET_ERROR (ENXIO);
 100     }
 101 
 102   files[dev].mode = 0;
 103 
 104   if ((file->f_flags & O_ACCMODE) == O_RDWR)
 105     files[dev].mode = OPEN_READWRITE;
 106   if ((file->f_flags & O_ACCMODE) == O_RDONLY)
 107     files[dev].mode = OPEN_READ;
 108   if ((file->f_flags & O_ACCMODE) == O_WRONLY)
 109     files[dev].mode = OPEN_WRITE;
 110 
 111   return sound_open_sw (dev, &files[dev]);
 112 }
 113 
 114 static void
 115 sound_release (struct inode *inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {
 117   int             dev;
 118 
 119   dev = inode->i_rdev;
 120   dev = MINOR (dev);
 121 
 122   sound_release_sw (dev, &files[dev]);
 123 }
 124 
 125 static int
 126 sound_ioctl (struct inode *inode, struct file *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 127              unsigned int cmd, unsigned long arg)
 128 {
 129   int             dev;
 130 
 131   dev = inode->i_rdev;
 132   dev = MINOR (dev);
 133 
 134   return sound_ioctl_sw (dev, &files[dev], cmd, arg);
 135 }
 136 
 137 static int
 138 sound_select (struct inode *inode, struct file *file, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 139 {
 140   int             dev;
 141 
 142   dev = inode->i_rdev;
 143   dev = MINOR (dev);
 144 
 145   DEB (printk ("sound_select(dev=%d, type=0x%x)\n", dev, sel_type));
 146 
 147   switch (dev & 0x0f)
 148     {
 149     case SND_DEV_SEQ:
 150       return sequencer_select (dev, &files[dev], sel_type, wait);
 151       break;
 152 
 153     default:
 154       return 0;
 155     }
 156 
 157   return 0;
 158 }
 159 
 160 static struct file_operations sound_fops =
 161 {
 162   sound_lseek,
 163   sound_read,
 164   sound_write,
 165   NULL,                         /* sound_readdir */
 166   sound_select,
 167   sound_ioctl,
 168   NULL,
 169   sound_open,
 170   sound_release
 171 };
 172 
 173 long
 174 soundcard_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 175 {
 176   register_chrdev (SOUND_MAJOR, "sound", &sound_fops);
 177 
 178   soundcard_configured = 1;
 179 
 180   mem_start = sndtable_init (mem_start);        /* Initialize call tables and
 181                                                  * detect cards */
 182 
 183   if (!(soundcards_installed = sndtable_get_cardcount ()))
 184     return mem_start;           /* No cards detected */
 185 
 186   if (num_dspdevs)              /* Audio devices present */
 187     {
 188       mem_start = DMAbuf_init (mem_start);
 189       mem_start = audio_init (mem_start);
 190     }
 191 
 192 #ifndef EXCLUDE_MPU401
 193   if (num_midis)
 194     mem_start = MIDIbuf_init (mem_start);
 195 #endif
 196 
 197   if (num_midis + num_synths)
 198     mem_start = sequencer_init (mem_start);
 199 
 200   return mem_start;
 201 }
 202 
 203 void
 204 tenmicrosec (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 205 {
 206   int             i;
 207 
 208   for (i = 0; i < 16; i++)
 209     inb (0x80);
 210 }
 211 
 212 int
 213 snd_set_irq_handler (int interrupt_level, void (*hndlr) (int))
     /* [previous][next][first][last][top][bottom][index][help] */
 214 {
 215   int             retcode;
 216 
 217   struct sigaction sa;
 218 
 219   sa.sa_handler = hndlr;
 220 
 221 #ifdef SND_SA_INTERRUPT
 222   sa.sa_flags = SA_INTERRUPT;
 223 #else
 224   sa.sa_flags = 0;
 225 #endif
 226 
 227   sa.sa_mask = 0;
 228   sa.sa_restorer = NULL;
 229 
 230   retcode = irqaction (interrupt_level, &sa);
 231 
 232   if (retcode < 0)
 233     {
 234       printk ("Sound: IRQ%d already in use\n", interrupt_level);
 235     }
 236 
 237   return retcode;
 238 }
 239 
 240 void
 241 snd_release_irq (int vect)
     /* [previous][next][first][last][top][bottom][index][help] */
 242 {
 243   free_irq (vect);
 244 }
 245 
 246 void
 247 request_sound_timer (int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 248 {
 249 #ifndef EXCLUDE_SEQUENCER
 250   if (count < 0)
 251     count = jiffies + (-count);
 252   else
 253     count += seq_time;
 254   timer_table[SOUND_TIMER].fn = sequencer_timer;
 255   timer_table[SOUND_TIMER].expires = count;
 256   timer_active |= 1 << SOUND_TIMER;
 257 #endif
 258 }
 259 
 260 void
 261 sound_stop_timer (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 262 {
 263 #ifndef EXCLUDE_SEQUENCER
 264   timer_table[SOUND_TIMER].expires = 0;
 265   timer_active &= ~(1 << SOUND_TIMER);
 266 #endif
 267 }
 268 
 269 #ifndef EXCLUDE_AUDIO
 270 static int
 271 valid_dma_page (unsigned long addr, unsigned long dev_buffsize, unsigned long dma_pagesize)
     /* [previous][next][first][last][top][bottom][index][help] */
 272 {
 273   if (((addr & (dma_pagesize - 1)) + dev_buffsize) <= dma_pagesize)
 274     return 1;
 275   else
 276     return 0;
 277 }
 278 
 279 void
 280 sound_mem_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 281 {
 282   int             i, dev;
 283   unsigned long   start_addr, end_addr, mem_ptr, dma_pagesize;
 284 
 285   mem_ptr = high_memory;
 286 
 287   /* Some sanity checks */
 288 
 289   if (mem_ptr > (16 * 1024 * 1024))
 290     mem_ptr = 16 * 1024 * 1024; /* Limit to 16M */
 291 
 292   for (dev = 0; dev < num_dspdevs; dev++)       /* Enumerate devices */
 293     if (sound_buffcounts[dev] > 0 && sound_dsp_dmachan[dev] > 0)
 294       {
 295         if (sound_dma_automode[dev])
 296           sound_buffcounts[dev] = 1;
 297 
 298         if (sound_dsp_dmachan[dev] > 3 && sound_buffsizes[dev] > 65536)
 299           dma_pagesize = 131072;/* 128k */
 300         else
 301           dma_pagesize = 65536;
 302 
 303         /* More sanity checks */
 304 
 305         if (sound_buffsizes[dev] > dma_pagesize)
 306           sound_buffsizes[dev] = dma_pagesize;
 307         sound_buffsizes[dev] &= 0xfffff000;     /* Truncate to n*4k */
 308         if (sound_buffsizes[dev] < 4096)
 309           sound_buffsizes[dev] = 4096;
 310 
 311         /* Now allocate the buffers */
 312 
 313         for (snd_raw_count[dev] = 0; snd_raw_count[dev] < sound_buffcounts[dev]; snd_raw_count[dev]++)
 314           {
 315             start_addr = mem_ptr - sound_buffsizes[dev];
 316             if (!valid_dma_page (start_addr, sound_buffsizes[dev], dma_pagesize))
 317               start_addr &= ~(dma_pagesize - 1);        /* Align address to
 318                                                          * dma_pagesize */
 319 
 320             end_addr = start_addr + sound_buffsizes[dev] - 1;
 321 
 322             snd_raw_buf[dev][snd_raw_count[dev]] = (char *) start_addr;
 323             snd_raw_buf_phys[dev][snd_raw_count[dev]] = start_addr;
 324             mem_ptr = start_addr;
 325 
 326             for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++)
 327               {
 328                 if (mem_map[i])
 329                   panic ("sound_mem_init: Page not free (driver incompatible with kernel).\n");
 330 
 331                 mem_map[i] = MAP_PAGE_RESERVED;
 332               }
 333           }
 334       }                         /* for dev */
 335 }
 336 
 337 #endif
 338 
 339 #else
 340 
 341 long
 342 soundcard_init (long mem_start) /* Dummy version */
     /* [previous][next][first][last][top][bottom][index][help] */
 343 {
 344   return mem_start;
 345 }
 346 
 347 #endif
 348 
 349 #if !defined(CONFIGURE_SOUNDCARD) || defined(EXCLUDE_AUDIO)
 350 void
 351 sound_mem_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 352 {
 353   /* Dummy version */
 354 }
 355 
 356 #endif

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