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. download_code
  6. maui_init
  7. maui_short_wait
  8. maui_load_patch
  9. probe_maui
  10. attach_maui
  11. 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 #ifdef HAVE_MAUI_BOOT
  59 #include "maui_boot.h"
  60 #endif
  61 
  62 static wait_handle *maui_sleeper = NULL;
  63 static volatile struct snd_wait maui_sleep_flag =
  64 {0};
  65 
  66 static int
  67 maui_wait (int mask)
     /* [previous][next][first][last][top][bottom][index][help] */
  68 {
  69   int             i;
  70 
  71 /*
  72  * Perform a short initial wait without sleeping
  73  */
  74 
  75   for (i = 0; i < 100; i++)
  76     {
  77       if (inb (HOST_STAT_PORT) & mask)
  78         {
  79           return 1;
  80         }
  81     }
  82 
  83 /*
  84  * Wait up to 15 seconds with sleeping
  85  */
  86 
  87   for (i = 0; i < 150; i++)
  88     {
  89       if (inb (HOST_STAT_PORT) & mask)
  90         {
  91           return 1;
  92         }
  93 
  94 
  95       {
  96         unsigned long   tl;
  97 
  98         if (HZ / 10)
  99           current_set_timeout (tl = jiffies + (HZ / 10));
 100         else
 101           tl = (unsigned long) -1;
 102         maui_sleep_flag.mode = WK_SLEEP;
 103         module_interruptible_sleep_on (&maui_sleeper);
 104         if (!(maui_sleep_flag.mode & WK_WAKEUP))
 105           {
 106             if (jiffies >= tl)
 107               maui_sleep_flag.mode |= WK_TIMEOUT;
 108           }
 109         maui_sleep_flag.mode &= ~WK_SLEEP;
 110       };
 111       if (current_got_fatal_signal ())
 112         return 0;
 113     }
 114 
 115   return 0;
 116 }
 117 
 118 static int
 119 maui_read (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 120 {
 121   if (maui_wait (STAT_RX_AVAIL))
 122     return inb (HOST_DATA_PORT);
 123 
 124   return -1;
 125 }
 126 
 127 static int
 128 maui_write (unsigned char data)
     /* [previous][next][first][last][top][bottom][index][help] */
 129 {
 130   if (maui_wait (STAT_TX_AVAIL))
 131     {
 132       outb (data, HOST_DATA_PORT);
 133       return 1;
 134     }
 135   printk ("Maui: Write timeout\n");
 136 
 137   return 0;
 138 }
 139 
 140 void
 141 mauiintr (int irq, void *dev_id, struct pt_regs *dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 142 {
 143   irq_ok = 1;
 144 }
 145 
 146 static int
 147 download_code (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 148 {
 149   int             i, lines = 0;
 150   int             eol_seen = 0, done = 0;
 151   int             skip = 1;
 152 
 153   printk ("Code download (%d bytes): ", maui_osLen);
 154 
 155   for (i = 0; i < maui_osLen; i++)
 156     {
 157       if (maui_os[i] != '\r')
 158         if (!skip || (maui_os[i] == 'S' && (i == 0 || maui_os[i - 1] == '\n')))
 159           {
 160             skip = 0;
 161 
 162             if (maui_os[i] == '\n')
 163               eol_seen = skip = 1;
 164             else if (maui_os[i] == 'S')
 165               {
 166                 if (maui_os[i + 1] == '8')
 167                   done = 1;
 168                 if (!maui_write (0xF1))
 169                   goto failure;
 170                 if (!maui_write ('S'))
 171                   goto failure;
 172               }
 173             else
 174               {
 175                 if (!maui_write (maui_os[i]))
 176                   goto failure;
 177               }
 178 
 179             if (eol_seen)
 180               {
 181                 int             c = 0;
 182 
 183                 int             n;
 184 
 185                 eol_seen = 0;
 186 
 187                 for (n = 0; n < 2; n++)
 188                   if (maui_wait (STAT_RX_AVAIL))
 189                     {
 190                       c = inb (HOST_DATA_PORT);
 191                       break;
 192                     }
 193 
 194                 if (c != 0x80)
 195                   {
 196                     printk ("Doanload not acknowledged\n");
 197                     return 0;
 198                   }
 199                 else if (!(lines++ % 10))
 200                   printk (".");
 201 
 202                 if (done)
 203                   {
 204                     printk ("\nDownload complete\n");
 205                     return 1;
 206                   }
 207               }
 208           }
 209     }
 210 
 211 failure:
 212 
 213   printk ("\nDownload failed!!!\n");
 214   return 0;
 215 }
 216 
 217 static int
 218 maui_init (int irq)
     /* [previous][next][first][last][top][bottom][index][help] */
 219 {
 220   int             i;
 221   unsigned char   bits;
 222 
 223   switch (irq)
 224     {
 225     case 9:
 226       bits = 0x00;
 227       break;
 228     case 5:
 229       bits = 0x08;
 230       break;
 231     case 12:
 232       bits = 0x10;
 233       break;
 234     case 15:
 235       bits = 0x18;
 236       break;
 237 
 238     default:
 239       printk ("Maui: Invalid IRQ %d\n", irq);
 240       return 0;
 241     }
 242 
 243   outb (0x00, HOST_CTRL_PORT);  /* Reset */
 244 
 245   outb (bits, HOST_DATA_PORT);  /* Set the IRQ bits */
 246   outb (bits | 0x80, HOST_DATA_PORT);   /* Set the IRQ bits again? */
 247 
 248   outb (0x80, HOST_CTRL_PORT);  /* Leave reset */
 249   outb (0x80, HOST_CTRL_PORT);  /* Leave reset */
 250 
 251   outb (0xD0, HOST_CTRL_PORT);  /* Cause interrupt */
 252 
 253   for (i = 0; i < 1000000 && !irq_ok; i++);
 254 
 255   if (!irq_ok)
 256     return 0;
 257 
 258   outb (0x80, HOST_CTRL_PORT);  /* Leave reset */
 259 
 260   printk ("Turtle Beach Maui initialization\n");
 261 
 262   if (!download_code ())
 263     return 0;
 264 
 265   outb (0xE0, HOST_CTRL_PORT);  /* Normal operation */
 266 
 267   /* Select mpu401 mode */
 268 
 269   maui_write (0xf0);
 270   maui_write (1);
 271   if (maui_read () != 0x80)
 272     {
 273       maui_write (0xf0);
 274       maui_write (1);
 275       if (maui_read () != 0x80)
 276         printk ("Maui didn't acknowledge set HW mode command\n");
 277     }
 278 
 279   printk ("Maui initialized OK\n");
 280   return 1;
 281 }
 282 
 283 static int
 284 maui_short_wait (int mask)
     /* [previous][next][first][last][top][bottom][index][help] */
 285 {
 286   int             i;
 287 
 288   for (i = 0; i < 1000; i++)
 289     {
 290       if (inb (HOST_STAT_PORT) & mask)
 291         {
 292           return 1;
 293         }
 294     }
 295 
 296   return 0;
 297 }
 298 
 299 int
 300 maui_load_patch (int dev, int format, const char *addr,
     /* [previous][next][first][last][top][bottom][index][help] */
 301                  int offs, int count, int pmgr_flag)
 302 {
 303 
 304   struct sysex_info header;
 305   unsigned long   left, src_offs;
 306   int             hdr_size = (unsigned long) &header.data[0] - (unsigned long) &header;
 307   int             i;
 308 
 309   if (format == SYSEX_PATCH)    /* Handled by midi_synth.c */
 310     return orig_load_patch (dev, format, addr, offs, count, pmgr_flag);
 311 
 312   if (format != MAUI_PATCH)
 313     {
 314       printk ("Maui: Unknown patch format\n");
 315     }
 316 
 317   if (count < hdr_size)
 318     {
 319       printk ("Maui error: Patch header too short\n");
 320       return -EINVAL;
 321     }
 322 
 323   count -= hdr_size;
 324 
 325   /*
 326    * Copy the header from user space but ignore the first bytes which have
 327    * been transferred already.
 328    */
 329 
 330   memcpy_fromfs (&((char *) &header)[offs], &((addr)[offs]), hdr_size - offs);
 331 
 332   if (count < header.len)
 333     {
 334       printk ("Maui warning: Host command record too short (%d<%d)\n",
 335               count, (int) header.len);
 336       header.len = count;
 337     }
 338 
 339   left = header.len;
 340   src_offs = 0;
 341 
 342   for (i = 0; i < left; i++)
 343     {
 344       unsigned char   data;
 345 
 346       data = get_fs_byte (&((addr)[hdr_size + i]));
 347       if (i == 0 && !(data & 0x80))
 348         return -EINVAL;
 349 
 350       if (maui_write (data) == -1)
 351         return -EIO;
 352     }
 353 
 354   if ((i = maui_read ()) != 0x80)
 355     {
 356       if (i != -1)
 357         printk ("Maui: Error status %02x\n", i);
 358 
 359       return -EIO;
 360     }
 361 
 362   return 0;
 363 }
 364 
 365 int
 366 probe_maui (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 367 {
 368   int             i;
 369   int             tmp1, tmp2, ret;
 370 
 371   if (check_region (hw_config->io_base, 8))
 372     return 0;
 373 
 374   maui_base = hw_config->io_base;
 375   maui_osp = hw_config->osp;
 376 
 377   if (snd_set_irq_handler (hw_config->irq, mauiintr, "Maui", maui_osp) < 0)
 378     return 0;
 379 
 380   maui_sleep_flag.mode = WK_NONE;
 381 /*
 382  * Initialize the processor if necessary
 383  */
 384 
 385   if (maui_osLen > 0)
 386     {
 387       if (!(inb (HOST_STAT_PORT) & STAT_TX_AVAIL) ||
 388           !maui_write (0x9F) || /* Report firmware version */
 389           !maui_short_wait (STAT_RX_AVAIL) ||
 390           maui_read () == -1 || maui_read () == -1)
 391         if (!maui_init (hw_config->irq))
 392           {
 393             snd_release_irq (hw_config->irq);
 394             return 0;
 395           }
 396     }
 397 
 398   if (!maui_write (0xCF))       /* Report hardware version */
 399     {
 400       printk ("No WaveFront firmware detected (card uninitialized?)\n");
 401       snd_release_irq (hw_config->irq);
 402       return 0;
 403     }
 404 
 405   if ((tmp1 = maui_read ()) == -1 || (tmp2 = maui_read ()) == -1)
 406     {
 407       printk ("No WaveFront firmware detected (card uninitialized?)\n");
 408       snd_release_irq (hw_config->irq);
 409       return 0;
 410     }
 411 
 412   if (tmp1 == 0xff || tmp2 == 0xff)
 413     {
 414       snd_release_irq (hw_config->irq);
 415       return 0;
 416     }
 417 
 418   if (trace_init)
 419     printk ("WaveFront hardware version %d.%d\n", tmp1, tmp2);
 420 
 421   if (!maui_write (0x9F))       /* Report firmware version */
 422     return 0;
 423   if ((tmp1 = maui_read ()) == -1 || (tmp2 = maui_read ()) == -1)
 424     return 0;
 425 
 426   if (trace_init)
 427     printk ("WaveFront firmware version %d.%d\n", tmp1, tmp2);
 428 
 429   if (!maui_write (0x85))       /* Report free DRAM */
 430     return 0;
 431   tmp1 = 0;
 432   for (i = 0; i < 4; i++)
 433     {
 434       tmp1 |= maui_read () << (7 * i);
 435     }
 436   if (trace_init)
 437     printk ("Available DRAM %dk\n", tmp1 / 1024);
 438 
 439   for (i = 0; i < 1000; i++)
 440     if (probe_mpu401 (hw_config))
 441       break;
 442 
 443   ret = probe_mpu401 (hw_config);
 444 
 445   if (ret)
 446     request_region (hw_config->io_base + 2, 6, "Maui");
 447 
 448   return ret;
 449 }
 450 
 451 long
 452 attach_maui (long mem_start, struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 453 {
 454   int             this_dev = num_midis;
 455 
 456   conf_printf ("Maui", hw_config);
 457 
 458   hw_config->irq *= -1;
 459   mem_start = attach_mpu401 (mem_start, hw_config);
 460 
 461   if (num_midis > this_dev)     /* The MPU401 driver installed itself */
 462     {
 463       struct synth_operations *synth;
 464 
 465       /*
 466        * Intercept patch loading calls so that they canbe handled
 467        * by the Maui driver.
 468        */
 469 
 470       synth = midi_devs[this_dev]->converter;
 471 
 472       if (synth != NULL)
 473         {
 474           orig_load_patch = synth->load_patch;
 475           synth->load_patch = &maui_load_patch;
 476         }
 477       else
 478         printk ("Maui: Can't install patch loader\n");
 479     }
 480   return mem_start;
 481 }
 482 
 483 void
 484 unload_maui (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 485 {
 486   int             irq = hw_config->irq;
 487 
 488   release_region (hw_config->io_base + 2, 6);
 489 
 490   unload_mpu401 (hw_config);
 491 
 492   if (irq < 0)
 493     irq = -irq;
 494 
 495   if (irq > 0)
 496     snd_release_irq (irq);
 497 }
 498 
 499 
 500 #endif

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