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

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