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  * linux/kernel/chr_drv/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   /* Reset input and output FIFO pointers */
  66   pas_write (M_C_RESET_INPUT_FIFO | M_C_RESET_OUTPUT_FIFO,
  67              MIDI_CONTROL);
  68 
  69   DISABLE_INTR (flags);
  70 
  71   if ((err = pas_set_intr (I_M_MIDI_IRQ_ENABLE)) < 0)
  72     return err;
  73 
  74   /* Enable input available and output FIFO empty interrupts */
  75 
  76   ctrl = 0;
  77   input_opened = 0;
  78   midi_input_intr = input;
  79 
  80   if (mode == OPEN_READ || mode == OPEN_READWRITE)
  81     {
  82       ctrl |= M_C_ENA_INPUT_IRQ;/* Enable input */
  83       input_opened = 1;
  84     }
  85 
  86   if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
  87     {
  88       ctrl |= M_C_ENA_OUTPUT_IRQ |      /* Enable output */
  89         M_C_ENA_OUTPUT_HALF_IRQ;
  90     }
  91 
  92   pas_write (ctrl,
  93              MIDI_CONTROL);
  94 
  95   /* Acknowledge any pending interrupts */
  96 
  97   pas_write (0xff, MIDI_STATUS);
  98   ofifo_bytes = 0;
  99 
 100   RESTORE_INTR (flags);
 101 
 102   midi_busy = 1;
 103   qlen = qhead = qtail = 0;
 104   return 0;
 105 }
 106 
 107 static void
 108 pas_midi_close (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 109 {
 110 
 111   /* Reset FIFO pointers, disable intrs */
 112   pas_write (M_C_RESET_INPUT_FIFO | M_C_RESET_OUTPUT_FIFO, MIDI_CONTROL);
 113 
 114   pas_remove_intr (I_M_MIDI_IRQ_ENABLE);
 115   midi_busy = 0;
 116 }
 117 
 118 static int
 119 dump_to_midi (unsigned char midi_byte)
     /* [previous][next][first][last][top][bottom][index][help] */
 120 {
 121   int             fifo_space, x;
 122 
 123   fifo_space = ((x = pas_read (MIDI_FIFO_STATUS)) >> 4) & 0x0f;
 124 
 125   if (fifo_space == 15 || (fifo_space < 2 && ofifo_bytes > 13)) /* Fifo full */
 126     {
 127       return 0;                 /* Upper layer will call again */
 128     }
 129 
 130   ofifo_bytes++;
 131 
 132   pas_write (midi_byte, MIDI_DATA);
 133 
 134   return 1;
 135 }
 136 
 137 static int
 138 pas_midi_out (int dev, unsigned char midi_byte)
     /* [previous][next][first][last][top][bottom][index][help] */
 139 {
 140 
 141   unsigned long   flags;
 142 
 143   /*
 144    * Drain the local queue first
 145    */
 146 
 147   DISABLE_INTR (flags);
 148 
 149   while (qlen && dump_to_midi (tmp_queue[qhead]))
 150     {
 151       qlen--;
 152       qhead++;
 153     }
 154 
 155   RESTORE_INTR (flags);
 156 
 157   /*
 158    * Output the byte if the local queue is empty.
 159    */
 160 
 161   if (!qlen)
 162     if (dump_to_midi (midi_byte))
 163       return 1;                 /* OK */
 164 
 165   /*
 166    * Put to the local queue
 167    */
 168 
 169   if (qlen >= 256)
 170     return 0;                   /* Local queue full */
 171 
 172   DISABLE_INTR (flags);
 173 
 174   tmp_queue[qtail] = midi_byte;
 175   qlen++;
 176   qtail++;
 177 
 178   RESTORE_INTR (flags);
 179 
 180   return 1;
 181 }
 182 
 183 static int
 184 pas_midi_start_read (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 185 {
 186   return 0;
 187 }
 188 
 189 static int
 190 pas_midi_end_read (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 191 {
 192   return 0;
 193 }
 194 
 195 static int
 196 pas_midi_ioctl (int dev, unsigned cmd, unsigned arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 197 {
 198   return RET_ERROR (EINVAL);
 199 }
 200 
 201 static void
 202 pas_midi_kick (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 203 {
 204   ofifo_bytes = 0;
 205 }
 206 
 207 static int
 208 pas_buffer_status (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 209 {
 210   return !qlen;
 211 }
 212 
 213 static struct midi_operations pas_midi_operations =
 214 {
 215   {"Pro Audio Spectrum", 0, 0, SNDCARD_PAS},
 216   pas_midi_open,
 217   pas_midi_close,
 218   pas_midi_ioctl,
 219   pas_midi_out,
 220   pas_midi_start_read,
 221   pas_midi_end_read,
 222   pas_midi_kick,
 223   NULL,                         /* command */
 224   pas_buffer_status
 225 };
 226 
 227 long
 228 pas_midi_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 229 {
 230   my_dev = num_midis;
 231   midi_devs[num_midis++] = &pas_midi_operations;
 232   return mem_start;
 233 }
 234 
 235 void
 236 pas_midi_interrupt (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 237 {
 238   unsigned char   stat;
 239   int             i, incount;
 240   unsigned long   flags;
 241 
 242   stat = pas_read (MIDI_STATUS);
 243 
 244   if (stat & M_S_INPUT_AVAIL)   /* Input byte available */
 245     {
 246       incount = pas_read (MIDI_FIFO_STATUS) & 0x0f;     /* Input FIFO count */
 247       if (!incount)
 248         incount = 16;
 249 
 250       for (i = 0; i < incount; i++)
 251         if (input_opened)
 252           {
 253             midi_input_intr (my_dev, pas_read (MIDI_DATA));
 254           }
 255         else
 256           pas_read (MIDI_DATA); /* Flush */
 257     }
 258 
 259   if (stat & (M_S_OUTPUT_EMPTY | M_S_OUTPUT_HALF_EMPTY))
 260     {
 261       if (!(stat & M_S_OUTPUT_EMPTY))
 262         {
 263           ofifo_bytes = 8;
 264         }
 265       else
 266         {
 267           ofifo_bytes = 0;
 268         }
 269 
 270       DISABLE_INTR (flags);
 271 
 272       while (qlen && dump_to_midi (tmp_queue[qhead]))
 273         {
 274           qlen--;
 275           qhead++;
 276         }
 277 
 278       RESTORE_INTR (flags);
 279     }
 280 
 281   if (stat & M_S_FRAMING_ERROR)
 282     printk ("MIDI framing error\n");
 283 
 284   if (stat & M_S_OUTPUT_OVERRUN)
 285     {
 286       printk ("MIDI output overrun %02x,%02x,%d \n", pas_read (MIDI_FIFO_STATUS), stat, ofifo_bytes);
 287       ofifo_bytes = 100;
 288     }
 289 
 290   pas_write (stat, MIDI_STATUS);/* Acknowledge interrupts */
 291 }
 292 
 293 #endif
 294 
 295 #endif

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