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

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