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. sbmidiintr
  4. sb16midi_open
  5. sb16midi_close
  6. sb16midi_out
  7. sb16midi_start_read
  8. sb16midi_end_read
  9. sb16midi_ioctl
  10. sb16midi_kick
  11. sb16midi_buffer_status
  12. attach_sb16midi
  13. reset_sb16midi
  14. probe_sb16midi
  15. 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 #if defined(CONFIG_SB) && defined(CONFIG_MIDI)
  33 
  34 #include "sb.h"
  35 
  36 #define DATAPORT   (sb16midi_base)
  37 #define COMDPORT   (sb16midi_base+1)
  38 #define STATPORT   (sb16midi_base+1)
  39 
  40 extern sound_os_info *sb_osp;
  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 extern int      Jazz16_detected;
  62 extern int      AudioDrive;
  63 
  64 static int      reset_sb16midi (void);
  65 static void     (*midi_input_intr) (int dev, unsigned char data);
  66 static volatile unsigned char input_byte;
  67 
  68 static void
  69 sb16midi_input_loop (void)
     /* [previous][next][first][last][top][bottom][index][help] */
  70 {
  71   while (input_avail ())
  72     {
  73       unsigned char   c = sb16midi_read ();
  74 
  75       if (c == MPU_ACK)
  76         input_byte = c;
  77       else if (sb16midi_opened & OPEN_READ && midi_input_intr)
  78         midi_input_intr (my_dev, c);
  79     }
  80 }
  81 
  82 void
  83 sb16midiintr (int unit)
     /* [previous][next][first][last][top][bottom][index][help] */
  84 {
  85   if (input_avail ())
  86     sb16midi_input_loop ();
  87 }
  88 
  89 void
  90 sbmidiintr (int irq, struct pt_regs *dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
  91 {
  92   if (input_avail ())
  93     sb16midi_input_loop ();
  94 }
  95 
  96 static int
  97 sb16midi_open (int dev, int mode,
     /* [previous][next][first][last][top][bottom][index][help] */
  98                void            (*input) (int dev, unsigned char data),
  99                void            (*output) (int dev)
 100 )
 101 {
 102   if (sb16midi_opened)
 103     {
 104       return -EBUSY;
 105     }
 106 
 107   sb16midi_input_loop ();
 108 
 109   midi_input_intr = input;
 110   sb16midi_opened = mode;
 111 
 112   return 0;
 113 }
 114 
 115 static void
 116 sb16midi_close (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 117 {
 118   sb16midi_opened = 0;
 119 }
 120 
 121 static int
 122 sb16midi_out (int dev, unsigned char midi_byte)
     /* [previous][next][first][last][top][bottom][index][help] */
 123 {
 124   int             timeout;
 125   unsigned long   flags;
 126 
 127   /*
 128    * Test for input since pending input seems to block the output.
 129    */
 130 
 131   save_flags (flags);
 132   cli ();
 133 
 134   if (input_avail ())
 135     sb16midi_input_loop ();
 136 
 137   restore_flags (flags);
 138 
 139   /*
 140    * Sometimes it takes about 13000 loops before the output becomes ready
 141    * (After reset). Normally it takes just about 10 loops.
 142    */
 143 
 144   for (timeout = 30000; timeout > 0 && !output_ready (); timeout--);    /*
 145                                                                          * Wait
 146                                                                          */
 147 
 148   if (!output_ready ())
 149     {
 150       printk ("MPU-401: Timeout\n");
 151       return 0;
 152     }
 153 
 154   sb16midi_write (midi_byte);
 155   return 1;
 156 }
 157 
 158 static int
 159 sb16midi_start_read (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 160 {
 161   return 0;
 162 }
 163 
 164 static int
 165 sb16midi_end_read (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 166 {
 167   return 0;
 168 }
 169 
 170 static int
 171 sb16midi_ioctl (int dev, unsigned cmd, ioctl_arg arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 172 {
 173   return -EINVAL;
 174 }
 175 
 176 static void
 177 sb16midi_kick (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 178 {
 179 }
 180 
 181 static int
 182 sb16midi_buffer_status (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 183 {
 184   return 0;                     /*
 185                                  * No data in buffers
 186                                  */
 187 }
 188 
 189 #define MIDI_SYNTH_NAME "SoundBlaster MPU"
 190 #define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
 191 #include "midi_synth.h"
 192 
 193 static struct midi_operations sb16midi_operations =
 194 {
 195   {"SoundBlaster MPU", 0, 0, SNDCARD_SB16MIDI},
 196   &std_midi_synth,
 197   {0},
 198   sb16midi_open,
 199   sb16midi_close,
 200   sb16midi_ioctl,
 201   sb16midi_out,
 202   sb16midi_start_read,
 203   sb16midi_end_read,
 204   sb16midi_kick,
 205   NULL,
 206   sb16midi_buffer_status,
 207   NULL
 208 };
 209 
 210 long
 211 attach_sb16midi (long mem_start, struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 212 {
 213   int             ok, timeout;
 214   unsigned long   flags;
 215 
 216   sb16midi_base = hw_config->io_base;
 217 
 218   if (!sb16midi_detected)
 219     return mem_start;
 220 
 221   request_region (hw_config->io_base, 4, "SB MIDI");
 222 
 223   save_flags (flags);
 224   cli ();
 225   for (timeout = 30000; timeout < 0 && !output_ready (); timeout--);    /*
 226                                                                          * Wait
 227                                                                          */
 228   input_byte = 0;
 229   sb16midi_cmd (UART_MODE_ON);
 230 
 231   ok = 0;
 232   for (timeout = 50000; timeout > 0 && !ok; timeout--)
 233     if (input_byte == MPU_ACK)
 234       ok = 1;
 235     else if (input_avail ())
 236       if (sb16midi_read () == MPU_ACK)
 237         ok = 1;
 238 
 239   restore_flags (flags);
 240 
 241   if (num_midis >= MAX_MIDI_DEV)
 242     {
 243       printk ("Sound: Too many midi devices detected\n");
 244       return mem_start;
 245     }
 246 
 247   conf_printf ("SoundBlaster MPU-401", hw_config);
 248 
 249   std_midi_synth.midi_dev = my_dev = num_midis;
 250   midi_devs[num_midis++] = &sb16midi_operations;
 251   return mem_start;
 252 }
 253 
 254 static int
 255 reset_sb16midi (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 256 {
 257   int             ok, timeout, n;
 258 
 259   /*
 260    * Send the RESET command. Try again if no success at the first time.
 261    */
 262 
 263   if (inb (STATPORT) == 0xff)
 264     return 0;
 265 
 266   ok = 0;
 267 
 268   /*save_flags(flags);cli(); */
 269 
 270   for (n = 0; n < 2 && !ok; n++)
 271     {
 272       for (timeout = 30000; timeout < 0 && !output_ready (); timeout--);        /*
 273                                                                                  * Wait
 274                                                                                  */
 275       input_byte = 0;
 276       sb16midi_cmd (MPU_RESET); /*
 277                                  * Send MPU-401 RESET Command
 278                                  */
 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_byte == MPU_ACK)      /* Interrupt */
 287           ok = 1;
 288         else if (input_avail ())
 289           if (sb16midi_read () == MPU_ACK)
 290             ok = 1;
 291 
 292     }
 293 
 294   sb16midi_opened = 0;
 295   if (ok)
 296     sb16midi_input_loop ();     /*
 297                                  * Flush input before enabling interrupts
 298                                  */
 299 
 300   /* restore_flags(flags); */
 301 
 302   return ok;
 303 }
 304 
 305 int
 306 probe_sb16midi (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 307 {
 308   int             ok = 0;
 309   extern int      sbc_major;
 310 
 311   extern void     ess_midi_init (struct address_info *hw_config);
 312   extern void     Jazz16_midi_init (struct address_info *hw_config);
 313 
 314   if (check_region (hw_config->io_base, 4))
 315     return 0;
 316 
 317   if (AudioDrive)
 318     ess_midi_init (hw_config);
 319   else if (Jazz16_detected)
 320     Jazz16_midi_init (hw_config);
 321   else if (sbc_major < 4)
 322     return 0;                   /* Not a SB16 */
 323 
 324   sb16midi_base = hw_config->io_base;
 325 
 326   if (sb_get_irq () < 0)
 327     return 0;
 328 
 329   ok = reset_sb16midi ();
 330 
 331   sb16midi_detected = ok;
 332   return ok;
 333 }
 334 
 335 void
 336 unload_sb16midi (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 337 {
 338   release_region (hw_config->io_base, 4);
 339 }
 340 
 341 #endif

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