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

📄 sscape.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
				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;}static int download_boot_block(void *dev_info, copr_buffer * buf){	if (buf->len <= 0 || buf->len > sizeof(buf->data))		return -EINVAL;	if (!sscape_download_boot(devc, buf->data, buf->len, buf->flags))	{		printk(KERN_ERR "soundscape: Unable to load microcode block to the OBP.\n");		return -EIO;	}	return 0;}static int sscape_coproc_ioctl(void *dev_info, unsigned int cmd, caddr_t arg, int local){	copr_buffer *buf;	int err;	switch (cmd) 	{		case SNDCTL_COPR_RESET:			sscape_coproc_reset(dev_info);			return 0;		case SNDCTL_COPR_LOAD:			buf = (copr_buffer *) vmalloc(sizeof(copr_buffer));			if (buf == NULL)				return -ENOSPC;			if (copy_from_user(buf, arg, sizeof(copr_buffer))) 			{				vfree(buf);				return -EFAULT;			}			err = download_boot_block(dev_info, buf);			vfree(buf);			return err;				default:			return -EINVAL;	}}static coproc_operations sscape_coproc_operations ={	"SoundScape M68K",	THIS_MODULE,	sscape_coproc_open,	sscape_coproc_close,	sscape_coproc_ioctl,	sscape_coproc_reset,	&adev_info};static int sscape_detected = 0;static int sscape_is_pnp   = 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;}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;}static	int sscape_read_host_ctrl(sscape_info* devc){	return host_read(devc);}static	void sscape_write_host_ctrl2(sscape_info *devc, int a, int b){	host_command2(devc, a, b);}static int sscape_alloc_dma(sscape_info *devc){	char *start_addr, *end_addr;	int dma_pagesize;	int sz, size;	struct page *page;	if (devc->raw_buf != NULL) return 0;	/* Already done */	dma_pagesize = (devc->dma < 4) ? (64 * 1024) : (128 * 1024);	devc->raw_buf = NULL;	devc->buffsize = 8192*4;	if (devc->buffsize > dma_pagesize) devc->buffsize = dma_pagesize;	start_addr = NULL;	/*	 * Now loop until we get a free buffer. Try to get smaller buffer if	 * it fails. Don't accept smaller than 8k buffer for performance	 * reasons.	 */	while (start_addr == NULL && devc->buffsize > PAGE_SIZE) {		for (sz = 0, size = PAGE_SIZE; size < devc->buffsize; sz++, size <<= 1);		devc->buffsize = PAGE_SIZE * (1 << sz);		start_addr = (char *) __get_free_pages(GFP_ATOMIC|GFP_DMA, sz);		if (start_addr == NULL) devc->buffsize /= 2;	}	if (start_addr == NULL) {		printk(KERN_ERR "sscape pnp init error: Couldn't allocate DMA buffer\n");		return 0;	} else {		/* make some checks */		end_addr = start_addr + devc->buffsize - 1;				/* now check if it fits into the same dma-pagesize */		if (((long) start_addr & ~(dma_pagesize - 1)) != ((long) end_addr & ~(dma_pagesize - 1))		    || end_addr >= (char *) (MAX_DMA_ADDRESS)) {			printk(KERN_ERR "sscape pnp: Got invalid address 0x%lx for %db DMA-buffer\n", (long) start_addr, devc->buffsize);			return 0;		}	}	devc->raw_buf = start_addr;	devc->raw_buf_phys = virt_to_bus(start_addr);	for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++)		mem_map_reserve(page);	return 1;}static void sscape_free_dma(sscape_info *devc){	int sz, size;	unsigned long start_addr, end_addr;	struct page *page;	if (devc->raw_buf == NULL) return;	for (sz = 0, size = PAGE_SIZE; size < devc->buffsize; sz++, size <<= 1);	start_addr = (unsigned long) devc->raw_buf;	end_addr = start_addr + devc->buffsize;	for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++)		mem_map_unreserve(page);	free_pages((unsigned long) devc->raw_buf, sz);	devc->raw_buf = NULL;}/* Intel version !!!!!!!!! */static int sscape_start_dma(int chan, unsigned long physaddr, int count, int dma_mode){	unsigned long flags;	flags = claim_dma_lock();	disable_dma(chan);	clear_dma_ff(chan);	set_dma_mode(chan, dma_mode);	set_dma_addr(chan, physaddr);	set_dma_count(chan, count);	enable_dma(chan);	release_dma_lock(flags);	return 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);}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;}static	int	sscape_pnp_alloc_dma(sscape_info* devc){	/* printk(KERN_INFO "sscape: requesting dma\n"); */	if (request_dma(devc -> dma, "sscape")) return 0;	/* printk(KERN_INFO "sscape: dma channel allocated\n"); */	if (!sscape_alloc_dma(devc)) {		free_dma(devc -> dma);		return 0;	};	return 1;}static	void	sscape_pnp_free_dma(sscape_info* devc){	sscape_free_dma( devc);	free_dma(devc -> dma );		/* printk(KERN_INFO "sscape: dma released\n"); */}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;}static void __init sscape_pnp_init_hw(sscape_info* devc){		unsigned char midi_irq = 0, sb_irq = 0;

⌨️ 快捷键说明

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