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  * 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 #include "sound_config.h"
  31 
  32 #ifdef CONFIGURE_SOUNDCARD
  33 
  34 #include <linux/major.h>
  35 
  36 static int      soundcards_installed = 0;       /* Number of installed
  37 
  38                                                  * soundcards */
  39 static int      soundcard_configured = 0;
  40 
  41 static struct fileinfo files[SND_NDEVS];
  42 
  43 int
  44 snd_ioctl_return (int *addr, int value)
     /* [previous][next][first][last][top][bottom][index][help] */
  45 {
  46   int error;
  47 
  48   if (value < 0)
  49     return value;
  50 
  51   error = verify_area(VERIFY_WRITE, addr, sizeof(int));
  52   if (error)
  53     return error;
  54 
  55   PUT_WORD_TO_USER (addr, 0, value);
  56   return 0;
  57 }
  58 
  59 static int
  60 sound_read (struct inode *inode, struct file *file, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  61 {
  62   int             dev;
  63 
  64   dev = inode->i_rdev;
  65   dev = MINOR (dev);
  66 
  67   return sound_read_sw (dev, &files[dev], buf, count);
  68 }
  69 
  70 static int
  71 sound_write (struct inode *inode, struct file *file, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73   int             dev;
  74 
  75   dev = inode->i_rdev;
  76   dev = MINOR (dev);
  77 
  78   return sound_write_sw (dev, &files[dev], buf, count);
  79 }
  80 
  81 static int
  82 sound_lseek (struct inode *inode, struct file *file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
  83 {
  84   return RET_ERROR (EPERM);
  85 }
  86 
  87 static int
  88 sound_open (struct inode *inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90   int             dev;
  91 
  92   dev = inode->i_rdev;
  93   dev = MINOR (dev);
  94 
  95   if (!soundcard_configured && dev != SND_DEV_CTL && dev != SND_DEV_STATUS)
  96     {
  97       printk ("SoundCard Error: The soundcard system has not been configured\n");
  98       return RET_ERROR (ENXIO);
  99     }
 100 
 101   files[dev].mode = 0;
 102 
 103   if ((file->f_flags & O_ACCMODE) == O_RDWR)
 104     files[dev].mode = OPEN_READWRITE;
 105   if ((file->f_flags & O_ACCMODE) == O_RDONLY)
 106     files[dev].mode = OPEN_READ;
 107   if ((file->f_flags & O_ACCMODE) == O_WRONLY)
 108     files[dev].mode = OPEN_WRITE;
 109 
 110   return sound_open_sw (dev, &files[dev]);
 111 }
 112 
 113 static void
 114 sound_release (struct inode *inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 115 {
 116   int             dev;
 117 
 118   dev = inode->i_rdev;
 119   dev = MINOR (dev);
 120 
 121   sound_release_sw (dev, &files[dev]);
 122 }
 123 
 124 static int
 125 sound_ioctl (struct inode *inode, struct file *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 126              unsigned int cmd, unsigned long arg)
 127 {
 128   int             dev;
 129 
 130   dev = inode->i_rdev;
 131   dev = MINOR (dev);
 132 
 133   return sound_ioctl_sw (dev, &files[dev], cmd, arg);
 134 }
 135 
 136 static int
 137 sound_select (struct inode *inode, struct file *file, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 138 {
 139   int             dev;
 140 
 141   dev = inode->i_rdev;
 142   dev = MINOR (dev);
 143 
 144   DEB (printk ("sound_select(dev=%d, type=0x%x)\n", dev, sel_type));
 145 
 146   switch (dev & 0x0f)
 147     {
 148 #ifndef EXCLUDE_SEQUENCER
 149     case SND_DEV_SEQ:
 150       return sequencer_select (dev, &files[dev], sel_type, wait);
 151       break;
 152 #endif
 153 
 154 #ifndef EXCLUDE_MIDI
 155     case SND_DEV_MIDIN:
 156       return MIDIbuf_select (dev, &files[dev], sel_type, wait);
 157       break;
 158 #endif
 159 
 160     default:
 161       return 0;
 162     }
 163 
 164   return 0;
 165 }
 166 
 167 static struct file_operations sound_fops =
 168 {
 169   sound_lseek,
 170   sound_read,
 171   sound_write,
 172   NULL,                         /* sound_readdir */
 173   sound_select,
 174   sound_ioctl,
 175   NULL,
 176   sound_open,
 177   sound_release
 178 };
 179 
 180 long
 181 soundcard_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 182 {
 183   register_chrdev (SOUND_MAJOR, "sound", &sound_fops);
 184 
 185   soundcard_configured = 1;
 186 
 187   mem_start = sndtable_init (mem_start);        /* Initialize call tables and
 188                                                  * detect cards */
 189 
 190   if (!(soundcards_installed = sndtable_get_cardcount ()))
 191     return mem_start;           /* No cards detected */
 192 
 193 #ifndef EXCLUDE_AUDIO
 194   if (num_audiodevs)            /* Audio devices present */
 195     {
 196       mem_start = DMAbuf_init (mem_start);
 197       mem_start = audio_init (mem_start);
 198     }
 199 #endif
 200 
 201 #ifndef EXCLUDE_MIDI
 202   if (num_midis)
 203     mem_start = MIDIbuf_init (mem_start);
 204 #endif
 205 
 206 #ifndef EXCLUDE_SEQUENCER
 207   if (num_midis + num_synths)
 208     mem_start = sequencer_init (mem_start);
 209 #endif
 210 
 211   return mem_start;
 212 }
 213 
 214 void
 215 tenmicrosec (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 216 {
 217   int             i;
 218 
 219   for (i = 0; i < 16; i++)
 220     inb (0x80);
 221 }
 222 
 223 int
 224 snd_set_irq_handler (int interrupt_level, void (*hndlr) (int))
     /* [previous][next][first][last][top][bottom][index][help] */
 225 {
 226   int             retcode;
 227 
 228   retcode = request_irq(interrupt_level, hndlr,
 229 #ifdef SND_SA_INTERRUPT
 230         SA_INTERRUPT,
 231 #else
 232         0,
 233 #endif
 234         "sound");
 235 
 236   if (retcode < 0)
 237     {
 238       printk ("Sound: IRQ%d already in use\n", interrupt_level);
 239     }
 240 
 241   return retcode;
 242 }
 243 
 244 void
 245 snd_release_irq (int vect)
     /* [previous][next][first][last][top][bottom][index][help] */
 246 {
 247   free_irq (vect);
 248 }
 249 
 250 #ifndef EXCLUDE_SEQUENCER
 251 void
 252 request_sound_timer (int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 253 {
 254   extern unsigned long seq_time;
 255 
 256 #if 1
 257   if (count < 0)
 258     count = jiffies + (-count);
 259   else
 260     count += seq_time;
 261   timer_table[SOUND_TIMER].fn = sequencer_timer;
 262   timer_table[SOUND_TIMER].expires = count;
 263   timer_active |= 1 << SOUND_TIMER;
 264 #endif
 265 }
 266 
 267 #endif
 268 
 269 void
 270 sound_stop_timer (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 271 {
 272 #if 1
 273   timer_table[SOUND_TIMER].expires = 0;
 274   timer_active &= ~(1 << SOUND_TIMER);
 275 #endif
 276 }
 277 
 278 #ifndef EXCLUDE_AUDIO
 279 static int
 280 valid_dma_page (unsigned long addr, unsigned long dev_buffsize, unsigned long dma_pagesize)
     /* [previous][next][first][last][top][bottom][index][help] */
 281 {
 282   if (((addr & (dma_pagesize - 1)) + dev_buffsize) <= dma_pagesize)
 283     return 1;
 284   else
 285     return 0;
 286 }
 287 
 288 void
 289 sound_mem_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 290 {
 291   int             i, dev;
 292   unsigned long   start_addr, end_addr, mem_ptr, dma_pagesize;
 293   struct dma_buffparms *dmap;
 294 
 295   mem_ptr = high_memory;
 296 
 297   /* Some sanity checks */
 298 
 299   if (mem_ptr > (16 * 1024 * 1024))
 300     mem_ptr = 16 * 1024 * 1024; /* Limit to 16M */
 301 
 302   for (dev = 0; dev < num_audiodevs; dev++)     /* Enumerate devices */
 303     if (audio_devs[dev]->buffcount > 0 && audio_devs[dev]->dmachan >= 0)
 304       {
 305         dmap = audio_devs[dev]->dmap;
 306 
 307         if (audio_devs[dev]->flags & DMA_AUTOMODE)
 308           audio_devs[dev]->buffcount = 1;
 309 
 310         if (audio_devs[dev]->dmachan > 3 && audio_devs[dev]->buffsize > 65536)
 311           dma_pagesize = 131072;/* 128k */
 312         else
 313           dma_pagesize = 65536;
 314 
 315         /* More sanity checks */
 316 
 317         if (audio_devs[dev]->buffsize > dma_pagesize)
 318           audio_devs[dev]->buffsize = dma_pagesize;
 319         audio_devs[dev]->buffsize &= 0xfffff000;        /* Truncate to n*4k */
 320         if (audio_devs[dev]->buffsize < 4096)
 321           audio_devs[dev]->buffsize = 4096;
 322 
 323         /* Now allocate the buffers */
 324 
 325         for (dmap->raw_count = 0; dmap->raw_count < audio_devs[dev]->buffcount; dmap->raw_count++)
 326           {
 327             start_addr = mem_ptr - audio_devs[dev]->buffsize;
 328             if (!valid_dma_page (start_addr, audio_devs[dev]->buffsize, dma_pagesize))
 329               start_addr &= ~(dma_pagesize - 1);        /* Align address to
 330                                                          * dma_pagesize */
 331 
 332             end_addr = start_addr + audio_devs[dev]->buffsize - 1;
 333 
 334             dmap->raw_buf[dmap->raw_count] = (char *) start_addr;
 335             dmap->raw_buf_phys[dmap->raw_count] = start_addr;
 336             mem_ptr = start_addr;
 337 
 338             for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++)
 339               {
 340                 if (mem_map[i])
 341                   panic ("sound_mem_init: Page not free (driver incompatible with kernel).\n");
 342 
 343                 mem_map[i] = MAP_PAGE_RESERVED;
 344               }
 345           }
 346       }                         /* for dev */
 347 }
 348 
 349 #endif
 350 
 351 #else
 352 
 353 long
 354 soundcard_init (long mem_start) /* Dummy version */
     /* [previous][next][first][last][top][bottom][index][help] */
 355 {
 356   return mem_start;
 357 }
 358 
 359 #endif
 360 
 361 #if !defined(CONFIGURE_SOUNDCARD) || defined(EXCLUDE_AUDIO)
 362 void
 363 sound_mem_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 364 {
 365   /* Dummy version */
 366 }
 367 
 368 #endif

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