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

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