home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / drivers / sound / pas2_midi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-18  |  6.4 KB  |  339 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.   /*
  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)
  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)
  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)
  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)
  206. {
  207.   return 0;
  208. }
  209.  
  210. static int
  211. pas_midi_end_read (int dev)
  212. {
  213.   return 0;
  214. }
  215.  
  216. static int
  217. pas_midi_ioctl (int dev, unsigned cmd, unsigned arg)
  218. {
  219.   return RET_ERROR (EINVAL);
  220. }
  221.  
  222. static void
  223. pas_midi_kick (int dev)
  224. {
  225.   ofifo_bytes = 0;
  226. }
  227.  
  228. static int
  229. pas_buffer_status (int dev)
  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)
  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)
  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
  339.