home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / drivers / sound / pas2_midi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-09  |  6.0 KB  |  296 lines

  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,
  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)
  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)
  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)
  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)
  185. {
  186.   return 0;
  187. }
  188.  
  189. static int
  190. pas_midi_end_read (int dev)
  191. {
  192.   return 0;
  193. }
  194.  
  195. static int
  196. pas_midi_ioctl (int dev, unsigned cmd, unsigned arg)
  197. {
  198.   return RET_ERROR (EINVAL);
  199. }
  200.  
  201. static void
  202. pas_midi_kick (int dev)
  203. {
  204.   ofifo_bytes = 0;
  205. }
  206.  
  207. static int
  208. pas_buffer_status (int dev)
  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)
  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)
  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 %x,%x,%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
  296.