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

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