root/drivers/sound/sb16_midi.c

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

DEFINITIONS

This source file includes following definitions.
  1. sb16midi_status
  2. sb16midi_cmd
  3. sb16midi_read
  4. sb16midi_write
  5. sb16midi_input_loop
  6. sb16midiintr
  7. sbmidiintr
  8. sb16midi_open
  9. sb16midi_close
  10. sb16midi_out
  11. sb16midi_start_read
  12. sb16midi_end_read
  13. sb16midi_ioctl
  14. sb16midi_kick
  15. sb16midi_buffer_status
  16. enter_uart_mode
  17. attach_sb16midi
  18. reset_sb16midi
  19. probe_sb16midi
  20. 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 /*
   7  * Copyright by Hannu Savolainen 1993-1996
   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 #include <linux/config.h>
  30 
  31 
  32 #include "sound_config.h"
  33 
  34 #if defined(CONFIG_SB) && defined(CONFIG_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 int     *sb_osp;
  43 static int      sb16midi_base = 0;
  44 
  45 static int 
  46 sb16midi_status (void)
     /* [previous][next][first][last][top][bottom][index][help] */
  47 {
  48   return inb (STATPORT);
  49 }
  50 #define input_avail()           (!(sb16midi_status()&INPUT_AVAIL))
  51 #define output_ready()          (!(sb16midi_status()&OUTPUT_READY))
  52 static void 
  53 sb16midi_cmd (unsigned char cmd)
     /* [previous][next][first][last][top][bottom][index][help] */
  54 {
  55   outb (cmd, COMDPORT);
  56 }
  57 static int 
  58 sb16midi_read (void)
     /* [previous][next][first][last][top][bottom][index][help] */
  59 {
  60   return inb (DATAPORT);
  61 }
  62 static void 
  63 sb16midi_write (unsigned char byte)
     /* [previous][next][first][last][top][bottom][index][help] */
  64 {
  65   outb (byte, DATAPORT);
  66 }
  67 
  68 #define OUTPUT_READY    0x40
  69 #define INPUT_AVAIL     0x80
  70 #define MPU_ACK         0xFE
  71 #define MPU_RESET       0xFF
  72 #define UART_MODE_ON    0x3F
  73 
  74 static int      sb16midi_opened = 0;
  75 static int      sb16midi_detected = 0;
  76 static int      my_dev;
  77 extern int      sbc_base;
  78 
  79 extern int      Jazz16_detected;
  80 extern int      AudioDrive;
  81 
  82 static int      reset_sb16midi (void);
  83 static void     (*midi_input_intr) (int dev, unsigned char data);
  84 static volatile unsigned char input_byte;
  85 
  86 static void
  87 sb16midi_input_loop (void)
     /* [previous][next][first][last][top][bottom][index][help] */
  88 {
  89   while (input_avail ())
  90     {
  91       unsigned char   c = sb16midi_read ();
  92 
  93       if (c == MPU_ACK)
  94         input_byte = c;
  95       else if (sb16midi_opened & OPEN_READ && midi_input_intr)
  96         midi_input_intr (my_dev, c);
  97     }
  98 }
  99 
 100 void
 101 sb16midiintr (int unit)
     /* [previous][next][first][last][top][bottom][index][help] */
 102 {
 103   if (sb16midi_base == 0)
 104     return;
 105 
 106   if (input_avail ())
 107     sb16midi_input_loop ();
 108 }
 109 
 110 void
 111 sbmidiintr (int irq, void *dev_id, struct pt_regs *dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 112 {
 113   if (input_avail ())
 114     sb16midi_input_loop ();
 115 }
 116 
 117 static int
 118 sb16midi_open (int dev, int mode,
     /* [previous][next][first][last][top][bottom][index][help] */
 119                void            (*input) (int dev, unsigned char data),
 120                void            (*output) (int dev)
 121 )
 122 {
 123   if (sb16midi_opened)
 124     {
 125       return -EBUSY;
 126     }
 127 
 128   reset_sb16midi ();
 129   while (input_avail ())
 130     sb16midi_read ();
 131 
 132   midi_input_intr = input;
 133   sb16midi_opened = mode;
 134 
 135   return 0;
 136 }
 137 
 138 static void
 139 sb16midi_close (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 140 {
 141   sb16midi_opened = 0;
 142 }
 143 
 144 static int
 145 sb16midi_out (int dev, unsigned char midi_byte)
     /* [previous][next][first][last][top][bottom][index][help] */
 146 {
 147   int             timeout;
 148   unsigned long   flags;
 149 
 150   /*
 151    * Test for input since pending input seems to block the output.
 152    */
 153 
 154   save_flags (flags);
 155   cli ();
 156 
 157   if (input_avail ())
 158     sb16midi_input_loop ();
 159 
 160   restore_flags (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--);    /*
 168                                                                          * Wait
 169                                                                          */
 170 
 171   if (!output_ready ())
 172     {
 173       printk ("MPU-401: Timeout\n");
 174       return 0;
 175     }
 176 
 177   sb16midi_write (midi_byte);
 178   return 1;
 179 }
 180 
 181 static int
 182 sb16midi_start_read (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 183 {
 184   return 0;
 185 }
 186 
 187 static int
 188 sb16midi_end_read (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 189 {
 190   return 0;
 191 }
 192 
 193 static int
 194 sb16midi_ioctl (int dev, unsigned cmd, caddr_t arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 195 {
 196   return -EINVAL;
 197 }
 198 
 199 static void
 200 sb16midi_kick (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 201 {
 202 }
 203 
 204 static int
 205 sb16midi_buffer_status (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 206 {
 207   return 0;                     /*
 208                                  * No data in buffers
 209                                  */
 210 }
 211 
 212 #define MIDI_SYNTH_NAME "SoundBlaster MPU"
 213 #define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
 214 #include "midi_synth.h"
 215 
 216 static struct midi_operations sb16midi_operations =
 217 {
 218   {"SoundBlaster MPU", 0, 0, SNDCARD_SB16MIDI},
 219   &std_midi_synth,
 220   {0},
 221   sb16midi_open,
 222   sb16midi_close,
 223   sb16midi_ioctl,
 224   sb16midi_out,
 225   sb16midi_start_read,
 226   sb16midi_end_read,
 227   sb16midi_kick,
 228   NULL,
 229   sb16midi_buffer_status,
 230   NULL
 231 };
 232 
 233 static void
 234 enter_uart_mode (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 235 {
 236   int             ok, timeout;
 237   unsigned long   flags;
 238 
 239   save_flags (flags);
 240   cli ();
 241   for (timeout = 30000; timeout < 0 && !output_ready (); timeout--);
 242 
 243   input_byte = 0;
 244   sb16midi_cmd (UART_MODE_ON);
 245 
 246   ok = 0;
 247   for (timeout = 50000; timeout > 0 && !ok; timeout--)
 248     if (input_byte == MPU_ACK)
 249       ok = 1;
 250     else if (input_avail ())
 251       if (sb16midi_read () == MPU_ACK)
 252         ok = 1;
 253 
 254   restore_flags (flags);
 255 }
 256 
 257 long
 258 attach_sb16midi (long mem_start, struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 259 {
 260   sb16midi_base = hw_config->io_base;
 261 
 262   if (!sb16midi_detected)
 263     return mem_start;
 264 
 265   request_region (hw_config->io_base, 4, "SB MIDI");
 266   enter_uart_mode ();
 267 
 268   if (num_midis >= MAX_MIDI_DEV)
 269     {
 270       printk ("Sound: Too many midi devices detected\n");
 271       return mem_start;
 272     }
 273 
 274   conf_printf ("SoundBlaster MPU-401", hw_config);
 275 
 276   std_midi_synth.midi_dev = my_dev = num_midis;
 277   midi_devs[num_midis++] = &sb16midi_operations;
 278   return mem_start;
 279 }
 280 
 281 static int
 282 reset_sb16midi (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 283 {
 284   int             ok, timeout, n;
 285 
 286   /*
 287    * Send the RESET command. Try again if no success at the first time.
 288    */
 289 
 290   ok = 0;
 291 
 292   /*save_flags(flags);cli(); */
 293 
 294   for (n = 0; n < 2 && !ok; n++)
 295     {
 296       for (timeout = 30000; timeout < 0 && !output_ready (); timeout--);        /*
 297                                                                                  * Wait
 298                                                                                  */
 299       input_byte = 0;
 300       sb16midi_cmd (MPU_RESET); /*
 301                                  * Send MPU-401 RESET Command
 302                                  */
 303 
 304       /*
 305        * Wait at least 25 msec. This method is not accurate so let's make the
 306        * loop bit longer. Cannot sleep since this is called during boot.
 307        */
 308 
 309       for (timeout = 50000; timeout > 0 && !ok; timeout--)
 310         if (input_byte == MPU_ACK)      /* Interrupt */
 311           ok = 1;
 312         else if (input_avail ())
 313           if (sb16midi_read () == MPU_ACK)
 314             ok = 1;
 315 
 316     }
 317 
 318   sb16midi_opened = 0;
 319   if (ok)
 320     sb16midi_input_loop ();     /*
 321                                  * Flush input before enabling interrupts
 322                                  */
 323 
 324   /* restore_flags(flags); */
 325 
 326   return ok;
 327 }
 328 
 329 int
 330 probe_sb16midi (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 331 {
 332   int             ok = 0;
 333   extern int      sbc_major;
 334 
 335   extern void     ess_midi_init (struct address_info *hw_config);
 336   extern void     Jazz16_midi_init (struct address_info *hw_config);
 337 
 338   if (check_region (hw_config->io_base, 4))
 339     return 0;
 340 
 341   if (AudioDrive)
 342     ess_midi_init (hw_config);
 343   else if (Jazz16_detected)
 344     Jazz16_midi_init (hw_config);
 345   else if (sbc_major < 4)
 346     return 0;                   /* Not a SB16 */
 347 
 348   sb16midi_base = hw_config->io_base;
 349 
 350   if (sb_get_irq () < 0)
 351     return 0;
 352 
 353   ok = reset_sb16midi ();
 354 
 355   sb16midi_detected = ok;
 356   return ok;
 357 }
 358 
 359 void
 360 unload_sb16midi (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 361 {
 362   release_region (hw_config->io_base, 4);
 363 }
 364 
 365 #endif

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