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 static struct wait_queue *midi_sleeper[MAX_MIDI_DEV] =
  41 {NULL};
  42 static volatile struct snd_wait midi_sleep_flag[MAX_MIDI_DEV] =
  43 {
  44   {0}};
  45 static struct wait_queue *input_sleeper[MAX_MIDI_DEV] =
  46 {NULL};
  47 static volatile struct snd_wait input_sleep_flag[MAX_MIDI_DEV] =
  48 {
  49   {0}};
  50 
  51 struct midi_buf
  52   {
  53     int             len, head, tail;
  54     unsigned char   queue[MAX_QUEUE_SIZE];
  55   };
  56 
  57 struct midi_parms
  58   {
  59     int             prech_timeout;      /*
  60                                          * Timeout before the first ch
  61                                          */
  62   };
  63 
  64 static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] =
  65 {NULL};
  66 static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] =
  67 {NULL};
  68 static struct midi_parms parms[MAX_MIDI_DEV];
  69 
  70 static void     midi_poll (unsigned long dummy);
  71 
  72 
  73 static struct timer_list poll_timer =
  74 {NULL, NULL, 0, 0, midi_poll};
  75 static volatile int open_devs = 0;
  76 
  77 #define DATA_AVAIL(q) (q->len)
  78 #define SPACE_AVAIL(q) (MAX_QUEUE_SIZE - q->len)
  79 
  80 #define QUEUE_BYTE(q, data) \
  81         if (SPACE_AVAIL(q)) \
  82         { \
  83           unsigned long flags; \
  84           save_flags(flags);cli(); \
  85           q->queue[q->tail] = (data); \
  86           q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \
  87           restore_flags(flags); \
  88         }
  89 
  90 #define REMOVE_BYTE(q, data) \
  91         if (DATA_AVAIL(q)) \
  92         { \
  93           unsigned long flags; \
  94           save_flags(flags);cli(); \
  95           data = q->queue[q->head]; \
  96           q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \
  97           restore_flags(flags); \
  98         }
  99 
 100 void
 101 drain_midi_queue (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 102 {
 103 
 104   /*
 105    * Give the Midi driver time to drain its output queues
 106    */
 107 
 108   if (midi_devs[dev]->buffer_status != NULL)
 109     while (!((current->signal & ~current->blocked)) &&
 110            midi_devs[dev]->buffer_status (dev))
 111 
 112       {
 113         unsigned long   tl;
 114 
 115         if (HZ / 10)
 116           tl = current->timeout = jiffies + (HZ / 10);
 117         else
 118           tl = 0xffffffff;
 119         midi_sleep_flag[dev].mode = WK_SLEEP;
 120         interruptible_sleep_on (&midi_sleeper[dev]);
 121         if (!(midi_sleep_flag[dev].mode & WK_WAKEUP))
 122           {
 123             if (current->signal & ~current->blocked)
 124               midi_sleep_flag[dev].aborting = 1;
 125             else if (jiffies >= tl)
 126               midi_sleep_flag[dev].mode |= WK_TIMEOUT;
 127           }
 128         midi_sleep_flag[dev].mode &= ~WK_SLEEP;
 129       };
 130 }
 131 
 132 static void
 133 midi_input_intr (int dev, unsigned char data)
     /* [previous][next][first][last][top][bottom][index][help] */
 134 {
 135   if (midi_in_buf[dev] == NULL)
 136     return;
 137 
 138   if (data == 0xfe)             /*
 139                                  * Active sensing
 140                                  */
 141     return;                     /*
 142                                  * Ignore
 143                                  */
 144 
 145   if (SPACE_AVAIL (midi_in_buf[dev]))
 146     {
 147       QUEUE_BYTE (midi_in_buf[dev], data);
 148       if ((input_sleep_flag[dev].mode & WK_SLEEP))
 149         {
 150           input_sleep_flag[dev].mode = WK_WAKEUP;
 151           wake_up (&input_sleeper[dev]);
 152         };
 153     }
 154 
 155 }
 156 
 157 static void
 158 midi_output_intr (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 159 {
 160   /*
 161    * Currently NOP
 162    */
 163 }
 164 
 165 static void
 166 midi_poll (unsigned long dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 167 {
 168   unsigned long   flags;
 169   int             dev;
 170 
 171   save_flags (flags);
 172   cli ();
 173   if (open_devs)
 174     {
 175       for (dev = 0; dev < num_midis; dev++)
 176         if (midi_out_buf[dev] != NULL)
 177           {
 178             while (DATA_AVAIL (midi_out_buf[dev]) &&
 179                    midi_devs[dev]->putc (dev,
 180                          midi_out_buf[dev]->queue[midi_out_buf[dev]->head]))
 181               {
 182                 midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE;
 183                 midi_out_buf[dev]->len--;
 184               }
 185 
 186             if (DATA_AVAIL (midi_out_buf[dev]) < 100 &&
 187                 (midi_sleep_flag[dev].mode & WK_SLEEP))
 188               {
 189                 midi_sleep_flag[dev].mode = WK_WAKEUP;
 190                 wake_up (&midi_sleeper[dev]);
 191               };
 192           }
 193 
 194       {
 195         poll_timer.expires = (1) + jiffies;
 196         add_timer (&poll_timer);
 197       };                        /*
 198                                    * Come back later
 199                                  */
 200     }
 201   restore_flags (flags);
 202 }
 203 
 204 int
 205 MIDIbuf_open (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 206 {
 207   int             mode, err;
 208   unsigned long   flags;
 209 
 210   dev = dev >> 4;
 211   mode = file->mode & O_ACCMODE;
 212 
 213   if (num_midis > MAX_MIDI_DEV)
 214     {
 215       printk ("Sound: FATAL ERROR: Too many midi interfaces\n");
 216       num_midis = MAX_MIDI_DEV;
 217     }
 218 
 219   if (dev < 0 || dev >= num_midis)
 220     {
 221       printk ("Sound: Nonexistent MIDI interface %d\n", dev);
 222       return -ENXIO;
 223     }
 224 
 225   /*
 226      *    Interrupts disabled. Be careful
 227    */
 228 
 229   save_flags (flags);
 230   cli ();
 231   if ((err = midi_devs[dev]->open (dev, mode,
 232                                    midi_input_intr, midi_output_intr)) < 0)
 233     {
 234       restore_flags (flags);
 235       return err;
 236     }
 237 
 238   parms[dev].prech_timeout = 0;
 239 
 240   {
 241     midi_sleep_flag[dev].aborting = 0;
 242     midi_sleep_flag[dev].mode = WK_NONE;
 243   };
 244   {
 245     input_sleep_flag[dev].aborting = 0;
 246     input_sleep_flag[dev].mode = WK_NONE;
 247   };
 248 
 249   midi_in_buf[dev] = (struct midi_buf *) (
 250                                            {
 251                                            caddr_t x;
 252                          x = kmalloc (sizeof (struct midi_buf), GFP_KERNEL);
 253 
 254                                            x;
 255                                            }
 256   );
 257 
 258   if (midi_in_buf[dev] == NULL)
 259     {
 260       printk ("midi: Can't allocate buffer\n");
 261       midi_devs[dev]->close (dev);
 262       restore_flags (flags);
 263       return -EIO;
 264     }
 265   midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
 266 
 267   midi_out_buf[dev] = (struct midi_buf *) (
 268                                             {
 269                                             caddr_t x;
 270                          x = kmalloc (sizeof (struct midi_buf), GFP_KERNEL);
 271 
 272                                             x;
 273                                             }
 274   );
 275 
 276   if (midi_out_buf[dev] == NULL)
 277     {
 278       printk ("midi: Can't allocate buffer\n");
 279       midi_devs[dev]->close (dev);
 280       kfree (midi_in_buf[dev]);
 281       midi_in_buf[dev] = NULL;
 282       restore_flags (flags);
 283       return -EIO;
 284     }
 285   midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
 286   if (!open_devs)
 287 
 288     {
 289       poll_timer.expires = (1) + jiffies;
 290       add_timer (&poll_timer);
 291     };                          /*
 292                                    * Come back later
 293                                  */
 294   open_devs++;
 295   restore_flags (flags);
 296 
 297   return err;
 298 }
 299 
 300 void
 301 MIDIbuf_release (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 302 {
 303   int             mode;
 304   unsigned long   flags;
 305 
 306   dev = dev >> 4;
 307   mode = file->mode & O_ACCMODE;
 308 
 309   save_flags (flags);
 310   cli ();
 311 
 312   /*
 313      * Wait until the queue is empty
 314    */
 315 
 316   if (mode != OPEN_READ)
 317     {
 318       midi_devs[dev]->putc (dev, 0xfe);         /*
 319                                                    * Active sensing to shut the
 320                                                    * devices
 321                                                  */
 322 
 323       while (!((current->signal & ~current->blocked)) &&
 324              DATA_AVAIL (midi_out_buf[dev]))
 325 
 326         {
 327           unsigned long   tl;
 328 
 329           if (0)
 330             tl = current->timeout = jiffies + (0);
 331           else
 332             tl = 0xffffffff;
 333           midi_sleep_flag[dev].mode = WK_SLEEP;
 334           interruptible_sleep_on (&midi_sleeper[dev]);
 335           if (!(midi_sleep_flag[dev].mode & WK_WAKEUP))
 336             {
 337               if (current->signal & ~current->blocked)
 338                 midi_sleep_flag[dev].aborting = 1;
 339               else if (jiffies >= tl)
 340                 midi_sleep_flag[dev].mode |= WK_TIMEOUT;
 341             }
 342           midi_sleep_flag[dev].mode &= ~WK_SLEEP;
 343         };                      /*
 344                                    * Sync
 345                                  */
 346 
 347       drain_midi_queue (dev);   /*
 348                                  * Ensure the output queues are empty
 349                                  */
 350     }
 351 
 352   midi_devs[dev]->close (dev);
 353   kfree (midi_in_buf[dev]);
 354   kfree (midi_out_buf[dev]);
 355   midi_in_buf[dev] = NULL;
 356   midi_out_buf[dev] = NULL;
 357   open_devs--;
 358   del_timer (&poll_timer);;
 359   restore_flags (flags);
 360 }
 361 
 362 int
 363 MIDIbuf_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 364 {
 365   unsigned long   flags;
 366   int             c, n, i;
 367   unsigned char   tmp_data;
 368 
 369   dev = dev >> 4;
 370 
 371   if (!count)
 372     return 0;
 373 
 374   save_flags (flags);
 375   cli ();
 376 
 377   c = 0;
 378 
 379   while (c < count)
 380     {
 381       n = SPACE_AVAIL (midi_out_buf[dev]);
 382 
 383       if (n == 0)               /*
 384                                  * No space just now. We have to sleep
 385                                  */
 386         {
 387 
 388           {
 389             unsigned long   tl;
 390 
 391             if (0)
 392               tl = current->timeout = jiffies + (0);
 393             else
 394               tl = 0xffffffff;
 395             midi_sleep_flag[dev].mode = WK_SLEEP;
 396             interruptible_sleep_on (&midi_sleeper[dev]);
 397             if (!(midi_sleep_flag[dev].mode & WK_WAKEUP))
 398               {
 399                 if (current->signal & ~current->blocked)
 400                   midi_sleep_flag[dev].aborting = 1;
 401                 else if (jiffies >= tl)
 402                   midi_sleep_flag[dev].mode |= WK_TIMEOUT;
 403               }
 404             midi_sleep_flag[dev].mode &= ~WK_SLEEP;
 405           };
 406           if (((current->signal & ~current->blocked)))
 407             {
 408               restore_flags (flags);
 409               return -EINTR;
 410             }
 411 
 412           n = SPACE_AVAIL (midi_out_buf[dev]);
 413         }
 414 
 415       if (n > (count - c))
 416         n = count - c;
 417 
 418       for (i = 0; i < n; i++)
 419         {
 420           memcpy_fromfs ((&tmp_data), &((buf)[c]), (1));
 421           QUEUE_BYTE (midi_out_buf[dev], tmp_data);
 422           c++;
 423         }
 424     }
 425 
 426   restore_flags (flags);
 427 
 428   return c;
 429 }
 430 
 431 
 432 int
 433 MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 434 {
 435   int             n, c = 0;
 436   unsigned long   flags;
 437   unsigned char   tmp_data;
 438 
 439   dev = dev >> 4;
 440 
 441   save_flags (flags);
 442   cli ();
 443 
 444   if (!DATA_AVAIL (midi_in_buf[dev]))   /*
 445                                          * No data yet, wait
 446                                          */
 447     {
 448 
 449       {
 450         unsigned long   tl;
 451 
 452         if (parms[dev].prech_timeout)
 453           tl = current->timeout = jiffies + (parms[dev].prech_timeout);
 454         else
 455           tl = 0xffffffff;
 456         input_sleep_flag[dev].mode = WK_SLEEP;
 457         interruptible_sleep_on (&input_sleeper[dev]);
 458         if (!(input_sleep_flag[dev].mode & WK_WAKEUP))
 459           {
 460             if (current->signal & ~current->blocked)
 461               input_sleep_flag[dev].aborting = 1;
 462             else if (jiffies >= tl)
 463               input_sleep_flag[dev].mode |= WK_TIMEOUT;
 464           }
 465         input_sleep_flag[dev].mode &= ~WK_SLEEP;
 466       };
 467       if (((current->signal & ~current->blocked)))
 468         c = -EINTR;             /*
 469                                    * The user is getting restless
 470                                  */
 471     }
 472 
 473   if (c == 0 && DATA_AVAIL (midi_in_buf[dev]))  /*
 474                                                  * Got some bytes
 475                                                  */
 476     {
 477       n = DATA_AVAIL (midi_in_buf[dev]);
 478       if (n > count)
 479         n = count;
 480       c = 0;
 481 
 482       while (c < n)
 483         {
 484           REMOVE_BYTE (midi_in_buf[dev], tmp_data);
 485           memcpy_tofs (&((buf)[c]), (&tmp_data), (1));
 486           c++;
 487         }
 488     }
 489 
 490   restore_flags (flags);
 491 
 492   return c;
 493 }
 494 
 495 int
 496 MIDIbuf_ioctl (int dev, struct fileinfo *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 497                unsigned int cmd, ioctl_arg arg)
 498 {
 499   int             val;
 500 
 501   dev = dev >> 4;
 502 
 503   if (((cmd >> 8) & 0xff) == 'C')
 504     {
 505       if (midi_devs[dev]->coproc)       /* Coprocessor ioctl */
 506         return midi_devs[dev]->coproc->ioctl (midi_devs[dev]->coproc->devc, cmd, arg, 0);
 507       else
 508         printk ("/dev/midi%d: No coprocessor for this device\n", dev);
 509 
 510       return -ENXIO;
 511     }
 512   else
 513     switch (cmd)
 514       {
 515 
 516       case SNDCTL_MIDI_PRETIME:
 517         val = (int) get_fs_long ((long *) arg);
 518         if (val < 0)
 519           val = 0;
 520 
 521         val = (HZ * val) / 10;
 522         parms[dev].prech_timeout = val;
 523         return snd_ioctl_return ((int *) arg, val);
 524         break;
 525 
 526       default:
 527         return midi_devs[dev]->ioctl (dev, cmd, arg);
 528       }
 529 }
 530 
 531 int
 532 MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 533 {
 534   dev = dev >> 4;
 535 
 536   switch (sel_type)
 537     {
 538     case SEL_IN:
 539       if (!DATA_AVAIL (midi_in_buf[dev]))
 540         {
 541           input_sleep_flag[dev].mode = WK_SLEEP;
 542           select_wait (&input_sleeper[dev], wait);
 543           return 0;
 544         }
 545       return 1;
 546       break;
 547 
 548     case SEL_OUT:
 549       if (SPACE_AVAIL (midi_out_buf[dev]))
 550         {
 551           midi_sleep_flag[dev].mode = WK_SLEEP;
 552           select_wait (&midi_sleeper[dev], wait);
 553           return 0;
 554         }
 555       return 1;
 556       break;
 557 
 558     case SEL_EX:
 559       return 0;
 560     }
 561 
 562   return 0;
 563 }
 564 
 565 
 566 long
 567 MIDIbuf_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 568 {
 569   return mem_start;
 570 }
 571 
 572 #endif

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