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

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