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 / sb16_midi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-13  |  6.4 KB  |  304 lines

  1. /*
  2.  * sound/sb16_midi.c
  3.  *
  4.  * The low level driver for the MPU-401 UART emulation of the SB16.
  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. #if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_MIDI)
  35.  
  36. #include "sb.h"
  37.  
  38. #define    DATAPORT   (sb16midi_base)
  39. #define    COMDPORT   (sb16midi_base+1)
  40. #define    STATPORT   (sb16midi_base+1)
  41.  
  42. #define sb16midi_status()        INB(STATPORT)
  43. #define input_avail()        (!(sb16midi_status()&INPUT_AVAIL))
  44. #define output_ready()        (!(sb16midi_status()&OUTPUT_READY))
  45. #define sb16midi_cmd(cmd)        OUTB(cmd, COMDPORT)
  46. #define sb16midi_read()        INB(DATAPORT)
  47. #define sb16midi_write(byte)    OUTB(byte, DATAPORT)
  48.  
  49. #define    OUTPUT_READY    0x40
  50. #define    INPUT_AVAIL    0x80
  51. #define    MPU_ACK        0xFE
  52. #define    MPU_RESET    0xFF
  53. #define    UART_MODE_ON    0x3F
  54.  
  55. static int      sb16midi_opened = 0;
  56. static int      sb16midi_base = 0x330;
  57. static int      sb16midi_detected = 0;
  58. static int      my_dev;
  59. extern int      sbc_base;
  60.  
  61. static int      reset_sb16midi (void);
  62. static void     (*midi_input_intr) (int dev, unsigned char data);
  63.  
  64. static void
  65. sb16midi_input_loop (void)
  66. {
  67.   while (input_avail ())
  68.     {
  69.       unsigned char   c = sb16midi_read ();
  70.  
  71.       if (sb16midi_opened & OPEN_READ)
  72.     midi_input_intr (my_dev, c);
  73.     }
  74. }
  75.  
  76. void
  77. sb16midiintr (int unit)
  78. {
  79.   if (input_avail ())
  80.     sb16midi_input_loop ();
  81. }
  82.  
  83. static int
  84. sb16midi_open (int dev, int mode,
  85.            void            (*input) (int dev, unsigned char data),
  86.            void            (*output) (int dev)
  87. )
  88. {
  89.   if (sb16midi_opened)
  90.     {
  91.       return RET_ERROR (EBUSY);
  92.     }
  93.  
  94.   sb16midi_input_loop ();
  95.  
  96.   midi_input_intr = input;
  97.   sb16midi_opened = mode;
  98.  
  99.   return 0;
  100. }
  101.  
  102. static void
  103. sb16midi_close (int dev)
  104. {
  105.   sb16midi_opened = 0;
  106. }
  107.  
  108. static int
  109. sb16midi_out (int dev, unsigned char midi_byte)
  110. {
  111.   int             timeout;
  112.   unsigned long   flags;
  113.  
  114.   /*
  115.    * Test for input since pending input seems to block the output.
  116.    */
  117.  
  118.   DISABLE_INTR (flags);
  119.  
  120.   if (input_avail ())
  121.     sb16midi_input_loop ();
  122.  
  123.   RESTORE_INTR (flags);
  124.  
  125.   /*
  126.    * Sometimes it takes about 13000 loops before the output becomes ready
  127.    * (After reset). Normally it takes just about 10 loops.
  128.    */
  129.  
  130.   for (timeout = 30000; timeout > 0 && !output_ready (); timeout--);    /*
  131.                                      * Wait
  132.                                      */
  133.  
  134.   if (!output_ready ())
  135.     {
  136.       printk ("MPU-401: Timeout\n");
  137.       return 0;
  138.     }
  139.  
  140.   sb16midi_write (midi_byte);
  141.   return 1;
  142. }
  143.  
  144. static int
  145. sb16midi_start_read (int dev)
  146. {
  147.   return 0;
  148. }
  149.  
  150. static int
  151. sb16midi_end_read (int dev)
  152. {
  153.   return 0;
  154. }
  155.  
  156. static int
  157. sb16midi_ioctl (int dev, unsigned cmd, unsigned arg)
  158. {
  159.   return RET_ERROR (EINVAL);
  160. }
  161.  
  162. static void
  163. sb16midi_kick (int dev)
  164. {
  165. }
  166.  
  167. static int
  168. sb16midi_buffer_status (int dev)
  169. {
  170.   return 0;            /*
  171.                  * No data in buffers
  172.                  */
  173. }
  174.  
  175. #define MIDI_SYNTH_NAME    "SoundBlaster 16 Midi"
  176. #define MIDI_SYNTH_CAPS    SYNTH_CAP_INPUT
  177. #include "midi_synth.h"
  178.  
  179. static struct midi_operations sb16midi_operations =
  180. {
  181.   {"SoundBlaster 16 Midi", 0, 0, SNDCARD_SB16MIDI},
  182.   &std_midi_synth,
  183.   sb16midi_open,
  184.   sb16midi_close,
  185.   sb16midi_ioctl,
  186.   sb16midi_out,
  187.   sb16midi_start_read,
  188.   sb16midi_end_read,
  189.   sb16midi_kick,
  190.   NULL,
  191.   sb16midi_buffer_status,
  192.   NULL
  193. };
  194.  
  195.  
  196. long
  197. attach_sb16midi (long mem_start, struct address_info *hw_config)
  198. {
  199.   int             ok, timeout;
  200.   unsigned long   flags;
  201.  
  202.   sb16midi_base = hw_config->io_base;
  203.  
  204.   if (!sb16midi_detected)
  205.     return RET_ERROR (EIO);
  206.  
  207.   DISABLE_INTR (flags);
  208.   for (timeout = 30000; timeout < 0 && !output_ready (); timeout--);    /*
  209.                                      * Wait
  210.                                      */
  211.   sb16midi_cmd (UART_MODE_ON);
  212.  
  213.   ok = 0;
  214.   for (timeout = 50000; timeout > 0 && !ok; timeout--)
  215.     if (input_avail ())
  216.       if (sb16midi_read () == MPU_ACK)
  217.     ok = 1;
  218.  
  219.   RESTORE_INTR (flags);
  220.  
  221.   if (num_midis >= MAX_MIDI_DEV)
  222.     {
  223.       printk ("Sound: Too many midi devices detected\n");
  224.       return mem_start;
  225.     }
  226.  
  227.   printk (" <SoundBlaster MPU-401>");
  228.  
  229.   std_midi_synth.midi_dev = my_dev = num_midis;
  230.   midi_devs[num_midis++] = &sb16midi_operations;
  231.   return mem_start;
  232. }
  233.  
  234. static int
  235. reset_sb16midi (void)
  236. {
  237.   unsigned long   flags;
  238.   int             ok, timeout, n;
  239.  
  240.   /*
  241.    * Send the RESET command. Try again if no success at the first time.
  242.    */
  243.  
  244.   ok = 0;
  245.  
  246.   DISABLE_INTR (flags);
  247.  
  248.   for (n = 0; n < 2 && !ok; n++)
  249.     {
  250.       for (timeout = 30000; timeout < 0 && !output_ready (); timeout--);    /*
  251.                                          * Wait
  252.                                          */
  253.       sb16midi_cmd (MPU_RESET);    /*
  254.                  * Send MPU-401 RESET Command
  255.                  */
  256.  
  257.       /*
  258.        * Wait at least 25 msec. This method is not accurate so let's make the
  259.        * loop bit longer. Cannot sleep since this is called during boot.
  260.        */
  261.  
  262.       for (timeout = 50000; timeout > 0 && !ok; timeout--)
  263.     if (input_avail ())
  264.       if (sb16midi_read () == MPU_ACK)
  265.         ok = 1;
  266.  
  267.     }
  268.  
  269.   sb16midi_opened = 0;
  270.   if (ok)
  271.     sb16midi_input_loop ();    /*
  272.                  * Flush input before enabling interrupts
  273.                  */
  274.  
  275.   RESTORE_INTR (flags);
  276.  
  277.   return ok;
  278. }
  279.  
  280.  
  281. int
  282. probe_sb16midi (struct address_info *hw_config)
  283. {
  284.   int             ok = 0;
  285.   extern int      sbc_major;
  286.  
  287.   if (sbc_major < 4)
  288.     return 0;            /* Not a SB16 */
  289.  
  290.   sb16midi_base = hw_config->io_base;
  291.  
  292.   if (sb_get_irq () < 0)
  293.     return 0;
  294.  
  295.   ok = reset_sb16midi ();
  296.  
  297.   sb16midi_detected = ok;
  298.   return ok;
  299. }
  300.  
  301. #endif
  302.  
  303. #endif
  304.