root/drivers/sound/sb16_midi.c

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

DEFINITIONS

This source file includes following definitions.
  1. sb16midi_input_loop
  2. sb16midiintr
  3. sb16midi_open
  4. sb16midi_close
  5. sb16midi_out
  6. sb16midi_start_read
  7. sb16midi_end_read
  8. sb16midi_ioctl
  9. sb16midi_kick
  10. sb16midi_buffer_status
  11. attach_sb16midi
  12. reset_sb16midi
  13. probe_sb16midi
  14. unload_sb16midi

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

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