root/drivers/sound/pas2_midi.c

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

DEFINITIONS

This source file includes following definitions.
  1. pas_midi_open
  2. pas_midi_close
  3. dump_to_midi
  4. pas_midi_out
  5. pas_midi_start_read
  6. pas_midi_end_read
  7. pas_midi_ioctl
  8. pas_midi_kick
  9. pas_buffer_status
  10. pas_midi_init
  11. pas_midi_interrupt

   1 /*
   2  * sound/pas2_midi.c
   3  *
   4  * The low level driver for the PAS Midi Interface.
   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 
  34 #include "pas.h"
  35 
  36 #if !defined(EXCLUDE_PAS) && !defined(EXCLUDE_MIDI)
  37 
  38 static int      midi_busy = 0, input_opened = 0;
  39 static int      my_dev;
  40 static volatile int ofifo_bytes = 0;
  41 
  42 static unsigned char tmp_queue[256];
  43 static volatile int qlen;
  44 static volatile unsigned char qhead, qtail;
  45 
  46 static void     (*midi_input_intr) (int dev, unsigned char data);
  47 
  48 static int
  49 pas_midi_open (int dev, int mode,
     /* [previous][next][first][last][top][bottom][index][help] */
  50                void            (*input) (int dev, unsigned char data),
  51                void            (*output) (int dev)
  52 )
  53 {
  54   int             err;
  55   unsigned long   flags;
  56   unsigned char   ctrl;
  57 
  58 
  59   if (midi_busy)
  60     {
  61       printk ("PAS2: Midi busy\n");
  62       return -EBUSY;
  63     }
  64 
  65   /*
  66    * Reset input and output FIFO pointers
  67    */
  68   pas_write (M_C_RESET_INPUT_FIFO | M_C_RESET_OUTPUT_FIFO,
  69              MIDI_CONTROL);
  70 
  71   save_flags (flags);
  72   cli ();
  73 
  74   if ((err = pas_set_intr (I_M_MIDI_IRQ_ENABLE)) < 0)
  75     return err;
  76 
  77   /*
  78    * Enable input available and output FIFO empty interrupts
  79    */
  80 
  81   ctrl = 0;
  82   input_opened = 0;
  83   midi_input_intr = input;
  84 
  85   if (mode == OPEN_READ || mode == OPEN_READWRITE)
  86     {
  87       ctrl |= M_C_ENA_INPUT_IRQ;        /*
  88                                            * Enable input
  89                                          */
  90       input_opened = 1;
  91     }
  92 
  93   if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
  94     {
  95       ctrl |= M_C_ENA_OUTPUT_IRQ |      /*
  96                                          * Enable output
  97                                          */
  98         M_C_ENA_OUTPUT_HALF_IRQ;
  99     }
 100 
 101   pas_write (ctrl,
 102              MIDI_CONTROL);
 103 
 104   /*
 105    * Acknowledge any pending interrupts
 106    */
 107 
 108   pas_write (0xff, MIDI_STATUS);
 109   ofifo_bytes = 0;
 110 
 111   restore_flags (flags);
 112 
 113   midi_busy = 1;
 114   qlen = qhead = qtail = 0;
 115   return 0;
 116 }
 117 
 118 static void
 119 pas_midi_close (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 120 {
 121 
 122   /*
 123    * Reset FIFO pointers, disable intrs
 124    */
 125   pas_write (M_C_RESET_INPUT_FIFO | M_C_RESET_OUTPUT_FIFO, MIDI_CONTROL);
 126 
 127   pas_remove_intr (I_M_MIDI_IRQ_ENABLE);
 128   midi_busy = 0;
 129 }
 130 
 131 static int
 132 dump_to_midi (unsigned char midi_byte)
     /* [previous][next][first][last][top][bottom][index][help] */
 133 {
 134   int             fifo_space, x;
 135 
 136   fifo_space = ((x = pas_read (MIDI_FIFO_STATUS)) >> 4) & 0x0f;
 137 
 138   if (fifo_space == 15 || (fifo_space < 2 && ofifo_bytes > 13))         /*
 139                                                                            * Fifo
 140                                                                            * full
 141                                                                          */
 142     {
 143       return 0;                 /*
 144                                  * Upper layer will call again
 145                                  */
 146     }
 147 
 148   ofifo_bytes++;
 149 
 150   pas_write (midi_byte, MIDI_DATA);
 151 
 152   return 1;
 153 }
 154 
 155 static int
 156 pas_midi_out (int dev, unsigned char midi_byte)
     /* [previous][next][first][last][top][bottom][index][help] */
 157 {
 158 
 159   unsigned long   flags;
 160 
 161   /*
 162    * Drain the local queue first
 163    */
 164 
 165   save_flags (flags);
 166   cli ();
 167 
 168   while (qlen && dump_to_midi (tmp_queue[qhead]))
 169     {
 170       qlen--;
 171       qhead++;
 172     }
 173 
 174   restore_flags (flags);
 175 
 176   /*
 177    * Output the byte if the local queue is empty.
 178    */
 179 
 180   if (!qlen)
 181     if (dump_to_midi (midi_byte))
 182       return 1;                 /*
 183                                  * OK
 184                                  */
 185 
 186   /*
 187    * Put to the local queue
 188    */
 189 
 190   if (qlen >= 256)
 191     return 0;                   /*
 192                                  * Local queue full
 193                                  */
 194 
 195   save_flags (flags);
 196   cli ();
 197 
 198   tmp_queue[qtail] = midi_byte;
 199   qlen++;
 200   qtail++;
 201 
 202   restore_flags (flags);
 203 
 204   return 1;
 205 }
 206 
 207 static int
 208 pas_midi_start_read (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 209 {
 210   return 0;
 211 }
 212 
 213 static int
 214 pas_midi_end_read (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 215 {
 216   return 0;
 217 }
 218 
 219 static int
 220 pas_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 221 {
 222   return -EINVAL;
 223 }
 224 
 225 static void
 226 pas_midi_kick (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 227 {
 228   ofifo_bytes = 0;
 229 }
 230 
 231 static int
 232 pas_buffer_status (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 233 {
 234   return qlen;
 235 }
 236 
 237 #define MIDI_SYNTH_NAME "Pro Audio Spectrum Midi"
 238 #define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
 239 #include "midi_synth.h"
 240 
 241 static struct midi_operations pas_midi_operations =
 242 {
 243   {"Pro Audio Spectrum", 0, 0, SNDCARD_PAS},
 244   &std_midi_synth,
 245   {0},
 246   pas_midi_open,
 247   pas_midi_close,
 248   pas_midi_ioctl,
 249   pas_midi_out,
 250   pas_midi_start_read,
 251   pas_midi_end_read,
 252   pas_midi_kick,
 253   NULL,                         /*
 254                                  * command
 255                                  */
 256   pas_buffer_status,
 257   NULL
 258 };
 259 
 260 long
 261 pas_midi_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 262 {
 263   if (num_midis >= MAX_MIDI_DEV)
 264     {
 265       printk ("Sound: Too many midi devices detected\n");
 266       return mem_start;
 267     }
 268 
 269   std_midi_synth.midi_dev = my_dev = num_midis;
 270   midi_devs[num_midis++] = &pas_midi_operations;
 271   return mem_start;
 272 }
 273 
 274 void
 275 pas_midi_interrupt (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 276 {
 277   unsigned char   stat;
 278   int             i, incount;
 279   unsigned long   flags;
 280 
 281   stat = pas_read (MIDI_STATUS);
 282 
 283   if (stat & M_S_INPUT_AVAIL)   /*
 284                                  * Input byte available
 285                                  */
 286     {
 287       incount = pas_read (MIDI_FIFO_STATUS) & 0x0f;     /*
 288                                                          * Input FIFO count
 289                                                          */
 290       if (!incount)
 291         incount = 16;
 292 
 293       for (i = 0; i < incount; i++)
 294         if (input_opened)
 295           {
 296             midi_input_intr (my_dev, pas_read (MIDI_DATA));
 297           }
 298         else
 299           pas_read (MIDI_DATA); /*
 300                                  * Flush
 301                                  */
 302     }
 303 
 304   if (stat & (M_S_OUTPUT_EMPTY | M_S_OUTPUT_HALF_EMPTY))
 305     {
 306       if (!(stat & M_S_OUTPUT_EMPTY))
 307         {
 308           ofifo_bytes = 8;
 309         }
 310       else
 311         {
 312           ofifo_bytes = 0;
 313         }
 314 
 315       save_flags (flags);
 316       cli ();
 317 
 318       while (qlen && dump_to_midi (tmp_queue[qhead]))
 319         {
 320           qlen--;
 321           qhead++;
 322         }
 323 
 324       restore_flags (flags);
 325     }
 326 
 327 
 328   if (stat & M_S_OUTPUT_OVERRUN)
 329     {
 330       printk ("MIDI output overrun %x,%x,%d \n", pas_read (MIDI_FIFO_STATUS), stat, ofifo_bytes);
 331       ofifo_bytes = 100;
 332     }
 333 
 334   pas_write (stat, MIDI_STATUS);        /*
 335                                            * Acknowledge interrupts
 336                                          */
 337 }
 338 
 339 #endif
 340 
 341 #endif

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