root/drivers/sound/maui.c

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

DEFINITIONS

This source file includes following definitions.
  1. maui_wait
  2. maui_read
  3. maui_write
  4. mauiintr
  5. maui_load_patch
  6. probe_maui
  7. attach_maui
  8. unload_maui

   1 /*
   2  * sound/maui.c
   3  *
   4  * The low level driver for Turtle Beach Maui and Tropez.
   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 #define USE_SEQ_MACROS
  33 #define USE_SIMPLE_MACROS
  34 
  35 #include "sound_config.h"
  36 
  37 #if defined(CONFIG_MAUI)
  38 
  39 static int      maui_base = 0x330;
  40 
  41 static volatile int irq_ok = 0;
  42 static int     *maui_osp;
  43 
  44 #define HOST_DATA_PORT  (maui_base + 2)
  45 #define HOST_STAT_PORT  (maui_base + 3)
  46 #define HOST_CTRL_PORT  (maui_base + 3)
  47 
  48 #define STAT_TX_INTR    0x40
  49 #define STAT_TX_AVAIL   0x20
  50 #define STAT_TX_IENA    0x10
  51 #define STAT_RX_INTR    0x04
  52 #define STAT_RX_AVAIL   0x02
  53 #define STAT_RX_IENA    0x01
  54 
  55 static int      (*orig_load_patch) (int dev, int format, const char *addr,
  56                                  int offs, int count, int pmgr_flag) = NULL;
  57 
  58 static wait_handle *maui_sleeper = NULL;
  59 static volatile struct snd_wait maui_sleep_flag =
  60 {0};
  61 
  62 static int
  63 maui_wait (int mask)
     /* [previous][next][first][last][top][bottom][index][help] */
  64 {
  65   int             i;
  66 
  67 /*
  68  * Perform a short initial wait without sleeping
  69  */
  70 
  71   for (i = 0; i < 100; i++)
  72     {
  73       if (inb (HOST_STAT_PORT) & mask)
  74         {
  75           return 1;
  76         }
  77     }
  78 
  79 /*
  80  * Wait up to 15 seconds with sleeping
  81  */
  82 
  83   for (i = 0; i < 150; i++)
  84     {
  85       if (inb (HOST_STAT_PORT) & mask)
  86         {
  87           return 1;
  88         }
  89 
  90 
  91       {
  92         unsigned long   tl;
  93 
  94         if (HZ / 10)
  95           current_set_timeout (tl = jiffies + (HZ / 10));
  96         else
  97           tl = (unsigned long) -1;
  98         maui_sleep_flag.mode = WK_SLEEP;
  99         module_interruptible_sleep_on (&maui_sleeper);
 100         if (!(maui_sleep_flag.mode & WK_WAKEUP))
 101           {
 102             if (jiffies >= tl)
 103               maui_sleep_flag.mode |= WK_TIMEOUT;
 104           }
 105         maui_sleep_flag.mode &= ~WK_SLEEP;
 106       };
 107       if (current_got_fatal_signal ())
 108         return 0;
 109     }
 110 
 111   return 0;
 112 }
 113 
 114 static int
 115 maui_read (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {
 117   if (maui_wait (STAT_RX_AVAIL))
 118     return inb (HOST_DATA_PORT);
 119 
 120   return -1;
 121 }
 122 
 123 static int
 124 maui_write (unsigned char data)
     /* [previous][next][first][last][top][bottom][index][help] */
 125 {
 126   if (maui_wait (STAT_TX_AVAIL))
 127     {
 128       outb (data, HOST_DATA_PORT);
 129       return 1;
 130     }
 131   printk ("Maui: Write timeout\n");
 132 
 133   return 0;
 134 }
 135 
 136 void
 137 mauiintr (int irq, void *dev_id, struct pt_regs *dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 138 {
 139   irq_ok = 1;
 140 }
 141 
 142 
 143 int
 144 maui_load_patch (int dev, int format, const char *addr,
     /* [previous][next][first][last][top][bottom][index][help] */
 145                  int offs, int count, int pmgr_flag)
 146 {
 147 
 148   struct sysex_info header;
 149   unsigned long   left, src_offs;
 150   int             hdr_size = (unsigned long) &header.data[0] - (unsigned long) &header;
 151   int             i;
 152 
 153   if (format == SYSEX_PATCH)    /* Handled by midi_synth.c */
 154     return orig_load_patch (dev, format, addr, offs, count, pmgr_flag);
 155 
 156   if (format != MAUI_PATCH)
 157     {
 158       printk ("Maui: Unknown patch format\n");
 159     }
 160 
 161   if (count < hdr_size)
 162     {
 163       printk ("Maui error: Patch header too short\n");
 164       return -EINVAL;
 165     }
 166 
 167   count -= hdr_size;
 168 
 169   /*
 170    * Copy the header from user space but ignore the first bytes which have
 171    * been transferred already.
 172    */
 173 
 174   memcpy_fromfs (&((char *) &header)[offs], &((addr)[offs]), hdr_size - offs);
 175 
 176   if (count < header.len)
 177     {
 178       printk ("Maui warning: Host command record too short (%d<%d)\n",
 179               count, (int) header.len);
 180       header.len = count;
 181     }
 182 
 183   left = header.len;
 184   src_offs = 0;
 185 
 186   for (i = 0; i < left; i++)
 187     {
 188       unsigned char   data;
 189 
 190       data = get_fs_byte (&((addr)[hdr_size + i]));
 191       if (i == 0 && !(data & 0x80))
 192         return -EINVAL;
 193 
 194       if (maui_write (data) == -1)
 195         return -EIO;
 196     }
 197 
 198   if ((i = maui_read ()) != 0x80)
 199     {
 200       if (i != -1)
 201         printk ("Maui: Error status %02x\n", i);
 202 
 203       return -EIO;
 204     }
 205 
 206   return 0;
 207 }
 208 
 209 int
 210 probe_maui (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 211 {
 212   int             i;
 213   int             tmp1, tmp2, ret;
 214 
 215   if (check_region (hw_config->io_base, 8))
 216     return 0;
 217 
 218   maui_base = hw_config->io_base;
 219   maui_osp = hw_config->osp;
 220 
 221   if (snd_set_irq_handler (hw_config->irq, mauiintr, "Maui", maui_osp) < 0)
 222     return 0;
 223 
 224   maui_sleep_flag.mode = WK_NONE;
 225 
 226   if (!maui_write (0xCF))       /* Report hardware version */
 227     {
 228       printk ("No WaveFront firmware detected (card uninitialized?)\n");
 229       snd_release_irq (hw_config->irq);
 230       return 0;
 231     }
 232 
 233   if ((tmp1 = maui_read ()) == -1 || (tmp2 = maui_read ()) == -1)
 234     {
 235       printk ("No WaveFront firmware detected (card uninitialized?)\n");
 236       snd_release_irq (hw_config->irq);
 237       return 0;
 238     }
 239 
 240   if (tmp1 == 0xff || tmp2 == 0xff)
 241     {
 242       snd_release_irq (hw_config->irq);
 243       return 0;
 244     }
 245 
 246   if (trace_init)
 247     printk ("WaveFront hardware version %d.%d\n", tmp1, tmp2);
 248 
 249   if (!maui_write (0x9F))       /* Report firmware version */
 250     return 0;
 251   if ((tmp1 = maui_read ()) == -1 || (tmp2 = maui_read ()) == -1)
 252     return 0;
 253 
 254   if (trace_init)
 255     printk ("WaveFront firmware version %d.%d\n", tmp1, tmp2);
 256 
 257   if (!maui_write (0x85))       /* Report free DRAM */
 258     return 0;
 259   tmp1 = 0;
 260   for (i = 0; i < 4; i++)
 261     {
 262       tmp1 |= maui_read () << (7 * i);
 263     }
 264   if (trace_init)
 265     printk ("Available DRAM %dk\n", tmp1 / 1024);
 266 
 267   for (i = 0; i < 1000; i++)
 268     if (probe_mpu401 (hw_config))
 269       break;
 270 
 271   ret = probe_mpu401 (hw_config);
 272 
 273   if (ret)
 274     request_region (hw_config->io_base + 2, 6, "Maui");
 275 
 276   return ret;
 277 }
 278 
 279 long
 280 attach_maui (long mem_start, struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 281 {
 282   int             this_dev = num_midis;
 283 
 284   conf_printf ("Maui", hw_config);
 285 
 286   hw_config->irq *= -1;
 287   mem_start = attach_mpu401 (mem_start, hw_config);
 288 
 289   if (num_midis > this_dev)     /* The MPU401 driver installed itself */
 290     {
 291       struct synth_operations *synth;
 292 
 293       /*
 294        * Intercept patch loading calls so that they canbe handled
 295        * by the Maui driver.
 296        */
 297 
 298       synth = midi_devs[this_dev]->converter;
 299 
 300       if (synth != NULL)
 301         {
 302           orig_load_patch = synth->load_patch;
 303           synth->load_patch = &maui_load_patch;
 304         }
 305       else
 306         printk ("Maui: Can't install patch loader\n");
 307     }
 308   return mem_start;
 309 }
 310 
 311 void
 312 unload_maui (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 313 {
 314   int             irq = hw_config->irq;
 315 
 316   release_region (hw_config->io_base + 2, 6);
 317 
 318   unload_mpu401 (hw_config);
 319 
 320   if (irq < 0)
 321     irq = -irq;
 322 
 323   if (irq > 0)
 324     snd_release_irq (irq);
 325 }
 326 
 327 
 328 #endif

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