root/drivers/sound/audio.c

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

DEFINITIONS

This source file includes following definitions.
  1. audio_open
  2. audio_release
  3. translate_bytes
  4. translate_bytes
  5. audio_write
  6. audio_read
  7. audio_ioctl
  8. audio_init
  9. audio_read
  10. audio_write
  11. audio_open
  12. audio_release
  13. audio_ioctl
  14. audio_lseek
  15. audio_init

   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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 312 {
 313   return RET_ERROR (EIO);
 314 }
 315 
 316 int
 317 audio_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 318 {
 319   return RET_ERROR (EIO);
 320 }
 321 
 322 int
 323 audio_open (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 324   {
 325     return RET_ERROR (ENXIO);
 326   }
 327 
 328 void
 329 audio_release (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 330   {
 331   };
 332 int
 333 audio_ioctl (int dev, struct fileinfo *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 341 {
 342   return RET_ERROR (EIO);
 343 }
 344 
 345 long
 346 audio_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 347 {
 348   return mem_start;
 349 }
 350 
 351 #endif
 352 
 353 #endif

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