Пример #1
0
void
sscapeintr(int irq)
{
    u_char   bits, tmp;

    DEB(printf("sscapeintr(0x%02x)\n", (bits = sscape_read(devc, GA_INTSTAT_REG))));
    if ((sscape_sleep_flag.mode & WK_SLEEP)) {
	sscape_sleep_flag.mode = WK_WAKEUP;
	wakeup(sscape_sleeper);
    }
    if (bits & 0x02) {	/* Host interface interrupt */
	printf("SSCAPE: Host interrupt, data=%02x\n", host_read(devc));
    }
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
    if (bits & 0x01) {
	static int debug = 0;

	mpuintr(irq);
	if (debug++ > 10) {	/* Temporary debugging hack */
	    sscape_write(devc, GA_INTENA_REG, 0x00); /* Disable all interr. */
	}
    }
#endif

    /*
     * Acknowledge interrupts (toggle the interrupt bits)
     */

    tmp = sscape_read(devc, GA_INTENA_REG);
    sscape_write(devc, GA_INTENA_REG, (~bits & 0x0e) | (tmp & 0xf1));
}
Пример #2
0
static void sscape_pnp_start_dma(sscape_info* devc, int arg )
{
	int reg;
	if (arg == 0) reg = 2;
	else reg = 3;

	sscape_write(devc, reg, sscape_read( devc, reg) | 0x01);
	sscape_write(devc, reg, sscape_read( devc, reg) & 0xFE);
}
Пример #3
0
static int detect_ga(sscape_info * devc)
{
	unsigned char save;

	DDB(printk("Entered Soundscape detect_ga(%x)\n", devc->base));

	if (check_region(devc->base, 8))
		return 0;

	/*
	 * First check that the address register of "ODIE" is
	 * there and that it has exactly 4 writable bits.
	 * First 4 bits
	 */
	
	if ((save = inb(PORT(ODIE_ADDR))) & 0xf0)
	{
		DDB(printk("soundscape: Detect error A\n"));
		return 0;
	}
	outb((0x00), PORT(ODIE_ADDR));
	if (inb(PORT(ODIE_ADDR)) != 0x00)
	{
		DDB(printk("soundscape: Detect error B\n"));
		return 0;
	}
	outb((0xff), PORT(ODIE_ADDR));
	if (inb(PORT(ODIE_ADDR)) != 0x0f)
	{
		DDB(printk("soundscape: Detect error C\n"));
		return 0;
	}
	outb((save), PORT(ODIE_ADDR));

	/*
	 * Now verify that some indirect registers return zero on some bits.
	 * This may break the driver with some future revisions of "ODIE" but...
	 */

	if (sscape_read(devc, 0) & 0x0c)
	{
		DDB(printk("soundscape: Detect error D (%x)\n", sscape_read(devc, 0)));
		return 0;
	}
	if (sscape_read(devc, 1) & 0x0f)
	{
		DDB(printk("soundscape: Detect error E\n"));
		return 0;
	}
	if (sscape_read(devc, 5) & 0x0f)
	{
		DDB(printk("soundscape: Detect error F\n"));
		return 0;
	}
	return 1;
}
Пример #4
0
static int __init probe_sscape(struct address_info *hw_config)
{
    devc->base = hw_config->io_base;
    devc->irq = hw_config->irq;
    devc->dma = hw_config->dma;
    devc->osp = hw_config->osp;

#ifdef SSCAPE_DEBUG1
    /*
     * Temporary debugging aid. Print contents of the registers before
     * changing them.
     */
    {
        int i;

        for (i = 0; i < 13; i++)
            printk("I%d = %02x (old value)\n", i, sscape_read(devc, i));
    }
#endif
    devc->failed = 1;

    sscape_ports = request_region(devc->base, 2, "mpu401");
    if (!sscape_ports)
        return 0;

    if (!request_region(devc->base + 2, 6, "SoundScape")) {
        release_region(devc->base, 2);
        return 0;
    }

    if (!detect_ga(devc)) {
        if (detect_sscape_pnp(devc))
            return 1;
        release_region(devc->base, 2);
        release_region(devc->base + 2, 6);
        return 0;
    }

    if (old_hardware)	/* Check that it's really an old Spea/Reveal card. */
    {
        unsigned char   tmp;
        int             cc;

        if (!((tmp = sscape_read(devc, GA_HMCTL_REG)) & 0xc0))
        {
            sscape_write(devc, GA_HMCTL_REG, tmp | 0x80);
            for (cc = 0; cc < 200000; ++cc)
                inb(devc->base + ODIE_ADDR);
        }
    }
    return 1;
}
Пример #5
0
static int
sscape_audio_open(int dev, int mode)
{
    u_long   flags;
    sscape_info    *devc = (sscape_info *) audio_devs[dev]->devc;

    flags = splhigh();
    if (devc->opened) {
	splx(flags);
	return -(EBUSY);
    }
    devc->opened = 1;
    splx(flags);
#ifdef SSCAPE_DEBUG4
    /*
     * Temporary debugging aid. Print contents of the registers when the
     * device is opened.
     */
    {
	int             i;

	for (i = 0; i < 13; i++)
	    printf("I%d = %02x\n", i, sscape_read(devc, i));
    }
#endif

    return 0;
}
Пример #6
0
static int sscape_pnp_wait_dma (sscape_info* devc, int arg )
{
	int		reg;
	unsigned long	i;
	unsigned char	d;

	if (arg == 0) reg = 2;
	else reg = 3;

	sleep ( 1 );
	i = 0;
	do {
		d = sscape_read(devc, reg) & 1;
		if ( d == 1)  break;
		i++;
	} while (i < 500000);
	d = sscape_read(devc, reg) & 1; 
	return d;
}
Пример #7
0
int probe_sscape(struct address_info *hw_config)
{

	if (sscape_detected != 0 && sscape_detected != hw_config->io_base)
		return 0;

	devc->base = hw_config->io_base;
	devc->irq = hw_config->irq;
	devc->dma = hw_config->dma;
	devc->osp = hw_config->osp;

#ifdef SSCAPE_DEBUG1
	/*
	 * Temporary debugging aid. Print contents of the registers before
	 * changing them.
	 */
	{
		int i;

		for (i = 0; i < 13; i++)
			printk("I%d = %02x (old value)\n", i, sscape_read(devc, i));
	}
#endif
	devc->failed = 1;

	if (!detect_ga(devc))
		return 0;

	if (old_hardware)	/* Check that it's really an old Spea/Reveal card. */
	{
		unsigned char   tmp;
		int             cc;

		if (!((tmp = sscape_read(devc, GA_HMCTL_REG)) & 0xc0))
		{
			sscape_write(devc, GA_HMCTL_REG, tmp | 0x80);
			for (cc = 0; cc < 200000; ++cc)
				inb(devc->base + ODIE_ADDR);
		}
	}
	sscape_detected = hw_config->io_base;
	return 1;
}
Пример #8
0
void
sscapeintr (int irq, void *dev_id, struct pt_regs *dummy)
{
  unsigned char   bits, tmp;
  static int      debug = 0;

  bits = sscape_read (devc, GA_INTSTAT_REG);
  if ((sscape_sleep_flag.flags & WK_SLEEP))
    {
      {
	sscape_sleep_flag.flags = WK_WAKEUP;
	module_wake_up (&sscape_sleeper);
      };
    }

  if (bits & 0x02)		/* Host interface interrupt */
    {
      printk ("SSCAPE: Host interrupt, data=%02x\n", host_read (devc));
    }

#if defined(CONFIG_MPU_EMU) && defined(CONFIG_MIDI)
  if (bits & 0x01)
    {
      mpuintr (irq, NULL, NULL);
      if (debug++ > 10)		/* Temporary debugging hack */
	{
	  sscape_write (devc, GA_INTENA_REG, 0x00);	/* Disable all interrupts */
	}
    }
#endif

  /*
     * Acknowledge interrupts (toggle the interrupt bits)
   */

  tmp = sscape_read (devc, GA_INTENA_REG);
  sscape_write (devc, GA_INTENA_REG, (~bits & 0x0e) | (tmp & 0xf1));

}
Пример #9
0
void __init attach_sscape(struct address_info *hw_config)
{
#ifndef SSCAPE_REGS
	/*
	 * Config register values for Spea/V7 Media FX and Ensoniq S-2000.
	 * These values are card
	 * dependent. If you have another SoundScape based card, you have to
	 * find the correct values. Do the following:
	 *  - Compile this driver with SSCAPE_DEBUG1 defined.
	 *  - Shut down and power off your machine.
	 *  - Boot with DOS so that the SSINIT.EXE program is run.
	 *  - Warm boot to {Linux|SYSV|BSD} and write down the lines displayed
	 *    when detecting the SoundScape.
	 *  - Modify the following list to use the values printed during boot.
	 *    Undefine the SSCAPE_DEBUG1
	 */
#define SSCAPE_REGS { \
/* I0 */	0x00, \
/* I1 */	0xf0, /* Note! Ignored. Set always to 0xf0 */ \
/* I2 */	0x20, /* Note! Ignored. Set always to 0x20 */ \
/* I3 */	0x20, /* Note! Ignored. Set always to 0x20 */ \
/* I4 */	0xf5, /* Ignored */ \
/* I5 */	0x10, \
/* I6 */	0x00, \
/* I7 */	0x2e, /* I7 MEM config A. Likely to vary between models */ \
/* I8 */	0x00, /* I8 MEM config B. Likely to vary between models */ \
/* I9 */	0x40 /* Ignored */ \
	}
#endif

	unsigned long   flags;
	static unsigned char regs[10] = SSCAPE_REGS;

	int i, irq_bits = 0xff;

	if (sscape_detected != hw_config->io_base)
		return;

	request_region(devc->base + 2, 6, "SoundScape");
	if (old_hardware)
	{
		valid_interrupts = valid_interrupts_old;
		conf_printf("Ensoniq SoundScape (old)", hw_config);
	}
	else
		conf_printf("Ensoniq SoundScape", hw_config);

	for (i = 0; i < sizeof(valid_interrupts); i++)
	{
		if (hw_config->irq == valid_interrupts[i])
		{
			irq_bits = i;
			break;
		}
	}
	if (hw_config->irq > 15 || ((regs[4] = irq_bits) == 0xff))
	{
		printk(KERN_ERR "Invalid IRQ%d\n", hw_config->irq);
		return;
	}
	
	if (!sscape_is_pnp) {
	
	    save_flags(flags);
	    cli();
	    for (i = 1; i < 10; i++)
	    {
		switch (i)
		{
			case 1:	/* Host interrupt enable */
				sscape_write(devc, i, 0xf0);	/* All interrupts enabled */
				break;

			case 2:	/* DMA A status/trigger register */
			case 3:	/* DMA B status/trigger register */
				sscape_write(devc, i, 0x20);	/* DMA channel disabled */
				break;

			case 4:	/* Host interrupt config reg */
				sscape_write(devc, i, 0xf0 | (irq_bits << 2) | irq_bits);
				break;

			case 5:	/* Don't destroy CD-ROM DMA config bits (0xc0) */
				sscape_write(devc, i, (regs[i] & 0x3f) | (sscape_read(devc, i) & 0xc0));
				break;

			case 6:	/* CD-ROM config (WSS codec actually) */
				sscape_write(devc, i, regs[i]);
				break;

			case 9:	/* Master control reg. Don't modify CR-ROM bits. Disable SB emul */
				sscape_write(devc, i, (sscape_read(devc, i) & 0xf0) | 0x08);
				break;

			default:
				sscape_write(devc, i, regs[i]);
		}
	    }
	    restore_flags(flags);
	}
#ifdef SSCAPE_DEBUG2
	/*
	 * Temporary debugging aid. Print contents of the registers after
	 * changing them.
	 */
	{
		int i;

		for (i = 0; i < 13; i++)
			printk("I%d = %02x (new value)\n", i, sscape_read(devc, i));
	}
#endif

	if (probe_mpu401(hw_config))
		hw_config->always_detect = 1;
	hw_config->name = "SoundScape";

	hw_config->irq *= -1;	/* Negative value signals IRQ sharing */
	attach_mpu401(hw_config, THIS_MODULE);
	hw_config->irq *= -1;	/* Restore it */

	if (hw_config->slots[1] != -1)	/* The MPU driver installed itself */
	{
		sscape_mididev = hw_config->slots[1];
		midi_devs[hw_config->slots[1]]->coproc = &sscape_coproc_operations;
	}
	sscape_write(devc, GA_INTENA_REG, 0x80);	/* Master IRQ enable */
	devc->ok = 1;
	devc->failed = 0;
}
Пример #10
0
static int sscape_download_boot(struct sscape_info *devc, unsigned char *block, int size, int flag)
{
	unsigned long flags;
	unsigned char temp;
	volatile int done, timeout_val;
	static unsigned char codec_dma_bits = 0;

	if (flag & CPF_FIRST)
	{
		/*
		 * First block. Have to allocate DMA and to reset the board
		 * before continuing.
		 */

		save_flags(flags);
		cli();
		codec_dma_bits = sscape_read(devc, GA_CDCFG_REG);

		if (devc->dma_allocated == 0)
			devc->dma_allocated = 1;

		restore_flags(flags);

		sscape_write(devc, GA_HMCTL_REG, 
			(temp = sscape_read(devc, GA_HMCTL_REG)) & 0x3f);	/*Reset */

		for (timeout_val = 10000; timeout_val > 0; timeout_val--)
			sscape_read(devc, GA_HMCTL_REG);	/* Delay */

		/* Take board out of reset */
		sscape_write(devc, GA_HMCTL_REG,
			(temp = sscape_read(devc, GA_HMCTL_REG)) | 0x80);
	}
	/*
	 * Transfer one code block using DMA
	 */
	if (audio_devs[devc->codec_audiodev]->dmap_out->raw_buf == NULL)
	{
		printk(KERN_WARNING "soundscape: DMA buffer not available\n");
		return 0;
	}
	memcpy(audio_devs[devc->codec_audiodev]->dmap_out->raw_buf, block, size);

	save_flags(flags);
	cli();
	
	/******** INTERRUPTS DISABLED NOW ********/
	
	do_dma(devc, SSCAPE_DMA_A,
	       audio_devs[devc->codec_audiodev]->dmap_out->raw_buf_phys,
	       size, DMA_MODE_WRITE);

	/*
	 * Wait until transfer completes.
	 */
	
	done = 0;
	timeout_val = 30;
	while (!done && timeout_val-- > 0)
	{
		int resid;

		if (HZ / 50)
			sleep(HZ / 50);
		clear_dma_ff(devc->dma);
		if ((resid = get_dma_residue(devc->dma)) == 0)
			done = 1;
	}

	restore_flags(flags);
	if (!done)
		return 0;

	if (flag & CPF_LAST)
	{
		/*
		 * Take the board out of reset
		 */
		outb((0x00), PORT(HOST_CTRL));
		outb((0x00), PORT(MIDI_CTRL));

		temp = sscape_read(devc, GA_HMCTL_REG);
		temp |= 0x40;
		sscape_write(devc, GA_HMCTL_REG, temp);	/* Kickstart the board */

		/*
		 * Wait until the ODB wakes up
		 */

		save_flags(flags);
		cli();
		done = 0;
		timeout_val = 5 * HZ;
		while (!done && timeout_val-- > 0)
		{
			unsigned char x;
			
			sleep(1);
			x = inb(PORT(HOST_DATA));
			if (x == 0xff || x == 0xfe)		/* OBP startup acknowledge */
			{
				DDB(printk("Soundscape: Acknowledge = %x\n", x));
				done = 1;
			}
		}
		sscape_write(devc, GA_CDCFG_REG, codec_dma_bits);

		restore_flags(flags);
		if (!done)
		{
			printk(KERN_ERR "soundscape: The OBP didn't respond after code download\n");
			return 0;
		}
		save_flags(flags);
		cli();
		done = 0;
		timeout_val = 5 * HZ;
		while (!done && timeout_val-- > 0)
		{
			sleep(1);
			if (inb(PORT(HOST_DATA)) == 0xfe)	/* Host startup acknowledge */
				done = 1;
		}
		restore_flags(flags);
		if (!done)
		{
			printk(KERN_ERR "soundscape: OBP Initialization failed.\n");
			return 0;
		}
		printk(KERN_INFO "SoundScape board initialized OK\n");
		set_control(devc, CTL_MASTER_VOL, 100);
		set_control(devc, CTL_SYNTH_VOL, 100);

#ifdef SSCAPE_DEBUG3
		/*
		 * Temporary debugging aid. Print contents of the registers after
		 * downloading the code.
		 */
		{
			int i;

			for (i = 0; i < 13; i++)
				printk("I%d = %02x (new value)\n", i, sscape_read(devc, i));
		}
#endif

	}
	return 1;
}
Пример #11
0
static void __init attach_ss_ms_sound(struct address_info *hw_config)
{
	/*
	 * This routine configures the SoundScape card for use with the
	 * Win Sound System driver. The AD1848 codec interface uses the CD-ROM
	 * config registers of the "ODIE".
	 */

	int i, irq_bits = 0xff;

 		
 	if (!sscape_is_pnp)  /*pnp is already setup*/
 	{
 		/*
     		 * Setup the DMA polarity.
 	    	 */
 		sscape_write(devc, GA_DMACFG_REG, 0x50);
 	
 		/*
 		 * Take the gate-array off of the DMA channel.
 		 */
 		sscape_write(devc, GA_DMAB_REG, 0x20);
 	
 		/*
 		 * Init the AD1848 (CD-ROM) config reg.
 		 */
 		for (i = 0; i < sizeof(valid_interrupts); i++)
 		{
 			if (hw_config->irq == valid_interrupts[i])
 			{
 				irq_bits = i;
 				break;
 			}
 		}	
 		sscape_write(devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) | (irq_bits << 1));
 	}
 	
 	if (hw_config->irq == devc->irq)
 		printk(KERN_WARNING "soundscape: Warning! The WSS mode can't share IRQ with MIDI\n");
 				
	hw_config->slots[0] = ad1848_init(
			sscape_is_pnp ? "SoundScape" : "SoundScape PNP",
			hw_config->io_base,
			hw_config->irq,
			hw_config->dma,
			hw_config->dma,
			0,
			devc->osp,
			THIS_MODULE);

 					  
	if (hw_config->slots[0] != -1)	/* The AD1848 driver installed itself */
	{
		audio_devs[hw_config->slots[0]]->coproc = &sscape_coproc_operations;
		devc->codec_audiodev = hw_config->slots[0];
		devc->my_audiodev = hw_config->slots[0];

		/* Set proper routings here (what are they) */
		AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE);
	}
		
#ifdef SSCAPE_DEBUG5
	/*
	 * Temporary debugging aid. Print contents of the registers
	 * after the AD1848 device has been initialized.
	 */
	{
		int i;

		for (i = 0; i < 13; i++)
			printk("I%d = %02x\n", i, sscape_read(devc, i));
	}
#endif

}
Пример #12
0
static int __init detect_sscape_pnp(sscape_info* devc)
{
	long	 i, irq_bits = 0xff;
	unsigned int d;

	DDB(printk("Entered detect_sscape_pnp(%x)\n", devc->base));

	if (check_region(devc->base, 8)) {
		printk(KERN_ERR "detect_sscape_pnp: port %x is not free\n", devc->base);	
		return 0;
	}
		
	if (check_region(devc->codec, 2)) {
		printk(KERN_ERR "detect_sscape_pnp: port %x is not free\n", devc->codec);	
		return 0;
	}

	if ( (inb( devc -> base + 2) & 0x78) != 0) return 0;

	d = inb ( devc -> base + 4) & 0xF0;
	if (  (d & 0x80) != 0)  return 0;
	
	if (d == 0) {
			devc->codec_type = 1;
			devc->ic_type = IC_ODIE;
	}
	else if ( (d & 0x60) != 0) {
			devc->codec_type = 2;
			devc->ic_type = IC_OPUS;
	}
	else if ( (d & 0x40) != 0) {
			devc->codec_type = 2;
			devc->ic_type = IC_ODIE;
	} 
	else return 0;
	
	sscape_is_pnp = 1;
		
	outb(0xFA, devc -> base+4);
	if  ((inb( devc -> base+4) & 0x9F) != 0x0A)
		return 0;
	outb(0xFE, devc -> base+4);
	if  ( (inb(devc -> base+4) & 0x9F) != 0x0E)
		return 0;
	if  ( (inb(devc -> base+5) & 0x9F) != 0x0E)
		return 0;

	if (devc->codec_type == 2) {
		if (devc -> codec != devc -> base + 8)
			printk("soundscape warning: incorrect codec port specified\n");
		devc -> codec = devc -> base + 8;
		d = 0x10 | (sscape_read(devc, 9)  & 0xCF);
		sscape_write(devc, 9, d);
		sscape_write(devc, 6, 0x80);
	} else {
		//todo: check codec is not base + 8
	}

	d  = (sscape_read(devc, 9) & 0x3F) | 0xC0;
	sscape_write(devc, 9, d);

	for (i = 0; i < 550000; i++)
		if ( !(inb(devc -> codec) & 0x80) ) break;

	d = inb(devc -> codec);
	if (d & 0x80)
		return 0;
	if ( inb(devc -> codec + 2) == 0xFF)
		return 0;

	sscape_write(devc, 9, sscape_read(devc, 9)  & 0x3F );

	d  = inb(devc -> codec) & 0x80;
	if ( d == 0) {
		printk(KERN_INFO "soundscape: hardware detected\n");
		valid_interrupts = valid_interrupts_new;
	} else	{
		printk(KERN_INFO "soundscape: board looks like media fx\n");
		valid_interrupts = valid_interrupts_old;
		old_hardware = 1;
	}

	sscape_write( devc, 9, 0xC0 | (sscape_read(devc, 9)  & 0x3F) );

	for (i = 0; i < 550000; i++)
		if ( !(inb(devc -> codec) & 0x80)) 
			break;
		
	sscape_pnp_init_hw(devc);

	for (i = 0; i < sizeof(valid_interrupts); i++)
	{
		if (devc->codec_irq == valid_interrupts[i]) {
			irq_bits = i;
			break;
		}
	}	
	sscape_write(devc, GA_INTENA_REG, 0x00);
	sscape_write(devc, GA_DMACFG_REG, 0x50);
	sscape_write(devc, GA_DMAA_REG, 0x70);
	sscape_write(devc, GA_DMAB_REG, 0x20);
	sscape_write(devc, GA_INTCFG_REG, 0xf0);
	sscape_write(devc, GA_CDCFG_REG, 0x89 | (devc->dma << 4) | (irq_bits << 1));

	sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 0) | 0x20);
	sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 1) | 0x20);

	return 1;	
}
Пример #13
0
static void __init sscape_pnp_init_hw(sscape_info* devc)
{	
	unsigned char midi_irq = 0, sb_irq = 0;
	unsigned i;
	static	char code_file_name[23] = "/sndscape/sndscape.cox";
	
	int sscape_sb_enable		= 0;
	int sscape_joystic_enable	= 0x7f;
	int sscape_mic_enable		= 0;
	int sscape_ext_midi		= 0;		

	if ( !sscape_pnp_alloc_dma(devc) ) {
		printk(KERN_ERR "sscape: faild to allocate dma\n");
		return;
	}

	for (i = 0; i < 4; i++) {
		if ( devc -> irq   == valid_interrupts[i] ) 
			midi_irq = i;
		if ( devc -> codec_irq == valid_interrupts[i] ) 
			sb_irq = i;
	}

	sscape_write( devc, 5, 0x50);
	sscape_write( devc, 7, 0x2e);
	sscape_write( devc, 8, 0x00);

	sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40);
	sscape_write( devc, 3, ( devc -> dma << 4) | 0x80);

	if ( sscape_sb_enable )
		sscape_write (devc, 4, 0xF0 | (sb_irq << 2) | midi_irq);
	else	
		sscape_write (devc, 4, 0xF0 | (midi_irq<<2) | midi_irq);

	i = 0x10; //sscape_read(devc, 9) & (devc->ic_type == IC_ODIE ? 0xf0 : 0xc0);
	if ( sscape_sb_enable )
		i |= devc->ic_type == IC_ODIE ? 0x05 : 0x07;	    
	if (sscape_joystic_enable) i |= 8;
	
	sscape_write (devc, 9, i);
	sscape_write (devc, 6, 0x80);
	sscape_write (devc, 1, 0x80);

	if (devc -> codec_type == 2) {
		sscape_pnp_write_codec( devc, 0x0C, 0x50);
		sscape_pnp_write_codec( devc, 0x10, sscape_pnp_read_codec( devc, 0x10) & 0x3F);
		sscape_pnp_write_codec( devc, 0x11, sscape_pnp_read_codec( devc, 0x11) | 0xC0);
		sscape_pnp_write_codec( devc, 29, 0x20);
	}

	if (sscape_pnp_upload_file(devc, "/sndscape/scope.cod") == 0 ) {
		printk(KERN_ERR "sscape: faild to upload file /sndscape/scope.cod\n");
		sscape_pnp_free_dma(devc);
		return;
	}

	i = sscape_read_host_ctrl( devc );
	
	if ( (i & 0x0F) >  7 ) {
		printk(KERN_ERR "sscape: scope.cod faild\n");
		sscape_pnp_free_dma(devc);
		return;
	}
	if ( i & 0x10 ) sscape_write( devc, 7, 0x2F);
	code_file_name[21] = (char) ( i & 0x0F) + 0x30;
	if (sscape_pnp_upload_file( devc, code_file_name) == 0) {
		printk(KERN_ERR "sscape: faild to upload file %s\n", code_file_name);
		sscape_pnp_free_dma(devc);
		return;
	}
	
	if (devc->ic_type != IC_ODIE) {
		sscape_pnp_write_codec( devc, 10, (sscape_pnp_read_codec(devc, 10) & 0x7f) |
		 ( sscape_mic_enable == 0 ? 0x00 : 0x80) );
	}
	sscape_write_host_ctrl2( devc, 0x84, 0x64 );  /* MIDI volume */
	sscape_write_host_ctrl2( devc, 0x86, 0x64 );  /* MIDI volume?? */
	sscape_write_host_ctrl2( devc, 0x8A, sscape_ext_midi);

	sscape_pnp_write_codec ( devc, 6, 0x3f ); //WAV_VOL
	sscape_pnp_write_codec ( devc, 7, 0x3f ); //WAV_VOL
	sscape_pnp_write_codec ( devc, 2, 0x1F ); //WD_CDXVOLL
	sscape_pnp_write_codec ( devc, 3, 0x1F ); //WD_CDXVOLR

	if (devc -> codec_type == 1) {
		sscape_pnp_write_codec ( devc, 4, 0x1F );
		sscape_pnp_write_codec ( devc, 5, 0x1F );
		sscape_write_host_ctrl2( devc, 0x88, sscape_mic_enable);
	} else {
		int t;
		sscape_pnp_write_codec ( devc, 0x10, 0x1F << 1);
		sscape_pnp_write_codec ( devc, 0x11, 0xC0 | (0x1F << 1));

		t = sscape_pnp_read_codec( devc, 0x00) & 0xDF;
		if ( (sscape_mic_enable == 0)) t |= 0;
		else t |= 0x20;
		sscape_pnp_write_codec ( devc, 0x00, t);
		t = sscape_pnp_read_codec( devc, 0x01) & 0xDF;
		if ( (sscape_mic_enable == 0) ) t |= 0;
		else t |= 0x20;
		sscape_pnp_write_codec ( devc, 0x01, t);
		sscape_pnp_write_codec ( devc, 0x40 | 29 , 0x20);
		outb(0, devc -> codec);
	}
	if (devc -> ic_type == IC_OPUS ) {
		int i = sscape_read( devc, 9 );
		sscape_write( devc, 9, i | 3 );
		sscape_write( devc, 3, 0x40);

		if (check_region(0x228, 1)) {
		    	    outb(0, 0x228);
			    release_region(0x228,1);
		}
		sscape_write( devc, 3, (devc -> dma << 4) | 0x80);
		sscape_write( devc, 9, i );
	}
	
	host_close ( devc );
	sscape_pnp_free_dma(devc);
}
Пример #14
0
static int
sscape_download_boot(struct sscape_info * devc, u_char *block, int size, int flag)
{
    u_long   flags;
    u_char   temp;
    int             done, timeout_val;

    if (flag & CPF_FIRST) {
	/*
	 * First block. Have to allocate DMA and to reset the board
	 * before continuing.
	 */

	flags = splhigh();
	if (devc->dma_allocated == 0) {
	    devc->dma_allocated = 1;
	}
	splx(flags);

	sscape_write(devc, GA_HMCTL_REG,
	   (temp = sscape_read(devc, GA_HMCTL_REG)) & 0x3f);	/* Reset */

	for (timeout_val = 10000; timeout_val > 0; timeout_val--)
	    sscape_read(devc, GA_HMCTL_REG);	/* Delay */

	/* Take board out of reset */
	sscape_write(devc, GA_HMCTL_REG,
		   (temp = sscape_read(devc, GA_HMCTL_REG)) | 0x80);
    }
    /*
     * Transfer one code block using DMA
     */
    bcopy(block, audio_devs[devc->my_audiodev]->dmap_out->raw_buf, size);

    flags = splhigh();
    /******** INTERRUPTS DISABLED NOW ********/
    do_dma(devc, SSCAPE_DMA_A,
	       audio_devs[devc->my_audiodev]->dmap_out->raw_buf_phys,
	       size, 1);

    /*
     * Wait until transfer completes.
     */
    sscape_sleep_flag.aborting = 0;
    sscape_sleep_flag.mode = WK_NONE;
    done = 0;
    timeout_val = 100;
    while (!done && timeout_val-- > 0) {
	int   chn;
	sscape_sleeper = &chn;
	DO_SLEEP(chn, sscape_sleep_flag, 1);

	done = 1;
    }

    splx(flags);
    if (!done)
	return 0;

    if (flag & CPF_LAST) {
	/*
	 * Take the board out of reset
	 */
	outb(PORT(HOST_CTRL), 0x00);
	outb(PORT(MIDI_CTRL), 0x00);

	temp = sscape_read(devc, GA_HMCTL_REG);
	temp |= 0x40;
	sscape_write(devc, GA_HMCTL_REG, temp);	/* Kickstart the board */

	/*
	 * Wait until the ODB wakes up
	 */

	flags = splhigh();
	done = 0;
	timeout_val = 5 * hz;
	while (!done && timeout_val-- > 0) {
	  int   chn;

	  sscape_sleeper = &chn;
	  DO_SLEEP(chn, sscape_sleep_flag, 1);

	  if (inb(PORT(HOST_DATA)) == 0xff)	/* OBP startup acknowledge */
	    done = 1;
	}
	splx(flags);
	if (!done) {
	    printf("SoundScape: The OBP didn't respond after code download\n");
	    return 0;
	}
	flags = splhigh();
	done = 0;
	timeout_val = 5 * hz;
	while (!done && timeout_val-- > 0) {
	  int   chn;

	  sscape_sleeper = &chn;
	  DO_SLEEP(chn, sscape_sleep_flag, 1);

	  if (inb(PORT(HOST_DATA)) == 0xfe)	/* Host startup acknowledge */
	    done = 1;
	}
	splx(flags);
	if (!done) {
	    printf("SoundScape: OBP Initialization failed.\n");
	    return 0;
	}
	printf("SoundScape board of type %d initialized OK\n",
	       get_board_type(devc));

	set_control(devc, CTL_MASTER_VOL, 100);
	set_control(devc, CTL_SYNTH_VOL, 100);

#ifdef SSCAPE_DEBUG3
	/*
	 * Temporary debugging aid. Print contents of the registers
	 * after downloading the code.
	 */
	{
	    int             i;

	    for (i = 0; i < 13; i++)
		printf("I%d = %02x (new value)\n", i, sscape_read(devc, i));
	}
#endif

    }
    return 1;
}
Пример #15
0
void
attach_ss_ms_sound (struct address_info *hw_config)
{
  /*
     * This routine configures the SoundScape card for use with the
     * Win Sound System driver. The AD1848 codec interface uses the CD-ROM
     * config registers of the "ODIE".
   */

  int             i, irq_bits = 0xff;

  int             prev_devs = num_audiodevs;

  hw_config->dma = devc->dma;	/* Share the DMA with the ODIE/OPUS chip */

  /*
   * Setup the DMA polarity.
   */
  sscape_write (devc, GA_DMACFG_REG, 0x50);

  /*
     * Take the gate-array off of the DMA channel.
   */
  sscape_write (devc, GA_DMAB_REG, 0x20);

  /*
     * Init the AD1848 (CD-ROM) config reg.
   */

  for (i = 0; i < sizeof (valid_interrupts); i++)
    if (hw_config->irq == valid_interrupts[i])
      {
	irq_bits = i;
	break;
      }

  sscape_write (devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) |
		(irq_bits << 1));

  if (hw_config->irq == devc->irq)
    printk ("SoundScape: Warning! The WSS mode can't share IRQ with MIDI\n");

  ad1848_init ("SoundScape", hw_config->io_base,
	       hw_config->irq,
	       hw_config->dma,
	       hw_config->dma,
	       0,
	       devc->osp);

  if (num_audiodevs == (prev_devs + 1))		/* The AD1848 driver installed itself */
    audio_devs[prev_devs]->coproc = &sscape_coproc_operations;
  devc->my_audiodev = prev_devs;

#ifdef SSCAPE_DEBUG5
  /*
     * Temporary debugging aid. Print contents of the registers
     * after the AD1848 device has been initialized.
   */
  {
    int             i;

    for (i = 0; i < 13; i++)
      printk ("I%d = %02x\n", i, sscape_read (devc, i));
  }
#endif

}
Пример #16
0
int
probe_sscape (struct address_info *hw_config)
{
  unsigned char   save;

  devc->failed = 1;
  devc->base = hw_config->io_base;
  devc->irq = hw_config->irq;
  devc->dma = hw_config->dma;
  devc->osp = hw_config->osp;

  if (sscape_detected != 0 && sscape_detected != hw_config->io_base)
    return 0;

  /*
     * First check that the address register of "ODIE" is
     * there and that it has exactly 4 writable bits.
     * First 4 bits
   */
  if ((save = inb (PORT (ODIE_ADDR))) & 0xf0)
    return 0;

  outb (0x00, PORT (ODIE_ADDR));
  if (inb (PORT (ODIE_ADDR)) != 0x00)
    return 0;

  outb (0xff, PORT (ODIE_ADDR));
  if (inb (PORT (ODIE_ADDR)) != 0x0f)
    return 0;

  outb (save, PORT (ODIE_ADDR));

  /*
     * Now verify that some indirect registers return zero on some bits.
     * This may break the driver with some future revisions of "ODIE" but...
   */

  if (sscape_read (devc, 0) & 0x0c)
    return 0;

  if (sscape_read (devc, 1) & 0x0f)
    return 0;

  if (sscape_read (devc, 5) & 0x0f)
    return 0;

#ifdef SSCAPE_DEBUG1
  /*
     * Temporary debugging aid. Print contents of the registers before
     * changing them.
   */
  {
    int             i;

    for (i = 0; i < 13; i++)
      printk ("I%d = %02x (old value)\n", i, sscape_read (devc, i));
  }
#endif

  if (old_hardware)		/* Check that it's really an old Spea/Reveal card. */
    {
      unsigned char   tmp;
      int             cc;

      if (!((tmp = sscape_read (devc, GA_HMCTL_REG)) & 0xc0))
	{
	  sscape_write (devc, GA_HMCTL_REG, tmp | 0x80);
	  for (cc = 0; cc < 200000; ++cc)
	    inb (devc->base + ODIE_ADDR);
	}
      else
	old_hardware = 0;
    }


  sscape_detected = hw_config->io_base;

  return 1;
}
Пример #17
0
static int
sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size, int flag)
{
  unsigned long   flags;
  unsigned char   temp;
  int             done, timeout_val;
  static unsigned char codec_dma_bits = 0;

  if (flag & CPF_FIRST)
    {
      /*
         * First block. Have to allocate DMA and to reset the board
         * before continuing.
       */

      save_flags (flags);
      cli ();
      codec_dma_bits = sscape_read (devc, GA_CDCFG_REG);
#if 0
      sscape_write (devc, GA_CDCFG_REG,
		    codec_dma_bits & ~0x08);	/* Disable codec DMA */
#endif

      if (devc->dma_allocated == 0)
	{
	  devc->dma_allocated = 1;
	}
      restore_flags (flags);

      sscape_write (devc, GA_HMCTL_REG,
		    (temp = sscape_read (devc, GA_HMCTL_REG)) & 0x3f);	/*Reset */

      for (timeout_val = 10000; timeout_val > 0; timeout_val--)
	sscape_read (devc, GA_HMCTL_REG);	/* Delay */

      /* Take board out of reset */
      sscape_write (devc, GA_HMCTL_REG,
		    (temp = sscape_read (devc, GA_HMCTL_REG)) | 0x80);
    }

  /*
   * Transfer one code block using DMA
   */
  memcpy (audio_devs[devc->my_audiodev]->dmap_out->raw_buf, block, size);

  save_flags (flags);
  cli ();
/******** INTERRUPTS DISABLED NOW ********/
  do_dma (devc, SSCAPE_DMA_A,
	  audio_devs[devc->my_audiodev]->dmap_out->raw_buf_phys,
	  size, DMA_MODE_WRITE);

  /*
   * Wait until transfer completes.
   */
  sscape_sleep_flag.flags = WK_NONE;
  done = 0;
  timeout_val = 100;
  while (!done && timeout_val-- > 0)
    {
      int             resid;


      {
	unsigned long   tlimit;

	if (1)
	  current_set_timeout (tlimit = jiffies + (1));
	else
	  tlimit = (unsigned long) -1;
	sscape_sleep_flag.flags = WK_SLEEP;
	module_interruptible_sleep_on (&sscape_sleeper);
	if (!(sscape_sleep_flag.flags & WK_WAKEUP))
	  {
	    if (jiffies >= tlimit)
	      sscape_sleep_flag.flags |= WK_TIMEOUT;
	  }
	sscape_sleep_flag.flags &= ~WK_SLEEP;
      };
      clear_dma_ff (devc->dma);
      if ((resid = get_dma_residue (devc->dma)) == 0)
	{
	  done = 1;
	}
    }

  restore_flags (flags);
  if (!done)
    return 0;

  if (flag & CPF_LAST)
    {
      /*
         * Take the board out of reset
       */
      outb (0x00, PORT (HOST_CTRL));
      outb (0x00, PORT (MIDI_CTRL));

      temp = sscape_read (devc, GA_HMCTL_REG);
      temp |= 0x40;
      sscape_write (devc, GA_HMCTL_REG, temp);	/* Kickstart the board */

      /*
         * Wait until the ODB wakes up
       */

      save_flags (flags);
      cli ();
      done = 0;
      timeout_val = 5 * HZ;
      while (!done && timeout_val-- > 0)
	{

	  {
	    unsigned long   tlimit;

	    if (1)
	      current_set_timeout (tlimit = jiffies + (1));
	    else
	      tlimit = (unsigned long) -1;
	    sscape_sleep_flag.flags = WK_SLEEP;
	    module_interruptible_sleep_on (&sscape_sleeper);
	    if (!(sscape_sleep_flag.flags & WK_WAKEUP))
	      {
		if (jiffies >= tlimit)
		  sscape_sleep_flag.flags |= WK_TIMEOUT;
	      }
	    sscape_sleep_flag.flags &= ~WK_SLEEP;
	  };
	  if (inb (PORT (HOST_DATA)) == 0xff)	/* OBP startup acknowledge */
	    done = 1;
	}
      sscape_write (devc, GA_CDCFG_REG, codec_dma_bits);

      restore_flags (flags);
      if (!done)
	{
	  printk ("SoundScape: The OBP didn't respond after code download\n");
	  return 0;
	}

      save_flags (flags);
      cli ();
      done = 0;
      timeout_val = 5 * HZ;
      while (!done && timeout_val-- > 0)
	{

	  {
	    unsigned long   tlimit;

	    if (1)
	      current_set_timeout (tlimit = jiffies + (1));
	    else
	      tlimit = (unsigned long) -1;
	    sscape_sleep_flag.flags = WK_SLEEP;
	    module_interruptible_sleep_on (&sscape_sleeper);
	    if (!(sscape_sleep_flag.flags & WK_WAKEUP))
	      {
		if (jiffies >= tlimit)
		  sscape_sleep_flag.flags |= WK_TIMEOUT;
	      }
	    sscape_sleep_flag.flags &= ~WK_SLEEP;
	  };
	  if (inb (PORT (HOST_DATA)) == 0xfe)	/* Host startup acknowledge */
	    done = 1;
	}
      restore_flags (flags);
      if (!done)
	{
	  printk ("SoundScape: OBP Initialization failed.\n");
	  return 0;
	}

      printk ("SoundScape board of type %d initialized OK\n",
	      get_board_type (devc));

      set_control (devc, CTL_MASTER_VOL, 100);
      set_control (devc, CTL_SYNTH_VOL, 100);

#ifdef SSCAPE_DEBUG3
      /*
         * Temporary debugging aid. Print contents of the registers after
         * downloading the code.
       */
      {
	int             i;

	for (i = 0; i < 13; i++)
	  printk ("I%d = %02x (new value)\n", i, sscape_read (devc, i));
      }
#endif

    }

  return 1;
}
Пример #18
0
void
attach_sscape(struct address_info * hw_config)
{
#ifndef SSCAPE_REGS
    /*
     * Config register values for Spea/V7 Media FX and Ensoniq S-2000.
     * These values are card dependent. If you have another SoundScape
     * based card, you have to find the correct values. Do the following:
     * - Compile this driver with SSCAPE_DEBUG1 defined. - Shut down and
     * power off your machine. - Boot with DOS so that the SSINIT.EXE
     * program is run. - Warm boot to {Linux|SYSV|BSD} and write down the
     * lines displayed when detecting the SoundScape. - Modify the
     * following list to use the values printed during boot. Undefine the
     * SSCAPE_DEBUG1
     */
#define SSCAPE_REGS { \
/* I0 */	0x00, \
		0xf0, /* Note! Ignored. Set always to 0xf0 */ \
		0x20, /* Note! Ignored. Set always to 0x20 */ \
		0x20, /* Note! Ignored. Set always to 0x20 */ \
		0xf5, /* Ignored */ \
		0x10, \
		0x00, \
		0x2e, /* I7 MEM config A. Likely to vary between models */ \
		0x00, /* I8 MEM config B. Likely to vary between models */ \
/* I9 */	0x40 /* Ignored */ \
	}
#endif

    u_long   flags;
    static u_char regs[10] = SSCAPE_REGS;

    int             i, irq_bits = 0xff;

    if (sscape_detected != hw_config->io_base)
	return;

    if (old_hardware) {
	valid_interrupts = valid_interrupts_old;
	conf_printf("Ensoniq Soundscape (old)", hw_config);
    } else
	conf_printf("Ensoniq Soundscape", hw_config);

    for (i = 0; i < sizeof(valid_interrupts); i++)
	if (hw_config->irq == valid_interrupts[i]) {
	    irq_bits = i;
	    break;
	}
    if (hw_config->irq > 15 || (regs[4] = irq_bits == 0xff)) {
	printf("Invalid IRQ%d\n", hw_config->irq);
	return;
    }
    flags = splhigh();

    for (i = 1; i < 10; i++)
	switch (i) {
	case 1:	/* Host interrupt enable */
	    sscape_write(devc, i, 0xf0);	/* All interrupts enabled */
	    break;

	case 2:	/* DMA A status/trigger register */
	case 3:	/* DMA B status/trigger register */
	    sscape_write(devc, i, 0x20);	/* DMA channel disabled */
	    break;

	case 4:	/* Host interrupt config reg */
	    sscape_write(devc, i, 0xf0 | (irq_bits << 2) | irq_bits);
	    break;

	case 5:	/* Don't destroy CD-ROM DMA config bits (0xc0) */
	    sscape_write(devc, i, (regs[i] & 0x3f) |
			 (sscape_read(devc, i) & 0xc0));
	    break;

	case 6:	/* CD-ROM config. Don't touch. */
	    break;

	case 9:	/* Master control reg. Don't modify CR-ROM
		 * bits. Disable SB emul */
	    sscape_write(devc, i, (sscape_read(devc, i) & 0xf0) | 0x00);
	    break;

	default:
	    sscape_write(devc, i, regs[i]);
	}

    splx(flags);

#ifdef SSCAPE_DEBUG2
    /*
     * Temporary debugging aid. Print contents of the registers after
     * changing them.
     */
    {
	int             i;

	for (i = 0; i < 13; i++)
	    printf("I%d = %02x (new value)\n", i, sscape_read(devc, i));
    }
#endif

#if defined(CONFIG_MIDI) && defined(CONFIG_MPU_EMU)
    if (probe_mpu401(hw_config))
	hw_config->always_detect = 1;
    {
	int             prev_devs;

	prev_devs = num_midis;
	attach_mpu401(hw_config);

	if (num_midis == (prev_devs + 1))	/* The MPU driver
						 * installed itself */
	    midi_devs[prev_devs]->coproc = &sscape_coproc_operations;
    }
#endif

#ifndef EXCLUDE_NATIVE_PCM
    /* Not supported yet */

#ifdef CONFIG_AUDIO
    if (num_audiodevs < MAX_AUDIO_DEV) {
	int my_dev;

	audio_devs[my_dev = num_audiodevs++] = &sscape_audio_operations;
	audio_devs[my_dev]->dmachan1 = hw_config->dma;
	audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
	audio_devs[my_dev]->devc = devc;
	devc->my_audiodev = my_dev;
	devc->opened = 0;
	audio_devs[my_dev]->coproc = &sscape_coproc_operations;
	if (snd_set_irq_handler(hw_config->irq, sscapeintr, devc->osp) < 0)
	    printf("Error: Can't allocate IRQ for SoundScape\n");
	sscape_write(devc, GA_INTENA_REG, 0x80);	/* Master IRQ enable */
    } else
	printf("SoundScape: More than enough audio devices detected\n");
#endif
#endif
    devc->ok = 1;
    devc->failed = 0;
    return;
}
Пример #19
0
static	int	sscape_pnp_upload_file(sscape_info* devc, char* fn)
{	
	int	     	done = 0;
	int	     	timeout_val;
	char*	     	data,*dt;
	int	     	len,l;
	unsigned long	flags;

	sscape_write( devc, 9, sscape_read(devc, 9 )  & 0x3F );
	sscape_write( devc, 2, (devc -> dma << 4) | 0x80 );
	sscape_write( devc, 3, 0x20 );
	sscape_write( devc, 9, sscape_read( devc, 9 )  | 0x80 );
	
	len = mod_firmware_load(fn, &data);
	if (len == 0) {
		    printk(KERN_ERR "sscape: file not found: %s\n", fn);
		    return 0;
	}
	dt = data;
	save_flags(flags);
	cli();
	while ( len > 0 ) {
		if (len > devc -> buffsize) l = devc->buffsize;
		else l = len;
		len -= l;		
		memcpy(devc->raw_buf, dt, l); dt += l;
		sscape_start_dma(devc->dma, devc->raw_buf_phys, l, 0x48);
		sscape_pnp_start_dma ( devc, 0 );
		if (sscape_pnp_wait_dma ( devc, 0 ) == 0) {
			restore_flags(flags);	    
			return 0;
		}
	}
	
	restore_flags(flags);	    
	vfree(data);
	
	outb(0, devc -> base + 2);
	outb(0, devc -> base);

	sscape_write ( devc, 9, sscape_read( devc, 9 ) | 0x40);

	timeout_val = 5 * HZ; 
	while (!done && timeout_val-- > 0)
	{
		unsigned char x;
		sleep(1);
		x = inb( devc -> base + 3);
		if (x == 0xff || x == 0xfe)		/* OBP startup acknowledge */
		{
			//printk(KERN_ERR "Soundscape: Acknowledge = %x\n", x);
			done = 1;
		}
	}
	timeout_val = 5 * HZ;
	done = 0;
	while (!done && timeout_val-- > 0)
	{
		unsigned char x;
		sleep(1);
		x = inb( devc -> base + 3);
		if (x == 0xfe)		/* OBP startup acknowledge */
		{
			//printk(KERN_ERR "Soundscape: Acknowledge = %x\n", x);
			done = 1;
		}
	}

	if ( !done ) printk(KERN_ERR "soundscape: OBP Initialization failed.\n");

	sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40);
	sscape_write( devc, 3, (devc -> dma << 4) + 0x80);
	return 1;
}
Пример #20
0
static int __init init_ss_ms_sound(struct address_info *hw_config)
{
    int i, irq_bits = 0xff;
    int ad_flags = 0;
    struct resource *ports;

    if (devc->failed)
    {
        printk(KERN_ERR "soundscape: Card not detected\n");
        return 0;
    }
    if (devc->ok == 0)
    {
        printk(KERN_ERR "soundscape: Invalid initialization order.\n");
        return 0;
    }
    for (i = 0; i < 4; i++)
    {
        if (hw_config->irq == valid_interrupts[i])
        {
            irq_bits = i;
            break;
        }
    }
    if (irq_bits == 0xff) {
        printk(KERN_ERR "soundscape: Invalid MSS IRQ%d\n", hw_config->irq);
        return 0;
    }

    if (old_hardware)
        ad_flags = 0x12345677;	/* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */
    else if (sscape_is_pnp)
        ad_flags = 0x87654321;  /* Tell that we have a soundscape pnp with 1845 chip */

    ports = request_region(hw_config->io_base, 4, "ad1848");
    if (!ports) {
        printk(KERN_ERR "soundscape: ports busy\n");
        return 0;
    }

    if (!ad1848_detect(ports, &ad_flags, hw_config->osp)) {
        release_region(hw_config->io_base, 4);
        return 0;
    }

    if (!sscape_is_pnp)  /*pnp is already setup*/
    {
        /*
        	 * Setup the DMA polarity.
        	 */
        sscape_write(devc, GA_DMACFG_REG, 0x50);

        /*
         * Take the gate-array off of the DMA channel.
         */
        sscape_write(devc, GA_DMAB_REG, 0x20);

        /*
         * Init the AD1848 (CD-ROM) config reg.
         */
        sscape_write(devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) | (irq_bits << 1));
    }

    if (hw_config->irq == devc->irq)
        printk(KERN_WARNING "soundscape: Warning! The WSS mode can't share IRQ with MIDI\n");

    hw_config->slots[0] = ad1848_init(
                              sscape_is_pnp ? "SoundScape" : "SoundScape PNP",
                              ports,
                              hw_config->irq,
                              hw_config->dma,
                              hw_config->dma,
                              0,
                              devc->osp,
                              THIS_MODULE);


    if (hw_config->slots[0] != -1)	/* The AD1848 driver installed itself */
    {
        audio_devs[hw_config->slots[0]]->coproc = &sscape_coproc_operations;
        devc->codec_audiodev = hw_config->slots[0];
        devc->my_audiodev = hw_config->slots[0];

        /* Set proper routings here (what are they) */
        AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE);
    }

#ifdef SSCAPE_DEBUG5
    /*
     * Temporary debugging aid. Print contents of the registers
     * after the AD1848 device has been initialized.
     */
    {
        int i;

        for (i = 0; i < 13; i++)
            printk("I%d = %02x\n", i, sscape_read(devc, i));
    }
#endif
    return 1;
}