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 / gus_midi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-18  |  6.0 KB  |  310 lines

  1. /*
  2.  * sound/gus2_midi.c
  3.  *
  4.  * The low level driver for the GUS 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 "gus_hw.h"
  35.  
  36. #if !defined(EXCLUDE_GUS) && !defined(EXCLUDE_MIDI)
  37.  
  38. static int      midi_busy = 0, input_opened = 0;
  39. static int      my_dev;
  40. static int      output_used = 0;
  41. static volatile unsigned char gus_midi_control;
  42.  
  43. static void     (*midi_input_intr) (int dev, unsigned char data);
  44.  
  45. static unsigned char tmp_queue[256];
  46. static volatile int qlen;
  47. static volatile unsigned char qhead, qtail;
  48. extern int      gus_base, gus_irq, gus_dma;
  49.  
  50. #define GUS_MIDI_STATUS()    INB(u_MidiStatus)
  51.  
  52. static int
  53. gus_midi_open (int dev, int mode,
  54.            void            (*input) (int dev, unsigned char data),
  55.            void            (*output) (int dev)
  56. )
  57. {
  58.  
  59.   if (midi_busy)
  60.     {
  61.       printk ("GUS: Midi busy\n");
  62.       return RET_ERROR (EBUSY);
  63.     }
  64.  
  65.   OUTB (MIDI_RESET, u_MidiControl);
  66.   gus_delay ();
  67.  
  68.   gus_midi_control = 0;
  69.   input_opened = 0;
  70.  
  71.   if (mode == OPEN_READ || mode == OPEN_READWRITE)
  72.     {
  73.       gus_midi_control |= MIDI_ENABLE_RCV;
  74.       input_opened = 1;
  75.     }
  76.  
  77.   if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
  78.     {
  79.       gus_midi_control |= MIDI_ENABLE_XMIT;
  80.     }
  81.  
  82.   OUTB (gus_midi_control, u_MidiControl);    /*
  83.                          * Enable
  84.                          */
  85.  
  86.   midi_busy = 1;
  87.   qlen = qhead = qtail = output_used = 0;
  88.   midi_input_intr = input;
  89.  
  90.   return 0;
  91. }
  92.  
  93. static int
  94. dump_to_midi (unsigned char midi_byte)
  95. {
  96.   unsigned long   flags;
  97.   int             ok = 0;
  98.  
  99.   output_used = 1;
  100.  
  101.   DISABLE_INTR (flags);
  102.  
  103.   if (GUS_MIDI_STATUS () & MIDI_XMIT_EMPTY)
  104.     {
  105.       ok = 1;
  106.       OUTB (midi_byte, u_MidiData);
  107.     }
  108.   else
  109.     {
  110.       /*
  111.        * Enable Midi xmit interrupts (again)
  112.        */
  113.       gus_midi_control |= MIDI_ENABLE_XMIT;
  114.       OUTB (gus_midi_control, u_MidiControl);
  115.     }
  116.  
  117.   RESTORE_INTR (flags);
  118.   return ok;
  119. }
  120.  
  121. static void
  122. gus_midi_close (int dev)
  123. {
  124.   /*
  125.    * Reset FIFO pointers, disable intrs
  126.    */
  127.  
  128.   OUTB (MIDI_RESET, u_MidiControl);
  129.   midi_busy = 0;
  130. }
  131.  
  132. static int
  133. gus_midi_out (int dev, unsigned char midi_byte)
  134. {
  135.  
  136.   unsigned long   flags;
  137.  
  138.   /*
  139.    * Drain the local queue first
  140.    */
  141.  
  142.   DISABLE_INTR (flags);
  143.  
  144.   while (qlen && dump_to_midi (tmp_queue[qhead]))
  145.     {
  146.       qlen--;
  147.       qhead++;
  148.     }
  149.  
  150.   RESTORE_INTR (flags);
  151.  
  152.   /*
  153.    * Output the byte if the local queue is empty.
  154.    */
  155.  
  156.   if (!qlen)
  157.     if (dump_to_midi (midi_byte))
  158.       return 1;            /*
  159.                  * OK
  160.                  */
  161.  
  162.   /*
  163.    * Put to the local queue
  164.    */
  165.  
  166.   if (qlen >= 256)
  167.     return 0;            /*
  168.                  * Local queue full
  169.                  */
  170.  
  171.   DISABLE_INTR (flags);
  172.  
  173.   tmp_queue[qtail] = midi_byte;
  174.   qlen++;
  175.   qtail++;
  176.  
  177.   RESTORE_INTR (flags);
  178.  
  179.   return 1;
  180. }
  181.  
  182. static int
  183. gus_midi_start_read (int dev)
  184. {
  185.   return 0;
  186. }
  187.  
  188. static int
  189. gus_midi_end_read (int dev)
  190. {
  191.   return 0;
  192. }
  193.  
  194. static int
  195. gus_midi_ioctl (int dev, unsigned cmd, unsigned arg)
  196. {
  197.   return RET_ERROR (EINVAL);
  198. }
  199.  
  200. static void
  201. gus_midi_kick (int dev)
  202. {
  203. }
  204.  
  205. static int
  206. gus_midi_buffer_status (int dev)
  207. {
  208.   unsigned long   flags;
  209.  
  210.   if (!output_used)
  211.     return 0;
  212.  
  213.   DISABLE_INTR (flags);
  214.  
  215.   if (qlen && dump_to_midi (tmp_queue[qhead]))
  216.     {
  217.       qlen--;
  218.       qhead++;
  219.     }
  220.  
  221.   RESTORE_INTR (flags);
  222.  
  223.   return (qlen > 0) | !(GUS_MIDI_STATUS () & MIDI_XMIT_EMPTY);
  224. }
  225.  
  226. #define MIDI_SYNTH_NAME    "Gravis Ultrasound Midi"
  227. #define MIDI_SYNTH_CAPS    SYNTH_CAP_INPUT
  228. #include "midi_synth.h"
  229.  
  230. static struct midi_operations gus_midi_operations =
  231. {
  232.   {"Gravis UltraSound Midi", 0, 0, SNDCARD_GUS},
  233.   &std_midi_synth,
  234.   gus_midi_open,
  235.   gus_midi_close,
  236.   gus_midi_ioctl,
  237.   gus_midi_out,
  238.   gus_midi_start_read,
  239.   gus_midi_end_read,
  240.   gus_midi_kick,
  241.   NULL,                /*
  242.                  * command
  243.                  */
  244.   gus_midi_buffer_status,
  245.   NULL
  246. };
  247.  
  248. long
  249. gus_midi_init (long mem_start)
  250. {
  251.   if (num_midis >= MAX_MIDI_DEV)
  252.     {
  253.       printk ("Sound: Too many midi devices detected\n");
  254.       return mem_start;
  255.     }
  256.  
  257.   OUTB (MIDI_RESET, u_MidiControl);
  258.  
  259.   std_midi_synth.midi_dev = my_dev = num_midis;
  260.   midi_devs[num_midis++] = &gus_midi_operations;
  261.   return mem_start;
  262. }
  263.  
  264. void
  265. gus_midi_interrupt (int dummy)
  266. {
  267.   unsigned char   stat, data;
  268.   unsigned long   flags;
  269.  
  270.   DISABLE_INTR (flags);
  271.  
  272.   stat = GUS_MIDI_STATUS ();
  273.  
  274.   if (stat & MIDI_RCV_FULL)
  275.     {
  276.       data = INB (u_MidiData);
  277.       if (input_opened)
  278.     midi_input_intr (my_dev, data);
  279.     }
  280.  
  281.   if (stat & MIDI_XMIT_EMPTY)
  282.     {
  283.       while (qlen && dump_to_midi (tmp_queue[qhead]))
  284.     {
  285.       qlen--;
  286.       qhead++;
  287.     }
  288.  
  289.       if (!qlen)
  290.     {
  291.       /*
  292.        * Disable Midi output interrupts, since no data in the buffer
  293.        */
  294.       gus_midi_control &= ~MIDI_ENABLE_XMIT;
  295.       OUTB (gus_midi_control, u_MidiControl);
  296.     }
  297.     }
  298.  
  299.   if (stat & MIDI_FRAME_ERR)
  300.     printk ("Midi framing error\n");
  301.   if (stat & MIDI_OVERRUN && input_opened)
  302.     printk ("GUS: Midi input overrun\n");
  303.  
  304.   RESTORE_INTR (flags);
  305. }
  306.  
  307. #endif
  308.  
  309. #endif
  310.