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 / sb_midi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-19  |  5.6 KB  |  253 lines

  1. /*
  2.  * sound/sb_dsp.c
  3.  *
  4.  * The low level driver for the SoundBlaster DS chips.
  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. #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_MIDI)
  33.  
  34. #include "sb.h"
  35. #undef SB_TEST_IRQ
  36.  
  37. /*
  38.  * The DSP channel can be used either for input or output. Variable
  39.  * 'sb_irq_mode' will be set when the program calls read or write first time
  40.  * after open. Current version doesn't support mode changes without closing
  41.  * and reopening the device. Support for this feature may be implemented in a
  42.  * future version of this driver.
  43.  */
  44.  
  45. extern int      sb_dsp_ok;    /* Set to 1 after successful initialization */
  46. extern int      sbc_base;
  47.  
  48. extern int      sb_midi_mode;
  49. extern int      sb_midi_busy;    /*
  50.  
  51.  
  52.                  * *  * * 1 if the process has output to MIDI
  53.                  *
  54.                  */
  55. extern int      sb_dsp_busy;
  56. extern int      sb_dsp_highspeed;
  57.  
  58. extern volatile int sb_irq_mode;
  59. extern int      sb_duplex_midi;
  60. extern int      sb_intr_active;
  61. int             input_opened = 0;
  62. static int      my_dev;
  63.  
  64. void            (*midi_input_intr) (int dev, unsigned char data);
  65.  
  66. static int
  67. sb_midi_open (int dev, int mode,
  68.           void            (*input) (int dev, unsigned char data),
  69.           void            (*output) (int dev)
  70. )
  71. {
  72.   int             ret;
  73.  
  74.   if (!sb_dsp_ok)
  75.     {
  76.       printk ("SB Error: MIDI hardware not installed\n");
  77.       return RET_ERROR (ENXIO);
  78.     }
  79.  
  80.   if (sb_midi_busy)
  81.     return RET_ERROR (EBUSY);
  82.  
  83.   if (mode != OPEN_WRITE && !sb_duplex_midi)
  84.     {
  85.       if (num_midis == 1)
  86.     printk ("SoundBlaster: Midi input not currently supported\n");
  87.       return RET_ERROR (EPERM);
  88.     }
  89.  
  90.   sb_midi_mode = NORMAL_MIDI;
  91.   if (mode != OPEN_WRITE)
  92.     {
  93.       if (sb_dsp_busy || sb_intr_active)
  94.     return RET_ERROR (EBUSY);
  95.       sb_midi_mode = UART_MIDI;
  96.     }
  97.  
  98.   if (sb_dsp_highspeed)
  99.     {
  100.       printk ("SB Error: Midi output not possible during stereo or high speed audio\n");
  101.       return RET_ERROR (EBUSY);
  102.     }
  103.  
  104.   if (sb_midi_mode == UART_MIDI)
  105.     {
  106.       sb_irq_mode = IMODE_MIDI;
  107.  
  108.       sb_reset_dsp ();
  109.  
  110.       if (!sb_dsp_command (0x35))
  111.     return RET_ERROR (EIO);    /*
  112.                  * Enter the UART mode
  113.                  */
  114.       sb_intr_active = 1;
  115.  
  116.       if ((ret = sb_get_irq ()) < 0)
  117.     {
  118.       sb_reset_dsp ();
  119.       return 0;        /*
  120.                  * IRQ not free
  121.                  */
  122.     }
  123.       input_opened = 1;
  124.       midi_input_intr = input;
  125.     }
  126.  
  127.   sb_midi_busy = 1;
  128.  
  129.   return 0;
  130. }
  131.  
  132. static void
  133. sb_midi_close (int dev)
  134. {
  135.   if (sb_midi_mode == UART_MIDI)
  136.     {
  137.       sb_reset_dsp ();        /*
  138.                  * The only way to kill the UART mode
  139.                  */
  140.       sb_free_irq ();
  141.     }
  142.   sb_intr_active = 0;
  143.   sb_midi_busy = 0;
  144.   input_opened = 0;
  145. }
  146.  
  147. static int
  148. sb_midi_out (int dev, unsigned char midi_byte)
  149. {
  150.   unsigned long   flags;
  151.  
  152.   if (sb_midi_mode == NORMAL_MIDI)
  153.     {
  154.       DISABLE_INTR (flags);
  155.       if (sb_dsp_command (0x38))
  156.     sb_dsp_command (midi_byte);
  157.       else
  158.     printk ("SB Error: Unable to send a MIDI byte\n");
  159.       RESTORE_INTR (flags);
  160.     }
  161.   else
  162.     sb_dsp_command (midi_byte);    /*
  163.                  * UART write
  164.                  */
  165.  
  166.   return 1;
  167. }
  168.  
  169. static int
  170. sb_midi_start_read (int dev)
  171. {
  172.   if (sb_midi_mode != UART_MIDI)
  173.     {
  174.       printk ("SoundBlaster: MIDI input not implemented.\n");
  175.       return RET_ERROR (EPERM);
  176.     }
  177.   return 0;
  178. }
  179.  
  180. static int
  181. sb_midi_end_read (int dev)
  182. {
  183.   if (sb_midi_mode == UART_MIDI)
  184.     {
  185.       sb_reset_dsp ();
  186.       sb_intr_active = 0;
  187.     }
  188.   return 0;
  189. }
  190.  
  191. static int
  192. sb_midi_ioctl (int dev, unsigned cmd, unsigned arg)
  193. {
  194.   return RET_ERROR (EPERM);
  195. }
  196.  
  197. void
  198. sb_midi_interrupt (int dummy)
  199. {
  200.   unsigned long   flags;
  201.   unsigned char   data;
  202.  
  203.   DISABLE_INTR (flags);
  204.  
  205.   data = INB (DSP_READ);
  206.   if (input_opened)
  207.     midi_input_intr (my_dev, data);
  208.  
  209.   RESTORE_INTR (flags);
  210. }
  211.  
  212. #define MIDI_SYNTH_NAME    "SoundBlaster Midi"
  213. #define MIDI_SYNTH_CAPS    0
  214. #include "midi_synth.h"
  215.  
  216. static struct midi_operations sb_midi_operations =
  217. {
  218.   {"SoundBlaster", 0, 0, SNDCARD_SB},
  219.   &std_midi_synth,
  220.   sb_midi_open,
  221.   sb_midi_close,
  222.   sb_midi_ioctl,
  223.   sb_midi_out,
  224.   sb_midi_start_read,
  225.   sb_midi_end_read,
  226.   NULL,                /*
  227.                  * Kick
  228.                  */
  229.   NULL,                /*
  230.                  * command
  231.                  */
  232.   NULL,                /*
  233.                  * buffer_status
  234.                  */
  235.   NULL
  236. };
  237.  
  238. void
  239. sb_midi_init (int model)
  240. {
  241.   if (num_midis >= MAX_MIDI_DEV)
  242.     {
  243.       printk ("Sound: Too many midi devices detected\n");
  244.       return;
  245.     }
  246.  
  247.   std_midi_synth.midi_dev = num_midis;
  248.   my_dev = num_midis;
  249.   midi_devs[num_midis++] = &sb_midi_operations;
  250. }
  251.  
  252. #endif
  253.