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 / audio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-09  |  7.2 KB  |  354 lines

  1. /*
  2.  * sound/audio.c
  3.  * 
  4.  * Device file manager for /dev/audio
  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. #ifndef EXCLUDE_AUDIO
  34.  
  35. #include "ulaw.h"
  36.  
  37. #define ON        1
  38. #define OFF        0
  39.  
  40. static int      wr_buff_no[MAX_DSP_DEV];    /* != -1, if there is a
  41.                          * incomplete output block */
  42. static int      wr_buff_size[MAX_DSP_DEV], wr_buff_ptr[MAX_DSP_DEV];
  43.  
  44. static int    audio_mode[MAX_DSP_DEV];
  45. #define        AM_NONE        0
  46. #define        AM_WRITE    1
  47. #define     AM_READ        2
  48.  
  49. static char    *wr_dma_buf[MAX_DSP_DEV];
  50.  
  51. int
  52. audio_open (int dev, struct fileinfo *file)
  53. {
  54.   int             ret;
  55.   int          bits;
  56.   int          dev_type = dev & 0x0f;
  57.   int          mode = file->mode & O_ACCMODE;
  58.  
  59.   dev = dev >> 4;
  60.  
  61.   if (dev_type == SND_DEV_DSP16)
  62.      bits = 16;
  63.   else
  64.      bits = 8;
  65.  
  66.   if ((ret = DMAbuf_open (dev, mode)) < 0)
  67.     return ret;
  68.  
  69.   if (DMAbuf_ioctl (dev, SNDCTL_DSP_SAMPLESIZE, bits, 1) != bits)
  70.     {
  71.       audio_release (dev, file);
  72.       return RET_ERROR (ENXIO);
  73.     }
  74.  
  75.   wr_buff_no[dev] = -1;
  76.   audio_mode[dev] = AM_NONE;
  77.  
  78.   return ret;
  79. }
  80.  
  81. void
  82. audio_release (int dev, struct fileinfo *file)
  83. {
  84.   int             mode;
  85.  
  86.   dev = dev >> 4;
  87.   mode = file->mode & O_ACCMODE;
  88.  
  89.   if (wr_buff_no[dev] >= 0)
  90.     {
  91.       DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
  92.  
  93.       wr_buff_no[dev] = -1;
  94.     }
  95.  
  96.   DMAbuf_release (dev, mode);
  97. }
  98.  
  99. #ifdef NO_INLINE_ASM
  100. static void
  101. translate_bytes (const unsigned char *table, unsigned char *buff, unsigned long n)
  102. {
  103.   unsigned long   i;
  104.  
  105.   for (i = 0; i < n; ++i)
  106.     buff[i] = table[buff[i]];
  107. }
  108.  
  109. #else
  110. extern inline void
  111. translate_bytes (const void *table, void *buff, unsigned long n)
  112. {
  113.   __asm__ ("cld\n"
  114.        "1:\tlodsb\n\t"
  115.        "xlatb\n\t"
  116.        "stosb\n\t"
  117.        "loop 1b\n\t":
  118.        :"b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff)
  119.        :"bx", "cx", "di", "si", "ax");
  120. }
  121.  
  122. #endif
  123.  
  124. int
  125. audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
  126. {
  127.   int             c, p, l;
  128.   int             err;
  129.   int          dev_type = dev & 0x0f;
  130.  
  131.   dev = dev >> 4;
  132.  
  133.   p = 0;
  134.   c = count;
  135.  
  136.   if (audio_mode[dev] == AM_READ)    /* Direction changed */
  137.   {
  138.       wr_buff_no[dev] = -1;
  139.   }
  140.  
  141.   audio_mode[dev] = AM_WRITE;
  142.  
  143.   if (!count)            /* Flush output */
  144.     {
  145.       if (wr_buff_no[dev] >= 0)
  146.     {
  147.       DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
  148.  
  149.       wr_buff_no[dev] = -1;
  150.     }
  151.       return 0;
  152.     }
  153.  
  154.   while (c)
  155.     {                /* Perform output blocking */
  156.       if (wr_buff_no[dev] < 0)    /* There is no incomplete buffers */
  157.     {
  158.       if ((wr_buff_no[dev] = DMAbuf_getwrbuffer (dev, &wr_dma_buf[dev], &wr_buff_size[dev])) < 0)
  159.         return wr_buff_no[dev];
  160.       wr_buff_ptr[dev] = 0;
  161.     }
  162.  
  163.       l = c;
  164.       if (l > (wr_buff_size[dev] - wr_buff_ptr[dev]))
  165.     l = (wr_buff_size[dev] - wr_buff_ptr[dev]);
  166.  
  167.       if (!dsp_devs[dev]->copy_from_user)
  168.     {            /* No device specific copy routine */
  169.       COPY_FROM_USER (&wr_dma_buf[dev][wr_buff_ptr[dev]], buf, p, l);
  170.     }
  171.       else
  172.     dsp_devs[dev]->copy_from_user (dev,
  173.                    wr_dma_buf[dev], wr_buff_ptr[dev], buf, p, l);
  174.  
  175.  
  176.       /* Insert local processing here */
  177.  
  178.       if (dev_type == SND_DEV_AUDIO)
  179.       {
  180. #ifdef linux
  181.       /* This just allows interrupts while the conversion is running */
  182.          __asm__ ("sti");
  183. #endif
  184.          translate_bytes (ulaw_dsp, &wr_dma_buf[dev][wr_buff_ptr[dev]], l);
  185.       }
  186.  
  187.       c -= l;
  188.       p += l;
  189.       wr_buff_ptr[dev] += l;
  190.  
  191.       if (wr_buff_ptr[dev] >= wr_buff_size[dev])
  192.     {
  193.       if ((err = DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev])) < 0)
  194.         return err;
  195.  
  196.       wr_buff_no[dev] = -1;
  197.     }
  198.  
  199.     }
  200.  
  201.   return count;
  202. }
  203.  
  204. int
  205. audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
  206. {
  207.   int             c, p, l;
  208.   char           *dmabuf;
  209.   int             buff_no;
  210.   int          dev_type = dev & 0x0f;
  211.  
  212.   dev = dev >> 4;
  213.   p = 0;
  214.   c = count;
  215.  
  216.   if (audio_mode[dev] == AM_WRITE)
  217.   {
  218.       if (wr_buff_no[dev] >= 0)
  219.     {
  220.       DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
  221.  
  222.       wr_buff_no[dev] = -1;
  223.     }
  224.   }
  225.  
  226.   audio_mode[dev] = AM_READ;
  227.  
  228.   while (c)
  229.     {
  230.       if ((buff_no = DMAbuf_getrdbuffer (dev, &dmabuf, &l)) < 0)
  231.     return buff_no;
  232.  
  233.       if (l > c)
  234.     l = c;
  235.  
  236.       /* Insert any local processing here. */
  237.  
  238.       if (dev_type == SND_DEV_AUDIO)
  239.       {
  240. #ifdef linux
  241.         /* This just allows interrupts while the conversion is running */
  242.         __asm__ ("sti");
  243. #endif
  244.  
  245.         translate_bytes (dsp_ulaw, dmabuf, l);
  246.       }
  247.  
  248.       COPY_TO_USER (buf, p, dmabuf, l);
  249.  
  250.       DMAbuf_rmchars (dev, buff_no, l);
  251.  
  252.       p += l;
  253.       c -= l;
  254.     }
  255.  
  256.   return count - c;
  257. }
  258.  
  259. int
  260. audio_ioctl (int dev, struct fileinfo *file,
  261.          unsigned int cmd, unsigned int arg)
  262. {
  263.   int          dev_type = dev & 0x0f;
  264.   dev = dev >> 4;
  265.  
  266.   switch (cmd)
  267.     {
  268.     case SNDCTL_DSP_SYNC:
  269.       if (wr_buff_no[dev] >= 0)
  270.     {
  271.       DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
  272.  
  273.       wr_buff_no[dev] = -1;
  274.     }
  275.       return DMAbuf_ioctl (dev, cmd, arg, 0);
  276.       break;
  277.  
  278.     case SNDCTL_DSP_POST:
  279.       if (wr_buff_no[dev] >= 0)
  280.     {
  281.       DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
  282.  
  283.       wr_buff_no[dev] = -1;
  284.     }
  285.       return 0;
  286.       break;
  287.  
  288.     case SNDCTL_DSP_RESET:
  289.       wr_buff_no[dev] = -1;
  290.       return DMAbuf_ioctl (dev, cmd, arg, 0);
  291.       break;
  292.  
  293.     default:
  294.       if (dev_type == SND_DEV_AUDIO)
  295.          return RET_ERROR (EIO);
  296.  
  297.       return DMAbuf_ioctl (dev, cmd, arg, 0);
  298.     }
  299. }
  300.  
  301. long
  302. audio_init (long mem_start)
  303. {
  304.   return mem_start;
  305. }
  306.  
  307. #else
  308. /* Stub versions */
  309.  
  310. int
  311. audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
  312. {
  313.   return RET_ERROR (EIO);
  314. }
  315.  
  316. int
  317. audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
  318. {
  319.   return RET_ERROR (EIO);
  320. }
  321.  
  322. int
  323. audio_open (int dev, struct fileinfo *file)
  324.   {
  325.     return RET_ERROR (ENXIO);
  326.   }
  327.  
  328. void
  329. audio_release (int dev, struct fileinfo *file)
  330.   {
  331.   };
  332. int
  333. audio_ioctl (int dev, struct fileinfo *file,
  334.          unsigned int cmd, unsigned int arg)
  335. {
  336.   return RET_ERROR (EIO);
  337. }
  338.  
  339. int
  340. audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig)
  341. {
  342.   return RET_ERROR (EIO);
  343. }
  344.  
  345. long
  346. audio_init (long mem_start)
  347. {
  348.   return mem_start;
  349. }
  350.  
  351. #endif
  352.  
  353. #endif
  354.