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

   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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  78 {
  79   if (input_avail ())
  80     sb16midi_input_loop ();
  81 }
  82 
  83 static int
  84 sb16midi_open (int dev, int mode,
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
 104 {
 105   sb16midi_opened = 0;
 106 }
 107 
 108 static int
 109 sb16midi_out (int dev, unsigned char midi_byte)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 146 {
 147   return 0;
 148 }
 149 
 150 static int
 151 sb16midi_end_read (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 152 {
 153   return 0;
 154 }
 155 
 156 static int
 157 sb16midi_ioctl (int dev, unsigned cmd, unsigned arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 158 {
 159   return RET_ERROR (EINVAL);
 160 }
 161 
 162 static void
 163 sb16midi_kick (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 164 {
 165 }
 166 
 167 static int
 168 sb16midi_buffer_status (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 283 {
 284   int             ok = 0;
 285   int             i;
 286   extern int      sbc_major;
 287 
 288   if (sbc_major < 4)
 289     return 0;                   /* Not a SB16 */
 290 
 291   sb16midi_base = hw_config->io_base;
 292 
 293   if (sb_get_irq () < 0)
 294     return 0;
 295 
 296   ok = reset_sb16midi ();
 297 
 298   sb16midi_detected = ok;
 299   return ok;
 300 }
 301 
 302 #endif
 303 
 304 #endif

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