root/drivers/sound/mad16_sb_midi.c

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

DEFINITIONS

This source file includes following definitions.
  1. mad16_sb_dsp_command
  2. mad16_sbintr
  3. mad16_sb_reset_dsp
  4. mad16_sb_dsp_detect
  5. mad16_sb_dsp_init
  6. mad16_sb_dsp_unload
  7. mad16_sb_midi_open
  8. mad16_sb_midi_close
  9. mad16_sb_midi_out
  10. mad16_sb_midi_start_read
  11. mad16_sb_midi_end_read
  12. mad16_sb_midi_ioctl
  13. mad16_sb_midi_init

   1 /*
   2  * sound/mad16_sb_midi.c
   3  *
   4  * The low level driver for MAD16 SoundBlaster-DS-chip-based MIDI.
   5  *
   6  * Copyright by Hannu Savolainen 1993, Aaron Ucko 1995
   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_MAD16) && defined(CONFIG_MIDI)
  33 
  34 #define sbc_base mad16_sb_base
  35 #include "sb.h"
  36 
  37 static int      input_opened = 0;
  38 static int      my_dev;
  39 static int      mad16_sb_base = 0x220;
  40 static int      mad16_sb_irq = 0;
  41 static int      mad16_sb_dsp_ok = 0;
  42 static int      mad16_sb_dsp_attached = 0;
  43 static sound_os_info *midi_osp;
  44 
  45 int             mad16_sb_midi_mode = NORMAL_MIDI;
  46 int             mad16_sb_midi_busy = 0;
  47 
  48 int             mad16_sb_duplex_midi = 0;
  49 volatile int    mad16_sb_intr_active = 0;
  50 
  51 void            (*midi_input_intr) (int dev, unsigned char data);
  52 
  53 static void     mad16_sb_midi_init (int model);
  54 
  55 static int
  56 mad16_sb_dsp_command (unsigned char val)
     /* [previous][next][first][last][top][bottom][index][help] */
  57 {
  58   int             i;
  59   unsigned long   limit;
  60 
  61   limit = jiffies + HZ / 10;    /*
  62                                    * The timeout is 0.1 secods
  63                                  */
  64 
  65   /*
  66    * Note! the i<500000 is an emergency exit. The mad16_sb_dsp_command() is sometimes
  67    * called while interrupts are disabled. This means that the timer is
  68    * disabled also. However the timeout situation is a abnormal condition.
  69    * Normally the DSP should be ready to accept commands after just couple of
  70    * loops.
  71    */
  72 
  73   for (i = 0; i < 500000 && jiffies < limit; i++)
  74     {
  75       if ((inb (DSP_STATUS) & 0x80) == 0)
  76         {
  77           outb (val, DSP_COMMAND);
  78           return 1;
  79         }
  80     }
  81 
  82   printk ("MAD16 (SBP mode): DSP Command(%x) Timeout.\n", val);
  83   printk ("IRQ conflict???\n");
  84   return 0;
  85 }
  86 
  87 void
  88 mad16_sbintr (int irq, struct pt_regs *dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90   int             status;
  91 
  92   unsigned long   flags;
  93   unsigned char   data;
  94 
  95   status = inb (DSP_DATA_AVAIL);        /*
  96                                            * Clear interrupt
  97                                          */
  98 
  99   save_flags (flags);
 100   cli ();
 101 
 102   data = inb (DSP_READ);
 103   if (input_opened)
 104     midi_input_intr (my_dev, data);
 105 
 106   restore_flags (flags);
 107 }
 108 
 109 static int
 110 mad16_sb_reset_dsp (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 111 {
 112   int             loopc;
 113 
 114   outb (1, DSP_RESET);
 115   tenmicrosec (midi_osp);
 116   outb (0, DSP_RESET);
 117   tenmicrosec (midi_osp);
 118   tenmicrosec (midi_osp);
 119   tenmicrosec (midi_osp);
 120 
 121   for (loopc = 0; loopc < 1000 && !(inb (DSP_DATA_AVAIL) & 0x80); loopc++);     /*
 122                                                                                    * Wait
 123                                                                                    * for
 124                                                                                    * data
 125                                                                                    * *
 126                                                                                    * available
 127                                                                                    * status
 128                                                                                  */
 129 
 130   if (inb (DSP_READ) != 0xAA)
 131     return 0;                   /*
 132                                  * Sorry
 133                                  */
 134 
 135   return 1;
 136 }
 137 
 138 int
 139 mad16_sb_dsp_detect (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 140 {
 141   mad16_sb_base = hw_config->io_base;
 142   mad16_sb_irq = hw_config->irq;
 143   midi_osp = hw_config->osp;
 144 
 145   if (check_region (hw_config->io_base, 16))
 146     {
 147       printk ("MAD16 SB MIDI: I/O base %x not free\n", hw_config->io_base);
 148       return 0;
 149     }
 150 
 151   if (mad16_sb_dsp_ok)
 152     return 0;                   /*
 153                                  * Already initialized
 154                                  */
 155   if (!mad16_sb_reset_dsp ())
 156     return 0;
 157 
 158   return 1;                     /*
 159                                  * Detected
 160                                  */
 161 }
 162 
 163 long
 164 mad16_sb_dsp_init (long mem_start, struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 165 /* this function now just verifies the reported version and calls
 166  * mad16_sb_midi_init -- everything else is done elsewhere */
 167 {
 168 
 169   mad16_sb_dsp_attached = 1;
 170   midi_osp = hw_config->osp;
 171   if (snd_set_irq_handler (mad16_sb_irq, mad16_sbintr, "MAD16 SB MIDI", midi_osp) < 0)
 172     {
 173       printk ("MAD16 SB MIDI: IRQ not free\n");
 174       return mem_start;
 175     }
 176 
 177   request_region (hw_config->io_base, 16, "mad16/Mozart MIDI");
 178 
 179   conf_printf ("MAD16 MIDI (SB mode)", hw_config);
 180   mad16_sb_midi_init (2);
 181 
 182   mad16_sb_dsp_ok = 1;
 183   return mem_start;
 184 }
 185 
 186 void
 187 mad16_sb_dsp_unload (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 188 {
 189   if (!mad16_sb_dsp_attached)
 190     return;
 191 
 192   release_region (hw_config->io_base, 16);
 193   snd_release_irq (hw_config->irq);
 194 }
 195 
 196 static int
 197 mad16_sb_midi_open (int dev, int mode,
     /* [previous][next][first][last][top][bottom][index][help] */
 198                     void            (*input) (int dev, unsigned char data),
 199                     void            (*output) (int dev)
 200 )
 201 {
 202 
 203   if (!mad16_sb_dsp_ok)
 204     {
 205       printk ("MAD16_SB Error: MIDI hardware not installed\n");
 206       return -ENXIO;
 207     }
 208 
 209   if (mad16_sb_midi_busy)
 210     return -EBUSY;
 211 
 212   if (mode != OPEN_WRITE && !mad16_sb_duplex_midi)
 213     {
 214       if (num_midis == 1)
 215         printk ("MAD16 (SBP mode): Midi input not currently supported\n");
 216       return -EPERM;
 217     }
 218 
 219   mad16_sb_midi_mode = NORMAL_MIDI;
 220   if (mode != OPEN_WRITE)
 221     {
 222       if (mad16_sb_intr_active)
 223         return -EBUSY;
 224       mad16_sb_midi_mode = UART_MIDI;
 225     }
 226 
 227   if (mad16_sb_midi_mode == UART_MIDI)
 228     {
 229       mad16_sb_reset_dsp ();
 230 
 231       if (!mad16_sb_dsp_command (0x35))
 232         return -EIO;            /*
 233                                    * Enter the UART mode
 234                                  */
 235       mad16_sb_intr_active = 1;
 236 
 237       input_opened = 1;
 238       midi_input_intr = input;
 239     }
 240 
 241   mad16_sb_midi_busy = 1;
 242 
 243   return 0;
 244 }
 245 
 246 static void
 247 mad16_sb_midi_close (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 248 {
 249   if (mad16_sb_midi_mode == UART_MIDI)
 250     {
 251       mad16_sb_reset_dsp ();    /*
 252                                    * The only way to kill the UART mode
 253                                  */
 254     }
 255   mad16_sb_intr_active = 0;
 256   mad16_sb_midi_busy = 0;
 257   input_opened = 0;
 258 }
 259 
 260 static int
 261 mad16_sb_midi_out (int dev, unsigned char midi_byte)
     /* [previous][next][first][last][top][bottom][index][help] */
 262 {
 263   unsigned long   flags;
 264 
 265   if (mad16_sb_midi_mode == NORMAL_MIDI)
 266     {
 267       save_flags (flags);
 268       cli ();
 269       if (mad16_sb_dsp_command (0x38))
 270         mad16_sb_dsp_command (midi_byte);
 271       else
 272         printk ("MAD16_SB Error: Unable to send a MIDI byte\n");
 273       restore_flags (flags);
 274     }
 275   else
 276     mad16_sb_dsp_command (midi_byte);   /*
 277                                            * UART write
 278                                          */
 279 
 280   return 1;
 281 }
 282 
 283 static int
 284 mad16_sb_midi_start_read (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 285 {
 286   if (mad16_sb_midi_mode != UART_MIDI)
 287     {
 288       printk ("MAD16 (SBP mode): MIDI input not implemented.\n");
 289       return -EPERM;
 290     }
 291   return 0;
 292 }
 293 
 294 static int
 295 mad16_sb_midi_end_read (int dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 296 {
 297   if (mad16_sb_midi_mode == UART_MIDI)
 298     {
 299       mad16_sb_reset_dsp ();
 300       mad16_sb_intr_active = 0;
 301     }
 302   return 0;
 303 }
 304 
 305 static int
 306 mad16_sb_midi_ioctl (int dev, unsigned cmd, ioctl_arg arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 307 {
 308   return -EPERM;
 309 }
 310 
 311 #define MIDI_SYNTH_NAME "pseudo-SoundBlaster Midi"
 312 #define MIDI_SYNTH_CAPS 0
 313 #include "midi_synth.h"
 314 
 315 static struct midi_operations mad16_sb_midi_operations =
 316 {
 317   {"MAD16 (SBP mode)", 0, 0, SNDCARD_MAD16},
 318   &std_midi_synth,
 319   {0},
 320   mad16_sb_midi_open,
 321   mad16_sb_midi_close,
 322   mad16_sb_midi_ioctl,
 323   mad16_sb_midi_out,
 324   mad16_sb_midi_start_read,
 325   mad16_sb_midi_end_read,
 326   NULL,                         /*
 327                                  * Kick
 328                                  */
 329   NULL,                         /*
 330                                  * command
 331                                  */
 332   NULL,                         /*
 333                                  * buffer_status
 334                                  */
 335   NULL
 336 };
 337 
 338 static void
 339 mad16_sb_midi_init (int model)
     /* [previous][next][first][last][top][bottom][index][help] */
 340 {
 341   if (num_midis >= MAX_MIDI_DEV)
 342     {
 343       printk ("Sound: Too many midi devices detected\n");
 344       return;
 345     }
 346 
 347   std_midi_synth.midi_dev = num_midis;
 348   my_dev = num_midis;
 349   midi_devs[num_midis++] = &mad16_sb_midi_operations;
 350 }
 351 
 352 #endif

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