home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / drivers / sound / soundcard.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-21  |  7.8 KB  |  356 lines

  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.                          * soundcards */
  41. static int      soundcard_configured = 0;
  42.  
  43. static struct fileinfo files[SND_NDEVS];
  44.  
  45. extern char    *snd_raw_buf[MAX_DSP_DEV][DSP_BUFFCOUNT];
  46. extern unsigned long snd_raw_buf_phys[MAX_DSP_DEV][DSP_BUFFCOUNT];
  47. extern int      snd_raw_count[MAX_DSP_DEV];
  48.  
  49. int
  50. snd_ioctl_return (int *addr, int value)
  51. {
  52.   if (value < 0)
  53.     return value;
  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)
  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)
  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)
  83. {
  84.   return RET_ERROR (EPERM);
  85. }
  86.  
  87. static int
  88. sound_open (struct inode *inode, struct file *file)
  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)
  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,
  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)
  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.     case SND_DEV_SEQ:
  149.       return sequencer_select (dev, &files[dev], sel_type, wait);
  150.       break;
  151.  
  152.     default:
  153.       return 0;
  154.     }
  155.  
  156.   return 0;
  157. }
  158.  
  159. static struct file_operations sound_fops =
  160. {
  161.   sound_lseek,
  162.   sound_read,
  163.   sound_write,
  164.   NULL,                /* sound_readdir */
  165.   sound_select,
  166.   sound_ioctl,
  167.   NULL,
  168.   sound_open,
  169.   sound_release
  170. };
  171.  
  172. long
  173. soundcard_init (long mem_start)
  174. {
  175.   register_chrdev (SOUND_MAJOR, "sound", &sound_fops);
  176.  
  177.   soundcard_configured = 1;
  178.  
  179.   mem_start = sndtable_init (mem_start);    /* Initialize call tables and
  180.                          * detect cards */
  181.  
  182.   if (!(soundcards_installed = sndtable_get_cardcount ()))
  183.     return mem_start;        /* No cards detected */
  184.  
  185.   if (num_dspdevs)        /* Audio devices present */
  186.     {
  187.       mem_start = DMAbuf_init (mem_start);
  188.       mem_start = audio_init (mem_start);
  189.     }
  190.  
  191. #ifndef EXCLUDE_MPU401
  192.   if (num_midis)
  193.     mem_start = MIDIbuf_init (mem_start);
  194. #endif
  195.  
  196.   if (num_midis + num_synths)
  197.     mem_start = sequencer_init (mem_start);
  198.  
  199.   return mem_start;
  200. }
  201.  
  202. void
  203. tenmicrosec (void)
  204. {
  205.   int             i;
  206.  
  207.   for (i = 0; i < 16; i++)
  208.     inb (0x80);
  209. }
  210.  
  211. int
  212. snd_set_irq_handler (int interrupt_level, void(*hndlr)(int))
  213. {
  214.   int             retcode;
  215.  
  216.   struct sigaction sa;
  217.  
  218.   sa.sa_handler = hndlr;
  219.  
  220. #ifdef SND_SA_INTERRUPT
  221.   sa.sa_flags = SA_INTERRUPT;
  222. #else
  223.   sa.sa_flags = 0;
  224. #endif
  225.  
  226.   sa.sa_mask = 0;
  227.   sa.sa_restorer = NULL;
  228.  
  229.   retcode = irqaction (interrupt_level, &sa);
  230.  
  231.   if (retcode < 0)
  232.     {
  233.       printk ("Sound: IRQ%d already in use\n", interrupt_level);
  234.     }
  235.  
  236.   return retcode;
  237. }
  238.  
  239. void
  240. snd_release_irq(int vect)
  241. {
  242.     free_irq(vect);
  243. }
  244.  
  245. void
  246. request_sound_timer (int count)
  247. {
  248. #ifndef EXCLUDE_SEQUENCER
  249.   if (count < 0)
  250.     count = jiffies + (-count);
  251.   else
  252.     count += seq_time;
  253.   timer_table[SOUND_TIMER].fn = sequencer_timer;
  254.   timer_table[SOUND_TIMER].expires = count;
  255.   timer_active |= 1 << SOUND_TIMER;
  256. #endif
  257. }
  258.  
  259. void
  260. sound_stop_timer (void)
  261. {
  262. #ifndef EXCLUDE_SEQUENCER
  263.   timer_table[SOUND_TIMER].expires = 0;
  264.   timer_active &= ~(1 << SOUND_TIMER);
  265. #endif
  266. }
  267.  
  268. #ifndef EXCLUDE_AUDIO
  269. static int
  270. valid_dma_page (unsigned long addr, unsigned long dev_buffsize, unsigned long dma_pagesize)
  271. {
  272.   if (((addr & (dma_pagesize - 1)) + dev_buffsize) <= dma_pagesize)
  273.     return 1;
  274.   else
  275.     return 0;
  276. }
  277.  
  278. void
  279. sound_mem_init (void)
  280. {
  281.   int             i, dev;
  282.   unsigned long   start_addr, end_addr, mem_ptr, dma_pagesize;
  283.  
  284.   mem_ptr = high_memory;
  285.  
  286.   /* Some sanity checks */
  287.  
  288.   if (mem_ptr > (16 * 1024 * 1024))
  289.     mem_ptr = 16 * 1024 * 1024;    /* Limit to 16M */
  290.  
  291.   for (dev = 0; dev < num_dspdevs; dev++)    /* Enumerate devices */
  292.     if (sound_buffcounts[dev] > 0 && sound_dsp_dmachan[dev] > 0)
  293.       {
  294.     if (sound_dma_automode[dev])
  295.       sound_buffcounts[dev] = 1;
  296.  
  297.     if (sound_dsp_dmachan[dev] > 3 && sound_buffsizes[dev] > 65536)
  298.       dma_pagesize = 131072;/* 128k */
  299.     else
  300.       dma_pagesize = 65536;
  301.  
  302.     /* More sanity checks */
  303.  
  304.     if (sound_buffsizes[dev] > dma_pagesize)
  305.       sound_buffsizes[dev] = dma_pagesize;
  306.     sound_buffsizes[dev] &= 0xfffff000;    /* Truncate to n*4k */
  307.     if (sound_buffsizes[dev] < 4096)
  308.       sound_buffsizes[dev] = 4096;
  309.  
  310.     /* Now allocate the buffers */
  311.  
  312.     for (snd_raw_count[dev] = 0; snd_raw_count[dev] < sound_buffcounts[dev]; snd_raw_count[dev]++)
  313.       {
  314.         start_addr = mem_ptr - sound_buffsizes[dev];
  315.         if (!valid_dma_page (start_addr, sound_buffsizes[dev], dma_pagesize))
  316.           start_addr &= ~(dma_pagesize - 1);    /* Align address to
  317.                              * dma_pagesize */
  318.  
  319.         end_addr = start_addr + sound_buffsizes[dev] - 1;
  320.  
  321.         snd_raw_buf[dev][snd_raw_count[dev]] = (char *) start_addr;
  322.         snd_raw_buf_phys[dev][snd_raw_count[dev]] = start_addr;
  323.         mem_ptr = start_addr;
  324.  
  325.         for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++)
  326.           {
  327.         if (mem_map[i])
  328.           panic ("sound_mem_init: Page not free (driver incompatible with kernel).\n");
  329.  
  330.         mem_map[i] = MAP_PAGE_RESERVED;
  331.           }
  332.       }
  333.       }                /* for dev */
  334. }
  335.  
  336. #endif
  337.  
  338. #else
  339.  
  340. long
  341. soundcard_init (long mem_start)    /* Dummy version */
  342. {
  343.   return mem_start;
  344. }
  345.  
  346. #endif
  347.  
  348. #if !defined(CONFIGURE_SOUNDCARD) || defined(EXCLUDE_AUDIO)
  349. void
  350. sound_mem_init (void)
  351. {
  352.   /* Dummy version */
  353. }
  354.  
  355. #endif
  356.