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 / gus_midi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-09  |  5.6 KB  |  284 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);    /* Enable */
  83.  
  84.   midi_busy = 1;
  85.   qlen = qhead = qtail = output_used = 0;
  86.   midi_input_intr = input;
  87.  
  88.   return 0;
  89. }
  90.  
  91. static int
  92. dump_to_midi (unsigned char midi_byte)
  93. {
  94.   unsigned long   flags;
  95.   int             ok = 0;
  96.  
  97.   output_used = 1;
  98.  
  99.   DISABLE_INTR (flags);
  100.  
  101.   if (GUS_MIDI_STATUS () & MIDI_XMIT_EMPTY)
  102.     {
  103.       ok = 1;
  104.       OUTB (midi_byte, u_MidiData);
  105.     }
  106.   else
  107.     {
  108.       /* Enable Midi xmit interrupts (again) */
  109.       gus_midi_control |= MIDI_ENABLE_XMIT;
  110.       OUTB (gus_midi_control, u_MidiControl);
  111.     }
  112.  
  113.   RESTORE_INTR (flags);
  114.   return ok;
  115. }
  116.  
  117. static void
  118. gus_midi_close (int dev)
  119. {
  120.   /* Reset FIFO pointers, disable intrs */
  121.  
  122.   OUTB (MIDI_RESET, u_MidiControl);
  123.   midi_busy = 0;
  124. }
  125.  
  126. static int
  127. gus_midi_out (int dev, unsigned char midi_byte)
  128. {
  129.  
  130.   unsigned long   flags;
  131.  
  132.   /*
  133.    * Drain the local queue first
  134.    */
  135.  
  136.   DISABLE_INTR (flags);
  137.  
  138.   while (qlen && dump_to_midi (tmp_queue[qhead]))
  139.     {
  140.       qlen--;
  141.       qhead++;
  142.     }
  143.  
  144.   RESTORE_INTR (flags);
  145.  
  146.   /*
  147.    * Output the byte if the local queue is empty.
  148.    */
  149.  
  150.   if (!qlen)
  151.     if (dump_to_midi (midi_byte))
  152.       return 1;            /* OK */
  153.  
  154.   /*
  155.    * Put to the local queue
  156.    */
  157.  
  158.   if (qlen >= 256)
  159.     return 0;            /* Local queue full */
  160.  
  161.   DISABLE_INTR (flags);
  162.  
  163.   tmp_queue[qtail] = midi_byte;
  164.   qlen++;
  165.   qtail++;
  166.  
  167.   RESTORE_INTR (flags);
  168.  
  169.   return 1;
  170. }
  171.  
  172. static int
  173. gus_midi_start_read (int dev)
  174. {
  175.   return 0;
  176. }
  177.  
  178. static int
  179. gus_midi_end_read (int dev)
  180. {
  181.   return 0;
  182. }
  183.  
  184. static int
  185. gus_midi_ioctl (int dev, unsigned cmd, unsigned arg)
  186. {
  187.   return RET_ERROR (EINVAL);
  188. }
  189.  
  190. static void
  191. gus_midi_kick (int dev)
  192. {
  193. }
  194.  
  195. static int
  196. gus_midi_buffer_status (int dev)
  197. {
  198.   unsigned long   flags;
  199.  
  200.   if (!output_used)
  201.     return 0;
  202.  
  203.   DISABLE_INTR (flags);
  204.  
  205.   if (qlen && dump_to_midi (tmp_queue[qhead]))
  206.     {
  207.       qlen--;
  208.       qhead++;
  209.     }
  210.  
  211.   RESTORE_INTR (flags);
  212.  
  213.   return (qlen > 0) | !(GUS_MIDI_STATUS () & MIDI_XMIT_EMPTY);
  214. }
  215.  
  216. static struct midi_operations gus_midi_operations =
  217. {
  218.   {"Gravis UltraSound", 0, 0, SNDCARD_GUS},
  219.   gus_midi_open,
  220.   gus_midi_close,
  221.   gus_midi_ioctl,
  222.   gus_midi_out,
  223.   gus_midi_start_read,
  224.   gus_midi_end_read,
  225.   gus_midi_kick,
  226.   NULL,                /* command */
  227.   gus_midi_buffer_status
  228. };
  229.  
  230. long
  231. gus_midi_init (long mem_start)
  232. {
  233.   OUTB (MIDI_RESET, u_MidiControl);
  234.  
  235.   my_dev = num_midis;
  236.   midi_devs[num_midis++] = &gus_midi_operations;
  237.   return mem_start;
  238. }
  239.  
  240. void
  241. gus_midi_interrupt (int dummy)
  242. {
  243.   unsigned char   stat, data;
  244.   unsigned long   flags;
  245.  
  246.   DISABLE_INTR (flags);
  247.  
  248.   stat = GUS_MIDI_STATUS ();
  249.  
  250.   if (stat & MIDI_RCV_FULL)
  251.     {
  252.       data = INB (u_MidiData);
  253.       if (input_opened)
  254.     midi_input_intr (my_dev, data);
  255.     }
  256.  
  257.   if (stat & MIDI_XMIT_EMPTY)
  258.     {
  259.       while (qlen && dump_to_midi (tmp_queue[qhead]))
  260.     {
  261.       qlen--;
  262.       qhead++;
  263.     }
  264.  
  265.       if (!qlen)
  266.     {
  267.       /* Disable Midi output interrupts, since no data in the buffer */
  268.       gus_midi_control &= ~MIDI_ENABLE_XMIT;
  269.       OUTB (gus_midi_control, u_MidiControl);
  270.     }
  271.     }
  272.  
  273.   if (stat & MIDI_FRAME_ERR)
  274.     printk ("Midi framing error\n");
  275.   if (stat & MIDI_OVERRUN && input_opened)
  276.     printk ("GUS: Midi input overrun\n");
  277.  
  278.   RESTORE_INTR (flags);
  279. }
  280.  
  281. #endif
  282.  
  283. #endif
  284.