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 / audio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-18  |  8.3 KB  |  425 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_AUDIO_DEV];    /*
  41.                          * != -1, if there is
  42.                          * a incomplete output
  43.                          * block in the queue.
  44.                          */
  45. static int      wr_buff_size[MAX_AUDIO_DEV], wr_buff_ptr[MAX_AUDIO_DEV];
  46.  
  47. static int      audio_mode[MAX_AUDIO_DEV];
  48.  
  49. #define        AM_NONE        0
  50. #define        AM_WRITE    1
  51. #define     AM_READ        2
  52.  
  53. static char    *wr_dma_buf[MAX_AUDIO_DEV];
  54. static int      audio_format[MAX_AUDIO_DEV];
  55. static int      local_conversion[MAX_AUDIO_DEV];
  56.  
  57. static int
  58. set_format (int dev, int fmt)
  59. {
  60.   if (fmt != AFMT_QUERY)
  61.     {
  62.  
  63.       local_conversion[dev] = 0;
  64.  
  65.       if (!(audio_devs[dev]->format_mask & fmt))    /* Not supported */
  66.     if (fmt == AFMT_MU_LAW)
  67.       {
  68.         fmt = AFMT_U8;
  69.         local_conversion[dev] = AFMT_MU_LAW;
  70.       }
  71.     else
  72.       fmt = AFMT_U8;    /* This is always supported */
  73.  
  74.       audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, fmt, 1);
  75.     }
  76.  
  77.   if (local_conversion[dev])    /* This shadows the HW format */
  78.     return local_conversion[dev];
  79.  
  80.   return audio_format[dev];
  81. }
  82.  
  83. int
  84. audio_open (int dev, struct fileinfo *file)
  85. {
  86.   int             ret;
  87.   int             bits;
  88.   int             dev_type = dev & 0x0f;
  89.   int             mode = file->mode & O_ACCMODE;
  90.  
  91.   dev = dev >> 4;
  92.  
  93.   if (dev_type == SND_DEV_DSP16)
  94.     bits = 16;
  95.   else
  96.     bits = 8;
  97.  
  98.   if ((ret = DMAbuf_open (dev, mode)) < 0)
  99.     return ret;
  100.  
  101.   local_conversion[dev] = 0;
  102.  
  103.   if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, bits, 1) != bits)
  104.     {
  105.       audio_release (dev, file);
  106.       return RET_ERROR (ENXIO);
  107.     }
  108.  
  109.   if (dev_type == SND_DEV_AUDIO)
  110.     {
  111.       set_format (dev, AFMT_MU_LAW);
  112.     }
  113.   else
  114.     set_format (dev, bits);
  115.  
  116.   wr_buff_no[dev] = -1;
  117.   audio_mode[dev] = AM_NONE;
  118.  
  119.   return ret;
  120. }
  121.  
  122. void
  123. audio_release (int dev, struct fileinfo *file)
  124. {
  125.   int             mode;
  126.  
  127.   dev = dev >> 4;
  128.   mode = file->mode & O_ACCMODE;
  129.  
  130.   if (wr_buff_no[dev] >= 0)
  131.     {
  132.       DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
  133.  
  134.       wr_buff_no[dev] = -1;
  135.     }
  136.  
  137.   DMAbuf_release (dev, mode);
  138. }
  139.  
  140. #ifdef NO_INLINE_ASM
  141. static void
  142. translate_bytes (const unsigned char *table, unsigned char *buff, unsigned long n)
  143. {
  144.   unsigned long   i;
  145.  
  146.   for (i = 0; i < n; ++i)
  147.     buff[i] = table[buff[i]];
  148. }
  149.  
  150. #else
  151. extern inline void
  152. translate_bytes (const void *table, void *buff, unsigned long n)
  153. {
  154.   __asm__ ("cld\n"
  155.        "1:\tlodsb\n\t"
  156.        "xlatb\n\t"
  157.        "stosb\n\t"
  158.        "loop 1b\n\t":
  159.        :"b" ((long) table), "c" (n), "D" ((long) buff), "S" ((long) buff)
  160.        :"bx", "cx", "di", "si", "ax");
  161. }
  162.  
  163. #endif
  164.  
  165. int
  166. audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
  167. {
  168.   int             c, p, l;
  169.   int             err;
  170.  
  171.   dev = dev >> 4;
  172.  
  173.   p = 0;
  174.   c = count;
  175.  
  176.   if (audio_mode[dev] == AM_READ)    /*
  177.                      * Direction changed
  178.                      */
  179.     {
  180.       wr_buff_no[dev] = -1;
  181.     }
  182.  
  183.   audio_mode[dev] = AM_WRITE;
  184.  
  185.   if (!count)            /*
  186.                  * Flush output
  187.                  */
  188.     {
  189.       if (wr_buff_no[dev] >= 0)
  190.     {
  191.       DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
  192.  
  193.       wr_buff_no[dev] = -1;
  194.     }
  195.       return 0;
  196.     }
  197.  
  198.   while (c)
  199.     {                /*
  200.                  * Perform output blocking
  201.                  */
  202.       if (wr_buff_no[dev] < 0)    /*
  203.                  * There is no incomplete buffers
  204.                  */
  205.     {
  206.       if ((wr_buff_no[dev] = DMAbuf_getwrbuffer (dev, &wr_dma_buf[dev], &wr_buff_size[dev])) < 0)
  207.         {
  208.           return wr_buff_no[dev];
  209.         }
  210.       wr_buff_ptr[dev] = 0;
  211.     }
  212.  
  213.       l = c;
  214.       if (l > (wr_buff_size[dev] - wr_buff_ptr[dev]))
  215.     l = (wr_buff_size[dev] - wr_buff_ptr[dev]);
  216.  
  217.       if (!audio_devs[dev]->copy_from_user)
  218.     {            /*
  219.                  * No device specific copy routine
  220.                  */
  221.       COPY_FROM_USER (&wr_dma_buf[dev][wr_buff_ptr[dev]], buf, p, l);
  222.     }
  223.       else
  224.     audio_devs[dev]->copy_from_user (dev,
  225.                   wr_dma_buf[dev], wr_buff_ptr[dev], buf, p, l);
  226.  
  227.  
  228.       /*
  229.        * Insert local processing here
  230.        */
  231.  
  232.       if (local_conversion[dev] == AFMT_MU_LAW)
  233.     {
  234. #ifdef linux
  235.       /*
  236.        * This just allows interrupts while the conversion is running
  237.        */
  238.       __asm__ ("sti");
  239. #endif
  240.       translate_bytes (ulaw_dsp, (unsigned char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l);
  241.     }
  242.  
  243.       c -= l;
  244.       p += l;
  245.       wr_buff_ptr[dev] += l;
  246.  
  247.       if (wr_buff_ptr[dev] >= wr_buff_size[dev])
  248.     {
  249.       if ((err = DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev])) < 0)
  250.         {
  251.           return err;
  252.         }
  253.  
  254.       wr_buff_no[dev] = -1;
  255.     }
  256.  
  257.     }
  258.  
  259.   return count;
  260. }
  261.  
  262. int
  263. audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
  264. {
  265.   int             c, p, l;
  266.   char           *dmabuf;
  267.   int             buff_no;
  268.  
  269.   dev = dev >> 4;
  270.   p = 0;
  271.   c = count;
  272.  
  273.   if (audio_mode[dev] == AM_WRITE)
  274.     {
  275.       if (wr_buff_no[dev] >= 0)
  276.     {
  277.       DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
  278.  
  279.       wr_buff_no[dev] = -1;
  280.     }
  281.     }
  282.  
  283.   audio_mode[dev] = AM_READ;
  284.  
  285.   while (c)
  286.     {
  287.       if ((buff_no = DMAbuf_getrdbuffer (dev, &dmabuf, &l)) < 0)
  288.     return buff_no;
  289.  
  290.       if (l > c)
  291.     l = c;
  292.  
  293.       /*
  294.        * Insert any local processing here.
  295.        */
  296.  
  297.       if (local_conversion[dev] == AFMT_MU_LAW)
  298.     {
  299. #ifdef linux
  300.       /*
  301.        * This just allows interrupts while the conversion is running
  302.        */
  303.       __asm__ ("sti");
  304. #endif
  305.  
  306.       translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l);
  307.     }
  308.  
  309.       COPY_TO_USER (buf, p, dmabuf, l);
  310.  
  311.       DMAbuf_rmchars (dev, buff_no, l);
  312.  
  313.       p += l;
  314.       c -= l;
  315.     }
  316.  
  317.   return count - c;
  318. }
  319.  
  320. int
  321. audio_ioctl (int dev, struct fileinfo *file,
  322.          unsigned int cmd, unsigned int arg)
  323. {
  324.  
  325.   dev = dev >> 4;
  326.  
  327.   switch (cmd)
  328.     {
  329.     case SNDCTL_DSP_SYNC:
  330.       if (wr_buff_no[dev] >= 0)
  331.     {
  332.       DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
  333.  
  334.       wr_buff_no[dev] = -1;
  335.     }
  336.       return DMAbuf_ioctl (dev, cmd, arg, 0);
  337.       break;
  338.  
  339.     case SNDCTL_DSP_POST:
  340.       if (wr_buff_no[dev] >= 0)
  341.     {
  342.       DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
  343.  
  344.       wr_buff_no[dev] = -1;
  345.     }
  346.       return 0;
  347.       break;
  348.  
  349.     case SNDCTL_DSP_RESET:
  350.       wr_buff_no[dev] = -1;
  351.       return DMAbuf_ioctl (dev, cmd, arg, 0);
  352.       break;
  353.  
  354.     case SNDCTL_DSP_GETFMTS:
  355.       return IOCTL_OUT (arg, audio_devs[dev]->format_mask);
  356.       break;
  357.  
  358.     case SNDCTL_DSP_SETFMT:
  359.       return IOCTL_OUT (arg, set_format (dev, IOCTL_IN (arg)));
  360.  
  361.     default:
  362.       return DMAbuf_ioctl (dev, cmd, arg, 0);
  363.       break;
  364.     }
  365. }
  366.  
  367. long
  368. audio_init (long mem_start)
  369. {
  370.   /*
  371.  * NOTE! This routine could be called several times during boot.
  372.  */
  373.   return mem_start;
  374. }
  375.  
  376. #else
  377. /*
  378.  * Stub versions
  379.  */
  380.  
  381. int
  382. audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
  383. {
  384.   return RET_ERROR (EIO);
  385. }
  386.  
  387. int
  388. audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
  389. {
  390.   return RET_ERROR (EIO);
  391. }
  392.  
  393. int
  394. audio_open (int dev, struct fileinfo *file)
  395. {
  396.   return RET_ERROR (ENXIO);
  397. }
  398.  
  399. void
  400. audio_release (int dev, struct fileinfo *file)
  401. {
  402. };
  403. int
  404. audio_ioctl (int dev, struct fileinfo *file,
  405.          unsigned int cmd, unsigned int arg)
  406. {
  407.   return RET_ERROR (EIO);
  408. }
  409.  
  410. int
  411. audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig)
  412. {
  413.   return RET_ERROR (EIO);
  414. }
  415.  
  416. long
  417. audio_init (long mem_start)
  418. {
  419.   return mem_start;
  420. }
  421.  
  422. #endif
  423.  
  424. #endif
  425.