linux/sound/oss/pss.c
<<
>>
Prefs
   1/*
   2 * sound/oss/pss.c
   3 *
   4 * The low level driver for the Personal Sound System (ECHO ESC614).
   5 *
   6 *
   7 * Copyright (C) by Hannu Savolainen 1993-1997
   8 *
   9 * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  10 * Version 2 (June 1991). See the "COPYING" file distributed with this software
  11 * for more info.
  12 *
  13 *
  14 * Thomas Sailer        ioctl code reworked (vmalloc/vfree removed)
  15 * Alan Cox             modularisation, clean up.
  16 *
  17 * 98-02-21: Vladimir Michl <vladimir.michl@upol.cz>
  18 *          Added mixer device for Beethoven ADSP-16 (master volume,
  19 *          bass, treble, synth), only for speakers.
  20 *          Fixed bug in pss_write (exchange parameters)
  21 *          Fixed config port of SB
  22 *          Requested two regions for PSS (PSS mixer, PSS config)
  23 *          Modified pss_download_boot
  24 *          To probe_pss_mss added test for initialize AD1848
  25 * 98-05-28: Vladimir Michl <vladimir.michl@upol.cz>
  26 *          Fixed computation of mixer volumes
  27 * 04-05-1999: Anthony Barbachan <barbcode@xmen.cis.fordham.edu>
  28 *          Added code that allows the user to enable his cdrom and/or 
  29 *          joystick through the module parameters pss_cdrom_port and 
  30 *          pss_enable_joystick.  pss_cdrom_port takes a port address as its
  31 *          argument.  pss_enable_joystick takes either a 0 or a non-0 as its
  32 *          argument.
  33 * 04-06-1999: Anthony Barbachan <barbcode@xmen.cis.fordham.edu>
  34 *          Separated some code into new functions for easier reuse.  
  35 *          Cleaned up and streamlined new code.  Added code to allow a user 
  36 *          to only use this driver for enabling non-sound components 
  37 *          through the new module parameter pss_no_sound (flag).  Added 
  38 *          code that would allow a user to decide whether the driver should 
  39 *          reset the configured hardware settings for the PSS board through 
  40 *          the module parameter pss_keep_settings (flag).   This flag will 
  41 *          allow a user to free up resources in use by this card if needbe, 
  42 *          furthermore it allows him to use this driver to just enable the 
  43 *          emulations and then be unloaded as it is no longer needed.  Both 
  44 *          new settings are only available to this driver if compiled as a 
  45 *          module.  The default settings of all new parameters are set to 
  46 *          load the driver as it did in previous versions.
  47 * 04-07-1999: Anthony Barbachan <barbcode@xmen.cis.fordham.edu>
  48 *          Added module parameter pss_firmware to allow the user to tell 
  49 *          the driver where the firmware file is located.  The default 
  50 *          setting is the previous hardcoded setting "/etc/sound/pss_synth".
  51 * 00-03-03: Christoph Hellwig <chhellwig@infradead.org>
  52 *          Adapted to module_init/module_exit
  53 * 11-10-2000: Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
  54 *          Added __init to probe_pss(), attach_pss() and probe_pss_mpu()
  55 * 02-Jan-2001: Chris Rankin
  56 *          Specify that this module owns the coprocessor
  57 */
  58
  59
  60#include <linux/init.h>
  61#include <linux/module.h>
  62#include <linux/spinlock.h>
  63
  64#include "sound_config.h"
  65#include "sound_firmware.h"
  66
  67#include "ad1848.h"
  68#include "mpu401.h"
  69
  70/*
  71 * PSS registers.
  72 */
  73#define REG(x)  (devc->base+x)
  74#define PSS_DATA        0
  75#define PSS_STATUS      2
  76#define PSS_CONTROL     2
  77#define PSS_ID          4
  78#define PSS_IRQACK      4
  79#define PSS_PIO         0x1a
  80
  81/*
  82 * Config registers
  83 */
  84#define CONF_PSS        0x10
  85#define CONF_WSS        0x12
  86#define CONF_SB         0x14
  87#define CONF_CDROM      0x16
  88#define CONF_MIDI       0x18
  89
  90/*
  91 * Status bits.
  92 */
  93#define PSS_FLAG3     0x0800
  94#define PSS_FLAG2     0x0400
  95#define PSS_FLAG1     0x1000
  96#define PSS_FLAG0     0x0800
  97#define PSS_WRITE_EMPTY  0x8000
  98#define PSS_READ_FULL    0x4000
  99
 100/*
 101 * WSS registers
 102 */
 103#define WSS_INDEX 4
 104#define WSS_DATA 5
 105
 106/*
 107 * WSS status bits
 108 */
 109#define WSS_INITIALIZING 0x80
 110#define WSS_AUTOCALIBRATION 0x20
 111
 112#define NO_WSS_MIXER    -1
 113
 114#include "coproc.h"
 115
 116#include "pss_boot.h"
 117
 118/* If compiled into kernel, it enable or disable pss mixer */
 119#ifdef CONFIG_PSS_MIXER
 120static int pss_mixer = 1;
 121#else
 122static int pss_mixer;
 123#endif
 124
 125
 126typedef struct pss_mixerdata {
 127        unsigned int volume_l;
 128        unsigned int volume_r;
 129        unsigned int bass;
 130        unsigned int treble;
 131        unsigned int synth;
 132} pss_mixerdata;
 133
 134typedef struct pss_confdata {
 135        int             base;
 136        int             irq;
 137        int             dma;
 138        int            *osp;
 139        pss_mixerdata   mixer;
 140        int             ad_mixer_dev;
 141} pss_confdata;
 142  
 143static pss_confdata pss_data;
 144static pss_confdata *devc = &pss_data;
 145static DEFINE_SPINLOCK(lock);
 146
 147static int      pss_initialized;
 148static int      nonstandard_microcode;
 149static int      pss_cdrom_port = -1;    /* Parameter for the PSS cdrom port */
 150static int      pss_enable_joystick;    /* Parameter for enabling the joystick */
 151static coproc_operations pss_coproc_operations;
 152
 153static void pss_write(pss_confdata *devc, int data)
 154{
 155        unsigned long i, limit;
 156
 157        limit = jiffies + HZ/10;        /* The timeout is 0.1 seconds */
 158        /*
 159         * Note! the i<5000000 is an emergency exit. The dsp_command() is sometimes
 160         * called while interrupts are disabled. This means that the timer is
 161         * disabled also. However the timeout situation is a abnormal condition.
 162         * Normally the DSP should be ready to accept commands after just couple of
 163         * loops.
 164         */
 165
 166        for (i = 0; i < 5000000 && time_before(jiffies, limit); i++)
 167        {
 168                if (inw(REG(PSS_STATUS)) & PSS_WRITE_EMPTY)
 169                {
 170                        outw(data, REG(PSS_DATA));
 171                        return;
 172                }
 173        }
 174        printk(KERN_WARNING "PSS: DSP Command (%04x) Timeout.\n", data);
 175}
 176
 177static int __init probe_pss(struct address_info *hw_config)
 178{
 179        unsigned short id;
 180        int irq, dma;
 181
 182        devc->base = hw_config->io_base;
 183        irq = devc->irq = hw_config->irq;
 184        dma = devc->dma = hw_config->dma;
 185        devc->osp = hw_config->osp;
 186
 187        if (devc->base != 0x220 && devc->base != 0x240)
 188                if (devc->base != 0x230 && devc->base != 0x250)         /* Some cards use these */
 189                        return 0;
 190
 191        if (!request_region(devc->base, 0x10, "PSS mixer, SB emulation")) {
 192                printk(KERN_ERR "PSS: I/O port conflict\n");
 193                return 0;
 194        }
 195        id = inw(REG(PSS_ID));
 196        if ((id >> 8) != 'E') {
 197                printk(KERN_ERR "No PSS signature detected at 0x%x (0x%x)\n",  devc->base,  id); 
 198                release_region(devc->base, 0x10);
 199                return 0;
 200        }
 201        if (!request_region(devc->base + 0x10, 0x9, "PSS config")) {
 202                printk(KERN_ERR "PSS: I/O port conflict\n");
 203                release_region(devc->base, 0x10);
 204                return 0;
 205        }
 206        return 1;
 207}
 208
 209static int set_irq(pss_confdata * devc, int dev, int irq)
 210{
 211        static unsigned short irq_bits[16] =
 212        {
 213                0x0000, 0x0000, 0x0000, 0x0008,
 214                0x0000, 0x0010, 0x0000, 0x0018,
 215                0x0000, 0x0020, 0x0028, 0x0030,
 216                0x0038, 0x0000, 0x0000, 0x0000
 217        };
 218
 219        unsigned short  tmp, bits;
 220
 221        if (irq < 0 || irq > 15)
 222                return 0;
 223
 224        tmp = inw(REG(dev)) & ~0x38;    /* Load confreg, mask IRQ bits out */
 225
 226        if ((bits = irq_bits[irq]) == 0 && irq != 0)
 227        {
 228                printk(KERN_ERR "PSS: Invalid IRQ %d\n", irq);
 229                return 0;
 230        }
 231        outw(tmp | bits, REG(dev));
 232        return 1;
 233}
 234
 235static void set_io_base(pss_confdata * devc, int dev, int base)
 236{
 237        unsigned short  tmp = inw(REG(dev)) & 0x003f;
 238        unsigned short  bits = (base & 0x0ffc) << 4;
 239
 240        outw(bits | tmp, REG(dev));
 241}
 242
 243static int set_dma(pss_confdata * devc, int dev, int dma)
 244{
 245        static unsigned short dma_bits[8] =
 246        {
 247                0x0001, 0x0002, 0x0000, 0x0003,
 248                0x0000, 0x0005, 0x0006, 0x0007
 249        };
 250
 251        unsigned short  tmp, bits;
 252
 253        if (dma < 0 || dma > 7)
 254                return 0;
 255
 256        tmp = inw(REG(dev)) & ~0x07;    /* Load confreg, mask DMA bits out */
 257
 258        if ((bits = dma_bits[dma]) == 0 && dma != 4)
 259        {
 260                  printk(KERN_ERR "PSS: Invalid DMA %d\n", dma);
 261                  return 0;
 262        }
 263        outw(tmp | bits, REG(dev));
 264        return 1;
 265}
 266
 267static int pss_reset_dsp(pss_confdata * devc)
 268{
 269        unsigned long   i, limit = jiffies + HZ/10;
 270
 271        outw(0x2000, REG(PSS_CONTROL));
 272        for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++)
 273                inw(REG(PSS_CONTROL));
 274        outw(0x0000, REG(PSS_CONTROL));
 275        return 1;
 276}
 277
 278static int pss_put_dspword(pss_confdata * devc, unsigned short word)
 279{
 280        int i, val;
 281
 282        for (i = 0; i < 327680; i++)
 283        {
 284                val = inw(REG(PSS_STATUS));
 285                if (val & PSS_WRITE_EMPTY)
 286                {
 287                        outw(word, REG(PSS_DATA));
 288                        return 1;
 289                }
 290        }
 291        return 0;
 292}
 293
 294static int pss_get_dspword(pss_confdata * devc, unsigned short *word)
 295{
 296        int i, val;
 297
 298        for (i = 0; i < 327680; i++)
 299        {
 300                val = inw(REG(PSS_STATUS));
 301                if (val & PSS_READ_FULL)
 302                {
 303                        *word = inw(REG(PSS_DATA));
 304                        return 1;
 305                }
 306        }
 307        return 0;
 308}
 309
 310static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size, int flags)
 311{
 312        int i, val, count;
 313        unsigned long limit;
 314
 315        if (flags & CPF_FIRST)
 316        {
 317/*_____ Warn DSP software that a boot is coming */
 318                outw(0x00fe, REG(PSS_DATA));
 319
 320                limit = jiffies + HZ/10;
 321                for (i = 0; i < 32768 && time_before(jiffies, limit); i++)
 322                        if (inw(REG(PSS_DATA)) == 0x5500)
 323                                break;
 324
 325                outw(*block++, REG(PSS_DATA));
 326                pss_reset_dsp(devc);
 327        }
 328        count = 1;
 329        while ((flags&CPF_LAST) || count<size )
 330        {
 331                int j;
 332
 333                for (j = 0; j < 327670; j++)
 334                {
 335/*_____ Wait for BG to appear */
 336                        if (inw(REG(PSS_STATUS)) & PSS_FLAG3)
 337                                break;
 338                }
 339
 340                if (j == 327670)
 341                {
 342                        /* It's ok we timed out when the file was empty */
 343                        if (count >= size && flags & CPF_LAST)
 344                                break;
 345                        else
 346                        {
 347                                printk("\n");
 348                                printk(KERN_ERR "PSS: Download timeout problems, byte %d=%d\n", count, size);
 349                                return 0;
 350                        }
 351                }
 352/*_____ Send the next byte */
 353                if (count >= size) 
 354                {
 355                        /* If not data in block send 0xffff */
 356                        outw (0xffff, REG (PSS_DATA));
 357                }
 358                else
 359                {
 360                        /*_____ Send the next byte */
 361                        outw (*block++, REG (PSS_DATA));
 362                };
 363                count++;
 364        }
 365
 366        if (flags & CPF_LAST)
 367        {
 368/*_____ Why */
 369                outw(0, REG(PSS_DATA));
 370
 371                limit = jiffies + HZ/10;
 372                for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++)
 373                        val = inw(REG(PSS_STATUS));
 374
 375                limit = jiffies + HZ/10;
 376                for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++)
 377                {
 378                        val = inw(REG(PSS_STATUS));
 379                        if (val & 0x4000)
 380                                break;
 381                }
 382
 383                /* now read the version */
 384                for (i = 0; i < 32000; i++)
 385                {
 386                        val = inw(REG(PSS_STATUS));
 387                        if (val & PSS_READ_FULL)
 388                                break;
 389                }
 390                if (i == 32000)
 391                        return 0;
 392
 393                val = inw(REG(PSS_DATA));
 394                /* printk( "<PSS: microcode version %d.%d loaded>",  val/16,  val % 16); */
 395        }
 396        return 1;
 397}
 398
 399/* Mixer */
 400static void set_master_volume(pss_confdata *devc, int left, int right)
 401{
 402        static unsigned char log_scale[101] =  {
 403                0xdb, 0xe0, 0xe3, 0xe5, 0xe7, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xee,
 404                0xef, 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3,
 405                0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7,
 406                0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9,
 407                0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb,
 408                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
 409                0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd,
 410                0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
 411                0xfe, 0xfe, 0xff, 0xff, 0xff
 412        };
 413        pss_write(devc, 0x0010);
 414        pss_write(devc, log_scale[left] | 0x0000);
 415        pss_write(devc, 0x0010);
 416        pss_write(devc, log_scale[right] | 0x0100);
 417}
 418
 419static void set_synth_volume(pss_confdata *devc, int volume)
 420{
 421        int vol = ((0x8000*volume)/100L);
 422        pss_write(devc, 0x0080);
 423        pss_write(devc, vol);
 424        pss_write(devc, 0x0081);
 425        pss_write(devc, vol);
 426}
 427
 428static void set_bass(pss_confdata *devc, int level)
 429{
 430        int vol = (int)(((0xfd - 0xf0) * level)/100L) + 0xf0;
 431        pss_write(devc, 0x0010);
 432        pss_write(devc, vol | 0x0200);
 433};
 434
 435static void set_treble(pss_confdata *devc, int level)
 436{       
 437        int vol = (((0xfd - 0xf0) * level)/100L) + 0xf0;
 438        pss_write(devc, 0x0010);
 439        pss_write(devc, vol | 0x0300);
 440};
 441
 442static void pss_mixer_reset(pss_confdata *devc)
 443{
 444        set_master_volume(devc, 33, 33);
 445        set_bass(devc, 50);
 446        set_treble(devc, 50);
 447        set_synth_volume(devc, 30);
 448        pss_write (devc, 0x0010);
 449        pss_write (devc, 0x0800 | 0xce);        /* Stereo */
 450        
 451        if(pss_mixer)
 452        {
 453                devc->mixer.volume_l = devc->mixer.volume_r = 33;
 454                devc->mixer.bass = 50;
 455                devc->mixer.treble = 50;
 456                devc->mixer.synth = 30;
 457        }
 458}
 459
 460static int set_volume_mono(unsigned __user *p, unsigned int *aleft)
 461{
 462        unsigned int left, volume;
 463        if (get_user(volume, p))
 464                return -EFAULT;
 465        
 466        left = volume & 0xff;
 467        if (left > 100)
 468                left = 100;
 469        *aleft = left;
 470        return 0;
 471}
 472
 473static int set_volume_stereo(unsigned __user *p,
 474                             unsigned int *aleft,
 475                             unsigned int *aright)
 476{
 477        unsigned int left, right, volume;
 478        if (get_user(volume, p))
 479                return -EFAULT;
 480
 481        left = volume & 0xff;
 482        if (left > 100)
 483                left = 100;
 484        right = (volume >> 8) & 0xff;
 485        if (right > 100)
 486                right = 100;
 487        *aleft = left;
 488        *aright = right;
 489        return 0;
 490}
 491
 492static int ret_vol_mono(int left)
 493{
 494        return ((left << 8) | left);
 495}
 496
 497static int ret_vol_stereo(int left, int right)
 498{
 499        return ((right << 8) | left);
 500}
 501
 502static int call_ad_mixer(pss_confdata *devc,unsigned int cmd, void __user *arg)
 503{
 504        if (devc->ad_mixer_dev != NO_WSS_MIXER) 
 505                return mixer_devs[devc->ad_mixer_dev]->ioctl(devc->ad_mixer_dev, cmd, arg);
 506        else 
 507                return -EINVAL;
 508}
 509
 510static int pss_mixer_ioctl (int dev, unsigned int cmd, void __user *arg)
 511{
 512        pss_confdata *devc = mixer_devs[dev]->devc;
 513        int cmdf = cmd & 0xff;
 514        
 515        if ((cmdf != SOUND_MIXER_VOLUME) && (cmdf != SOUND_MIXER_BASS) &&
 516                (cmdf != SOUND_MIXER_TREBLE) && (cmdf != SOUND_MIXER_SYNTH) &&
 517                (cmdf != SOUND_MIXER_DEVMASK) && (cmdf != SOUND_MIXER_STEREODEVS) &&
 518                (cmdf != SOUND_MIXER_RECMASK) && (cmdf != SOUND_MIXER_CAPS) &&
 519                (cmdf != SOUND_MIXER_RECSRC)) 
 520        {
 521                return call_ad_mixer(devc, cmd, arg);
 522        }
 523        
 524        if (((cmd >> 8) & 0xff) != 'M') 
 525                return -EINVAL;
 526                
 527        if (_SIOC_DIR (cmd) & _SIOC_WRITE)
 528        {
 529                switch (cmdf)   
 530                {
 531                        case SOUND_MIXER_RECSRC:
 532                                if (devc->ad_mixer_dev != NO_WSS_MIXER)
 533                                        return call_ad_mixer(devc, cmd, arg);
 534                                else
 535                                {
 536                                        int v;
 537                                        if (get_user(v, (int __user *)arg))
 538                                                return -EFAULT;
 539                                        if (v != 0)
 540                                                return -EINVAL;
 541                                        return 0;
 542                                }
 543                        case SOUND_MIXER_VOLUME:
 544                                if (set_volume_stereo(arg,
 545                                        &devc->mixer.volume_l,
 546                                        &devc->mixer.volume_r))
 547                                        return -EFAULT;
 548                                set_master_volume(devc, devc->mixer.volume_l,
 549                                        devc->mixer.volume_r);
 550                                return ret_vol_stereo(devc->mixer.volume_l,
 551                                        devc->mixer.volume_r);
 552                  
 553                        case SOUND_MIXER_BASS:
 554                                if (set_volume_mono(arg, &devc->mixer.bass))
 555                                        return -EFAULT;
 556                                set_bass(devc, devc->mixer.bass);
 557                                return ret_vol_mono(devc->mixer.bass);
 558                  
 559                        case SOUND_MIXER_TREBLE:
 560                                if (set_volume_mono(arg, &devc->mixer.treble))
 561                                        return -EFAULT;
 562                                set_treble(devc, devc->mixer.treble);
 563                                return ret_vol_mono(devc->mixer.treble);
 564                  
 565                        case SOUND_MIXER_SYNTH:
 566                                if (set_volume_mono(arg, &devc->mixer.synth))
 567                                        return -EFAULT;
 568                                set_synth_volume(devc, devc->mixer.synth);
 569                                return ret_vol_mono(devc->mixer.synth);
 570                  
 571                        default:
 572                                return -EINVAL;
 573                }
 574        }
 575        else                    
 576        {
 577                int val, and_mask = 0, or_mask = 0;
 578                /*
 579                 * Return parameters
 580                 */
 581                switch (cmdf)
 582                {
 583                        case SOUND_MIXER_DEVMASK:
 584                                if (call_ad_mixer(devc, cmd, arg) == -EINVAL)
 585                                        break;
 586                                and_mask = ~0;
 587                                or_mask = SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_SYNTH;
 588                                break;
 589                  
 590                        case SOUND_MIXER_STEREODEVS:
 591                                if (call_ad_mixer(devc, cmd, arg) == -EINVAL)
 592                                        break;
 593                                and_mask = ~0;
 594                                or_mask = SOUND_MASK_VOLUME;
 595                                break;
 596                  
 597                        case SOUND_MIXER_RECMASK:
 598                                if (devc->ad_mixer_dev != NO_WSS_MIXER)
 599                                        return call_ad_mixer(devc, cmd, arg);
 600                                break;
 601
 602                        case SOUND_MIXER_CAPS:
 603                                if (devc->ad_mixer_dev != NO_WSS_MIXER)
 604                                        return call_ad_mixer(devc, cmd, arg);
 605                                or_mask = SOUND_CAP_EXCL_INPUT;
 606                                break;
 607
 608                        case SOUND_MIXER_RECSRC:
 609                                if (devc->ad_mixer_dev != NO_WSS_MIXER)
 610                                        return call_ad_mixer(devc, cmd, arg);
 611                                break;
 612
 613                        case SOUND_MIXER_VOLUME:
 614                                or_mask =  ret_vol_stereo(devc->mixer.volume_l, devc->mixer.volume_r);
 615                                break;
 616                          
 617                        case SOUND_MIXER_BASS:
 618                                or_mask =  ret_vol_mono(devc->mixer.bass);
 619                                break;
 620                          
 621                        case SOUND_MIXER_TREBLE:
 622                                or_mask = ret_vol_mono(devc->mixer.treble);
 623                                break;
 624                          
 625                        case SOUND_MIXER_SYNTH:
 626                                or_mask = ret_vol_mono(devc->mixer.synth);
 627                                break;
 628                        default:
 629                                return -EINVAL;
 630                }
 631                if (get_user(val, (int __user *)arg))
 632                        return -EFAULT;
 633                val &= and_mask;
 634                val |= or_mask;
 635                if (put_user(val, (int __user *)arg))
 636                        return -EFAULT;
 637                return val;
 638        }
 639}
 640
 641static struct mixer_operations pss_mixer_operations =
 642{
 643        .owner  = THIS_MODULE,
 644        .id     = "SOUNDPORT",
 645        .name   = "PSS-AD1848",
 646        .ioctl  = pss_mixer_ioctl
 647};
 648
 649static void disable_all_emulations(void)
 650{
 651        outw(0x0000, REG(CONF_PSS));    /* 0x0400 enables joystick */
 652        outw(0x0000, REG(CONF_WSS));
 653        outw(0x0000, REG(CONF_SB));
 654        outw(0x0000, REG(CONF_MIDI));
 655        outw(0x0000, REG(CONF_CDROM));
 656}
 657
 658static void configure_nonsound_components(void)
 659{
 660        /* Configure Joystick port */
 661
 662        if(pss_enable_joystick)
 663        {
 664                outw(0x0400, REG(CONF_PSS));    /* 0x0400 enables joystick */
 665                printk(KERN_INFO "PSS: joystick enabled.\n");
 666        }
 667        else
 668        {
 669                printk(KERN_INFO "PSS: joystick port not enabled.\n");
 670        }
 671
 672        /* Configure CDROM port */
 673
 674        if (pss_cdrom_port == -1) {     /* If cdrom port enablation wasn't requested */
 675                printk(KERN_INFO "PSS: CDROM port not enabled.\n");
 676        } else if (check_region(pss_cdrom_port, 2)) {
 677                printk(KERN_ERR "PSS: CDROM I/O port conflict.\n");
 678        } else {
 679                set_io_base(devc, CONF_CDROM, pss_cdrom_port);
 680                printk(KERN_INFO "PSS: CDROM I/O port set to 0x%x.\n", pss_cdrom_port);
 681        }
 682}
 683
 684static int __init attach_pss(struct address_info *hw_config)
 685{
 686        unsigned short  id;
 687        char tmp[100];
 688
 689        devc->base = hw_config->io_base;
 690        devc->irq = hw_config->irq;
 691        devc->dma = hw_config->dma;
 692        devc->osp = hw_config->osp;
 693        devc->ad_mixer_dev = NO_WSS_MIXER;
 694
 695        if (!probe_pss(hw_config))
 696                return 0;
 697
 698        id = inw(REG(PSS_ID)) & 0x00ff;
 699
 700        /*
 701         * Disable all emulations. Will be enabled later (if required).
 702         */
 703         
 704        disable_all_emulations();
 705
 706#ifdef YOU_REALLY_WANT_TO_ALLOCATE_THESE_RESOURCES
 707        if (sound_alloc_dma(hw_config->dma, "PSS"))
 708        {
 709                printk("pss.c: Can't allocate DMA channel.\n");
 710                release_region(hw_config->io_base, 0x10);
 711                release_region(hw_config->io_base+0x10, 0x9);
 712                return 0;
 713        }
 714        if (!set_irq(devc, CONF_PSS, devc->irq))
 715        {
 716                printk("PSS: IRQ allocation error.\n");
 717                release_region(hw_config->io_base, 0x10);
 718                release_region(hw_config->io_base+0x10, 0x9);
 719                return 0;
 720        }
 721        if (!set_dma(devc, CONF_PSS, devc->dma))
 722        {
 723                printk(KERN_ERR "PSS: DMA allocation error\n");
 724                release_region(hw_config->io_base, 0x10);
 725                release_region(hw_config->io_base+0x10, 0x9);
 726                return 0;
 727        }
 728#endif
 729
 730        configure_nonsound_components();
 731        pss_initialized = 1;
 732        sprintf(tmp, "ECHO-PSS  Rev. %d", id);
 733        conf_printf(tmp, hw_config);
 734        return 1;
 735}
 736
 737static int __init probe_pss_mpu(struct address_info *hw_config)
 738{
 739        struct resource *ports;
 740        int timeout;
 741
 742        if (!pss_initialized)
 743                return 0;
 744
 745        ports = request_region(hw_config->io_base, 2, "mpu401");
 746
 747        if (!ports) {
 748                printk(KERN_ERR "PSS: MPU I/O port conflict\n");
 749                return 0;
 750        }
 751        set_io_base(devc, CONF_MIDI, hw_config->io_base);
 752        if (!set_irq(devc, CONF_MIDI, hw_config->irq)) {
 753                printk(KERN_ERR "PSS: MIDI IRQ allocation error.\n");
 754                goto fail;
 755        }
 756        if (!pss_synthLen) {
 757                printk(KERN_ERR "PSS: Can't enable MPU. MIDI synth microcode not available.\n");
 758                goto fail;
 759        }
 760        if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) {
 761                printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n");
 762                goto fail;
 763        }
 764
 765        /*
 766         * Finally wait until the DSP algorithm has initialized itself and
 767         * deactivates receive interrupt.
 768         */
 769
 770        for (timeout = 900000; timeout > 0; timeout--)
 771        {
 772                if ((inb(hw_config->io_base + 1) & 0x80) == 0)  /* Input data avail */
 773                        inb(hw_config->io_base);        /* Discard it */
 774                else
 775                        break;  /* No more input */
 776        }
 777
 778        if (!probe_mpu401(hw_config, ports))
 779                goto fail;
 780
 781        attach_mpu401(hw_config, THIS_MODULE);  /* Slot 1 */
 782        if (hw_config->slots[1] != -1)  /* The MPU driver installed itself */
 783                midi_devs[hw_config->slots[1]]->coproc = &pss_coproc_operations;
 784        return 1;
 785fail:
 786        release_region(hw_config->io_base, 2);
 787        return 0;
 788}
 789
 790static int pss_coproc_open(void *dev_info, int sub_device)
 791{
 792        switch (sub_device)
 793        {
 794                case COPR_MIDI:
 795                        if (pss_synthLen == 0)
 796                        {
 797                                printk(KERN_ERR "PSS: MIDI synth microcode not available.\n");
 798                                return -EIO;
 799                        }
 800                        if (nonstandard_microcode)
 801                                if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST))
 802                        {
 803                                printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n");
 804                                return -EIO;
 805                        }
 806                        nonstandard_microcode = 0;
 807                        break;
 808
 809                default:
 810                        break;
 811        }
 812        return 0;
 813}
 814
 815static void pss_coproc_close(void *dev_info, int sub_device)
 816{
 817        return;
 818}
 819
 820static void pss_coproc_reset(void *dev_info)
 821{
 822        if (pss_synthLen)
 823                if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST))
 824                {
 825                        printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n");
 826                }
 827        nonstandard_microcode = 0;
 828}
 829
 830static int download_boot_block(void *dev_info, copr_buffer * buf)
 831{
 832        if (buf->len <= 0 || buf->len > sizeof(buf->data))
 833                return -EINVAL;
 834
 835        if (!pss_download_boot(devc, buf->data, buf->len, buf->flags))
 836        {
 837                printk(KERN_ERR "PSS: Unable to load microcode block to DSP.\n");
 838                return -EIO;
 839        }
 840        nonstandard_microcode = 1;      /* The MIDI microcode has been overwritten */
 841        return 0;
 842}
 843
 844static int pss_coproc_ioctl(void *dev_info, unsigned int cmd, void __user *arg, int local)
 845{
 846        copr_buffer *buf;
 847        copr_msg *mbuf;
 848        copr_debug_buf dbuf;
 849        unsigned short tmp;
 850        unsigned long flags;
 851        unsigned short *data;
 852        int i, err;
 853        /* printk( "PSS coproc ioctl %x %x %d\n",  cmd,  arg,  local); */
 854        
 855        switch (cmd) 
 856        {
 857                case SNDCTL_COPR_RESET:
 858                        pss_coproc_reset(dev_info);
 859                        return 0;
 860
 861                case SNDCTL_COPR_LOAD:
 862                        buf = vmalloc(sizeof(copr_buffer));
 863                        if (buf == NULL)
 864                                return -ENOSPC;
 865                        if (copy_from_user(buf, arg, sizeof(copr_buffer))) {
 866                                vfree(buf);
 867                                return -EFAULT;
 868                        }
 869                        err = download_boot_block(dev_info, buf);
 870                        vfree(buf);
 871                        return err;
 872                
 873                case SNDCTL_COPR_SENDMSG:
 874                        mbuf = vmalloc(sizeof(copr_msg));
 875                        if (mbuf == NULL)
 876                                return -ENOSPC;
 877                        if (copy_from_user(mbuf, arg, sizeof(copr_msg))) {
 878                                vfree(mbuf);
 879                                return -EFAULT;
 880                        }
 881                        data = (unsigned short *)(mbuf->data);
 882                        spin_lock_irqsave(&lock, flags);
 883                        for (i = 0; i < mbuf->len; i++) {
 884                                if (!pss_put_dspword(devc, *data++)) {
 885                                        spin_unlock_irqrestore(&lock,flags);
 886                                        mbuf->len = i;  /* feed back number of WORDs sent */
 887                                        err = copy_to_user(arg, mbuf, sizeof(copr_msg));
 888                                        vfree(mbuf);
 889                                        return err ? -EFAULT : -EIO;
 890                                }
 891                        }
 892                        spin_unlock_irqrestore(&lock,flags);
 893                        vfree(mbuf);
 894                        return 0;
 895
 896                case SNDCTL_COPR_RCVMSG:
 897                        err = 0;
 898                        mbuf = vmalloc(sizeof(copr_msg));
 899                        if (mbuf == NULL)
 900                                return -ENOSPC;
 901                        data = (unsigned short *)mbuf->data;
 902                        spin_lock_irqsave(&lock, flags);
 903                        for (i = 0; i < sizeof(mbuf->data)/sizeof(unsigned short); i++) {
 904                                mbuf->len = i;  /* feed back number of WORDs read */
 905                                if (!pss_get_dspword(devc, data++)) {
 906                                        if (i == 0)
 907                                                err = -EIO;
 908                                        break;
 909                                }
 910                        }
 911                        spin_unlock_irqrestore(&lock,flags);
 912                        if (copy_to_user(arg, mbuf, sizeof(copr_msg)))
 913                                err = -EFAULT;
 914                        vfree(mbuf);
 915                        return err;
 916                
 917                case SNDCTL_COPR_RDATA:
 918                        if (copy_from_user(&dbuf, arg, sizeof(dbuf)))
 919                                return -EFAULT;
 920                        spin_lock_irqsave(&lock, flags);
 921                        if (!pss_put_dspword(devc, 0x00d0)) {
 922                                spin_unlock_irqrestore(&lock,flags);
 923                                return -EIO;
 924                        }
 925                        if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) {
 926                                spin_unlock_irqrestore(&lock,flags);
 927                                return -EIO;
 928                        }
 929                        if (!pss_get_dspword(devc, &tmp)) {
 930                                spin_unlock_irqrestore(&lock,flags);
 931                                return -EIO;
 932                        }
 933                        dbuf.parm1 = tmp;
 934                        spin_unlock_irqrestore(&lock,flags);
 935                        if (copy_to_user(arg, &dbuf, sizeof(dbuf)))
 936                                return -EFAULT;
 937                        return 0;
 938                
 939                case SNDCTL_COPR_WDATA:
 940                        if (copy_from_user(&dbuf, arg, sizeof(dbuf)))
 941                                return -EFAULT;
 942                        spin_lock_irqsave(&lock, flags);
 943                        if (!pss_put_dspword(devc, 0x00d1)) {
 944                                spin_unlock_irqrestore(&lock,flags);
 945                                return -EIO;
 946                        }
 947                        if (!pss_put_dspword(devc, (unsigned short) (dbuf.parm1 & 0xffff))) {
 948                                spin_unlock_irqrestore(&lock,flags);
 949                                return -EIO;
 950                        }
 951                        tmp = (unsigned int)dbuf.parm2 & 0xffff;
 952                        if (!pss_put_dspword(devc, tmp)) {
 953                                spin_unlock_irqrestore(&lock,flags);
 954                                return -EIO;
 955                        }
 956                        spin_unlock_irqrestore(&lock,flags);
 957                        return 0;
 958                
 959                case SNDCTL_COPR_WCODE:
 960                        if (copy_from_user(&dbuf, arg, sizeof(dbuf)))
 961                                return -EFAULT;
 962                        spin_lock_irqsave(&lock, flags);
 963                        if (!pss_put_dspword(devc, 0x00d3)) {
 964                                spin_unlock_irqrestore(&lock,flags);
 965                                return -EIO;
 966                        }
 967                        if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) {
 968                                spin_unlock_irqrestore(&lock,flags);
 969                                return -EIO;
 970                        }
 971                        tmp = (unsigned int)dbuf.parm2 & 0x00ff;
 972                        if (!pss_put_dspword(devc, tmp)) {
 973                                spin_unlock_irqrestore(&lock,flags);
 974                                return -EIO;
 975                        }
 976                        tmp = ((unsigned int)dbuf.parm2 >> 8) & 0xffff;
 977                        if (!pss_put_dspword(devc, tmp)) {
 978                                spin_unlock_irqrestore(&lock,flags);
 979                                return -EIO;
 980                        }
 981                        spin_unlock_irqrestore(&lock,flags);
 982                        return 0;
 983                
 984                case SNDCTL_COPR_RCODE:
 985                        if (copy_from_user(&dbuf, arg, sizeof(dbuf)))
 986                                return -EFAULT;
 987                        spin_lock_irqsave(&lock, flags);
 988                        if (!pss_put_dspword(devc, 0x00d2)) {
 989                                spin_unlock_irqrestore(&lock,flags);
 990                                return -EIO;
 991                        }
 992                        if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) {
 993                                spin_unlock_irqrestore(&lock,flags);
 994                                return -EIO;
 995                        }
 996                        if (!pss_get_dspword(devc, &tmp)) { /* Read MSB */
 997                                spin_unlock_irqrestore(&lock,flags);
 998                                return -EIO;
 999                        }
1000                        dbuf.parm1 = tmp << 8;
1001                        if (!pss_get_dspword(devc, &tmp)) { /* Read LSB */
1002                                spin_unlock_irqrestore(&lock,flags);
1003                                return -EIO;
1004                        }
1005                        dbuf.parm1 |= tmp & 0x00ff;
1006                        spin_unlock_irqrestore(&lock,flags);
1007                        if (copy_to_user(arg, &dbuf, sizeof(dbuf)))
1008                                return -EFAULT;
1009                        return 0;
1010
1011                default:
1012                        return -EINVAL;
1013        }
1014        return -EINVAL;
1015}
1016
1017static coproc_operations pss_coproc_operations =
1018{
1019        "ADSP-2115",
1020        THIS_MODULE,
1021        pss_coproc_open,
1022        pss_coproc_close,
1023        pss_coproc_ioctl,
1024        pss_coproc_reset,
1025        &pss_data
1026};
1027
1028static int __init probe_pss_mss(struct address_info *hw_config)
1029{
1030        volatile int timeout;
1031        struct resource *ports;
1032        int        my_mix = -999;       /* gcc shut up */
1033
1034        if (!pss_initialized)
1035                return 0;
1036
1037        if (!request_region(hw_config->io_base, 4, "WSS config")) {
1038                printk(KERN_ERR "PSS: WSS I/O port conflicts.\n");
1039                return 0;
1040        }
1041        ports = request_region(hw_config->io_base + 4, 4, "ad1848");
1042        if (!ports) {
1043                printk(KERN_ERR "PSS: WSS I/O port conflicts.\n");
1044                release_region(hw_config->io_base, 4);
1045                return 0;
1046        }
1047        set_io_base(devc, CONF_WSS, hw_config->io_base);
1048        if (!set_irq(devc, CONF_WSS, hw_config->irq)) {
1049                printk("PSS: WSS IRQ allocation error.\n");
1050                goto fail;
1051        }
1052        if (!set_dma(devc, CONF_WSS, hw_config->dma)) {
1053                printk(KERN_ERR "PSS: WSS DMA allocation error\n");
1054                goto fail;
1055        }
1056        /*
1057         * For some reason the card returns 0xff in the WSS status register
1058         * immediately after boot. Probably MIDI+SB emulation algorithm
1059         * downloaded to the ADSP2115 spends some time initializing the card.
1060         * Let's try to wait until it finishes this task.
1061         */
1062        for (timeout = 0; timeout < 100000 && (inb(hw_config->io_base + WSS_INDEX) &
1063          WSS_INITIALIZING); timeout++)
1064                ;
1065
1066        outb((0x0b), hw_config->io_base + WSS_INDEX);   /* Required by some cards */
1067
1068        for (timeout = 0; (inb(hw_config->io_base + WSS_DATA) & WSS_AUTOCALIBRATION) &&
1069          (timeout < 100000); timeout++)
1070                ;
1071
1072        if (!probe_ms_sound(hw_config, ports))
1073                goto fail;
1074
1075        devc->ad_mixer_dev = NO_WSS_MIXER;
1076        if (pss_mixer) 
1077        {
1078                if ((my_mix = sound_install_mixer (MIXER_DRIVER_VERSION,
1079                        "PSS-SPEAKERS and AD1848 (through MSS audio codec)",
1080                        &pss_mixer_operations,
1081                        sizeof (struct mixer_operations),
1082                        devc)) < 0) 
1083                {
1084                        printk(KERN_ERR "Could not install PSS mixer\n");
1085                        goto fail;
1086                }
1087        }
1088        pss_mixer_reset(devc);
1089        attach_ms_sound(hw_config, ports, THIS_MODULE); /* Slot 0 */
1090
1091        if (hw_config->slots[0] != -1)
1092        {
1093                /* The MSS driver installed itself */
1094                audio_devs[hw_config->slots[0]]->coproc = &pss_coproc_operations;
1095                if (pss_mixer && (num_mixers == (my_mix + 2)))
1096                {
1097                        /* The MSS mixer installed */
1098                        devc->ad_mixer_dev = audio_devs[hw_config->slots[0]]->mixer_dev;
1099                }
1100        }
1101        return 1;
1102fail:
1103        release_region(hw_config->io_base + 4, 4);
1104        release_region(hw_config->io_base, 4);
1105        return 0;
1106}
1107
1108static inline void __exit unload_pss(struct address_info *hw_config)
1109{
1110        release_region(hw_config->io_base, 0x10);
1111        release_region(hw_config->io_base+0x10, 0x9);
1112}
1113
1114static inline void __exit unload_pss_mpu(struct address_info *hw_config)
1115{
1116        unload_mpu401(hw_config);
1117}
1118
1119static inline void __exit unload_pss_mss(struct address_info *hw_config)
1120{
1121        unload_ms_sound(hw_config);
1122}
1123
1124
1125static struct address_info cfg;
1126static struct address_info cfg2;
1127static struct address_info cfg_mpu;
1128
1129static int pss_io __initdata    = -1;
1130static int mss_io __initdata    = -1;
1131static int mss_irq __initdata   = -1;
1132static int mss_dma __initdata   = -1;
1133static int mpu_io __initdata    = -1;
1134static int mpu_irq __initdata   = -1;
1135static int pss_no_sound = 0;    /* Just configure non-sound components */
1136static int pss_keep_settings  = 1;      /* Keep hardware settings at module exit */
1137static char *pss_firmware = "/etc/sound/pss_synth";
1138
1139module_param(pss_io, int, 0);
1140MODULE_PARM_DESC(pss_io, "Set i/o base of PSS card (probably 0x220 or 0x240)");
1141module_param(mss_io, int, 0);
1142MODULE_PARM_DESC(mss_io, "Set WSS (audio) i/o base (0x530, 0x604, 0xE80, 0xF40, or other. Address must end in 0 or 4 and must be from 0x100 to 0xFF4)");
1143module_param(mss_irq, int, 0);
1144MODULE_PARM_DESC(mss_irq, "Set WSS (audio) IRQ (3, 5, 7, 9, 10, 11, 12)");
1145module_param(mss_dma, int, 0);
1146MODULE_PARM_DESC(mss_dma, "Set WSS (audio) DMA (0, 1, 3)");
1147module_param(mpu_io, int, 0);
1148MODULE_PARM_DESC(mpu_io, "Set MIDI i/o base (0x330 or other. Address must be on 4 location boundaries and must be from 0x100 to 0xFFC)");
1149module_param(mpu_irq, int, 0);
1150MODULE_PARM_DESC(mpu_irq, "Set MIDI IRQ (3, 5, 7, 9, 10, 11, 12)");
1151module_param(pss_cdrom_port, int, 0);
1152MODULE_PARM_DESC(pss_cdrom_port, "Set the PSS CDROM port i/o base (0x340 or other)");
1153module_param(pss_enable_joystick, bool, 0);
1154MODULE_PARM_DESC(pss_enable_joystick, "Enables the PSS joystick port (1 to enable, 0 to disable)");
1155module_param(pss_no_sound, bool, 0);
1156MODULE_PARM_DESC(pss_no_sound, "Configure sound compoents (0 - no, 1 - yes)");
1157module_param(pss_keep_settings, bool, 0);
1158MODULE_PARM_DESC(pss_keep_settings, "Keep hardware setting at driver unloading (0 - no, 1 - yes)");
1159module_param(pss_firmware, charp, 0);
1160MODULE_PARM_DESC(pss_firmware, "Location of the firmware file (default - /etc/sound/pss_synth)");
1161module_param(pss_mixer, bool, 0);
1162MODULE_PARM_DESC(pss_mixer, "Enable (1) or disable (0) PSS mixer (controlling of output volume, bass, treble, synth volume). The mixer is not available on all PSS cards.");
1163MODULE_AUTHOR("Hannu Savolainen, Vladimir Michl");
1164MODULE_DESCRIPTION("Module for PSS sound cards (based on AD1848, ADSP-2115 and ESC614). This module includes control of output amplifier and synth volume of the Beethoven ADSP-16 card (this may work with other PSS cards).");
1165MODULE_LICENSE("GPL");
1166
1167
1168static int fw_load = 0;
1169static int pssmpu = 0, pssmss = 0;
1170
1171/*
1172 *    Load a PSS sound card module
1173 */
1174
1175static int __init init_pss(void)
1176{
1177
1178        if(pss_no_sound)                /* If configuring only nonsound components */
1179        {
1180                cfg.io_base = pss_io;
1181                if(!probe_pss(&cfg))
1182                        return -ENODEV;
1183                printk(KERN_INFO "ECHO-PSS  Rev. %d\n", inw(REG(PSS_ID)) & 0x00ff);
1184                printk(KERN_INFO "PSS: loading in no sound mode.\n");
1185                disable_all_emulations();
1186                configure_nonsound_components();
1187                release_region(pss_io, 0x10);
1188                release_region(pss_io + 0x10, 0x9);
1189                return 0;
1190        }
1191
1192        cfg.io_base = pss_io;
1193
1194        cfg2.io_base = mss_io;
1195        cfg2.irq = mss_irq;
1196        cfg2.dma = mss_dma;
1197
1198        cfg_mpu.io_base = mpu_io;
1199        cfg_mpu.irq = mpu_irq;
1200
1201        if (cfg.io_base == -1 || cfg2.io_base == -1 || cfg2.irq == -1 || cfg.dma == -1) {
1202                printk(KERN_INFO "pss: mss_io, mss_dma, mss_irq and pss_io must be set.\n");
1203                return -EINVAL;
1204        }
1205
1206        if (!pss_synth) {
1207                fw_load = 1;
1208                pss_synthLen = mod_firmware_load(pss_firmware, (void *) &pss_synth);
1209        }
1210        if (!attach_pss(&cfg))
1211                return -ENODEV;
1212        /*
1213         *    Attach stuff
1214         */
1215        if (probe_pss_mpu(&cfg_mpu))
1216                pssmpu = 1;
1217
1218        if (probe_pss_mss(&cfg2))
1219                pssmss = 1;
1220
1221        return 0;
1222}
1223
1224static void __exit cleanup_pss(void)
1225{
1226        if(!pss_no_sound)
1227        {
1228                if(fw_load && pss_synth)
1229                        vfree(pss_synth);
1230                if(pssmss)
1231                        unload_pss_mss(&cfg2);
1232                if(pssmpu)
1233                        unload_pss_mpu(&cfg_mpu);
1234                unload_pss(&cfg);
1235        }
1236
1237        if(!pss_keep_settings)  /* Keep hardware settings if asked */
1238        {
1239                disable_all_emulations();
1240                printk(KERN_INFO "Resetting PSS sound card configurations.\n");
1241        }
1242}
1243
1244module_init(init_pss);
1245module_exit(cleanup_pss);
1246
1247#ifndef MODULE
1248static int __init setup_pss(char *str)
1249{
1250        /* io, mss_io, mss_irq, mss_dma, mpu_io, mpu_irq */
1251        int ints[7];
1252        
1253        str = get_options(str, ARRAY_SIZE(ints), ints);
1254
1255        pss_io  = ints[1];
1256        mss_io  = ints[2];
1257        mss_irq = ints[3];
1258        mss_dma = ints[4];
1259        mpu_io  = ints[5];
1260        mpu_irq = ints[6];
1261
1262        return 1;
1263}
1264
1265__setup("pss=", setup_pss);
1266#endif
1267