home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / drivers / sound / soundcard.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-23  |  8.0 KB  |  370 lines

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