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

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