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 / uart6850.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-17  |  6.8 KB  |  324 lines

  1. /*
  2.  * sound/uart6850.c
  3.  *
  4.  * Copyright by Hannu Savolainen 1993
  5.  *
  6.  * Mon Nov 22 22:38:35 MET 1993 marco@driq.home.usn.nl:
  7.  *      added 6850 support, used with COVOX SoundMaster II and custom cards.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions are
  11.  * met: 1. Redistributions of source code must retain the above copyright
  12.  * notice, this list of conditions and the following disclaimer. 2.
  13.  * Redistributions in binary form must reproduce the above copyright notice,
  14.  * this list of conditions and the following disclaimer in the documentation
  15.  * and/or other materials provided with the distribution.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  18.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20.  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  21.  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  23.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27.  * SUCH DAMAGE.
  28.  *
  29.  */
  30.  
  31. #include "sound_config.h"
  32.  
  33. #ifdef CONFIGURE_SOUNDCARD
  34.  
  35. #if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI)
  36.  
  37. #define    DATAPORT   (uart6850_base)    /*
  38.                        * * * Midi6850 Data I/O Port on IBM
  39.                        *  */
  40. #define    COMDPORT   (uart6850_base+1)    /*
  41.                        * * * Midi6850 Command Port on IBM   */
  42. #define    STATPORT   (uart6850_base+1)    /*
  43.                        * * * Midi6850 Status Port on IBM   */
  44.  
  45. #define uart6850_status()        INB(STATPORT)
  46. #define input_avail()        ((uart6850_status()&INPUT_AVAIL))
  47. #define output_ready()        ((uart6850_status()&OUTPUT_READY))
  48. #define uart6850_cmd(cmd)    OUTB(cmd, COMDPORT)
  49. #define uart6850_read()        INB(DATAPORT)
  50. #define uart6850_write(byte)    OUTB(byte, DATAPORT)
  51.  
  52. #define    OUTPUT_READY    0x02    /*
  53.                    * * * Mask for Data Read Ready Bit   */
  54. #define    INPUT_AVAIL    0x01    /*
  55.                    * * * Mask for Data Send Ready Bit   */
  56.  
  57. #define    UART_RESET    0x95    /*
  58.                    * * * 6850 Total Reset Command   */
  59. #define    UART_MODE_ON    0x03    /*
  60.                    * * * 6850 Send/Receive UART Mode   */
  61.  
  62. static int      uart6850_opened = 0;
  63. static int      uart6850_base = 0x330;
  64. static int      uart6850_irq;
  65. static int      uart6850_detected = 0;
  66. static int      my_dev;
  67.  
  68. static int      reset_uart6850 (void);
  69. static void     (*midi_input_intr) (int dev, unsigned char data);
  70.  
  71. static void
  72. uart6850_input_loop (void)
  73. {
  74.   int             count;
  75.  
  76.   count = 10;
  77.  
  78.   while (count)            /*
  79.                  * Not timed out
  80.                  */
  81.     if (input_avail ())
  82.       {
  83.     unsigned char   c = uart6850_read ();
  84.  
  85.     count = 100;
  86.  
  87.     if (uart6850_opened & OPEN_READ)
  88.       midi_input_intr (my_dev, c);
  89.       }
  90.     else
  91.       while (!input_avail () && count)
  92.     count--;
  93. }
  94.  
  95. void
  96. m6850intr (int unit, struct pt_regs * regs)
  97. {
  98.   printk ("M");
  99.   if (input_avail ())
  100.     uart6850_input_loop ();
  101. }
  102.  
  103. /*
  104.  * It looks like there is no input interrupts in the UART mode. Let's try
  105.  * polling.
  106.  */
  107.  
  108. static void
  109. poll_uart6850 (unsigned long dummy)
  110. {
  111.   unsigned long   flags;
  112.  
  113.   DEFINE_TIMER (uart6850_timer, poll_uart6850);
  114.  
  115.   if (!(uart6850_opened & OPEN_READ))
  116.     return;            /*
  117.                  * No longer required
  118.                  */
  119.  
  120.   DISABLE_INTR (flags);
  121.  
  122.   if (input_avail ())
  123.     uart6850_input_loop ();
  124.  
  125.   ACTIVATE_TIMER (uart6850_timer, poll_uart6850, 1);    /*
  126.                              * Come back later
  127.                              */
  128.  
  129.   RESTORE_INTR (flags);
  130. }
  131.  
  132. static int
  133. uart6850_open (int dev, int mode,
  134.            void            (*input) (int dev, unsigned char data),
  135.            void            (*output) (int dev)
  136. )
  137. {
  138.   if (uart6850_opened)
  139.     {
  140.       printk ("Midi6850: Midi busy\n");
  141.       return RET_ERROR (EBUSY);
  142.     }
  143.  
  144.   uart6850_cmd (UART_RESET);
  145.  
  146.   uart6850_input_loop ();
  147.  
  148.   midi_input_intr = input;
  149.   uart6850_opened = mode;
  150.   poll_uart6850 (0);        /*
  151.                  * Enable input polling
  152.                  */
  153.  
  154.   return 0;
  155. }
  156.  
  157. static void
  158. uart6850_close (int dev)
  159. {
  160.   uart6850_cmd (UART_MODE_ON);
  161.  
  162.   uart6850_opened = 0;
  163. }
  164.  
  165. static int
  166. uart6850_out (int dev, unsigned char midi_byte)
  167. {
  168.   int             timeout;
  169.   unsigned long   flags;
  170.  
  171.   /*
  172.    * Test for input since pending input seems to block the output.
  173.    */
  174.  
  175.   DISABLE_INTR (flags);
  176.  
  177.   if (input_avail ())
  178.     uart6850_input_loop ();
  179.  
  180.   RESTORE_INTR (flags);
  181.  
  182.   /*
  183.    * Sometimes it takes about 13000 loops before the output becomes ready
  184.    * (After reset). Normally it takes just about 10 loops.
  185.    */
  186.  
  187.   for (timeout = 30000; timeout > 0 && !output_ready (); timeout--);    /*
  188.                                      * Wait
  189.                                      */
  190.  
  191.   if (!output_ready ())
  192.     {
  193.       printk ("Midi6850: Timeout\n");
  194.       return 0;
  195.     }
  196.  
  197.   uart6850_write (midi_byte);
  198.   return 1;
  199. }
  200.  
  201. static int
  202. uart6850_command (int dev, unsigned char *midi_byte)
  203. {
  204.   return 1;
  205. }
  206.  
  207. static int
  208. uart6850_start_read (int dev)
  209. {
  210.   return 0;
  211. }
  212.  
  213. static int
  214. uart6850_end_read (int dev)
  215. {
  216.   return 0;
  217. }
  218.  
  219. static int
  220. uart6850_ioctl (int dev, unsigned cmd, unsigned arg)
  221. {
  222.   return RET_ERROR (EINVAL);
  223. }
  224.  
  225. static void
  226. uart6850_kick (int dev)
  227. {
  228. }
  229.  
  230. static int
  231. uart6850_buffer_status (int dev)
  232. {
  233.   return 0;            /*
  234.                  * No data in buffers
  235.                  */
  236. }
  237.  
  238. #define MIDI_SYNTH_NAME    "6850 UART Midi"
  239. #define MIDI_SYNTH_CAPS    SYNTH_CAP_INPUT
  240. #include "midi_synth.h"
  241.  
  242. static struct midi_operations uart6850_operations =
  243. {
  244.   {"6850 UART", 0, 0, SNDCARD_UART6850},
  245.   &std_midi_synth,
  246.   uart6850_open,
  247.   uart6850_close,
  248.   uart6850_ioctl,
  249.   uart6850_out,
  250.   uart6850_start_read,
  251.   uart6850_end_read,
  252.   uart6850_kick,
  253.   uart6850_command,
  254.   uart6850_buffer_status
  255. };
  256.  
  257.  
  258. long
  259. attach_uart6850 (long mem_start, struct address_info *hw_config)
  260. {
  261.   int             ok, timeout;
  262.   unsigned long   flags;
  263.  
  264.   if (num_midis >= MAX_MIDI_DEV)
  265.     {
  266.       printk ("Sound: Too many midi devices detected\n");
  267.       return mem_start;
  268.     }
  269.  
  270.   uart6850_base = hw_config->io_base;
  271.   uart6850_irq = hw_config->irq;
  272.  
  273.   if (!uart6850_detected)
  274.     return RET_ERROR (EIO);
  275.  
  276.   DISABLE_INTR (flags);
  277.  
  278.   for (timeout = 30000; timeout < 0 && !output_ready (); timeout--);    /*
  279.                                      * Wait
  280.                                      */
  281.   uart6850_cmd (UART_MODE_ON);
  282.  
  283.   ok = 1;
  284.  
  285.   RESTORE_INTR (flags);
  286.  
  287.   printk (" <6850 Midi Interface>");
  288.  
  289.   std_midi_synth.midi_dev = my_dev = num_midis;
  290.   midi_devs[num_midis++] = &uart6850_operations;
  291.   return mem_start;
  292. }
  293.  
  294. static int
  295. reset_uart6850 (void)
  296. {
  297.   uart6850_read ();
  298.   return 1;            /*
  299.                  * OK
  300.                  */
  301. }
  302.  
  303.  
  304. int
  305. probe_uart6850 (struct address_info *hw_config)
  306. {
  307.   int             ok = 0;
  308.  
  309.   uart6850_base = hw_config->io_base;
  310.   uart6850_irq = hw_config->irq;
  311.  
  312.   if (snd_set_irq_handler (uart6850_irq, m6850intr) < 0)
  313.     return 0;
  314.  
  315.   ok = reset_uart6850 ();
  316.  
  317.   uart6850_detected = ok;
  318.   return ok;
  319. }
  320.  
  321. #endif
  322.  
  323. #endif
  324.