root/drivers/sound/pss.c

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

DEFINITIONS

This source file includes following definitions.
  1. pss_outpw
  2. pss_inpw
  3. PSS_write
  4. pss_setaddr
  5. pss_checkint
  6. pss_setint
  7. pss_setsbint
  8. pss_setsbdma
  9. pss_setwssdma
  10. pss_setspeaker
  11. pss_init1848
  12. pss_configure_registers_to_look_like_sb
  13. attach_pss
  14. probe_pss
  15. pss_reattach
  16. pss_reset_dsp
  17. pss_download_boot
  18. pss_open
  19. pss_release
  20. pss_read
  21. pss_write
  22. pss_ioctl
  23. pss_select
  24. pss_init

   1 /* Marc.Hoffman@analog.com
   2 
   3    This is a pss driver.
   4 
   5    it is based on Greg.Yukna@analog.com @file{host} for DOG
   6 
   7    Unfortunately I can't distribute the ld file needed to
   8    make the pss card to emulate the SB stuff.
   9 
  10    I have provided a simple interface to the PSS unlike the
  11    DOG version.  to download a new algorithm just cat it to
  12    /dev/pss 14,9.
  13 
  14    You really need to rebuild this with the synth.ld file
  15 
  16    get the <synth>.ld from your dos directory maybe
  17    voyetra\dsp001.ld
  18 
  19    ld2inc < synth.ld > synth-ld.h
  20    (make config does the same).
  21 
  22    rebuild
  23 
  24    Okay if you blow things away no problem just
  25 
  26    main(){ioctl(open("/dev/pss"),SNDCTL_PSS_RESET)};
  27 
  28    and everything will be okay.
  29 
  30    At first I was going to worry about applications that were using
  31    the sound stuff and disallow the use of /dev/pss.  But for
  32    now I figured it doesn't matter.
  33 
  34    And if you change algos all the other applications running die off
  35    due to DMA problems.  Yeah just pull the plug and watch em die.
  36 
  37    If the registers get hosed
  38    main(){ioctl(open("/dev/pss"),SNDCTL_PSS_SETUP_REGISTERS)};
  39 
  40    Probably everything else can be done via mmap
  41 
  42    Oh if you want to develop code for the ADSP-21xx or Program the
  43    1848 just send me mail and I will hook you up.
  44 
  45                marc.hoffman@analog.com
  46 
  47    */
  48 #include "sound_config.h"
  49 
  50 #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PSS)
  51 
  52 #ifndef PSS_MSS_BASE
  53 #define PSS_MSS_BASE 0
  54 #endif
  55 
  56 #ifndef PSS_MPU_BASE
  57 #define PSS_MPU_BASE 0
  58 #endif
  59 
  60 #ifndef PSS_MPU_IRQ
  61 #define PSS_MPU_IRQ 0
  62 #endif
  63 
  64 #undef DEB
  65 #define DEB(x) x
  66 
  67 #include "pss.h"
  68 
  69 static int      pss_ok = 0;
  70 static int      sb_ok = 0;
  71 
  72 static int      pss_base;
  73 static int      pss_irq;
  74 static int      pss_dma;
  75 
  76 static int      gamePort = 0;
  77 
  78 static int      sbInt;
  79 static int      cdPol;
  80 static int      cdAddr = 0;     /* 0x340;       */
  81 static int      cdInt = 10;
  82 
  83 /* Define these by hand in local.h */
  84 static int      wssAddr = PSS_MSS_BASE;
  85 static int      midiAddr = PSS_MPU_BASE;
  86 static int      midiInt = PSS_MPU_IRQ;
  87 
  88 static int      SoundPortAddress;
  89 static int      SoundPortData;
  90 static int      speaker = 1;
  91 
  92 
  93 static struct pss_speaker default_speaker =
  94 {0, 0, 0, PSS_STEREO};
  95 
  96 DEFINE_WAIT_QUEUE (pss_sleeper, pss_sleep_flag);
  97 
  98 #include "synth-ld.h"
  99 
 100 static int      pss_download_boot (unsigned char *block, int size);
 101 static int      pss_reset_dsp (void);
 102 
 103 static inline void
 104 pss_outpw (unsigned short port, unsigned short value)
     /* [previous][next][first][last][top][bottom][index][help] */
 105 {
 106   __asm__         __volatile__ ("outw %w0, %w1"
 107                                 :       /* no outputs */
 108                                 :"a"            (value), "d" (port));
 109 }
 110 
 111 static inline unsigned int
 112 pss_inpw (unsigned short port)
     /* [previous][next][first][last][top][bottom][index][help] */
 113 {
 114   unsigned int    _v;
 115   __asm__         __volatile__ ("inw %w1,%w0"
 116                                 :"=a"           (_v):"d" (port), "0" (0));
 117 
 118   return _v;
 119 }
 120 
 121 static void
 122 PSS_write (int data)
     /* [previous][next][first][last][top][bottom][index][help] */
 123 {
 124   int             i, limit;
 125 
 126   limit = GET_TIME () + 10;     /* The timeout is 0.1 seconds */
 127   /*
 128    * Note! the i<5000000 is an emergency exit. The dsp_command() is sometimes
 129    * called while interrupts are disabled. This means that the timer is
 130    * disabled also. However the timeout situation is a abnormal condition.
 131    * Normally the DSP should be ready to accept commands after just couple of
 132    * loops.
 133    */
 134 
 135   for (i = 0; i < 5000000 && GET_TIME () < limit; i++)
 136     {
 137       if (pss_inpw (pss_base + PSS_STATUS) & PSS_WRITE_EMPTY)
 138         {
 139           pss_outpw (pss_base + PSS_DATA, data);
 140           return;
 141         }
 142     }
 143   printk ("PSS: DSP Command (%04x) Timeout.\n", data);
 144   printk ("IRQ conflict???\n");
 145 }
 146 
 147 
 148 static void
 149 pss_setaddr (int addr, int configAddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151   int             val;
 152 
 153   val = pss_inpw (configAddr);
 154   val &= ADDR_MASK;
 155   val |= (addr << 4);
 156   pss_outpw (configAddr, val);
 157 }
 158 
 159 /*_____ pss_checkint
 160          This function tests an interrupt number to see if
 161          it is available. It takes the interrupt button
 162          as it's argument and returns TRUE if the interrupt
 163          is ok.
 164 */
 165 static int
 166 pss_checkint (int intNum)
     /* [previous][next][first][last][top][bottom][index][help] */
 167 {
 168   int             val;
 169   int             ret;
 170   int             i;
 171 
 172   /*_____ Set the interrupt bits */
 173   switch (intNum)
 174     {
 175     case 3:
 176       val = pss_inpw (pss_base + PSS_CONFIG);
 177       val &= INT_MASK;
 178       val |= INT_3_BITS;
 179       pss_outpw (pss_base + PSS_CONFIG, val);
 180       break;
 181     case 5:
 182       val = pss_inpw (pss_base + PSS_CONFIG);
 183       val &= INT_MASK;
 184       val |= INT_5_BITS;
 185       pss_outpw (pss_base + PSS_CONFIG, val);
 186       break;
 187     case 7:
 188       val = pss_inpw (pss_base + PSS_CONFIG);
 189       val &= INT_MASK;
 190       val |= INT_7_BITS;
 191       pss_outpw (pss_base + PSS_CONFIG, val);
 192       break;
 193     case 9:
 194       val = pss_inpw (pss_base + PSS_CONFIG);
 195       val &= INT_MASK;
 196       val |= INT_9_BITS;
 197       pss_outpw (pss_base + PSS_CONFIG, val);
 198       break;
 199     case 10:
 200       val = pss_inpw (pss_base + PSS_CONFIG);
 201       val &= INT_MASK;
 202       val |= INT_10_BITS;
 203       pss_outpw (pss_base + PSS_CONFIG, val);
 204       break;
 205     case 11:
 206       val = pss_inpw (pss_base + PSS_CONFIG);
 207       val &= INT_MASK;
 208       val |= INT_11_BITS;
 209       pss_outpw (pss_base + PSS_CONFIG, val);
 210       break;
 211     case 12:
 212       val = pss_inpw (pss_base + PSS_CONFIG);
 213       val &= INT_MASK;
 214       val |= INT_12_BITS;
 215       pss_outpw (pss_base + PSS_CONFIG, val);
 216       break;
 217     default:
 218       printk ("unknown interrupt selected. %d\n", intNum);
 219       return 0;
 220     }
 221 
 222   /*_____ Set the interrupt test bit */
 223   val = pss_inpw (pss_base + PSS_CONFIG);
 224   val |= INT_TEST_BIT;
 225   pss_outpw (pss_base + PSS_CONFIG, val);
 226 
 227   /*_____ Check if the interrupt is in use */
 228   /*_____ Do it a few times in case there is a delay */
 229   ret = 0;
 230   for (i = 0; i < 5; i++)
 231     {
 232       val = pss_inpw (pss_base + PSS_CONFIG);
 233       if (val & INT_TEST_PASS)
 234         {
 235           ret = 1;
 236           break;
 237         }
 238     }
 239   /*_____ Clear the Test bit and the interrupt bits */
 240   val = pss_inpw (pss_base + PSS_CONFIG);
 241   val &= INT_TEST_BIT_MASK;
 242   val &= INT_MASK;
 243   pss_outpw (pss_base + PSS_CONFIG, val);
 244   return (ret);
 245 }
 246 
 247 /*____ pss_setint
 248         This function sets the correct bits in the
 249         configuration register to
 250         enable the chosen interrupt.
 251 */
 252 static void
 253 pss_setint (int intNum, int configAddress)
     /* [previous][next][first][last][top][bottom][index][help] */
 254 {
 255   int             val;
 256 
 257   switch (intNum)
 258     {
 259     case 0:
 260       val = pss_inpw (configAddress);
 261       val &= INT_MASK;
 262       pss_outpw (configAddress, val);
 263       break;
 264     case 3:
 265       val = pss_inpw (configAddress);
 266       val &= INT_MASK;
 267       val |= INT_3_BITS;
 268       pss_outpw (configAddress, val);
 269       break;
 270     case 5:
 271       val = pss_inpw (configAddress);
 272       val &= INT_MASK;
 273       val |= INT_5_BITS;
 274       pss_outpw (configAddress, val);
 275       break;
 276     case 7:
 277       val = pss_inpw (configAddress);
 278       val &= INT_MASK;
 279       val |= INT_7_BITS;
 280       pss_outpw (configAddress, val);
 281       break;
 282     case 9:
 283       val = pss_inpw (configAddress);
 284       val &= INT_MASK;
 285       val |= INT_9_BITS;
 286       pss_outpw (configAddress, val);
 287       break;
 288     case 10:
 289       val = pss_inpw (configAddress);
 290       val &= INT_MASK;
 291       val |= INT_10_BITS;
 292       pss_outpw (configAddress, val);
 293       break;
 294     case 11:
 295       val = pss_inpw (configAddress);
 296       val &= INT_MASK;
 297       val |= INT_11_BITS;
 298       pss_outpw (configAddress, val);
 299       break;
 300     case 12:
 301       val = pss_inpw (configAddress);
 302       val &= INT_MASK;
 303       val |= INT_12_BITS;
 304       pss_outpw (configAddress, val);
 305       break;
 306     default:
 307       printk ("pss_setint unknown int\n");
 308     }
 309 }
 310 
 311 
 312 /*____ pss_setsbint
 313         This function sets the correct bits in the
 314         SoundBlaster configuration PSS register to
 315         enable the chosen interrupt.
 316         It takes a interrupt button as its argument.
 317 */
 318 static void
 319 pss_setsbint (int intNum)
     /* [previous][next][first][last][top][bottom][index][help] */
 320 {
 321   int             val;
 322   int             sbConfigAddress;
 323 
 324   sbConfigAddress = pss_base + SB_CONFIG;
 325   switch (intNum)
 326     {
 327     case 3:
 328       val = pss_inpw (sbConfigAddress);
 329       val &= INT_MASK;
 330       val |= INT_3_BITS;
 331       pss_outpw (sbConfigAddress, val);
 332       break;
 333     case 5:
 334       val = pss_inpw (sbConfigAddress);
 335       val &= INT_MASK;
 336       val |= INT_5_BITS;
 337       pss_outpw (sbConfigAddress, val);
 338       break;
 339     case 7:
 340       val = pss_inpw (sbConfigAddress);
 341       val &= INT_MASK;
 342       val |= INT_7_BITS;
 343       pss_outpw (sbConfigAddress, val);
 344       break;
 345     default:
 346       printk ("pss_setsbint: unknown_int\n");
 347     }
 348 }
 349 
 350 /*____ pss_setsbdma
 351         This function sets the correct bits in the
 352         SoundBlaster configuration PSS register to
 353         enable the chosen DMA channel.
 354         It takes a DMA button as its argument.
 355 */
 356 static void
 357 pss_setsbdma (int dmaNum)
     /* [previous][next][first][last][top][bottom][index][help] */
 358 {
 359   int             val;
 360   int             sbConfigAddress;
 361 
 362   sbConfigAddress = pss_base + SB_CONFIG;
 363 
 364   switch (dmaNum)
 365     {
 366     case 1:
 367       val = pss_inpw (sbConfigAddress);
 368       val &= DMA_MASK;
 369       val |= DMA_1_BITS;
 370       pss_outpw (sbConfigAddress, val);
 371       break;
 372     default:
 373       printk ("Personal Sound System ERROR! pss_setsbdma: unknown_dma\n");
 374     }
 375 }
 376 
 377 /*____ pss_setwssdma
 378         This function sets the correct bits in the
 379         WSS configuration PSS register to
 380         enable the chosen DMA channel.
 381         It takes a DMA button as its argument.
 382 */
 383 static void
 384 pss_setwssdma (int dmaNum)
     /* [previous][next][first][last][top][bottom][index][help] */
 385 {
 386   int             val;
 387   int             wssConfigAddress;
 388 
 389   wssConfigAddress = pss_base + PSS_WSS_CONFIG;
 390 
 391   switch (dmaNum)
 392     {
 393     case 0:
 394       val = pss_inpw (wssConfigAddress);
 395       val &= DMA_MASK;
 396       val |= DMA_0_BITS;
 397       pss_outpw (wssConfigAddress, val);
 398       break;
 399     case 1:
 400       val = pss_inpw (wssConfigAddress);
 401       val &= DMA_MASK;
 402       val |= DMA_1_BITS;
 403       pss_outpw (wssConfigAddress, val);
 404       break;
 405     case 3:
 406       val = pss_inpw (wssConfigAddress);
 407       val &= DMA_MASK;
 408       val |= DMA_3_BITS;
 409       pss_outpw (wssConfigAddress, val);
 410       break;
 411     default:
 412       printk ("Personal Sound System ERROR! pss_setwssdma: unknown_dma\n");
 413     }
 414 }
 415 
 416 
 417 /*_____ SetSpeakerOut
 418          This function sets the Volume, Bass, Treble and Mode of
 419          the speaker out channel.
 420          */
 421 void
 422 pss_setspeaker (struct pss_speaker *spk)
     /* [previous][next][first][last][top][bottom][index][help] */
 423 {
 424   PSS_write (SET_MASTER_COMMAND);
 425   if (spk->volume > PHILLIPS_VOL_MAX)
 426     spk->volume = PHILLIPS_VOL_MAX;
 427   if (spk->volume < PHILLIPS_VOL_MIN)
 428     spk->volume = PHILLIPS_VOL_MIN;
 429 
 430   PSS_write (MASTER_VOLUME_LEFT
 431              | (PHILLIPS_VOL_CONSTANT + spk->volume / PHILLIPS_VOL_STEP));
 432   PSS_write (SET_MASTER_COMMAND);
 433   PSS_write (MASTER_VOLUME_RIGHT
 434              | (PHILLIPS_VOL_CONSTANT + spk->volume / PHILLIPS_VOL_STEP));
 435 
 436   if (spk->bass > PHILLIPS_BASS_MAX)
 437     spk->bass = PHILLIPS_BASS_MAX;
 438   if (spk->bass < PHILLIPS_BASS_MIN)
 439     spk->bass = PHILLIPS_BASS_MIN;
 440   PSS_write (SET_MASTER_COMMAND);
 441   PSS_write (MASTER_BASS
 442              | (PHILLIPS_BASS_CONSTANT + spk->bass / PHILLIPS_BASS_STEP));
 443 
 444   if (spk->treb > PHILLIPS_TREBLE_MAX)
 445     spk->treb = PHILLIPS_TREBLE_MAX;
 446   if (spk->treb < PHILLIPS_TREBLE_MIN)
 447     spk->treb = PHILLIPS_TREBLE_MIN;
 448   PSS_write (SET_MASTER_COMMAND);
 449   PSS_write (MASTER_TREBLE
 450            | (PHILLIPS_TREBLE_CONSTANT + spk->treb / PHILLIPS_TREBLE_STEP));
 451 
 452   PSS_write (SET_MASTER_COMMAND);
 453   PSS_write (MASTER_SWITCH | spk->mode);
 454 }
 455 
 456 static void
 457 pss_init1848 (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 458 {
 459   /*_____ Wait for 1848 to init */
 460   while (INB (SoundPortAddress) & SP_IN_INIT);
 461 
 462   /*_____ Wait for 1848 to autocal */
 463   OUTB (SoundPortAddress, SP_TEST_AND_INIT);
 464   while (INB (SoundPortData) & AUTO_CAL_IN_PROG);
 465 }
 466 
 467 static int
 468 pss_configure_registers_to_look_like_sb (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 469 {
 470   pss_setaddr (wssAddr, pss_base + PSS_WSS_CONFIG);
 471 
 472   SoundPortAddress = wssAddr + 4;
 473   SoundPortData = wssAddr + 5;
 474 
 475   DEB (printk ("Turning Game Port %s.\n",
 476                gamePort ? "On" : "Off"));
 477 
 478   /*_____ Turn on the Game port */
 479   if (gamePort)
 480     pss_outpw (pss_base + PSS_STATUS,
 481                pss_inpw (pss_base + PSS_STATUS) | GAME_BIT);
 482   else
 483     pss_outpw (pss_base + PSS_STATUS,
 484                pss_inpw (pss_base + PSS_STATUS) & GAME_BIT_MASK);
 485 
 486 
 487   DEB (printk ("PSS attaching base %x irq %d dma %d\n",
 488                pss_base, pss_irq, pss_dma));
 489 
 490   /* Check if sb is enabled if it is check the interrupt */
 491   pss_outpw (pss_base + SB_CONFIG, 0);
 492 
 493   if (pss_irq != 0)
 494     {
 495       DEB (printk ("PSS Emulating Sound Blaster ADDR %04x\n", pss_base));
 496       DEB (printk ("PSS SBC: attaching base %x irq %d dma %d\n",
 497                    SBC_BASE, SBC_IRQ, SBC_DMA));
 498 
 499       if (pss_checkint (SBC_IRQ) == 0)
 500         {
 501           printk ("PSS! attach: int_error\n");
 502           return 0;
 503         }
 504 
 505       pss_setsbint (SBC_IRQ);
 506       pss_setsbdma (SBC_DMA);
 507       sb_ok = 1;
 508     }
 509   else
 510     {
 511       sb_ok = 0;
 512       printk ("PSS: sound blaster error init\n");
 513     }
 514 
 515   /* Check if cd is enabled if it is check the interrupt */
 516   pss_outpw (pss_base + CD_CONFIG, 0);
 517 
 518   if (cdAddr != 0)
 519     {
 520       DEB (printk ("PSS:CD drive %x irq: %d", cdAddr, cdInt));
 521       if (cdInt != 0)
 522         {
 523           if (pss_checkint (cdInt) == 0)
 524             {
 525               printk ("Can't allocate cdInt %d\n", cdInt);
 526             }
 527           else
 528             {
 529               int             val;
 530 
 531               printk ("CD poll ");
 532               pss_setaddr (cdAddr, pss_base + CD_CONFIG);
 533               pss_setint (cdInt, pss_base + CD_CONFIG);
 534 
 535               /* set the correct bit in the
 536                  configuration register to
 537                  set the irq polarity for the CD-Rom.
 538                  NOTE: This bit is in the address config
 539                  field, It must be configured after setting
 540                  the CD-ROM ADDRESS!!! */
 541               val = pss_inpw (pss_base + CD_CONFIG);
 542               pss_outpw (pss_base + CD_CONFIG, 0);
 543               val &= CD_POL_MASK;
 544               if (cdPol)
 545                 val |= CD_POL_BIT;
 546               pss_outpw (pss_base + CD_CONFIG, val);
 547             }
 548         }
 549     }
 550 
 551   /* Check if midi is enabled if it is check the interrupt */
 552   pss_outpw (pss_base + MIDI_CONFIG, 0);
 553   if (midiAddr != 0)
 554     {
 555       printk ("midi init %x %d\n", midiAddr, midiInt);
 556       if (pss_checkint (midiInt) == 0)
 557         {
 558           printk ("midi init int error %x %d\n", midiAddr, midiInt);
 559         }
 560       else
 561         {
 562           pss_setaddr (midiAddr, pss_base + MIDI_CONFIG);
 563           pss_setint (midiInt, pss_base + MIDI_CONFIG);
 564         }
 565     }
 566   return 1;
 567 }
 568 
 569 long
 570 attach_pss (long mem_start, struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 571 {
 572   if (pss_ok)
 573     {
 574       if (hw_config)
 575         {
 576           printk (" <PSS-ESC614>");
 577         }
 578 
 579       return mem_start;
 580     }
 581 
 582   pss_ok = 1;
 583 
 584   if (pss_configure_registers_to_look_like_sb () == 0)
 585     return mem_start;
 586 
 587   if (sb_ok)
 588     if (pss_synthLen
 589         && pss_download_boot (pss_synth, pss_synthLen))
 590       {
 591         if (speaker)
 592           pss_setspeaker (&default_speaker);
 593         pss_ok = 1;
 594       }
 595     else
 596       pss_reset_dsp ();
 597 
 598   return mem_start;
 599 }
 600 
 601 int
 602 probe_pss (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 603 {
 604   pss_base = hw_config->io_base;
 605   pss_irq = hw_config->irq;
 606   pss_dma = hw_config->dma;
 607 
 608   if ((pss_inpw (pss_base + 4) & 0xff00) == 0x4500)
 609     {
 610       attach_pss (0, hw_config);
 611       return 1;
 612     }
 613   printk (" fail base %x irq %d dma %d\n", pss_base, pss_irq, pss_dma);
 614   return 0;
 615 }
 616 
 617 
 618 static int
 619 pss_reattach (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 620 {
 621   pss_ok = 0;
 622   attach_pss (0, 0);
 623   return 1;
 624 }
 625 
 626 static int
 627 pss_reset_dsp ()
     /* [previous][next][first][last][top][bottom][index][help] */
 628 {
 629   unsigned long   i, limit = GET_TIME () + 10;
 630 
 631   pss_outpw (pss_base + PSS_CONTROL, 0x2000);
 632 
 633   for (i = 0; i < 32768 && GET_TIME () < limit; i++)
 634     pss_inpw (pss_base + PSS_CONTROL);
 635 
 636   pss_outpw (pss_base + PSS_CONTROL, 0x0000);
 637 
 638   return 1;
 639 }
 640 
 641 
 642 static int
 643 pss_download_boot (unsigned char *block, int size)
     /* [previous][next][first][last][top][bottom][index][help] */
 644 {
 645   int             i, limit, val, count;
 646 
 647   printk ("PSS: downloading boot code synth.ld... ");
 648 
 649   /*_____ Warn DSP software that a boot is coming */
 650   pss_outpw (pss_base + PSS_DATA, 0x00fe);
 651 
 652   limit = GET_TIME () + 10;
 653 
 654   for (i = 0; i < 32768 && GET_TIME () < limit; i++)
 655     if (pss_inpw (pss_base + PSS_DATA) == 0x5500)
 656       break;
 657 
 658   pss_outpw (pss_base + PSS_DATA, *block++);
 659 
 660   pss_reset_dsp ();
 661   printk ("start ");
 662 
 663   count = 1;
 664   while (1)
 665     {
 666       int             j;
 667 
 668       for (j = 0; j < 327670; j++)
 669         {
 670           /*_____ Wait for BG to appear */
 671           if (pss_inpw (pss_base + PSS_STATUS) & PSS_FLAG3)
 672             break;
 673         }
 674 
 675       if (j == 327670)
 676         {
 677           /* It's ok we timed out when the file was empty */
 678           if (count >= size)
 679             break;
 680           else
 681             {
 682               printk ("\nPSS: DownLoad timeout problems, byte %d=%d\n",
 683                       count, size);
 684               return 0;
 685             }
 686         }
 687       /*_____ Send the next byte */
 688       pss_outpw (pss_base + PSS_DATA, *block++);
 689       count++;
 690     }
 691 
 692   /*_____ Why */
 693   pss_outpw (pss_base + PSS_DATA, 0);
 694 
 695   limit = GET_TIME () + 10;
 696   for (i = 0; i < 32768 && GET_TIME () < limit; i++)
 697     val = pss_inpw (pss_base + PSS_STATUS);
 698 
 699   printk ("downloaded\n");
 700 
 701   limit = GET_TIME () + 10;
 702   for (i = 0; i < 32768 && GET_TIME () < limit; i++)
 703     {
 704       val = pss_inpw (pss_base + PSS_STATUS);
 705       if (val & 0x4000)
 706         break;
 707     }
 708 
 709   /* now read the version */
 710   for (i = 0; i < 32000; i++)
 711     {
 712       val = pss_inpw (pss_base + PSS_STATUS_REG);
 713       if (val & PSS_READ_FULL)
 714         break;
 715     }
 716   if (i == 32000)
 717     return 0;
 718 
 719   val = pss_inpw (pss_base + PSS_DATA_REG);
 720 
 721   return 1;
 722 }
 723 
 724 
 725 /* The following is a simple device driver for the pss.
 726    All I really care about is communication to and from the pss.
 727 
 728    The ability to reinitialize the <synth.ld>  This will be
 729    default when release is chosen.
 730 
 731    SNDCTL_PSS_DOWNLOAD:
 732 
 733    Okay we need to creat new minor numbers for the
 734    DOWNLOAD functionality.
 735 
 736    14,0x19 -- /dev/pssld where a read operation would output the
 737                          current ld to user space
 738                          where a write operation would effectively
 739                          download a new ld.
 740 
 741    14,0x09 -- /dev/psecho  would open up a communication path to the
 742                          esc614 asic.  Given the ability to send
 743                          messages to the asic and receive messages too.
 744 
 745                          All messages would get read and written in the
 746                          same manner.  It would be up to the application
 747                          and the ld to maintain a relationship
 748                          of what the messages mean.
 749                         
 750                          for this device we need to implement select. */
 751 #define CODE_BUFFER_LEN (64*1024)
 752 static char    *code_buffer;
 753 static int      code_length;
 754 
 755 static int      lock_pss = 0;
 756 
 757 int
 758 pss_open (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 759 {
 760   int             mode;
 761 
 762   DEB (printk ("pss_open\n"));
 763 
 764   if (pss_ok == 0)
 765     return RET_ERROR (EIO);
 766 
 767   if (lock_pss)
 768     return 0;
 769 
 770   lock_pss = 1;
 771 
 772   dev = dev >> 4;
 773   mode = file->mode & O_ACCMODE;
 774   if (mode == O_WRONLY)
 775     {
 776       printk ("pss-open for WRONLY\n");
 777       code_length = 0;
 778     }
 779 
 780   RESET_WAIT_QUEUE (pss_sleeper, pss_sleep_flag);
 781   return 1;
 782 }
 783 
 784 void
 785 pss_release (int dev, struct fileinfo *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 786 {
 787   int             mode;
 788 
 789   DEB (printk ("pss_release\n"));
 790   if (pss_ok == 0)
 791     return RET_ERROR (EIO);
 792 
 793   dev = dev >> 4;
 794   mode = file->mode & O_ACCMODE;
 795   if (mode == O_WRONLY && code_length > 0)
 796     {
 797 #ifdef linux
 798       /* This just allows interrupts while the conversion is running */
 799       __asm__ ("sti");
 800 #endif
 801       if (!pss_download_boot (code_buffer, code_length))
 802         {
 803           pss_reattach ();
 804         }
 805     }
 806   lock_pss = 0;
 807 }
 808 
 809 int
 810 pss_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 811 {
 812   int             c, p;
 813 
 814   DEB (printk ("pss_read\n"));
 815   if (pss_ok == 0)
 816     return RET_ERROR (EIO);
 817 
 818   dev = dev >> 4;
 819   p = 0;
 820   c = count;
 821 
 822   return count - c;
 823 }
 824 
 825 int
 826 pss_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 827 {
 828   DEB (printk ("pss_write\n"));
 829   if (pss_ok == 0)
 830     return RET_ERROR (EIO);
 831   dev = dev >> 4;
 832 
 833   if (count)                    /* Flush output */
 834     {
 835       COPY_FROM_USER (&code_buffer[code_length], buf, 0, count);
 836       code_length += count;
 837     }
 838   return count;
 839 }
 840 
 841 
 842 int
 843 pss_ioctl (int dev, struct fileinfo *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 844            unsigned int cmd, unsigned int arg)
 845 {
 846   DEB (printk ("pss_ioctl dev=%d cmd=%x\n", dev, cmd));
 847   if (pss_ok == 0)
 848     return RET_ERROR (EIO);
 849 
 850   dev = dev >> 4;
 851 
 852   switch (cmd)
 853     {
 854     case SNDCTL_PSS_RESET:
 855       pss_reattach ();
 856       return 1;
 857 
 858     case SNDCTL_PSS_SETUP_REGISTERS:
 859       pss_configure_registers_to_look_like_sb ();
 860       return 1;
 861 
 862     case SNDCTL_PSS_SPEAKER:
 863       {
 864         struct pss_speaker params;
 865         COPY_FROM_USER (&params, (char *) arg, 0, sizeof (struct pss_speaker));
 866 
 867         pss_setspeaker (&params);
 868         return 0;
 869       }
 870     default:
 871       return RET_ERROR (EIO);
 872     }
 873 }
 874 
 875 /* This is going to be used to implement
 876    waiting on messages sent from the DSP and to the
 877    DSP when communication is used via the pss directly.
 878 
 879    We need to find out if the pss can generate a different
 880    interrupt other than the one it has been setup for.
 881 
 882    This way we can carry on a conversation with the pss
 883    on a separate channel.  This would be useful for debugging. */
 884 
 885 pss_select (int dev, struct fileinfo * file, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 886 {
 887   return 0;
 888   if (pss_ok == 0)
 889     return RET_ERROR (EIO);
 890 
 891   dev = dev >> 4;
 892 
 893   switch (sel_type)
 894     {
 895     case SEL_IN:
 896       select_wait (&pss_sleeper, wait);
 897       return 0;
 898       break;
 899 
 900     case SEL_OUT:
 901       select_wait (&pss_sleeper, wait);
 902       return 0;
 903       break;
 904 
 905     case SEL_EX:
 906       return 0;
 907     }
 908 
 909   return 0;
 910 }
 911 
 912 long
 913 pss_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 914 {
 915   DEB (printk ("pss_init\n"));
 916   if (pss_ok)
 917     {
 918       code_buffer = mem_start;
 919       mem_start += CODE_BUFFER_LEN;
 920     }
 921   return mem_start;
 922 }
 923 
 924 #endif

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