⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sb_common.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 */	DDB(printk("sb_dsp_init(%x) entered\n", hw_config->io_base));	name[0] = 0;	if (detected_devc == NULL)	{		MDB(printk("No detected device\n"));		return 0;	}	devc = detected_devc;	detected_devc = NULL;	if (devc->base != hw_config->io_base)	{		DDB(printk("I/O port mismatch\n"));		return 0;	}	/*	 * Now continue initialization of the device	 */	devc->caps = hw_config->driver_use_1;	if (!((devc->caps & SB_NO_AUDIO) && (devc->caps & SB_NO_MIDI)) && hw_config->irq > 0)	{			/* IRQ setup */				/*		 *	ESS PCI cards do shared PCI IRQ stuff. Since they		 *	will get shared PCI irq lines we must cope.		 */		 		int i=(devc->caps&SB_PCI_IRQ)?SA_SHIRQ:0;				if (request_irq(hw_config->irq, sbintr, i, "soundblaster", devc) < 0)		{			printk(KERN_ERR "SB: Can't allocate IRQ%d\n", hw_config->irq);			return 0;		}		devc->irq_ok = 0;		if (devc->major == 4)			if (!sb16_set_irq_hw(devc, devc->irq))	/* Unsupported IRQ */			{				free_irq(devc->irq, devc);				return 0;			}		if ((devc->type == 0 || devc->type == MDL_ESS) &&			devc->major == 3 && devc->minor == 1)		{		/* Handle various chipsets which claim they are SB Pro compatible */			if ((devc->type != 0 && devc->type != MDL_ESS) ||				!ess_init(devc, hw_config))			{				if ((devc->type != 0 && devc->type != MDL_JAZZ &&					 devc->type != MDL_SMW) || !init_Jazz16(devc, hw_config))				{					DDB(printk("This is a genuine SB Pro\n"));				}			}		}		if (devc->major == 4 && devc->minor <= 11 )	/* Won't work */			devc->irq_ok = 1;		else		{			int n;			for (n = 0; n < 3 && devc->irq_ok == 0; n++)			{				if (sb_dsp_command(devc, 0xf2))	/* Cause interrupt immediately */				{					int i;					for (i = 0; !devc->irq_ok && i < 10000; i++);				}			}			if (!devc->irq_ok)				printk(KERN_WARNING "sb: Interrupt test on IRQ%d failed - Probable IRQ conflict\n", devc->irq);			else			{				DDB(printk("IRQ test OK (IRQ%d)\n", devc->irq));			}		}	}			/* IRQ setup */	request_region(hw_config->io_base, 16, "soundblaster");	last_sb = devc;		switch (devc->major)	{		case 1:		/* SB 1.0 or 1.5 */			devc->model = hw_config->card_subtype = MDL_SB1;			break;		case 2:		/* SB 2.x */			if (devc->minor == 0)				devc->model = hw_config->card_subtype = MDL_SB2;			else				devc->model = hw_config->card_subtype = MDL_SB201;			break;		case 3:		/* SB Pro and most clones */			switch (devc->model) {			case 0:				devc->model = hw_config->card_subtype = MDL_SBPRO;				if (hw_config->name == NULL)					hw_config->name = "Sound Blaster Pro (8 BIT ONLY)";				break;			case MDL_ESS:				ess_dsp_init(devc, hw_config);				break;			}			break;		case 4:			devc->model = hw_config->card_subtype = MDL_SB16;			/* 			 * ALS007 and ALS100 return DSP version 4.2 and have 2 post-reset !=0			 * registers at 0x3c and 0x4c (output ctrl registers on ALS007) whereas			 * a "standard" SB16 doesn't have a register at 0x4c.  ALS100 actively			 * updates register 0x22 whenever 0x30 changes, as per the SB16 spec.			 * Since ALS007 doesn't, this can be used to differentiate the 2 cards.			 */			if ((devc->minor == 2) && sb_getmixer(devc,0x3c) && sb_getmixer(devc,0x4c)) 			{				mixer30 = sb_getmixer(devc,0x30);				sb_setmixer(devc,0x22,(mixer22=sb_getmixer(devc,0x22)) & 0x0f);				sb_setmixer(devc,0x30,0xff);				/* ALS100 will force 0x30 to 0xf8 like SB16; ALS007 will allow 0xff. */				/* Register 0x22 & 0xf0 on ALS100 == 0xf0; on ALS007 it == 0x10.     */				if ((sb_getmixer(devc,0x30) != 0xff) || ((sb_getmixer(devc,0x22) & 0xf0) != 0x10)) 				{					devc->submodel = SUBMDL_ALS100;					if (hw_config->name == NULL)						hw_config->name = "Sound Blaster 16 (ALS-100)";        			}        			else        			{        				sb_setmixer(devc,0x3c,0x1f);    /* Enable all inputs */					sb_setmixer(devc,0x4c,0x1f);					sb_setmixer(devc,0x22,mixer22); /* Restore 0x22 to original value */					devc->submodel = SUBMDL_ALS007;					if (hw_config->name == NULL)						hw_config->name = "Sound Blaster 16 (ALS-007)";				}				sb_setmixer(devc,0x30,mixer30);			}			else if (hw_config->name == NULL)				hw_config->name = "Sound Blaster 16";			if (hw_config->dma2 == -1)				devc->dma16 = devc->dma8;			else if (hw_config->dma2 < 5 || hw_config->dma2 > 7)			{				printk(KERN_WARNING  "SB16: Bad or missing 16 bit DMA channel\n");				devc->dma16 = devc->dma8;			}			else				devc->dma16 = hw_config->dma2;			if(!sb16_set_dma_hw(devc)) {				free_irq(devc->irq, devc);			        release_region(hw_config->io_base, 16);				return 0;			}			devc->caps |= SB_NO_MIDI;	}	if (!(devc->caps & SB_NO_MIXER))		if (devc->major == 3 || devc->major == 4)			sb_mixer_init(devc, owner);	if (!(devc->caps & SB_NO_MIDI))		sb_dsp_midi_init(devc, owner);	if (hw_config->name == NULL)		hw_config->name = "Sound Blaster (8 BIT/MONO ONLY)";	sprintf(name, "%s (%d.%02d)", hw_config->name, devc->major, devc->minor);	conf_printf(name, hw_config);	/*	 * Assuming that a sound card is Sound Blaster (compatible) is the most common	 * configuration error and the mother of all problems. Usually sound cards	 * emulate SB Pro but in addition they have a 16 bit native mode which should be	 * used in Unix. See Readme.cards for more information about configuring OSS/Free	 * properly.	 */	if (devc->model <= MDL_SBPRO)	{		if (devc->major == 3 && devc->minor != 1)	/* "True" SB Pro should have v3.1 (rare ones may have 3.2). */		{			printk(KERN_INFO "This sound card may not be fully Sound Blaster Pro compatible.\n");			printk(KERN_INFO "In many cases there is another way to configure OSS so that\n");			printk(KERN_INFO "it works properly with OSS (for example in 16 bit mode).\n");			printk(KERN_INFO "Please ignore this message if you _really_ have a SB Pro.\n");		}		else if (!sb_be_quiet && devc->model == MDL_SBPRO)		{			printk(KERN_INFO "SB DSP version is just %d.%02d which means that your card is\n", devc->major, devc->minor);			printk(KERN_INFO "several years old (8 bit only device) or alternatively the sound driver\n");			printk(KERN_INFO "is incorrectly configured.\n");		}	}	hw_config->card_subtype = devc->model;	hw_config->slots[0]=devc->dev;	last_devc = devc;	/* For SB MPU detection */	if (!(devc->caps & SB_NO_AUDIO) && devc->dma8 >= 0)	{		if (sound_alloc_dma(devc->dma8, "SoundBlaster8"))		{			printk(KERN_WARNING "Sound Blaster: Can't allocate 8 bit DMA channel %d\n", devc->dma8);		}		if (devc->dma16 >= 0 && devc->dma16 != devc->dma8)		{			if (sound_alloc_dma(devc->dma16, "SoundBlaster16"))				printk(KERN_WARNING "Sound Blaster:  can't allocate 16 bit DMA channel %d.\n", devc->dma16);		}		sb_audio_init(devc, name, owner);		hw_config->slots[0]=devc->dev;	}	else	{		MDB(printk("Sound Blaster:  no audio devices found.\n"));	}	return 1;}void sb_dsp_disable_midi(int io_base){}void sb_dsp_disable_recording(int io_base){}/* if (sbmpu) below we allow mpu401 to manage the midi devs   otherwise we have to unload them. (Andrzej Krzysztofowicz) */   void sb_dsp_unload(struct address_info *hw_config, int sbmpu){	sb_devc *devc;	devc = audio_devs[hw_config->slots[0]]->devc;	if (devc && devc->base == hw_config->io_base)	{		if ((devc->model & MDL_ESS) && devc->pcibase)			release_region(devc->pcibase, 8);		release_region(devc->base, 16);		if (!(devc->caps & SB_NO_AUDIO))		{			sound_free_dma(devc->dma8);			if (devc->dma16 >= 0)				sound_free_dma(devc->dma16);		}		if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI))		{			if (devc->irq > 0)				free_irq(devc->irq, devc);			sb_mixer_unload(devc);			/* We don't have to do this bit any more the UART401 is its own				master  -- Krzysztof Halasa */			/* But we have to do it, if UART401 is not detected */			if (!sbmpu)				sound_unload_mididev(devc->my_mididev);			sound_unload_audiodev(devc->dev);		}		kfree(devc);	}	else		release_region(hw_config->io_base, 16);	if(detected_devc)		kfree(detected_devc);}/* *	Mixer access routines * *	ES1887 modifications: some mixer registers reside in the *	range above 0xa0. These must be accessed in another way. */void sb_setmixer(sb_devc * devc, unsigned int port, unsigned int value){	unsigned long flags;	if (devc->model == MDL_ESS) return ess_setmixer (devc, port, value);	save_flags(flags);	cli();	outb(((unsigned char) (port & 0xff)), MIXER_ADDR);	udelay(20);	outb(((unsigned char) (value & 0xff)), MIXER_DATA);	udelay(20);	restore_flags(flags);}unsigned int sb_getmixer(sb_devc * devc, unsigned int port){	unsigned int val;	unsigned long flags;	if (devc->model == MDL_ESS) return ess_getmixer (devc, port);	save_flags(flags);	cli();	outb(((unsigned char) (port & 0xff)), MIXER_ADDR);	udelay(20);	val = inb(MIXER_DATA);	udelay(20);	restore_flags(flags);	return val;}void sb_chgmixer	(sb_devc * devc, unsigned int reg, unsigned int mask, unsigned int val){	int value;	value = sb_getmixer(devc, reg);	value = (value & ~mask) | (val & mask);	sb_setmixer(devc, reg, value);}/* *	MPU401 MIDI initialization. */static void smw_putmem(sb_devc * devc, int base, int addr, unsigned char val){	unsigned long flags;	save_flags(flags);	cli();	outb((addr & 0xff), base + 1);	/* Low address bits */	outb((addr >> 8), base + 2);	/* High address bits */	outb((val), base);	/* Data */	restore_flags(flags);}static unsigned char smw_getmem(sb_devc * devc, int base, int addr){	unsigned long flags;	unsigned char val;	save_flags(flags);	cli();	outb((addr & 0xff), base + 1);	/* Low address bits */	outb((addr >> 8), base + 2);	/* High address bits */	val = inb(base);	/* Data */	restore_flags(flags);	return val;}static int smw_midi_init(sb_devc * devc, struct address_info *hw_config){	int mpu_base = hw_config->io_base;	int mp_base = mpu_base + 4;		/* Microcontroller base */	int i;	unsigned char control;	/*	 *  Reset the microcontroller so that the RAM can be accessed	 */	control = inb(mpu_base + 7);	outb((control | 3), mpu_base + 7);	/* Set last two bits to 1 (?) */	outb(((control & 0xfe) | 2), mpu_base + 7);	/* xxxxxxx0 resets the mc */	mdelay(3);	/* Wait at least 1ms */	outb((control & 0xfc), mpu_base + 7);	/* xxxxxx00 enables RAM */	/*	 *  Detect microcontroller by probing the 8k RAM area	 */	smw_putmem(devc, mp_base, 0, 0x00);	smw_putmem(devc, mp_base, 1, 0xff);	udelay(10);	if (smw_getmem(devc, mp_base, 0) != 0x00 || smw_getmem(devc, mp_base, 1) != 0xff)	{		DDB(printk("SM Wave: No microcontroller RAM detected (%02x, %02x)\n", smw_getmem(devc, mp_base, 0), smw_getmem(devc, mp_base, 1)));		return 0;	/* No RAM */	}	/*	 *  There is RAM so assume it's really a SM Wave	 */	devc->model = MDL_SMW;	smw_mixer_init(devc);#ifdef MODULE	if (!smw_ucode)	{		smw_ucodeLen = mod_firmware_load("/etc/sound/midi0001.bin", (void *) &smw_ucode);		smw_free = smw_ucode;	}#endif	if (smw_ucodeLen > 0)	{		if (smw_ucodeLen != 8192)		{			printk(KERN_ERR "SM Wave: Invalid microcode (MIDI0001.BIN) length\n");			return 1;		}		/*		 *  Download microcode		 */		for (i = 0; i < 8192; i++)			smw_putmem(devc, mp_base, i, smw_ucode[i]);		/*		 *  Verify microcode		 */		for (i = 0; i < 8192; i++)			if (smw_getmem(devc, mp_base, i) != smw_ucode[i])			{				printk(KERN_ERR "SM Wave: Microcode verification failed\n");				return 0;			}	}	control = 0;#ifdef SMW_SCSI_IRQ	/*	 * Set the SCSI interrupt (IRQ2/9, IRQ3 or IRQ10). The SCSI interrupt	 * is disabled by default.	 *	 * FIXME - make this a module option	 *	 * BTW the Zilog 5380 SCSI controller is located at MPU base + 0x10.	 */	{		static unsigned char scsi_irq_bits[] = {			0, 0, 3, 1, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0		};		control |= scsi_irq_bits[SMW_SCSI_IRQ] << 6;	}#endif#ifdef SMW_OPL4_ENABLE	/*	 *  Make the OPL4 chip visible on the PC bus at 0x380.	 *	 *  There is no need to enable this feature since this driver	 *  doesn't support OPL4 yet. Also there is no RAM in SM Wave so	 *  enabling OPL4 is pretty useless.	 */	control |= 0x10;	/* Uses IRQ12 if bit 0x20 == 0 */	/* control |= 0x20;      Uncomment this if you want to use IRQ7 */#endif	outb((control | 0x03), mpu_base + 7);	/* xxxxxx11 restarts */	hw_config->name = "SoundMan Wave";	return 1;}static int init_Jazz16_midi(sb_devc * devc, struct address_info *hw_config){	int mpu_base = hw_config->io_base;	int sb_base = devc->base;	int irq = hw_config->irq;	unsigned char bits = 0;	unsigned long flags;	if (irq < 0)		irq *= -1;	if (irq < 1 || irq > 15 ||	    jazz_irq_bits[irq] == 0)	{		printk(KERN_ERR "Jazz16: Invalid MIDI interrupt (IRQ%d)\n", irq);		return 0;	}	switch (sb_base)	{		case 0x220:			bits = 1;			break;		case 0x240:			bits = 2;			break;		case 0x260:			bits = 3;			break;		default:			return 0;	}	bits = jazz16_bits = bits << 5;	switch (mpu_base)	{		case 0x310:			bits |= 1;			break;		case 0x320:			bits |= 2;			break;		case 0x330:			bits |= 3;			break;		default:			printk(KERN_ERR "Jazz16: Invalid MIDI I/O port %x\n", mpu_base);			return 0;	}	/*	 *	Magic wake up sequence by writing to 0x201 (aka Joystick port)	 */	save_flags(flags);	cli();	outb(0xAF, 0x201);	outb(0x50, 0x201);	outb(bits, 0x201);	restore_flags(flags);	hw_config->name = "Jazz16";	smw_midi_init(devc, hw_config);	if (!sb_dsp_command(devc, 0xfb))		return 0;	if (!sb_dsp_command(devc, jazz_dma_bits[devc->dma8] |			    (jazz_dma_bits[devc->dma16] << 4)))		return 0;	if (!sb_dsp_command(devc, jazz_irq_bits[devc->irq] |			    (jazz_irq_bits[irq] << 4)))		return 0;	return 1;}int probe_sbmpu(struct address_info *hw_config, struct module *owner){	sb_devc *devc = last_devc;	int ret;	if (last_devc == NULL)		return 0;	last_devc = 0;	if (hw_config->io_base <= 0)	{		/* The real vibra16 is fine about this, but we have to go		   wipe up after Cyrix again */		   	   		if(devc->model == MDL_SB16 && devc->minor >= 12)		{			unsigned char   bits = sb_getmixer(devc, 0x84) & ~0x06;			sb_setmixer(devc, 0x84, bits | 0x02);		/* Disable MPU */		}		return 0;	}#if defined(CONFIG_SOUND_MPU401)	if (devc->model == MDL_ESS)	{		if (check_region(hw_config->io_base, 2))		{			printk(KERN_ERR "sbmpu: I/O port conflict (%x)\n", hw_config->io_base);			return 0;		}		if (!ess_midi_init(devc, hw_config))			return 0;		hw_config->name = "ESS1xxx MPU";		devc->midi_irq_cookie = -1;		if (!probe_mpu401(hw_config))			return 0;		attach_mpu401(hw_config, owner);		if (last_sb->irq == -hw_config->irq)			last_sb->midi_irq_cookie=(void *)hw_config->slots[1];		return 1;	}#endif	switch (devc->model)	{		case MDL_SB16:			if (hw_config->io_base != 0x300 && hw_config->io_base != 0x330)			{				printk(KERN_ERR "SB16: Invalid MIDI port %x\n", hw_config->io_base);				return 0;			}			hw_config->name = "Sound Blaster 16";			if (hw_config->irq < 3 || hw_config->irq == devc->irq)				hw_config->irq = -devc->irq;			if (devc->minor > 12)		/* What is Vibra's version??? */				sb16_set_mpu_port(devc, hw_config);			break;		case MDL_JAZZ:			if (hw_config->irq < 3 || hw_config->irq == devc->irq)				hw_config->irq = -devc->irq;			if (!init_Jazz16_midi(devc, hw_config))				return 0;			break;		case MDL_YMPCI:			hw_config->name = "Yamaha PCI Legacy";			printk("Yamaha PCI legacy UART401 check.\n");			break;		default:			return 0;	}		ret = probe_uart401(hw_config, owner);	if (ret)		last_sb->midi_irq_cookie=midi_devs[hw_config->slots[4]]->devc;	return ret;}void unload_sbmpu(struct address_info *hw_config){#if defined(CONFIG_SOUND_MPU401)	if (!strcmp (hw_config->name, "ESS1xxx MPU")) {		unload_mpu401(hw_config);		return;	}#endif	unload_uart401(hw_config);}EXPORT_SYMBOL(sb_dsp_init);EXPORT_SYMBOL(sb_dsp_detect);EXPORT_SYMBOL(sb_dsp_unload);EXPORT_SYMBOL(sb_dsp_disable_midi);EXPORT_SYMBOL(sb_be_quiet);EXPORT_SYMBOL(probe_sbmpu);EXPORT_SYMBOL(unload_sbmpu);EXPORT_SYMBOL(smw_free);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -