root/drivers/sound/pss.c

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

DEFINITIONS

This source file includes following definitions.
  1. probe_pss
  2. set_irq
  3. set_io_base
  4. set_dma
  5. pss_reset_dsp
  6. pss_put_dspword
  7. pss_get_dspword
  8. pss_download_boot
  9. attach_pss
  10. probe_pss_mpu
  11. pss_coproc_open
  12. pss_coproc_close
  13. pss_coproc_reset
  14. download_boot_block
  15. pss_coproc_ioctl
  16. attach_pss_mpu
  17. probe_pss_mss
  18. attach_pss_mss
  19. unload_pss
  20. unload_pss_mpu
  21. unload_pss_mss

   1 /*
   2  * sound/pss.c
   3  *
   4  * The low level driver for the Personal Sound System (ECHO ESC614).
   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 #include "sound_config.h"
  33 
  34 #if defined(CONFIG_PSS) && defined(CONFIG_AUDIO)
  35 
  36 /*
  37  * PSS registers.
  38  */
  39 #define REG(x)  (devc->base+x)
  40 #define PSS_DATA        0
  41 #define PSS_STATUS      2
  42 #define PSS_CONTROL     2
  43 #define PSS_ID          4
  44 #define PSS_IRQACK      4
  45 #define PSS_PIO         0x1a
  46 
  47 /*
  48  * Config registers
  49  */
  50 #define CONF_PSS        0x10
  51 #define CONF_WSS        0x12
  52 #define CONF_SB         0x13
  53 #define CONF_CDROM      0x16
  54 #define CONF_MIDI       0x18
  55 
  56 /*
  57  * Status bits.
  58  */
  59 #define PSS_FLAG3     0x0800
  60 #define PSS_FLAG2     0x0400
  61 #define PSS_FLAG1     0x1000
  62 #define PSS_FLAG0     0x0800
  63 #define PSS_WRITE_EMPTY  0x8000
  64 #define PSS_READ_FULL    0x4000
  65 
  66 #include "coproc.h"
  67 
  68 #ifdef PSS_HAVE_LD
  69 #include "synth-ld.h"
  70 #else
  71 static int      pss_synthLen = 0;
  72 static unsigned char pss_synth[1] =
  73 {0};
  74 
  75 #endif
  76 
  77 typedef struct pss_config
  78   {
  79     int             base;
  80     int             irq;
  81     int             dma;
  82     int            *osp;
  83   }
  84 
  85 pss_config;
  86 
  87 static pss_config pss_data;
  88 static pss_config *devc = &pss_data;
  89 
  90 static int      pss_initialized = 0;
  91 static int      nonstandard_microcode = 0;
  92 
  93 int
  94 probe_pss (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
  95 {
  96   unsigned short  id;
  97   int             irq, dma;
  98 
  99   devc->base = hw_config->io_base;
 100   irq = devc->irq = hw_config->irq;
 101   dma = devc->dma = hw_config->dma;
 102   devc->osp = hw_config->osp;
 103 
 104   if (devc->base != 0x220 && devc->base != 0x240)
 105     if (devc->base != 0x230 && devc->base != 0x250)     /* Some cards use these */
 106       return 0;
 107 
 108   if (check_region (devc->base, 16))
 109     {
 110       printk ("PSS: I/O port conflict\n");
 111       return 0;
 112     }
 113 
 114   id = inw (REG (PSS_ID));
 115   if ((id >> 8) != 'E')
 116     {
 117       /* printk ("No PSS signature detected at 0x%x (0x%x)\n", devc->base, id); */
 118       return 0;
 119     }
 120 
 121   return 1;
 122 }
 123 
 124 static int
 125 set_irq (pss_config * devc, int dev, int irq)
     /* [previous][next][first][last][top][bottom][index][help] */
 126 {
 127   static unsigned short irq_bits[16] =
 128   {
 129     0x0000, 0x0000, 0x0000, 0x0008,
 130     0x0000, 0x0010, 0x0000, 0x0018,
 131     0x0000, 0x0020, 0x0028, 0x0030,
 132     0x0038, 0x0000, 0x0000, 0x0000
 133   };
 134 
 135   unsigned short  tmp, bits;
 136 
 137   if (irq < 0 || irq > 15)
 138     return 0;
 139 
 140   tmp = inw (REG (dev)) & ~0x38;        /* Load confreg, mask IRQ bits out */
 141 
 142   if ((bits = irq_bits[irq]) == 0 && irq != 0)
 143     {
 144       printk ("PSS: Invalid IRQ %d\n", irq);
 145       return 0;
 146     }
 147 
 148   outw (tmp | bits, REG (dev));
 149   return 1;
 150 }
 151 
 152 static int
 153 set_io_base (pss_config * devc, int dev, int base)
     /* [previous][next][first][last][top][bottom][index][help] */
 154 {
 155   unsigned short  tmp = inw (REG (dev)) & 0x003f;
 156   unsigned short  bits = (base & 0x0ffc) << 4;
 157 
 158   outw (bits | tmp, REG (dev));
 159 
 160   return 1;
 161 }
 162 
 163 static int
 164 set_dma (pss_config * devc, int dev, int dma)
     /* [previous][next][first][last][top][bottom][index][help] */
 165 {
 166   static unsigned short dma_bits[8] =
 167   {
 168     0x0001, 0x0002, 0x0000, 0x0003,
 169     0x0000, 0x0005, 0x0006, 0x0007
 170   };
 171 
 172   unsigned short  tmp, bits;
 173 
 174   if (dma < 0 || dma > 7)
 175     return 0;
 176 
 177   tmp = inw (REG (dev)) & ~0x07;        /* Load confreg, mask DMA bits out */
 178 
 179   if ((bits = dma_bits[dma]) == 0 && dma != 4)
 180     {
 181       printk ("PSS: Invalid DMA %d\n", dma);
 182       return 0;
 183     }
 184 
 185   outw (tmp | bits, REG (dev));
 186   return 1;
 187 }
 188 
 189 static int
 190 pss_reset_dsp (pss_config * devc)
     /* [previous][next][first][last][top][bottom][index][help] */
 191 {
 192   unsigned long   i, limit = jiffies + 10;
 193 
 194   outw (0x2000, REG (PSS_CONTROL));
 195 
 196   for (i = 0; i < 32768 && jiffies < limit; i++)
 197     inw (REG (PSS_CONTROL));
 198 
 199   outw (0x0000, REG (PSS_CONTROL));
 200 
 201   return 1;
 202 }
 203 
 204 static int
 205 pss_put_dspword (pss_config * devc, unsigned short word)
     /* [previous][next][first][last][top][bottom][index][help] */
 206 {
 207   int             i, val;
 208 
 209   for (i = 0; i < 327680; i++)
 210     {
 211       val = inw (REG (PSS_STATUS));
 212       if (val & PSS_WRITE_EMPTY)
 213         {
 214           outw (word, REG (PSS_DATA));
 215           return 1;
 216         }
 217     }
 218   return 0;
 219 }
 220 
 221 static int
 222 pss_get_dspword (pss_config * devc, unsigned short *word)
     /* [previous][next][first][last][top][bottom][index][help] */
 223 {
 224   int             i, val;
 225 
 226   for (i = 0; i < 327680; i++)
 227     {
 228       val = inw (REG (PSS_STATUS));
 229       if (val & PSS_READ_FULL)
 230         {
 231           *word = inw (REG (PSS_DATA));
 232           return 1;
 233         }
 234     }
 235 
 236   return 0;
 237 }
 238 
 239 static int
 240 pss_download_boot (pss_config * devc, unsigned char *block, int size, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 241 {
 242   int             i, limit, val, count;
 243 
 244   if (flags & CPF_FIRST)
 245     {
 246 /*_____ Warn DSP software that a boot is coming */
 247       outw (0x00fe, REG (PSS_DATA));
 248 
 249       limit = jiffies + 10;
 250 
 251       for (i = 0; i < 32768 && jiffies < limit; i++)
 252         if (inw (REG (PSS_DATA)) == 0x5500)
 253           break;
 254 
 255       outw (*block++, REG (PSS_DATA));
 256 
 257       pss_reset_dsp (devc);
 258     }
 259 
 260   count = 1;
 261   while (1)
 262     {
 263       int             j;
 264 
 265       for (j = 0; j < 327670; j++)
 266         {
 267 /*_____ Wait for BG to appear */
 268           if (inw (REG (PSS_STATUS)) & PSS_FLAG3)
 269             break;
 270         }
 271 
 272       if (j == 327670)
 273         {
 274           /* It's ok we timed out when the file was empty */
 275           if (count >= size && flags & CPF_LAST)
 276             break;
 277           else
 278             {
 279               printk ("\nPSS: DownLoad timeout problems, byte %d=%d\n",
 280                       count, size);
 281               return 0;
 282             }
 283         }
 284 /*_____ Send the next byte */
 285       outw (*block++, REG (PSS_DATA));
 286       count++;
 287     }
 288 
 289   if (flags & CPF_LAST)
 290     {
 291 /*_____ Why */
 292       outw (0, REG (PSS_DATA));
 293 
 294       limit = jiffies + 10;
 295       for (i = 0; i < 32768 && jiffies < limit; i++)
 296         val = inw (REG (PSS_STATUS));
 297 
 298       limit = jiffies + 10;
 299       for (i = 0; i < 32768 && jiffies < limit; i++)
 300         {
 301           val = inw (REG (PSS_STATUS));
 302           if (val & 0x4000)
 303             break;
 304         }
 305 
 306       /* now read the version */
 307       for (i = 0; i < 32000; i++)
 308         {
 309           val = inw (REG (PSS_STATUS));
 310           if (val & PSS_READ_FULL)
 311             break;
 312         }
 313       if (i == 32000)
 314         return 0;
 315 
 316       val = inw (REG (PSS_DATA));
 317       /* printk("<PSS: microcode version %d.%d loaded>", val/16, val % 16); */
 318     }
 319 
 320   return 1;
 321 }
 322 
 323 long
 324 attach_pss (long mem_start, struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 325 {
 326   unsigned short  id;
 327   char            tmp[100];
 328 
 329   devc->base = hw_config->io_base;
 330   devc->irq = hw_config->irq;
 331   devc->dma = hw_config->dma;
 332   devc->osp = hw_config->osp;
 333 
 334   if (!probe_pss (hw_config))
 335     return mem_start;
 336 
 337   id = inw (REG (PSS_ID)) & 0x00ff;
 338 
 339   /*
 340      * Disable all emulations. Will be enabled later (if required).
 341    */
 342   outw (0x0000, REG (CONF_PSS));
 343   outw (0x0000, REG (CONF_WSS));
 344   outw (0x0000, REG (CONF_SB));
 345   outw (0x0000, REG (CONF_MIDI));
 346   outw (0x0000, REG (CONF_CDROM));
 347 
 348 #if YOU_REALLY_WANT_TO_ALLOCATE_THESE_RESOURCES
 349   if (sound_alloc_dma (hw_config->dma, "PSS"))
 350     {
 351       printk ("pss.c: Can't allocate DMA channel\n");
 352       return mem_start;
 353     }
 354 
 355   if (!set_irq (devc, CONF_PSS, devc->irq))
 356     {
 357       printk ("PSS: IRQ error\n");
 358       return mem_start;
 359     }
 360 
 361   if (!set_dma (devc, CONF_PSS, devc->dma))
 362     {
 363       printk ("PSS: DRQ error\n");
 364       return mem_start;
 365     }
 366 #endif
 367 
 368   pss_initialized = 1;
 369   sprintf (tmp, "ECHO-PSS  Rev. %d", id);
 370   conf_printf (tmp, hw_config);
 371 
 372   return mem_start;
 373 }
 374 
 375 int
 376 probe_pss_mpu (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 377 {
 378   int             timeout;
 379 
 380   if (!pss_initialized)
 381     return 0;
 382 
 383   if (check_region (hw_config->io_base, 2))
 384     {
 385       printk ("PSS: MPU I/O port conflict\n");
 386       return 0;
 387     }
 388 
 389   if (!set_io_base (devc, CONF_MIDI, hw_config->io_base))
 390     {
 391       printk ("PSS: MIDI base error.\n");
 392       return 0;
 393     }
 394 
 395   if (!set_irq (devc, CONF_MIDI, hw_config->irq))
 396     {
 397       printk ("PSS: MIDI IRQ error.\n");
 398       return 0;
 399     }
 400 
 401   if (!pss_synthLen)
 402     {
 403       printk ("PSS: Can't enable MPU. MIDI synth microcode not available.\n");
 404       return 0;
 405     }
 406 
 407   if (!pss_download_boot (devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST))
 408     {
 409       printk ("PSS: Unable to load MIDI synth microcode to DSP.\n");
 410       return 0;
 411     }
 412 
 413 /*
 414  * Finally wait until the DSP algorithm has initialized itself and
 415  * deactivates receive interrupt.
 416  */
 417 
 418   for (timeout = 900000; timeout > 0; timeout--)
 419     {
 420       if ((inb (hw_config->io_base + 1) & 0x80) == 0)   /* Input data avail */
 421         inb (hw_config->io_base);       /* Discard it */
 422       else
 423         break;                  /* No more input */
 424     }
 425 
 426 #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
 427   return probe_mpu401 (hw_config);
 428 #else
 429   return 0;
 430 #endif
 431 }
 432 
 433 static int
 434 pss_coproc_open (void *dev_info, int sub_device)
     /* [previous][next][first][last][top][bottom][index][help] */
 435 {
 436   switch (sub_device)
 437     {
 438     case COPR_MIDI:
 439 
 440       if (pss_synthLen == 0)
 441         {
 442           printk ("PSS: MIDI synth microcode not available.\n");
 443           return -EIO;
 444         }
 445 
 446       if (nonstandard_microcode)
 447         if (!pss_download_boot (devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST))
 448           {
 449             printk ("PSS: Unable to load MIDI synth microcode to DSP.\n");
 450             return -EIO;
 451           }
 452       nonstandard_microcode = 0;
 453       break;
 454 
 455     default:;
 456     }
 457   return 0;
 458 }
 459 
 460 static void
 461 pss_coproc_close (void *dev_info, int sub_device)
     /* [previous][next][first][last][top][bottom][index][help] */
 462 {
 463   return;
 464 }
 465 
 466 static void
 467 pss_coproc_reset (void *dev_info)
     /* [previous][next][first][last][top][bottom][index][help] */
 468 {
 469   if (pss_synthLen)
 470     if (!pss_download_boot (devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST))
 471       {
 472         printk ("PSS: Unable to load MIDI synth microcode to DSP.\n");
 473       }
 474   nonstandard_microcode = 0;
 475 }
 476 
 477 static int
 478 download_boot_block (void *dev_info, copr_buffer * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 479 {
 480   if (buf->len <= 0 || buf->len > sizeof (buf->data))
 481     return -EINVAL;
 482 
 483   if (!pss_download_boot (devc, buf->data, buf->len, buf->flags))
 484     {
 485       printk ("PSS: Unable to load microcode block to DSP.\n");
 486       return -EIO;
 487     }
 488   nonstandard_microcode = 1;    /* The MIDI microcode has been overwritten */
 489 
 490   return 0;
 491 }
 492 
 493 static int
 494 pss_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local)
     /* [previous][next][first][last][top][bottom][index][help] */
 495 {
 496   /* printk("PSS coproc ioctl %x %x %d\n", cmd, arg, local); */
 497 
 498   switch (cmd)
 499     {
 500     case SNDCTL_COPR_RESET:
 501       pss_coproc_reset (dev_info);
 502       return 0;
 503       break;
 504 
 505     case SNDCTL_COPR_LOAD:
 506       {
 507         copr_buffer    *buf;
 508         int             err;
 509 
 510         buf = (copr_buffer *) kmalloc (sizeof (copr_buffer), GFP_KERNEL);
 511         if (buf == NULL)
 512           return -ENOSPC;
 513 
 514         memcpy_fromfs ((char *) buf, &(((char *) arg)[0]), sizeof (*buf));
 515         err = download_boot_block (dev_info, buf);
 516         kfree (buf);
 517         return err;
 518       }
 519       break;
 520 
 521     case SNDCTL_COPR_SENDMSG:
 522       {
 523         /* send buf->len words from buf->data to DSP */
 524 
 525         copr_msg       *buf;
 526         unsigned long   flags;
 527         unsigned short *data;
 528         int             i;
 529 
 530         buf = (copr_msg *) kmalloc (sizeof (copr_msg), GFP_KERNEL);
 531         if (buf == NULL)
 532           return -ENOSPC;
 533 
 534         memcpy_fromfs ((char *) buf, &(((char *) arg)[0]), sizeof (*buf));
 535 
 536         data = (unsigned short *) (buf->data);
 537 
 538         save_flags (flags);
 539         cli ();
 540 
 541         for (i = 0; i < buf->len; i++)
 542           {
 543             if (!pss_put_dspword (devc, *data++))
 544               {
 545                 restore_flags (flags);
 546                 /* feed back number of WORDs sent */
 547                 memcpy_tofs( (char *)(&(((copr_msg *)arg)->len)),
 548                                 (char *)(&i), sizeof(buf->len));
 549                 kfree (buf);
 550                 return -EIO;
 551               }
 552           }
 553 
 554         restore_flags (flags);
 555         kfree (buf);
 556 
 557         return 0;
 558       }
 559       break;
 560 
 561 
 562     case SNDCTL_COPR_RCVMSG:
 563       {
 564         /* try to read as much words as possible from DSP into buf */
 565         copr_msg       *buf;
 566         unsigned long   flags;
 567         unsigned short *data;
 568         unsigned int    i;
 569         int             err = 0;
 570 
 571         buf = (copr_msg *) kmalloc (sizeof (copr_msg), GFP_KERNEL);
 572         if (buf == NULL)
 573           return -ENOSPC;
 574 #if 0
 575         memcpy_fromfs ((char *) buf, &(((char *) arg)[0]), sizeof (*buf));
 576 #endif
 577 
 578         data = (unsigned short *) buf->data;
 579 
 580         save_flags (flags);
 581         cli ();
 582 
 583         for (i = 0; i < sizeof(buf->data); i++)
 584           {
 585             if (!pss_get_dspword (devc, data++))
 586               {
 587                 buf->len = i;   /* feed back number of WORDs read */
 588                 err = (i==0)? -EIO : 0;    /* EIO only if no word read */
 589                 break;
 590               }
 591           }
 592 
 593         if( i==sizeof(buf->data) )
 594                 buf->len = i;
 595 
 596         restore_flags (flags);
 597 
 598         memcpy_tofs ((&((char *) arg)[0]), buf, sizeof (*buf));
 599         kfree (buf);
 600 
 601         return err;
 602       }
 603       break;
 604 
 605 
 606     case SNDCTL_COPR_RDATA:
 607       {
 608         copr_debug_buf  buf;
 609         unsigned long   flags;
 610         unsigned short  tmp;
 611 
 612         memcpy_fromfs ((char *) &buf, &(((char *) arg)[0]), sizeof (buf));
 613 
 614         save_flags (flags);
 615         cli ();
 616         if (!pss_put_dspword (devc, 0x00d0))
 617           {
 618             restore_flags (flags);
 619             return -EIO;
 620           }
 621 
 622         if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff)))
 623           {
 624             restore_flags (flags);
 625             return -EIO;
 626           }
 627 
 628         if (!pss_get_dspword (devc, &tmp))
 629           {
 630             restore_flags (flags);
 631             return -EIO;
 632           }
 633 
 634         buf.parm1 = tmp;
 635         restore_flags (flags);
 636 
 637         memcpy_tofs ((&((char *) arg)[0]), &buf, sizeof (buf));
 638         return 0;
 639       }
 640       break;
 641 
 642     case SNDCTL_COPR_WDATA:
 643       {
 644         copr_debug_buf  buf;
 645         unsigned long   flags;
 646         unsigned short  tmp;
 647 
 648         memcpy_fromfs ((char *) &buf, &(((char *) arg)[0]), sizeof (buf));
 649 
 650         save_flags (flags);
 651         cli ();
 652         if (!pss_put_dspword (devc, 0x00d1))
 653           {
 654             restore_flags (flags);
 655             return -EIO;
 656           }
 657 
 658         if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff)))
 659           {
 660             restore_flags (flags);
 661             return -EIO;
 662           }
 663 
 664         tmp = (unsigned int) buf.parm2 & 0xffff;
 665         if (!pss_put_dspword (devc, tmp))
 666           {
 667             restore_flags (flags);
 668             return -EIO;
 669           }
 670 
 671         restore_flags (flags);
 672         return 0;
 673       }
 674       break;
 675 
 676     case SNDCTL_COPR_WCODE:
 677       {
 678         copr_debug_buf  buf;
 679         unsigned long   flags;
 680         unsigned short  tmp;
 681 
 682         memcpy_fromfs ((char *) &buf, &(((char *) arg)[0]), sizeof (buf));
 683 
 684         save_flags (flags);
 685         cli ();
 686         if (!pss_put_dspword (devc, 0x00d3))
 687           {
 688             restore_flags (flags);
 689             return -EIO;
 690           }
 691 
 692         if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff)))
 693           {
 694             restore_flags (flags);
 695             return -EIO;
 696           }
 697 
 698         tmp = (unsigned int) buf.parm2 & 0x00ff;
 699         if (!pss_put_dspword (devc, tmp))
 700           {
 701             restore_flags (flags);
 702             return -EIO;
 703           }
 704 
 705         tmp = ((unsigned int) buf.parm2 >> 8) & 0xffff;
 706         if (!pss_put_dspword (devc, tmp))
 707           {
 708             restore_flags (flags);
 709             return -EIO;
 710           }
 711 
 712         restore_flags (flags);
 713         return 0;
 714       }
 715       break;
 716 
 717     case SNDCTL_COPR_RCODE:
 718       {
 719         copr_debug_buf  buf;
 720         unsigned long   flags;
 721         unsigned short  tmp;
 722 
 723         memcpy_fromfs ((char *) &buf, &(((char *) arg)[0]), sizeof (buf));
 724 
 725         save_flags (flags);
 726         cli ();
 727         if (!pss_put_dspword (devc, 0x00d2))
 728           {
 729             restore_flags (flags);
 730             return -EIO;
 731           }
 732 
 733         if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff)))
 734           {
 735             restore_flags (flags);
 736             return -EIO;
 737           }
 738 
 739         if (!pss_get_dspword (devc, &tmp))      /* Read msb */
 740           {
 741             restore_flags (flags);
 742             return -EIO;
 743           }
 744 
 745         buf.parm1 = tmp << 8;
 746 
 747         if (!pss_get_dspword (devc, &tmp))      /* Read lsb */
 748           {
 749             restore_flags (flags);
 750             return -EIO;
 751           }
 752 
 753         buf.parm1 |= tmp & 0x00ff;
 754 
 755         restore_flags (flags);
 756 
 757         memcpy_tofs ((&((char *) arg)[0]), &buf, sizeof (buf));
 758         return 0;
 759       }
 760       break;
 761 
 762     default:
 763       return -EINVAL;
 764     }
 765 
 766   return -EINVAL;
 767 }
 768 
 769 static coproc_operations pss_coproc_operations =
 770 {
 771   "ADSP-2115",
 772   pss_coproc_open,
 773   pss_coproc_close,
 774   pss_coproc_ioctl,
 775   pss_coproc_reset,
 776   &pss_data
 777 };
 778 
 779 long
 780 attach_pss_mpu (long mem_start, struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 781 {
 782   long            ret;
 783 
 784 #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
 785   {
 786     int             prev_devs;
 787     prev_devs = num_midis;
 788     ret = attach_mpu401 (mem_start, hw_config);
 789 
 790     if (num_midis == (prev_devs + 1))   /* The MPU driver installed itself */
 791       midi_devs[prev_devs]->coproc = &pss_coproc_operations;
 792   }
 793 #endif
 794   return ret;
 795 }
 796 
 797 int
 798 probe_pss_mss (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 799 {
 800   int             timeout;
 801 
 802   if (!pss_initialized)
 803     return 0;
 804 
 805   if (check_region (hw_config->io_base, 8))
 806     {
 807       printk ("PSS: WSS I/O port conflict\n");
 808       return 0;
 809     }
 810 
 811   if (!set_io_base (devc, CONF_WSS, hw_config->io_base))
 812     {
 813       printk ("PSS: WSS base error.\n");
 814       return 0;
 815     }
 816 
 817   if (!set_irq (devc, CONF_WSS, hw_config->irq))
 818     {
 819       printk ("PSS: WSS IRQ error.\n");
 820       return 0;
 821     }
 822 
 823   if (!set_dma (devc, CONF_WSS, hw_config->dma))
 824     {
 825       printk ("PSS: WSS DRQ error\n");
 826       return 0;
 827     }
 828 
 829   /*
 830      * For some reason the card returns 0xff in the WSS status register
 831      * immediately after boot. Probably MIDI+SB emulation algorithm
 832      * downloaded to the ADSP2115 spends some time initializing the card.
 833      * Let's try to wait until it finishes this task.
 834    */
 835   for (timeout = 0;
 836        timeout < 100000 && (inb (hw_config->io_base + 3) & 0x3f) != 0x04;
 837        timeout++);
 838 
 839   outb (0x0b, hw_config->io_base + 4);  /* Required by some cards */
 840   return probe_ms_sound (hw_config);
 841 }
 842 
 843 long
 844 attach_pss_mss (long mem_start, struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 845 {
 846   int             prev_devs;
 847   long            ret;
 848 
 849   prev_devs = num_audiodevs;
 850   ret = attach_ms_sound (mem_start, hw_config);
 851 
 852   if (num_audiodevs == (prev_devs + 1))         /* The MSS driver installed itself */
 853     audio_devs[prev_devs]->coproc = &pss_coproc_operations;
 854 
 855   return ret;
 856 }
 857 
 858 void
 859 unload_pss (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 860 {
 861 }
 862 
 863 void
 864 unload_pss_mpu (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 865 {
 866   unload_mpu401 (hw_config);
 867 }
 868 
 869 void
 870 unload_pss_mss (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 871 {
 872   unload_ms_sound (hw_config);
 873 }
 874 
 875 #endif

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