Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.9.
   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 bool pss_mixer = 1;
 121#else
 122static bool pss_mixer;
 123#endif
 124
 125
 126struct 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};
 133
 134struct pss_confdata {
 135	int             base;
 136	int             irq;
 137	int             dma;
 138	int            *osp;
 139	struct pss_mixerdata mixer;
 140	int             ad_mixer_dev;
 141};
 142  
 143static struct pss_confdata pss_data;
 144static struct 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 bool	pss_enable_joystick;    /* Parameter for enabling the joystick */
 151static coproc_operations pss_coproc_operations;
 152
 153static void pss_write(struct 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(struct 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(struct 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(struct 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(struct 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(struct 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(struct 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(struct pss_confdata *devc, unsigned char *block,
 311			     int size, int flags)
 312{
 313	int i, val, count;
 314	unsigned long limit;
 315
 316	if (flags & CPF_FIRST)
 317	{
 318/*_____ Warn DSP software that a boot is coming */
 319		outw(0x00fe, REG(PSS_DATA));
 320
 321		limit = jiffies + HZ/10;
 322		for (i = 0; i < 32768 && time_before(jiffies, limit); i++)
 323			if (inw(REG(PSS_DATA)) == 0x5500)
 324				break;
 325
 326		outw(*block++, REG(PSS_DATA));
 327		pss_reset_dsp(devc);
 328	}
 329	count = 1;
 330	while ((flags&CPF_LAST) || count<size )
 331	{
 332		int j;
 333
 334		for (j = 0; j < 327670; j++)
 335		{
 336/*_____ Wait for BG to appear */
 337			if (inw(REG(PSS_STATUS)) & PSS_FLAG3)
 338				break;
 339		}
 340
 341		if (j == 327670)
 342		{
 343			/* It's ok we timed out when the file was empty */
 344			if (count >= size && flags & CPF_LAST)
 345				break;
 346			else
 347			{
 348				printk("\n");
 349				printk(KERN_ERR "PSS: Download timeout problems, byte %d=%d\n", count, size);
 350				return 0;
 351			}
 352		}
 353/*_____ Send the next byte */
 354		if (count >= size) 
 355		{
 356			/* If not data in block send 0xffff */
 357			outw (0xffff, REG (PSS_DATA));
 358		}
 359		else
 360		{
 361			/*_____ Send the next byte */
 362			outw (*block++, REG (PSS_DATA));
 363		}
 364		count++;
 365	}
 366
 367	if (flags & CPF_LAST)
 368	{
 369/*_____ Why */
 370		outw(0, REG(PSS_DATA));
 371
 372		limit = jiffies + HZ/10;
 373		for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++)
 374			val = inw(REG(PSS_STATUS));
 375
 376		limit = jiffies + HZ/10;
 377		for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++)
 378		{
 379			val = inw(REG(PSS_STATUS));
 380			if (val & 0x4000)
 381				break;
 382		}
 383
 384		/* now read the version */
 385		for (i = 0; i < 32000; i++)
 386		{
 387			val = inw(REG(PSS_STATUS));
 388			if (val & PSS_READ_FULL)
 389				break;
 390		}
 391		if (i == 32000)
 392			return 0;
 393
 394		val = inw(REG(PSS_DATA));
 395		/* printk( "<PSS: microcode version %d.%d loaded>",  val/16,  val % 16); */
 396	}
 397	return 1;
 398}
 399
 400/* Mixer */
 401static void set_master_volume(struct pss_confdata *devc, int left, int right)
 402{
 403	static unsigned char log_scale[101] =  {
 404		0xdb, 0xe0, 0xe3, 0xe5, 0xe7, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xee,
 405		0xef, 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3,
 406		0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7,
 407		0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9,
 408		0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb,
 409		0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
 410		0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd,
 411		0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
 412		0xfe, 0xfe, 0xff, 0xff, 0xff
 413	};
 414	pss_write(devc, 0x0010);
 415	pss_write(devc, log_scale[left] | 0x0000);
 416	pss_write(devc, 0x0010);
 417	pss_write(devc, log_scale[right] | 0x0100);
 418}
 419
 420static void set_synth_volume(struct pss_confdata *devc, int volume)
 421{
 422	int vol = ((0x8000*volume)/100L);
 423	pss_write(devc, 0x0080);
 424	pss_write(devc, vol);
 425	pss_write(devc, 0x0081);
 426	pss_write(devc, vol);
 427}
 428
 429static void set_bass(struct pss_confdata *devc, int level)
 430{
 431	int vol = (int)(((0xfd - 0xf0) * level)/100L) + 0xf0;
 432	pss_write(devc, 0x0010);
 433	pss_write(devc, vol | 0x0200);
 434};
 435
 436static void set_treble(struct pss_confdata *devc, int level)
 437{	
 438	int vol = (((0xfd - 0xf0) * level)/100L) + 0xf0;
 439	pss_write(devc, 0x0010);
 440	pss_write(devc, vol | 0x0300);
 441};
 442
 443static void pss_mixer_reset(struct pss_confdata *devc)
 444{
 445	set_master_volume(devc, 33, 33);
 446	set_bass(devc, 50);
 447	set_treble(devc, 50);
 448	set_synth_volume(devc, 30);
 449	pss_write (devc, 0x0010);
 450	pss_write (devc, 0x0800 | 0xce);	/* Stereo */
 451	
 452	if(pss_mixer)
 453	{
 454		devc->mixer.volume_l = devc->mixer.volume_r = 33;
 455		devc->mixer.bass = 50;
 456		devc->mixer.treble = 50;
 457		devc->mixer.synth = 30;
 458	}
 459}
 460
 461static int set_volume_mono(unsigned __user *p, unsigned int *aleft)
 462{
 463	unsigned int left, volume;
 464	if (get_user(volume, p))
 465		return -EFAULT;
 466	
 467	left = volume & 0xff;
 468	if (left > 100)
 469		left = 100;
 470	*aleft = left;
 471	return 0;
 472}
 473
 474static int set_volume_stereo(unsigned __user *p,
 475			     unsigned int *aleft,
 476			     unsigned int *aright)
 477{
 478	unsigned int left, right, volume;
 479	if (get_user(volume, p))
 480		return -EFAULT;
 481
 482	left = volume & 0xff;
 483	if (left > 100)
 484		left = 100;
 485	right = (volume >> 8) & 0xff;
 486	if (right > 100)
 487		right = 100;
 488	*aleft = left;
 489	*aright = right;
 490	return 0;
 491}
 492
 493static int ret_vol_mono(int left)
 494{
 495	return ((left << 8) | left);
 496}
 497
 498static int ret_vol_stereo(int left, int right)
 499{
 500	return ((right << 8) | left);
 501}
 502
 503static int call_ad_mixer(struct pss_confdata *devc, unsigned int cmd,
 504			 void __user *arg)
 505{
 506	if (devc->ad_mixer_dev != NO_WSS_MIXER) 
 507		return mixer_devs[devc->ad_mixer_dev]->ioctl(devc->ad_mixer_dev, cmd, arg);
 508	else 
 509		return -EINVAL;
 510}
 511
 512static int pss_mixer_ioctl (int dev, unsigned int cmd, void __user *arg)
 513{
 514	struct pss_confdata *devc = mixer_devs[dev]->devc;
 515	int cmdf = cmd & 0xff;
 516	
 517	if ((cmdf != SOUND_MIXER_VOLUME) && (cmdf != SOUND_MIXER_BASS) &&
 518		(cmdf != SOUND_MIXER_TREBLE) && (cmdf != SOUND_MIXER_SYNTH) &&
 519		(cmdf != SOUND_MIXER_DEVMASK) && (cmdf != SOUND_MIXER_STEREODEVS) &&
 520		(cmdf != SOUND_MIXER_RECMASK) && (cmdf != SOUND_MIXER_CAPS) &&
 521		(cmdf != SOUND_MIXER_RECSRC)) 
 522	{
 523		return call_ad_mixer(devc, cmd, arg);
 524	}
 525	
 526	if (((cmd >> 8) & 0xff) != 'M')	
 527		return -EINVAL;
 528		
 529	if (_SIOC_DIR (cmd) & _SIOC_WRITE)
 530	{
 531		switch (cmdf)	
 532		{
 533			case SOUND_MIXER_RECSRC:
 534				if (devc->ad_mixer_dev != NO_WSS_MIXER)
 535					return call_ad_mixer(devc, cmd, arg);
 536				else
 537				{
 538					int v;
 539					if (get_user(v, (int __user *)arg))
 540						return -EFAULT;
 541					if (v != 0)
 542						return -EINVAL;
 543					return 0;
 544				}
 545			case SOUND_MIXER_VOLUME:
 546				if (set_volume_stereo(arg,
 547					&devc->mixer.volume_l,
 548					&devc->mixer.volume_r))
 549					return -EFAULT;
 550				set_master_volume(devc, devc->mixer.volume_l,
 551					devc->mixer.volume_r);
 552				return ret_vol_stereo(devc->mixer.volume_l,
 553					devc->mixer.volume_r);
 554		  
 555			case SOUND_MIXER_BASS:
 556				if (set_volume_mono(arg, &devc->mixer.bass))
 557					return -EFAULT;
 558				set_bass(devc, devc->mixer.bass);
 559				return ret_vol_mono(devc->mixer.bass);
 560		  
 561			case SOUND_MIXER_TREBLE:
 562				if (set_volume_mono(arg, &devc->mixer.treble))
 563					return -EFAULT;
 564				set_treble(devc, devc->mixer.treble);
 565				return ret_vol_mono(devc->mixer.treble);
 566		  
 567			case SOUND_MIXER_SYNTH:
 568				if (set_volume_mono(arg, &devc->mixer.synth))
 569					return -EFAULT;
 570				set_synth_volume(devc, devc->mixer.synth);
 571				return ret_vol_mono(devc->mixer.synth);
 572		  
 573			default:
 574				return -EINVAL;
 575		}
 576	}
 577	else			
 578	{
 579		int val, and_mask = 0, or_mask = 0;
 580		/*
 581		 * Return parameters
 582		 */
 583		switch (cmdf)
 584		{
 585			case SOUND_MIXER_DEVMASK:
 586				if (call_ad_mixer(devc, cmd, arg) == -EINVAL)
 587					break;
 588				and_mask = ~0;
 589				or_mask = SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_SYNTH;
 590				break;
 591		  
 592			case SOUND_MIXER_STEREODEVS:
 593				if (call_ad_mixer(devc, cmd, arg) == -EINVAL)
 594					break;
 595				and_mask = ~0;
 596				or_mask = SOUND_MASK_VOLUME;
 597				break;
 598		  
 599			case SOUND_MIXER_RECMASK:
 600				if (devc->ad_mixer_dev != NO_WSS_MIXER)
 601					return call_ad_mixer(devc, cmd, arg);
 602				break;
 603
 604			case SOUND_MIXER_CAPS:
 605				if (devc->ad_mixer_dev != NO_WSS_MIXER)
 606					return call_ad_mixer(devc, cmd, arg);
 607				or_mask = SOUND_CAP_EXCL_INPUT;
 608				break;
 609
 610			case SOUND_MIXER_RECSRC:
 611				if (devc->ad_mixer_dev != NO_WSS_MIXER)
 612					return call_ad_mixer(devc, cmd, arg);
 613				break;
 614
 615			case SOUND_MIXER_VOLUME:
 616				or_mask =  ret_vol_stereo(devc->mixer.volume_l, devc->mixer.volume_r);
 617				break;
 618			  
 619			case SOUND_MIXER_BASS:
 620				or_mask =  ret_vol_mono(devc->mixer.bass);
 621				break;
 622			  
 623			case SOUND_MIXER_TREBLE:
 624				or_mask = ret_vol_mono(devc->mixer.treble);
 625				break;
 626			  
 627			case SOUND_MIXER_SYNTH:
 628				or_mask = ret_vol_mono(devc->mixer.synth);
 629				break;
 630			default:
 631				return -EINVAL;
 632		}
 633		if (get_user(val, (int __user *)arg))
 634			return -EFAULT;
 635		val &= and_mask;
 636		val |= or_mask;
 637		if (put_user(val, (int __user *)arg))
 638			return -EFAULT;
 639		return val;
 640	}
 641}
 642
 643static struct mixer_operations pss_mixer_operations =
 644{
 645	.owner	= THIS_MODULE,
 646	.id	= "SOUNDPORT",
 647	.name	= "PSS-AD1848",
 648	.ioctl	= pss_mixer_ioctl
 649};
 650
 651static void disable_all_emulations(void)
 652{
 653	outw(0x0000, REG(CONF_PSS));	/* 0x0400 enables joystick */
 654	outw(0x0000, REG(CONF_WSS));
 655	outw(0x0000, REG(CONF_SB));
 656	outw(0x0000, REG(CONF_MIDI));
 657	outw(0x0000, REG(CONF_CDROM));
 658}
 659
 660static void configure_nonsound_components(void)
 661{
 662	/* Configure Joystick port */
 663
 664	if(pss_enable_joystick)
 665	{
 666		outw(0x0400, REG(CONF_PSS));	/* 0x0400 enables joystick */
 667		printk(KERN_INFO "PSS: joystick enabled.\n");
 668	}
 669	else
 670	{
 671		printk(KERN_INFO "PSS: joystick port not enabled.\n");
 672	}
 673
 674	/* Configure CDROM port */
 675
 676	if (pss_cdrom_port == -1) {	/* If cdrom port enablation wasn't requested */
 677		printk(KERN_INFO "PSS: CDROM port not enabled.\n");
 678	} else if (!request_region(pss_cdrom_port, 2, "PSS CDROM")) {
 679		pss_cdrom_port = -1;
 680		printk(KERN_ERR "PSS: CDROM I/O port conflict.\n");
 681	} else {
 682		set_io_base(devc, CONF_CDROM, pss_cdrom_port);
 683		printk(KERN_INFO "PSS: CDROM I/O port set to 0x%x.\n", pss_cdrom_port);
 684	}
 685}
 686
 687static int __init attach_pss(struct address_info *hw_config)
 688{
 689	unsigned short  id;
 690	char tmp[100];
 691
 692	devc->base = hw_config->io_base;
 693	devc->irq = hw_config->irq;
 694	devc->dma = hw_config->dma;
 695	devc->osp = hw_config->osp;
 696	devc->ad_mixer_dev = NO_WSS_MIXER;
 697
 698	if (!probe_pss(hw_config))
 699		return 0;
 700
 701	id = inw(REG(PSS_ID)) & 0x00ff;
 702
 703	/*
 704	 * Disable all emulations. Will be enabled later (if required).
 705	 */
 706	 
 707	disable_all_emulations();
 708
 709#ifdef YOU_REALLY_WANT_TO_ALLOCATE_THESE_RESOURCES
 710	if (sound_alloc_dma(hw_config->dma, "PSS"))
 711	{
 712		printk("pss.c: Can't allocate DMA channel.\n");
 713		release_region(hw_config->io_base, 0x10);
 714		release_region(hw_config->io_base+0x10, 0x9);
 715		return 0;
 716	}
 717	if (!set_irq(devc, CONF_PSS, devc->irq))
 718	{
 719		printk("PSS: IRQ allocation error.\n");
 720		release_region(hw_config->io_base, 0x10);
 721		release_region(hw_config->io_base+0x10, 0x9);
 722		return 0;
 723	}
 724	if (!set_dma(devc, CONF_PSS, devc->dma))
 725	{
 726		printk(KERN_ERR "PSS: DMA allocation error\n");
 727		release_region(hw_config->io_base, 0x10);
 728		release_region(hw_config->io_base+0x10, 0x9);
 729		return 0;
 730	}
 731#endif
 732
 733	configure_nonsound_components();
 734	pss_initialized = 1;
 735	sprintf(tmp, "ECHO-PSS  Rev. %d", id);
 736	conf_printf(tmp, hw_config);
 737	return 1;
 738}
 739
 740static int __init probe_pss_mpu(struct address_info *hw_config)
 741{
 742	struct resource *ports;
 743	int timeout;
 744
 745	if (!pss_initialized)
 746		return 0;
 747
 748	ports = request_region(hw_config->io_base, 2, "mpu401");
 749
 750	if (!ports) {
 751		printk(KERN_ERR "PSS: MPU I/O port conflict\n");
 752		return 0;
 753	}
 754	set_io_base(devc, CONF_MIDI, hw_config->io_base);
 755	if (!set_irq(devc, CONF_MIDI, hw_config->irq)) {
 756		printk(KERN_ERR "PSS: MIDI IRQ allocation error.\n");
 757		goto fail;
 758	}
 759	if (!pss_synthLen) {
 760		printk(KERN_ERR "PSS: Can't enable MPU. MIDI synth microcode not available.\n");
 761		goto fail;
 762	}
 763	if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) {
 764		printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n");
 765		goto fail;
 766	}
 767
 768	/*
 769	 * Finally wait until the DSP algorithm has initialized itself and
 770	 * deactivates receive interrupt.
 771	 */
 772
 773	for (timeout = 900000; timeout > 0; timeout--)
 774	{
 775		if ((inb(hw_config->io_base + 1) & 0x80) == 0)	/* Input data avail */
 776			inb(hw_config->io_base);	/* Discard it */
 777		else
 778			break;	/* No more input */
 779	}
 780
 781	if (!probe_mpu401(hw_config, ports))
 782		goto fail;
 783
 784	attach_mpu401(hw_config, THIS_MODULE);	/* Slot 1 */
 785	if (hw_config->slots[1] != -1)	/* The MPU driver installed itself */
 786		midi_devs[hw_config->slots[1]]->coproc = &pss_coproc_operations;
 787	return 1;
 788fail:
 789	release_region(hw_config->io_base, 2);
 790	return 0;
 791}
 792
 793static int pss_coproc_open(void *dev_info, int sub_device)
 794{
 795	switch (sub_device)
 796	{
 797		case COPR_MIDI:
 798			if (pss_synthLen == 0)
 799			{
 800				printk(KERN_ERR "PSS: MIDI synth microcode not available.\n");
 801				return -EIO;
 802			}
 803			if (nonstandard_microcode)
 804				if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST))
 805			{
 806				printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n");
 807				return -EIO;
 808			}
 809			nonstandard_microcode = 0;
 810			break;
 811
 812		default:
 813			break;
 814	}
 815	return 0;
 816}
 817
 818static void pss_coproc_close(void *dev_info, int sub_device)
 819{
 820	return;
 821}
 822
 823static void pss_coproc_reset(void *dev_info)
 824{
 825	if (pss_synthLen)
 826		if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST))
 827		{
 828			printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n");
 829		}
 830	nonstandard_microcode = 0;
 831}
 832
 833static int download_boot_block(void *dev_info, copr_buffer * buf)
 834{
 835	if (buf->len <= 0 || buf->len > sizeof(buf->data))
 836		return -EINVAL;
 837
 838	if (!pss_download_boot(devc, buf->data, buf->len, buf->flags))
 839	{
 840		printk(KERN_ERR "PSS: Unable to load microcode block to DSP.\n");
 841		return -EIO;
 842	}
 843	nonstandard_microcode = 1;	/* The MIDI microcode has been overwritten */
 844	return 0;
 845}
 846
 847static int pss_coproc_ioctl(void *dev_info, unsigned int cmd, void __user *arg, int local)
 848{
 849	copr_buffer *buf;
 850	copr_msg *mbuf;
 851	copr_debug_buf dbuf;
 852	unsigned short tmp;
 853	unsigned long flags;
 854	unsigned short *data;
 855	int i, err;
 856	/* printk( "PSS coproc ioctl %x %x %d\n",  cmd,  arg,  local); */
 857	
 858	switch (cmd) 
 859	{
 860		case SNDCTL_COPR_RESET:
 861			pss_coproc_reset(dev_info);
 862			return 0;
 863
 864		case SNDCTL_COPR_LOAD:
 865			buf = vmalloc(sizeof(copr_buffer));
 866			if (buf == NULL)
 867				return -ENOSPC;
 868			if (copy_from_user(buf, arg, sizeof(copr_buffer))) {
 869				vfree(buf);
 870				return -EFAULT;
 871			}
 872			err = download_boot_block(dev_info, buf);
 873			vfree(buf);
 874			return err;
 875		
 876		case SNDCTL_COPR_SENDMSG:
 877			mbuf = vmalloc(sizeof(copr_msg));
 878			if (mbuf == NULL)
 879				return -ENOSPC;
 880			if (copy_from_user(mbuf, arg, sizeof(copr_msg))) {
 881				vfree(mbuf);
 882				return -EFAULT;
 883			}
 884			data = (unsigned short *)(mbuf->data);
 885			spin_lock_irqsave(&lock, flags);
 886			for (i = 0; i < mbuf->len; i++) {
 887				if (!pss_put_dspword(devc, *data++)) {
 888					spin_unlock_irqrestore(&lock,flags);
 889					mbuf->len = i;	/* feed back number of WORDs sent */
 890					err = copy_to_user(arg, mbuf, sizeof(copr_msg));
 891					vfree(mbuf);
 892					return err ? -EFAULT : -EIO;
 893				}
 894			}
 895			spin_unlock_irqrestore(&lock,flags);
 896			vfree(mbuf);
 897			return 0;
 898
 899		case SNDCTL_COPR_RCVMSG:
 900			err = 0;
 901			mbuf = vmalloc(sizeof(copr_msg));
 902			if (mbuf == NULL)
 903				return -ENOSPC;
 904			data = (unsigned short *)mbuf->data;
 905			spin_lock_irqsave(&lock, flags);
 906			for (i = 0; i < sizeof(mbuf->data)/sizeof(unsigned short); i++) {
 907				mbuf->len = i;	/* feed back number of WORDs read */
 908				if (!pss_get_dspword(devc, data++)) {
 909					if (i == 0)
 910						err = -EIO;
 911					break;
 912				}
 913			}
 914			spin_unlock_irqrestore(&lock,flags);
 915			if (copy_to_user(arg, mbuf, sizeof(copr_msg)))
 916				err = -EFAULT;
 917			vfree(mbuf);
 918			return err;
 919		
 920		case SNDCTL_COPR_RDATA:
 921			if (copy_from_user(&dbuf, arg, sizeof(dbuf)))
 922				return -EFAULT;
 923			spin_lock_irqsave(&lock, flags);
 924			if (!pss_put_dspword(devc, 0x00d0)) {
 925				spin_unlock_irqrestore(&lock,flags);
 926				return -EIO;
 927			}
 928			if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) {
 929				spin_unlock_irqrestore(&lock,flags);
 930				return -EIO;
 931			}
 932			if (!pss_get_dspword(devc, &tmp)) {
 933				spin_unlock_irqrestore(&lock,flags);
 934				return -EIO;
 935			}
 936			dbuf.parm1 = tmp;
 937			spin_unlock_irqrestore(&lock,flags);
 938			if (copy_to_user(arg, &dbuf, sizeof(dbuf)))
 939				return -EFAULT;
 940			return 0;
 941		
 942		case SNDCTL_COPR_WDATA:
 943			if (copy_from_user(&dbuf, arg, sizeof(dbuf)))
 944				return -EFAULT;
 945			spin_lock_irqsave(&lock, flags);
 946			if (!pss_put_dspword(devc, 0x00d1)) {
 947				spin_unlock_irqrestore(&lock,flags);
 948				return -EIO;
 949			}
 950			if (!pss_put_dspword(devc, (unsigned short) (dbuf.parm1 & 0xffff))) {
 951				spin_unlock_irqrestore(&lock,flags);
 952				return -EIO;
 953			}
 954			tmp = (unsigned int)dbuf.parm2 & 0xffff;
 955			if (!pss_put_dspword(devc, tmp)) {
 956				spin_unlock_irqrestore(&lock,flags);
 957				return -EIO;
 958			}
 959			spin_unlock_irqrestore(&lock,flags);
 960			return 0;
 961		
 962		case SNDCTL_COPR_WCODE:
 963			if (copy_from_user(&dbuf, arg, sizeof(dbuf)))
 964				return -EFAULT;
 965			spin_lock_irqsave(&lock, flags);
 966			if (!pss_put_dspword(devc, 0x00d3)) {
 967				spin_unlock_irqrestore(&lock,flags);
 968				return -EIO;
 969			}
 970			if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) {
 971				spin_unlock_irqrestore(&lock,flags);
 972				return -EIO;
 973			}
 974			tmp = (unsigned int)dbuf.parm2 & 0x00ff;
 975			if (!pss_put_dspword(devc, tmp)) {
 976				spin_unlock_irqrestore(&lock,flags);
 977				return -EIO;
 978			}
 979			tmp = ((unsigned int)dbuf.parm2 >> 8) & 0xffff;
 980			if (!pss_put_dspword(devc, tmp)) {
 981				spin_unlock_irqrestore(&lock,flags);
 982				return -EIO;
 983			}
 984			spin_unlock_irqrestore(&lock,flags);
 985			return 0;
 986		
 987		case SNDCTL_COPR_RCODE:
 988			if (copy_from_user(&dbuf, arg, sizeof(dbuf)))
 989				return -EFAULT;
 990			spin_lock_irqsave(&lock, flags);
 991			if (!pss_put_dspword(devc, 0x00d2)) {
 992				spin_unlock_irqrestore(&lock,flags);
 993				return -EIO;
 994			}
 995			if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) {
 996				spin_unlock_irqrestore(&lock,flags);
 997				return -EIO;
 998			}
 999			if (!pss_get_dspword(devc, &tmp)) { /* Read MSB */
1000				spin_unlock_irqrestore(&lock,flags);
1001				return -EIO;
1002			}
1003			dbuf.parm1 = tmp << 8;
1004			if (!pss_get_dspword(devc, &tmp)) { /* Read LSB */
1005				spin_unlock_irqrestore(&lock,flags);
1006				return -EIO;
1007			}
1008			dbuf.parm1 |= tmp & 0x00ff;
1009			spin_unlock_irqrestore(&lock,flags);
1010			if (copy_to_user(arg, &dbuf, sizeof(dbuf)))
1011				return -EFAULT;
1012			return 0;
1013
1014		default:
1015			return -EINVAL;
1016	}
1017	return -EINVAL;
1018}
1019
1020static coproc_operations pss_coproc_operations =
1021{
1022	"ADSP-2115",
1023	THIS_MODULE,
1024	pss_coproc_open,
1025	pss_coproc_close,
1026	pss_coproc_ioctl,
1027	pss_coproc_reset,
1028	&pss_data
1029};
1030
1031static int __init probe_pss_mss(struct address_info *hw_config)
1032{
1033	volatile int timeout;
1034	struct resource *ports;
1035	int        my_mix = -999;	/* gcc shut up */
1036
1037	if (!pss_initialized)
1038		return 0;
1039
1040	if (!request_region(hw_config->io_base, 4, "WSS config")) {
1041		printk(KERN_ERR "PSS: WSS I/O port conflicts.\n");
1042		return 0;
1043	}
1044	ports = request_region(hw_config->io_base + 4, 4, "ad1848");
1045	if (!ports) {
1046		printk(KERN_ERR "PSS: WSS I/O port conflicts.\n");
1047		release_region(hw_config->io_base, 4);
1048		return 0;
1049	}
1050	set_io_base(devc, CONF_WSS, hw_config->io_base);
1051	if (!set_irq(devc, CONF_WSS, hw_config->irq)) {
1052		printk("PSS: WSS IRQ allocation error.\n");
1053		goto fail;
1054	}
1055	if (!set_dma(devc, CONF_WSS, hw_config->dma)) {
1056		printk(KERN_ERR "PSS: WSS DMA allocation error\n");
1057		goto fail;
1058	}
1059	/*
1060	 * For some reason the card returns 0xff in the WSS status register
1061	 * immediately after boot. Probably MIDI+SB emulation algorithm
1062	 * downloaded to the ADSP2115 spends some time initializing the card.
1063	 * Let's try to wait until it finishes this task.
1064	 */
1065	for (timeout = 0; timeout < 100000 && (inb(hw_config->io_base + WSS_INDEX) &
1066	  WSS_INITIALIZING); timeout++)
1067		;
1068
1069	outb((0x0b), hw_config->io_base + WSS_INDEX);	/* Required by some cards */
1070
1071	for (timeout = 0; (inb(hw_config->io_base + WSS_DATA) & WSS_AUTOCALIBRATION) &&
1072	  (timeout < 100000); timeout++)
1073		;
1074
1075	if (!probe_ms_sound(hw_config, ports))
1076		goto fail;
1077
1078	devc->ad_mixer_dev = NO_WSS_MIXER;
1079	if (pss_mixer) 
1080	{
1081		if ((my_mix = sound_install_mixer (MIXER_DRIVER_VERSION,
1082			"PSS-SPEAKERS and AD1848 (through MSS audio codec)",
1083			&pss_mixer_operations,
1084			sizeof (struct mixer_operations),
1085			devc)) < 0) 
1086		{
1087			printk(KERN_ERR "Could not install PSS mixer\n");
1088			goto fail;
1089		}
1090	}
1091	pss_mixer_reset(devc);
1092	attach_ms_sound(hw_config, ports, THIS_MODULE);	/* Slot 0 */
1093
1094	if (hw_config->slots[0] != -1)
1095	{
1096		/* The MSS driver installed itself */
1097		audio_devs[hw_config->slots[0]]->coproc = &pss_coproc_operations;
1098		if (pss_mixer && (num_mixers == (my_mix + 2)))
1099		{
1100			/* The MSS mixer installed */
1101			devc->ad_mixer_dev = audio_devs[hw_config->slots[0]]->mixer_dev;
1102		}
1103	}
1104	return 1;
1105fail:
1106	release_region(hw_config->io_base + 4, 4);
1107	release_region(hw_config->io_base, 4);
1108	return 0;
1109}
1110
1111static inline void __exit unload_pss(struct address_info *hw_config)
1112{
1113	release_region(hw_config->io_base, 0x10);
1114	release_region(hw_config->io_base+0x10, 0x9);
1115}
1116
1117static inline void __exit unload_pss_mpu(struct address_info *hw_config)
1118{
1119	unload_mpu401(hw_config);
1120}
1121
1122static inline void __exit unload_pss_mss(struct address_info *hw_config)
1123{
1124	unload_ms_sound(hw_config);
1125}
1126
1127
1128static struct address_info cfg;
1129static struct address_info cfg2;
1130static struct address_info cfg_mpu;
1131
1132static int pss_io __initdata	= -1;
1133static int mss_io __initdata	= -1;
1134static int mss_irq __initdata	= -1;
1135static int mss_dma __initdata	= -1;
1136static int mpu_io __initdata	= -1;
1137static int mpu_irq __initdata	= -1;
1138static bool pss_no_sound = 0;	/* Just configure non-sound components */
1139static bool pss_keep_settings  = 1;	/* Keep hardware settings at module exit */
1140static char *pss_firmware = "/etc/sound/pss_synth";
1141
1142module_param(pss_io, int, 0);
1143MODULE_PARM_DESC(pss_io, "Set i/o base of PSS card (probably 0x220 or 0x240)");
1144module_param(mss_io, int, 0);
1145MODULE_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)");
1146module_param(mss_irq, int, 0);
1147MODULE_PARM_DESC(mss_irq, "Set WSS (audio) IRQ (3, 5, 7, 9, 10, 11, 12)");
1148module_param(mss_dma, int, 0);
1149MODULE_PARM_DESC(mss_dma, "Set WSS (audio) DMA (0, 1, 3)");
1150module_param(mpu_io, int, 0);
1151MODULE_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)");
1152module_param(mpu_irq, int, 0);
1153MODULE_PARM_DESC(mpu_irq, "Set MIDI IRQ (3, 5, 7, 9, 10, 11, 12)");
1154module_param(pss_cdrom_port, int, 0);
1155MODULE_PARM_DESC(pss_cdrom_port, "Set the PSS CDROM port i/o base (0x340 or other)");
1156module_param(pss_enable_joystick, bool, 0);
1157MODULE_PARM_DESC(pss_enable_joystick, "Enables the PSS joystick port (1 to enable, 0 to disable)");
1158module_param(pss_no_sound, bool, 0);
1159MODULE_PARM_DESC(pss_no_sound, "Configure sound compoents (0 - no, 1 - yes)");
1160module_param(pss_keep_settings, bool, 0);
1161MODULE_PARM_DESC(pss_keep_settings, "Keep hardware setting at driver unloading (0 - no, 1 - yes)");
1162module_param(pss_firmware, charp, 0);
1163MODULE_PARM_DESC(pss_firmware, "Location of the firmware file (default - /etc/sound/pss_synth)");
1164module_param(pss_mixer, bool, 0);
1165MODULE_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.");
1166MODULE_AUTHOR("Hannu Savolainen, Vladimir Michl");
1167MODULE_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).");
1168MODULE_LICENSE("GPL");
1169
1170
1171static int fw_load = 0;
1172static int pssmpu = 0, pssmss = 0;
1173
1174/*
1175 *    Load a PSS sound card module
1176 */
1177
1178static int __init init_pss(void)
1179{
1180
1181	if(pss_no_sound)		/* If configuring only nonsound components */
1182	{
1183		cfg.io_base = pss_io;
1184		if(!probe_pss(&cfg))
1185			return -ENODEV;
1186		printk(KERN_INFO "ECHO-PSS  Rev. %d\n", inw(REG(PSS_ID)) & 0x00ff);
1187		printk(KERN_INFO "PSS: loading in no sound mode.\n");
1188		disable_all_emulations();
1189		configure_nonsound_components();
1190		release_region(pss_io, 0x10);
1191		release_region(pss_io + 0x10, 0x9);
1192		return 0;
1193	}
1194
1195	cfg.io_base = pss_io;
1196
1197	cfg2.io_base = mss_io;
1198	cfg2.irq = mss_irq;
1199	cfg2.dma = mss_dma;
1200
1201	cfg_mpu.io_base = mpu_io;
1202	cfg_mpu.irq = mpu_irq;
1203
1204	if (cfg.io_base == -1 || cfg2.io_base == -1 || cfg2.irq == -1 || cfg.dma == -1) {
1205		printk(KERN_INFO "pss: mss_io, mss_dma, mss_irq and pss_io must be set.\n");
1206		return -EINVAL;
1207	}
1208
1209	if (!pss_synth) {
1210		fw_load = 1;
1211		pss_synthLen = mod_firmware_load(pss_firmware, (void *) &pss_synth);
1212	}
1213	if (!attach_pss(&cfg))
1214		return -ENODEV;
1215	/*
1216	 *    Attach stuff
1217	 */
1218	if (probe_pss_mpu(&cfg_mpu))
1219		pssmpu = 1;
1220
1221	if (probe_pss_mss(&cfg2))
1222		pssmss = 1;
1223
1224	return 0;
1225}
1226
1227static void __exit cleanup_pss(void)
1228{
1229	if(!pss_no_sound)
1230	{
1231		if (fw_load)
1232			vfree(pss_synth);
1233		if(pssmss)
1234			unload_pss_mss(&cfg2);
1235		if(pssmpu)
1236			unload_pss_mpu(&cfg_mpu);
1237		unload_pss(&cfg);
1238	} else if (pss_cdrom_port != -1)
1239		release_region(pss_cdrom_port, 2);
1240
1241	if(!pss_keep_settings)	/* Keep hardware settings if asked */
1242	{
1243		disable_all_emulations();
1244		printk(KERN_INFO "Resetting PSS sound card configurations.\n");
1245	}
1246}
1247
1248module_init(init_pss);
1249module_exit(cleanup_pss);
1250
1251#ifndef MODULE
1252static int __init setup_pss(char *str)
1253{
1254	/* io, mss_io, mss_irq, mss_dma, mpu_io, mpu_irq */
1255	int ints[7];
1256	
1257	str = get_options(str, ARRAY_SIZE(ints), ints);
1258
1259	pss_io	= ints[1];
1260	mss_io	= ints[2];
1261	mss_irq	= ints[3];
1262	mss_dma	= ints[4];
1263	mpu_io	= ints[5];
1264	mpu_irq	= ints[6];
1265
1266	return 1;
1267}
1268
1269__setup("pss=", setup_pss);
1270#endif