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

📄 wavefront_synth.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
			err = 0;		kfree(wc);		return err;	default:		return -EINVAL;	}	return 0;}/***********************************************************************//*  WaveFront: interface for card-level wavefront module               *//***********************************************************************/voidsnd_wavefront_internal_interrupt (snd_wavefront_card_t *card){	snd_wavefront_t *dev = &card->wavefront;	/*	   Some comments on interrupts. I attempted a version of this	   driver that used interrupts throughout the code instead of	   doing busy and/or sleep-waiting. Alas, it appears that once	   the Motorola firmware is downloaded, the card *never*	   generates an RX interrupt. These are successfully generated	   during firmware loading, and after that wavefront_status()	   reports that an interrupt is pending on the card from time	   to time, but it never seems to be delivered to this	   driver. Note also that wavefront_status() continues to	   report that RX interrupts are enabled, suggesting that I	   didn't goof up and disable them by mistake.	   Thus, I stepped back to a prior version of	   wavefront_wait(), the only place where this really	   matters. Its sad, but I've looked through the code to check	   on things, and I really feel certain that the Motorola	   firmware prevents RX-ready interrupts.	*/	if ((wavefront_status(dev) & (STAT_INTR_READ|STAT_INTR_WRITE)) == 0) {		return;	}	spin_lock(&dev->irq_lock);	dev->irq_ok = 1;	dev->irq_cnt++;	spin_unlock(&dev->irq_lock);	wake_up(&dev->interrupt_sleeper);}/* STATUS REGISTER 0 Host Rx Interrupt Enable (1=Enabled)1 Host Rx Register Full (1=Full)2 Host Rx Interrupt Pending (1=Interrupt)3 Unused4 Host Tx Interrupt (1=Enabled)5 Host Tx Register empty (1=Empty)6 Host Tx Interrupt Pending (1=Interrupt)7 Unused*/static int __initsnd_wavefront_interrupt_bits (int irq){	int bits;	switch (irq) {	case 9:		bits = 0x00;		break;	case 5:		bits = 0x08;		break;	case 12:		bits = 0x10;		break;	case 15:		bits = 0x18;		break;		default:		snd_printk ("invalid IRQ %d\n", irq);		bits = -1;	}	return bits;}static void __initwavefront_should_cause_interrupt (snd_wavefront_t *dev, 				  int val, int port, int timeout){	wait_queue_t wait;	init_waitqueue_entry(&wait, current);	spin_lock_irq(&dev->irq_lock);	add_wait_queue(&dev->interrupt_sleeper, &wait);	dev->irq_ok = 0;	outb (val,port);	spin_unlock_irq(&dev->irq_lock);	while (1) {		if ((timeout = schedule_timeout_interruptible(timeout)) == 0)			return;		if (dev->irq_ok)			return;	}}static int __initwavefront_reset_to_cleanliness (snd_wavefront_t *dev){	int bits;	int hwv[2];	/* IRQ already checked */	bits = snd_wavefront_interrupt_bits (dev->irq);	/* try reset of port */	outb (0x0, dev->control_port);   	/* At this point, the board is in reset, and the H/W initialization	   register is accessed at the same address as the data port.     	   Bit 7 - Enable IRQ Driver		   0 - Tri-state the Wave-Board drivers for the PC Bus IRQs	   1 - Enable IRQ selected by bits 5:3 to be driven onto the PC Bus.     	   Bit 6 - MIDI Interface Select	   0 - Use the MIDI Input from the 26-pin WaveBlaster	   compatible header as the serial MIDI source	   1 - Use the MIDI Input from the 9-pin D connector as the	   serial MIDI source.     	   Bits 5:3 - IRQ Selection	   0 0 0 - IRQ 2/9	   0 0 1 - IRQ 5	   0 1 0 - IRQ 12	   0 1 1 - IRQ 15	   1 0 0 - Reserved	   1 0 1 - Reserved	   1 1 0 - Reserved	   1 1 1 - Reserved     	   Bits 2:1 - Reserved	   Bit 0 - Disable Boot ROM	   0 - memory accesses to 03FC30-03FFFFH utilize the internal Boot ROM	   1 - memory accesses to 03FC30-03FFFFH are directed to external 	   storage.     	*/	/* configure hardware: IRQ, enable interrupts, 	   plus external 9-pin MIDI interface selected	*/	outb (0x80 | 0x40 | bits, dev->data_port);	  	/* CONTROL REGISTER	   0 Host Rx Interrupt Enable (1=Enabled)      0x1	   1 Unused                                    0x2	   2 Unused                                    0x4	   3 Unused                                    0x8	   4 Host Tx Interrupt Enable                 0x10	   5 Mute (0=Mute; 1=Play)                    0x20	   6 Master Interrupt Enable (1=Enabled)      0x40	   7 Master Reset (0=Reset; 1=Run)            0x80	   Take us out of reset, mute output, master + TX + RX interrupts on.	   	   We'll get an interrupt presumably to tell us that the TX	   register is clear.	*/	wavefront_should_cause_interrupt(dev, 0x80|0x40|0x10|0x1,					 dev->control_port,					 (reset_time*HZ)/100);	/* Note: data port is now the data port, not the h/w initialization	   port.	 */	if (!dev->irq_ok) {		snd_printk ("intr not received after h/w un-reset.\n");		goto gone_bad;	} 	/* Note: data port is now the data port, not the h/w initialization	   port.	   At this point, only "HW VERSION" or "DOWNLOAD OS" commands	   will work. So, issue one of them, and wait for TX	   interrupt. This can take a *long* time after a cold boot,	   while the ISC ROM does its RAM test. The SDK says up to 4	   seconds - with 12MB of RAM on a Tropez+, it takes a lot	   longer than that (~16secs). Note that the card understands	   the difference between a warm and a cold boot, so	   subsequent ISC2115 reboots (say, caused by module	   reloading) will get through this much faster.	   XXX Interesting question: why is no RX interrupt received first ?	*/	wavefront_should_cause_interrupt(dev, WFC_HARDWARE_VERSION, 					 dev->data_port, ramcheck_time*HZ);	if (!dev->irq_ok) {		snd_printk ("post-RAM-check interrupt not received.\n");		goto gone_bad;	} 	if (!wavefront_wait (dev, STAT_CAN_READ)) {		snd_printk ("no response to HW version cmd.\n");		goto gone_bad;	}		if ((hwv[0] = wavefront_read (dev)) == -1) {		snd_printk ("board not responding correctly.\n");		goto gone_bad;	}	if (hwv[0] == 0xFF) { /* NAK */		/* Board's RAM test failed. Try to read error code,		   and tell us about it either way.		*/				if ((hwv[0] = wavefront_read (dev)) == -1) {			snd_printk ("on-board RAM test failed "				    "(bad error code).\n");		} else {			snd_printk ("on-board RAM test failed "				    "(error code: 0x%x).\n",				hwv[0]);		}		goto gone_bad;	}	/* We're OK, just get the next byte of the HW version response */	if ((hwv[1] = wavefront_read (dev)) == -1) {		snd_printk ("incorrect h/w response.\n");		goto gone_bad;	}	snd_printk ("hardware version %d.%d\n",		    hwv[0], hwv[1]);	return 0;     gone_bad:	return (1);}#include <linux/fs.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/unistd.h>#include <linux/syscalls.h>#include <asm/uaccess.h>static int __initwavefront_download_firmware (snd_wavefront_t *dev, char *path){	unsigned char section[WF_SECTION_MAX];	signed char section_length; /* yes, just a char; max value is WF_SECTION_MAX */	int section_cnt_downloaded = 0;	int fd;	int c;	int i;	mm_segment_t fs;	/* This tries to be a bit cleverer than the stuff Alan Cox did for	   the generic sound firmware, in that it actually knows	   something about the structure of the Motorola firmware. In	   particular, it uses a version that has been stripped of the	   20K of useless header information, and had section lengths	   added, making it possible to load the entire OS without any	   [kv]malloc() activity, since the longest entity we ever read is	   42 bytes (well, WF_SECTION_MAX) long.	*/	fs = get_fs();	set_fs (get_ds());	if ((fd = sys_open ((char __user *) path, 0, 0)) < 0) {		snd_printk ("Unable to load \"%s\".\n",			path);		return 1;	}	while (1) {		int x;		if ((x = sys_read (fd, (char __user *) &section_length, sizeof (section_length))) !=		    sizeof (section_length)) {			snd_printk ("firmware read error.\n");			goto failure;		}		if (section_length == 0) {			break;		}		if (section_length < 0 || section_length > WF_SECTION_MAX) {			snd_printk ("invalid firmware section length %d\n",				    section_length);			goto failure;		}		if (sys_read (fd, (char __user *) section, section_length) != section_length) {			snd_printk ("firmware section "				"read error.\n");			goto failure;		}		/* Send command */			if (wavefront_write (dev, WFC_DOWNLOAD_OS)) {			goto failure;		}			for (i = 0; i < section_length; i++) {			if (wavefront_write (dev, section[i])) {				goto failure;			}		}			/* get ACK */			if (wavefront_wait (dev, STAT_CAN_READ)) {			if ((c = inb (dev->data_port)) != WF_ACK) {				snd_printk ("download "					    "of section #%d not "					    "acknowledged, ack = 0x%x\n",					    section_cnt_downloaded + 1, c);				goto failure;					}		} else {			snd_printk ("time out for firmware ACK.\n");			goto failure;		}	}	sys_close (fd);	set_fs (fs);	return 0; failure:	sys_close (fd);	set_fs (fs);	snd_printk ("firmware download failed!!!\n");	return 1;}static int __initwavefront_do_reset (snd_wavefront_t *dev){	char voices[1];	if (wavefront_reset_to_cleanliness (dev)) {		snd_printk ("hw reset failed.\n");		goto gone_bad;	}	if (dev->israw) {		if (wavefront_download_firmware (dev, ospath)) {			goto gone_bad;		}		dev->israw = 0;		/* Wait for the OS to get running. The protocol for		   this is non-obvious, and was determined by		   using port-IO tracing in DOSemu and some		   experimentation here.		   		   Rather than using timed waits, use interrupts creatively.		*/		wavefront_should_cause_interrupt (dev, WFC_NOOP,						  dev->data_port,						  (osrun_time*HZ));		if (!dev->irq_ok) {			snd_printk ("no post-OS interrupt.\n");			goto gone_bad;		}				/* Now, do it again ! */				wavefront_should_cause_interrupt (dev, WFC_NOOP,						  dev->data_port, (10*HZ));				if (!dev->irq_ok) {			snd_printk ("no post-OS interrupt(2).\n");			goto gone_bad;		}		/* OK, no (RX/TX) interrupts any more, but leave mute		   in effect. 		*/				outb (0x80|0x40, dev->control_port); 	}	/* SETUPSND.EXE asks for sample memory config here, but since i	   have no idea how to interpret the result, we'll forget	   about it.	*/		if ((dev->freemem = wavefront_freemem (dev)) < 0) {		goto gone_bad;	}			snd_printk ("available DRAM %dk\n", dev->freemem / 1024);	if (wavefront_write (dev, 0xf0) ||	    wavefront_write (dev, 1) ||	    (wavefront_read (dev) < 0)) {		dev->debug = 0;		snd_printk ("MPU emulation mode not set.\n");		goto gone_bad;	}	voices[0] = 32;	if (snd_wavefront_cmd (dev, WFC_SET_NVOICES, NULL, voices)) {		snd_printk ("cannot set number of voices to 32.\n");		goto gone_bad;	}	return 0; gone_bad:	/* reset that sucker so that it doesn't bother us. */	outb (0x0, dev->control_port);	dev->interrupts_are_midi = 0;	return 1;}int __initsnd_wavefront_start (snd_wavefront_t *dev){	int samples_are_from_rom;	/* IMPORTANT: assumes that snd_wavefront_detect() and/or	   wavefront_reset_to_cleanliness() has already been called 	*/	if (dev->israw) {		samples_are_from_rom = 1;	} else {		/* XXX is this always true ? */		samples_are_from_rom = 0;	}	if (dev->israw || fx_raw) {		if (wavefront_do_reset (dev)) {			return -1;		}	}	/* Check for FX device, present only on Tropez+ */	dev->has_fx = (snd_wavefront_fx_detect (dev) == 0);	if (dev->has_fx && fx_raw) {		snd_wavefront_fx_start (dev);	}	wavefront_get_sample_status (dev, samples_are_from_rom);	wavefront_get_program_status (dev);	wavefront_get_patch_status (dev);	/* Start normal operation: unreset, master interrupt enabled, no mute	*/	outb (0x80|0x40|0x20, dev->control_port); 	return (0);}int __initsnd_wavefront_detect (snd_wavefront_card_t *card){	unsigned char   rbuf[4], wbuf[4];	snd_wavefront_t *dev = &card->wavefront;		/* returns zero if a WaveFront card is successfully detected.	   negative otherwise.	*/	dev->israw = 0;	dev->has_fx = 0;	dev->debug = debug_default;	dev->interrupts_are_midi = 0;	dev->irq_cnt = 0;	dev->rom_samples_rdonly = 1;	if (snd_wavefront_cmd (dev, WFC_FIRMWARE_VERSION, rbuf, wbuf) == 0) {		dev->fw_version[0] = rbuf[0];		dev->fw_version[1] = rbuf[1];		snd_printk ("firmware %d.%d already loaded.\n",			    rbuf[0], rbuf[1]);		/* check that a command actually works */      		if (snd_wavefront_cmd (dev, WFC_HARDWARE_VERSION,				       rbuf, wbuf) == 0) {			dev->hw_version[0] = rbuf[0];			dev->hw_version[1] = rbuf[1];		} else {			snd_printk ("not raw, but no "				    "hardware version!\n");			return -1;		}		if (!wf_raw) {			return 0;		} else {			snd_printk ("reloading firmware as you requested.\n");			dev->israw = 1;		}	} else {		dev->israw = 1;		snd_printk ("no response to firmware probe, assume raw.\n");	}	return 0;}

⌨️ 快捷键说明

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