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