root/drivers/sound/midibuf.c

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

DEFINITIONS

This source file includes following definitions.
  1. drain_midi_queue
  2. midi_input_intr
  3. midi_output_intr
  4. midi_poll
  5. MIDIbuf_open
  6. MIDIbuf_release
  7. MIDIbuf_write
  8. MIDIbuf_read
  9. MIDIbuf_ioctl
  10. MIDIbuf_select
  11. MIDIbuf_init

   1 /*
   2  * sound/midibuf.c
   3  *
   4  * Device file manager for /dev/midi#
   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 #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MIDI)
  33 
  34 /*
  35  * Don't make MAX_QUEUE_SIZE larger than 4000
  36  */
  37 
  38 #define MAX_QUEUE_SIZE  4000
  39 
  40 DEFINE_WAIT_QUEUES (midi_sleeper[MAX_MIDI_DEV], midi_sleep_flag[MAX_MIDI_DEV]);
  41 DEFINE_WAIT_QUEUES (input_sleeper[MAX_MIDI_DEV], input_sleep_flag[MAX_MIDI_DEV]);
  42 
  43 struct midi_buf
  44   {
  45     int             len, head, tail;
  46     unsigned char   queue[MAX_QUEUE_SIZE];
  47   };
  48 
  49 struct midi_parms
  50   {
  51     int             prech_timeout;      /*
  52                                          * Timeout before the first ch
  53                                          */
  54   };
  55 
  56 static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] =
  57 {NULL};
  58 static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] =
  59 {NULL};
  60 static struct midi_parms parms[MAX_MIDI_DEV];
  61 
  62 static void     midi_poll (unsigned long dummy);
  63 
  64 DEFINE_TIMER (poll_timer, midi_poll);
  65 static volatile int open_devs = 0;
  66 
  67 #define DATA_AVAIL(q) (q->len)
  68 #define SPACE_AVAIL(q) (MAX_QUEUE_SIZE - q->len)
  69 
  70 #define QUEUE_BYTE(q, data) \
  71         if (SPACE_AVAIL(q)) \
  72         { \
  73           unsigned long flags; \
  74           DISABLE_INTR(flags); \
  75           q->queue[q->tail] = (data); \
  76           q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \
  77           RESTORE_INTR(flags); \
  78         }
  79 
  80 #define REMOVE_BYTE(q, data) \
  81         if (DATA_AVAIL(q)) \
  82         { \
  83           unsigned long flags; \
  84           DISABLE_INTR(flags); \
  85           data = q->queue[q->head]; \
  86           q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \
  87           RESTORE_INTR(flags); \
  88         }
  89 
  90 void
  91 drain_midi_queue (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  92 {
  93 
  94   /*
  95    * Give the Midi driver time to drain its output queues
  96    */
  97 
  98   if (midi_devs[dev]->buffer_status != NULL)
  99     while (!PROCESS_ABORTING (midi_sleeper[dev], midi_sleep_flag[dev]) &&
 100            midi_devs[dev]->buffer_status (dev))
 101       DO_SLEEP (midi_sleeper[dev], midi_sleep_flag[dev], HZ / 10);
 102 }
 103 
 104 static void
 105 midi_input_intr (int dev, unsigned char data)
     /* [previous][next][first][last][top][bottom][index][help] */
 106 {
 107   if (midi_in_buf[dev] == NULL)
 108     return;
 109 
 110   if (data == 0xfe)             /*
 111                                  * Active sensing
 112                                  */
 113     return;                     /*
 114                                  * Ignore
 115                                  */
 116 
 117   if (SPACE_AVAIL (midi_in_buf[dev]))
 118     {
 119       QUEUE_BYTE (midi_in_buf[dev], data);
 120       if (SOMEONE_WAITING (input_sleeper[dev], input_sleep_flag[dev]))
 121         WAKE_UP (input_sleeper[dev], input_sleep_flag[dev]);
 122     }
 123 
 124 }
 125 
 126 static void
 127 midi_output_intr (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 128 {
 129   /*
 130    * Currently NOP
 131    */
 132 }
 133 
 134 static void
 135 midi_poll (unsigned long dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 136 {
 137   unsigned long   flags;
 138   int             dev;
 139 
 140   DISABLE_INTR (flags);
 141   if (open_devs)
 142     {
 143       for (dev = 0; dev < num_midis; dev++)
 144         if (midi_out_buf[dev] != NULL)
 145           {
 146             while (DATA_AVAIL (midi_out_buf[dev]) &&
 147                    midi_devs[dev]->putc (dev,
 148                          midi_out_buf[dev]->queue[midi_out_buf[dev]->head]))
 149               {
 150                 midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE;
 151                 midi_out_buf[dev]->len--;
 152               }
 153 
 154             if (DATA_AVAIL (midi_out_buf[dev]) < 100 &&
 155                 SOMEONE_WAITING (midi_sleeper[dev], midi_sleep_flag[dev]))
 156               WAKE_UP (midi_sleeper[dev], midi_sleep_flag[dev]);
 157           }
 158       ACTIVATE_TIMER (poll_timer, midi_poll, 1);        /*
 159                                                          * Come back later
 160                                                          */
 161     }
 162   RESTORE_INTR (flags);
 163 }
 164 
 165 int
 166 MIDIbuf_open (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 167 {
 168   int             mode, err;
 169   unsigned long   flags;
 170 
 171   dev = dev >> 4;
 172   mode = file->mode & O_ACCMODE;
 173 
 174   if (num_midis > MAX_MIDI_DEV)
 175     {
 176       printk ("Sound: FATAL ERROR: Too many midi interfaces\n");
 177       num_midis = MAX_MIDI_DEV;
 178     }
 179 
 180   if (dev < 0 || dev >= num_midis)
 181     {
 182       printk ("Sound: Nonexistent MIDI interface %d\n", dev);
 183       return RET_ERROR (ENXIO);
 184     }
 185 
 186   /*
 187      *    Interrupts disabled. Be careful
 188    */
 189 
 190   DISABLE_INTR (flags);
 191   if ((err = midi_devs[dev]->open (dev, mode,
 192                                    midi_input_intr, midi_output_intr)) < 0)
 193     {
 194       RESTORE_INTR (flags);
 195       return err;
 196     }
 197 
 198   parms[dev].prech_timeout = 0;
 199 
 200   RESET_WAIT_QUEUE (midi_sleeper[dev], midi_sleep_flag[dev]);
 201   RESET_WAIT_QUEUE (input_sleeper[dev], input_sleep_flag[dev]);
 202 
 203   midi_in_buf[dev] = (struct midi_buf *) KERNEL_MALLOC (sizeof (struct midi_buf));
 204 
 205   if (midi_in_buf[dev] == NULL)
 206     {
 207       printk ("midi: Can't allocate buffer\n");
 208       midi_devs[dev]->close (dev);
 209       RESTORE_INTR (flags);
 210       return RET_ERROR (EIO);
 211     }
 212   midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
 213 
 214   midi_out_buf[dev] = (struct midi_buf *) KERNEL_MALLOC (sizeof (struct midi_buf));
 215 
 216   if (midi_out_buf[dev] == NULL)
 217     {
 218       printk ("midi: Can't allocate buffer\n");
 219       midi_devs[dev]->close (dev);
 220       KERNEL_FREE (midi_in_buf[dev]);
 221       midi_in_buf[dev] = NULL;
 222       RESTORE_INTR (flags);
 223       return RET_ERROR (EIO);
 224     }
 225   midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
 226   if (!open_devs)
 227     ACTIVATE_TIMER (poll_timer, midi_poll, 1);  /*
 228                                                  * Come back later
 229                                                  */
 230   open_devs++;
 231   RESTORE_INTR (flags);
 232 
 233   return err;
 234 }
 235 
 236 void
 237 MIDIbuf_release (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 238 {
 239   int             mode;
 240   unsigned long   flags;
 241 
 242   dev = dev >> 4;
 243   mode = file->mode & O_ACCMODE;
 244 
 245   DISABLE_INTR (flags);
 246 
 247   /*
 248      * Wait until the queue is empty
 249    */
 250 
 251   if (mode != OPEN_READ)
 252     {
 253       midi_devs[dev]->putc (dev, 0xfe);         /*
 254                                                    * Active sensing to shut the
 255                                                    * devices
 256                                                  */
 257 
 258       while (!PROCESS_ABORTING (midi_sleeper[dev], midi_sleep_flag[dev]) &&
 259              DATA_AVAIL (midi_out_buf[dev]))
 260         DO_SLEEP (midi_sleeper[dev], midi_sleep_flag[dev], 0);  /*
 261                                                                  * Sync
 262                                                                  */
 263 
 264       drain_midi_queue (dev);   /*
 265                                  * Ensure the output queues are empty
 266                                  */
 267     }
 268 
 269   midi_devs[dev]->close (dev);
 270   KERNEL_FREE (midi_in_buf[dev]);
 271   KERNEL_FREE (midi_out_buf[dev]);
 272   midi_in_buf[dev] = NULL;
 273   midi_out_buf[dev] = NULL;
 274   open_devs--;
 275   RESTORE_INTR (flags);
 276 }
 277 
 278 int
 279 MIDIbuf_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 280 {
 281   unsigned long   flags;
 282   int             c, n, i;
 283   unsigned char   tmp_data;
 284 
 285   dev = dev >> 4;
 286 
 287   if (!count)
 288     return 0;
 289 
 290   DISABLE_INTR (flags);
 291 
 292   c = 0;
 293 
 294   while (c < count)
 295     {
 296       n = SPACE_AVAIL (midi_out_buf[dev]);
 297 
 298       if (n == 0)               /*
 299                                  * No space just now. We have to sleep
 300                                  */
 301         {
 302           DO_SLEEP (midi_sleeper[dev], midi_sleep_flag[dev], 0);
 303           if (PROCESS_ABORTING (midi_sleeper[dev], midi_sleep_flag[dev]))
 304             {
 305               RESTORE_INTR (flags);
 306               return RET_ERROR (EINTR);
 307             }
 308 
 309           n = SPACE_AVAIL (midi_out_buf[dev]);
 310         }
 311 
 312       if (n > (count - c))
 313         n = count - c;
 314 
 315       for (i = 0; i < n; i++)
 316         {
 317           COPY_FROM_USER (&tmp_data, buf, c, 1);
 318           QUEUE_BYTE (midi_out_buf[dev], tmp_data);
 319           c++;
 320         }
 321     }
 322 
 323   RESTORE_INTR (flags);
 324 
 325   return c;
 326 }
 327 
 328 
 329 int
 330 MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 331 {
 332   int             n, c = 0;
 333   unsigned long   flags;
 334   unsigned char   tmp_data;
 335 
 336   dev = dev >> 4;
 337 
 338   DISABLE_INTR (flags);
 339 
 340   if (!DATA_AVAIL (midi_in_buf[dev]))   /*
 341                                          * No data yet, wait
 342                                          */
 343     {
 344       DO_SLEEP (input_sleeper[dev], input_sleep_flag[dev],
 345                 parms[dev].prech_timeout);
 346       if (PROCESS_ABORTING (input_sleeper[dev], input_sleep_flag[dev]))
 347         c = RET_ERROR (EINTR);  /*
 348                                  * The user is getting restless
 349                                  */
 350     }
 351 
 352   if (c == 0 && DATA_AVAIL (midi_in_buf[dev]))  /*
 353                                                  * Got some bytes
 354                                                  */
 355     {
 356       n = DATA_AVAIL (midi_in_buf[dev]);
 357       if (n > count)
 358         n = count;
 359       c = 0;
 360 
 361       while (c < n)
 362         {
 363           REMOVE_BYTE (midi_in_buf[dev], tmp_data);
 364           COPY_TO_USER (buf, c, &tmp_data, 1);
 365           c++;
 366         }
 367     }
 368 
 369   RESTORE_INTR (flags);
 370 
 371   return c;
 372 }
 373 
 374 int
 375 MIDIbuf_ioctl (int dev, struct fileinfo *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 376                unsigned int cmd, unsigned int arg)
 377 {
 378   int             val;
 379 
 380   dev = dev >> 4;
 381 
 382   if (((cmd >> 8) & 0xff) == 'C')
 383     {
 384       if (midi_devs[dev]->coproc)       /* Coprocessor ioctl */
 385         return midi_devs[dev]->coproc->ioctl (midi_devs[dev]->coproc->devc, cmd, arg, 0);
 386       else
 387         printk ("/dev/midi%d: No coprocessor for this device\n", dev);
 388 
 389       return RET_ERROR (EREMOTEIO);
 390     }
 391   else
 392     switch (cmd)
 393       {
 394 
 395       case SNDCTL_MIDI_PRETIME:
 396         val = IOCTL_IN (arg);
 397         if (val < 0)
 398           val = 0;
 399 
 400         val = (HZ * val) / 10;
 401         parms[dev].prech_timeout = val;
 402         return IOCTL_OUT (arg, val);
 403         break;
 404 
 405       default:
 406         return midi_devs[dev]->ioctl (dev, cmd, arg);
 407       }
 408 }
 409 
 410 #ifdef ALLOW_SELECT
 411 int
 412 MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 413 {
 414   dev = dev >> 4;
 415 
 416   switch (sel_type)
 417     {
 418     case SEL_IN:
 419       if (!DATA_AVAIL (midi_in_buf[dev]))
 420         {
 421           input_sleep_flag[dev].mode = WK_SLEEP;
 422           select_wait (&input_sleeper[dev], wait);
 423           return 0;
 424         }
 425       return 1;
 426       break;
 427 
 428     case SEL_OUT:
 429       if (SPACE_AVAIL (midi_out_buf[dev]))
 430         {
 431           midi_sleep_flag[dev].mode = WK_SLEEP;
 432           select_wait (&midi_sleeper[dev], wait);
 433           return 0;
 434         }
 435       return 1;
 436       break;
 437 
 438     case SEL_EX:
 439       return 0;
 440     }
 441 
 442   return 0;
 443 }
 444 
 445 #endif /* ALLOW_SELECT */
 446 
 447 long
 448 MIDIbuf_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 449 {
 450   return mem_start;
 451 }
 452 
 453 #endif

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