root/drivers/sound/mpu401.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mpu401_input_loop
  2. mpuintr
  3. poll_mpu401
  4. mpu401_open
  5. mpu401_close
  6. mpu401_out
  7. mpu401_command
  8. mpu401_start_read
  9. mpu401_end_read
  10. mpu401_ioctl
  11. mpu401_kick
  12. mpu401_buffer_status
  13. attach_mpu401
  14. reset_mpu401
  15. probe_mpu401

   1 /*
   2  * sound/mpu401.c
   3  * 
   4  * The low level driver for Roland MPU-401 compatible Midi cards.
   5  * 
   6  * This version supports just the DUMB UART mode.
   7  * 
   8  * Copyright by Hannu Savolainen 1993
   9  * 
  10  * Redistribution and use in source and binary forms, with or without
  11  * modification, are permitted provided that the following conditions are
  12  * met: 1. Redistributions of source code must retain the above copyright
  13  * notice, this list of conditions and the following disclaimer. 2.
  14  * Redistributions in binary form must reproduce the above copyright notice,
  15  * this list of conditions and the following disclaimer in the documentation
  16  * and/or other materials provided with the distribution.
  17  * 
  18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  22  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  25  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28  * SUCH DAMAGE.
  29  * 
  30  */
  31 
  32 #include "sound_config.h"
  33 
  34 #ifdef CONFIGURE_SOUNDCARD
  35 
  36 #if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI)
  37 
  38 #define DATAPORT   (mpu401_base)        /* MPU-401 Data I/O Port on IBM */
  39 #define COMDPORT   (mpu401_base+1)      /* MPU-401 Command Port on IBM */
  40 #define STATPORT   (mpu401_base+1)      /* MPU-401 Status Port on IBM */
  41 
  42 #define mpu401_status()         INB(STATPORT)
  43 #define input_avail()           (!(mpu401_status()&INPUT_AVAIL))
  44 #define output_ready()          (!(mpu401_status()&OUTPUT_READY))
  45 #define mpu401_cmd(cmd)         OUTB(cmd, COMDPORT)
  46 #define mpu401_read()           INB(DATAPORT)
  47 #define mpu401_write(byte)      OUTB(byte, DATAPORT)
  48 
  49 #define OUTPUT_READY    0x40    /* Mask for Data Read Redy Bit */
  50 #define INPUT_AVAIL     0x80    /* Mask for Data Send Ready Bit */
  51 #define MPU_ACK         0xFE    /* MPU-401 Acknowledge Response */
  52 #define MPU_RESET       0xFF    /* MPU-401 Total Reset Command */
  53 #define UART_MODE_ON    0x3F    /* MPU-401 "Dumb UART Mode" */
  54 
  55 static int      mpu401_opened = 0;
  56 static int      mpu401_base = 0x330;
  57 static int      mpu401_irq;
  58 static int      mpu401_detected = 0;
  59 static int      my_dev;
  60 
  61 static int      reset_mpu401 (void);
  62 static void     (*midi_input_intr) (int dev, unsigned char data);
  63 
  64 static void
  65 mpu401_input_loop (void)
     /* [previous][next][first][last][top][bottom][index][help] */
  66 {
  67   int             count;
  68 
  69   count = 10;
  70 
  71   while (count)                 /* Not timed out */
  72     if (input_avail ())
  73       {
  74         unsigned char   c = mpu401_read ();
  75 
  76         count = 100;
  77 
  78         if (mpu401_opened & OPEN_READ)
  79           midi_input_intr (my_dev, c);
  80       }
  81     else
  82       while (!input_avail () && count)
  83         count--;
  84 }
  85 
  86 void
  87 mpuintr (int unit)
     /* [previous][next][first][last][top][bottom][index][help] */
  88 {
  89   if (input_avail ())
  90     mpu401_input_loop ();
  91 }
  92 
  93 /*
  94  * It looks like there is no input interrupts in the UART mode. Let's try
  95  * polling.
  96  */
  97 
  98 static void
  99 poll_mpu401 (unsigned long dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 100 {
 101   unsigned long   flags;
 102 
 103   DEFINE_TIMER(mpu401_timer, poll_mpu401);
 104 
 105   if (!(mpu401_opened & OPEN_READ))
 106     return;                     /* No longer required */
 107 
 108   DISABLE_INTR (flags);
 109 
 110   if (input_avail ())
 111     mpu401_input_loop ();
 112 
 113   ACTIVATE_TIMER(mpu401_timer, poll_mpu401, 1); /* Come back later */
 114 
 115   RESTORE_INTR (flags);
 116 }
 117 
 118 static int
 119 mpu401_open (int dev, int mode,
     /* [previous][next][first][last][top][bottom][index][help] */
 120              void            (*input) (int dev, unsigned char data),
 121              void            (*output) (int dev)
 122 )
 123 {
 124   if (mpu401_opened)
 125     {
 126       printk ("MPU-401: Midi busy\n");
 127       return RET_ERROR (EBUSY);
 128     }
 129 
 130   mpu401_input_loop ();
 131 
 132   midi_input_intr = input;
 133   mpu401_opened = mode;
 134   poll_mpu401 (0);              /* Enable input polling */
 135 
 136   return 0;
 137 }
 138 
 139 static void
 140 mpu401_close (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 141 {
 142   mpu401_opened = 0;
 143 }
 144 
 145 static int
 146 mpu401_out (int dev, unsigned char midi_byte)
     /* [previous][next][first][last][top][bottom][index][help] */
 147 {
 148   int             timeout;
 149   unsigned long   flags;
 150 
 151   /*
 152    * Test for input since pending input seems to block the output.
 153    */
 154 
 155   DISABLE_INTR (flags);
 156 
 157   if (input_avail ())
 158     mpu401_input_loop ();
 159 
 160   RESTORE_INTR (flags);
 161 
 162   /*
 163    * Sometimes it takes about 13000 loops before the output becomes ready
 164    * (After reset). Normally it takes just about 10 loops.
 165    */
 166 
 167   for (timeout = 30000; timeout > 0 && !output_ready (); timeout--);    /* Wait */
 168 
 169   if (!output_ready ())
 170     {
 171       printk ("MPU-401: Timeout\n");
 172       return 0;
 173     }
 174 
 175   mpu401_write (midi_byte);
 176   return 1;
 177 }
 178 
 179 static int
 180 mpu401_command (int dev, unsigned char midi_byte)
     /* [previous][next][first][last][top][bottom][index][help] */
 181 {
 182   return 1;
 183 }
 184 
 185 static int
 186 mpu401_start_read (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 187 {
 188   return 0;
 189 }
 190 
 191 static int
 192 mpu401_end_read (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 193 {
 194   return 0;
 195 }
 196 
 197 static int
 198 mpu401_ioctl (int dev, unsigned cmd, unsigned arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 199 {
 200   return RET_ERROR (EINVAL);
 201 }
 202 
 203 static void
 204 mpu401_kick (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 205 {
 206 }
 207 
 208 static int
 209 mpu401_buffer_status (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 210 {
 211   return 0;                     /* No data in buffers */
 212 }
 213 
 214 static struct midi_operations mpu401_operations =
 215 {
 216   {"MPU-401", 0, 0, SNDCARD_MPU401},
 217   mpu401_open,
 218   mpu401_close,
 219   mpu401_ioctl,
 220   mpu401_out,
 221   mpu401_start_read,
 222   mpu401_end_read,
 223   mpu401_kick,
 224   mpu401_command,
 225   mpu401_buffer_status
 226 };
 227 
 228 
 229 long
 230 attach_mpu401 (long mem_start, struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 231 {
 232   int             ok, timeout;
 233   unsigned long   flags;
 234 
 235   mpu401_base = hw_config->io_base;
 236   mpu401_irq = hw_config->irq;
 237 
 238   if (!mpu401_detected)
 239     return RET_ERROR (EIO);
 240 
 241   DISABLE_INTR (flags);
 242   for (timeout = 30000; timeout < 0 && !output_ready (); timeout--);    /* Wait */
 243   mpu401_cmd (UART_MODE_ON);
 244 
 245   ok = 0;
 246   for (timeout = 50000; timeout > 0 && !ok; timeout--)
 247     if (input_avail ())
 248       if (mpu401_read () == MPU_ACK)
 249         ok = 1;
 250 
 251   RESTORE_INTR (flags);
 252 
 253   printk (" <Roland MPU-401>");
 254 
 255   my_dev = num_midis;
 256   mpu401_dev = num_midis;
 257   midi_devs[num_midis++] = &mpu401_operations;
 258   return mem_start;
 259 }
 260 
 261 static int
 262 reset_mpu401 (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 263 {
 264   unsigned long   flags;
 265   int             ok, timeout, n;
 266 
 267   /*
 268    * Send the RESET command. Try again if no success at the first time.
 269    */
 270 
 271   ok = 0;
 272 
 273   DISABLE_INTR (flags);
 274 
 275   for (n = 0; n < 2 && !ok; n++)
 276     {
 277       for (timeout = 30000; timeout < 0 && !output_ready (); timeout--);        /* Wait */
 278       mpu401_cmd (MPU_RESET);   /* Send MPU-401 RESET Command */
 279 
 280       /*
 281        * Wait at least 25 msec. This method is not accurate so let's make the
 282        * loop bit longer. Cannot sleep since this is called during boot.
 283        */
 284 
 285       for (timeout = 50000; timeout > 0 && !ok; timeout--)
 286         if (input_avail ())
 287           if (mpu401_read () == MPU_ACK)
 288             ok = 1;
 289 
 290     }
 291 
 292   mpu401_opened = 0;
 293   if (ok)
 294     mpu401_input_loop ();       /* Flush input before enabling interrupts */
 295 
 296   RESTORE_INTR (flags);
 297 
 298   return ok;
 299 }
 300 
 301 
 302 int
 303 probe_mpu401 (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 304 {
 305   int             ok = 0;
 306 
 307   mpu401_base = hw_config->io_base;
 308   mpu401_irq = hw_config->irq;
 309 
 310   if (snd_set_irq_handler (mpu401_irq, mpuintr) < 0)
 311     return 0;
 312 
 313   ok = reset_mpu401 ();
 314 
 315   mpu401_detected = ok;
 316   return ok;
 317 }
 318 
 319 #endif
 320 
 321 #endif

/* [previous][next][first][last][top][bottom][index][help] */