wavefront_fx.c

来自「鼎力推荐!本程序是基于嵌入式LUNUX系统开发的源程序代码」· C语言 代码 · 共 1,020 行 · 第 1/3 页

C
1,020
字号
0xe1, 0x0b, 0x0a, 0x0b, 0x0a, 0x0b, 0x33, 0x0b, 0x33, 0x0b, 0x5c,0x0b, 0x5c, 0x0b, 0x85, 0x0b, 0x85, 0x0b, 0xae, 0x0b, 0xae, 0x0b,0xd7, 0x0b, 0xd7, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x28, 0x0c, 0x28,0x0c, 0x51, 0x0c, 0x51, 0x0c, 0x7a, 0x0c, 0x7a, 0x0c, 0xa3, 0x0c,0xa3, 0x0c, 0xcc, 0x0c, 0xcc, 0x0c, 0xf5, 0x0c, 0xf5, 0x0d, 0x1e,0x0d, 0x1e, 0x0d, 0x47, 0x0d, 0x47, 0x0d, 0x70, 0x0d, 0x70, 0x0d,0x99, 0x0d, 0x99, 0x0d, 0xc2, 0x0d, 0xc2, 0x0d, 0xeb, 0x0d, 0xeb,0x0e, 0x14, 0x0e, 0x14, 0x0e, 0x3d, 0x0e, 0x3d, 0x0e, 0x66, 0x0e,0x66, 0x0e, 0x8f, 0x0e, 0x8f, 0x0e, 0xb8, 0x0e, 0xb8, 0x0e, 0xe1,0x0e, 0xe1, 0x0f, 0x0a, 0x0f, 0x0a, 0x0f, 0x33, 0x0f, 0x33, 0x0f,0x5c, 0x0f, 0x5c, 0x0f, 0x85, 0x0f, 0x85, 0x0f, 0xae, 0x0f, 0xae,0x0f, 0xd7, 0x0f, 0xd7, 0x0f, 0xff, 0x0f, 0xff};static intwavefront_fx_idle (snd_wavefront_t *dev){	int i;	unsigned int x = 0x80;	for (i = 0; i < 1000; i++) {		x = inb (dev->fx_status);		if ((x & 0x80) == 0) {			break;		}	}	if (x & 0x80) {		snd_printk ("FX device never idle.\n");		return 0;	}	return (1);}static voidwavefront_fx_mute (snd_wavefront_t *dev, int onoff){	if (!wavefront_fx_idle(dev)) {		return;	}	outb (onoff ? 0x02 : 0x00, dev->fx_op);}static intwavefront_fx_memset (snd_wavefront_t *dev,		     int page,		     int addr,		     int cnt,		     unsigned short *data){	if (page < 0 || page > 7) {		snd_printk ("FX memset: "			"page must be >= 0 and <= 7\n");		return -(EINVAL);	}	if (addr < 0 || addr > 0x7f) {		snd_printk ("FX memset: "			"addr must be >= 0 and <= 7f\n");		return -(EINVAL);	}	if (cnt == 1) {		outb (FX_LSB_TRANSFER, dev->fx_lcr);		outb (page, dev->fx_dsp_page);		outb (addr, dev->fx_dsp_addr);		outb ((data[0] >> 8), dev->fx_dsp_msb);		outb ((data[0] & 0xff), dev->fx_dsp_lsb);		snd_printk ("FX: addr %d:%x set to 0x%x\n",			page, addr, data[0]);	} else {		int i;		outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);		outb (page, dev->fx_dsp_page);		outb (addr, dev->fx_dsp_addr);		for (i = 0; i < cnt; i++) {			outb ((data[i] >> 8), dev->fx_dsp_msb);			outb ((data[i] & 0xff), dev->fx_dsp_lsb);			if (!wavefront_fx_idle (dev)) {				break;			}		}		if (i != cnt) {			snd_printk ("FX memset "				    "(0x%x, 0x%x, 0x%lx, %d) incomplete\n",				    page, addr, (unsigned long) data, cnt);			return -(EIO);		}	}	return 0;}intsnd_wavefront_fx_detect (snd_wavefront_t *dev){	/* This is a crude check, but its the best one I have for now.	   Certainly on the Maui and the Tropez, wavefront_fx_idle() will	   report "never idle", which suggests that this test should	   work OK.	*/	if (inb (dev->fx_status) & 0x80) {		snd_printk ("Hmm, probably a Maui or Tropez.\n");		return -1;	}	return 0;}intsnd_wavefront_fx_open (snd_hwdep_t *hw, struct file *file){	if (!try_module_get(hw->card->module))		return -EFAULT;	file->private_data = hw;	return 0;}int snd_wavefront_fx_release (snd_hwdep_t *hw, struct file *file){	module_put(hw->card->module);	return 0;}intsnd_wavefront_fx_ioctl (snd_hwdep_t *sdev, struct file *file,			unsigned int cmd, unsigned long arg){	snd_card_t *card;	snd_wavefront_card_t *acard;	snd_wavefront_t *dev;	wavefront_fx_info r;	unsigned short *page_data = NULL;	unsigned short *pd;	int err = 0;	snd_assert(sdev->card != NULL, return -ENODEV);		card = sdev->card;	snd_assert(card->private_data != NULL, return -ENODEV);	acard = card->private_data;	dev = &acard->wavefront;	if (copy_from_user (&r, (void __user *)arg, sizeof (wavefront_fx_info)))		return -EFAULT;	switch (r.request) {	case WFFX_MUTE:		wavefront_fx_mute (dev, r.data[0]);		return -EIO;	case WFFX_MEMSET:		if (r.data[2] <= 0) {			snd_printk ("cannot write "				"<= 0 bytes to FX\n");			return -EIO;		} else if (r.data[2] == 1) {			pd = (unsigned short *) &r.data[3];		} else {			if (r.data[2] > 256) {				snd_printk ("cannot write "					    "> 512 bytes to FX\n");				return -EIO;			}			page_data = kmalloc(r.data[2] * sizeof(short), GFP_KERNEL);			if (!page_data)				return -ENOMEM;			if (copy_from_user (page_data,					    (unsigned char __user *) r.data[3],					    r.data[2] * sizeof(short))) {				kfree(page_data);				return -EFAULT;			}			pd = page_data;		}		err = wavefront_fx_memset (dev,			     r.data[0], /* page */			     r.data[1], /* addr */			     r.data[2], /* cnt */			     pd);		kfree(page_data);		break;	default:		snd_printk ("FX: ioctl %d not yet supported\n",			    r.request);		return -ENOTTY;	}	return err;}/* YSS225 initialization.   This code was developed using DOSEMU. The Turtle Beach SETUPSND   utility was run with I/O tracing in DOSEMU enabled, and a reconstruction   of the port I/O done, using the Yamaha faxback document as a guide   to add more logic to the code. Its really pretty weird.   There was an alternative approach of just dumping the whole I/O   sequence as a series of port/value pairs and a simple loop   that output it. However, I hope that eventually I'll get more   control over what this code does, and so I tried to stick with   a somewhat "algorithmic" approach.*/int __initsnd_wavefront_fx_start (snd_wavefront_t *dev){	unsigned int i, j;	/* Set all bits for all channels on the MOD unit to zero */	/* XXX But why do this twice ? */	for (j = 0; j < 2; j++) {		for (i = 0x10; i <= 0xff; i++) {	    			if (!wavefront_fx_idle (dev)) {				return (-1);			}	    			outb (i, dev->fx_mod_addr);			outb (0x0, dev->fx_mod_data);		}	}	if (!wavefront_fx_idle (dev)) return (-1);	outb (0x02, dev->fx_op);                        /* mute on */	if (!wavefront_fx_idle (dev)) return (-1);	outb (0x07, dev->fx_dsp_page);	outb (0x44, dev->fx_dsp_addr);	outb (0x00, dev->fx_dsp_msb);	outb (0x00, dev->fx_dsp_lsb);	if (!wavefront_fx_idle (dev)) return (-1);	outb (0x07, dev->fx_dsp_page);	outb (0x42, dev->fx_dsp_addr);	outb (0x00, dev->fx_dsp_msb);	outb (0x00, dev->fx_dsp_lsb);	if (!wavefront_fx_idle (dev)) return (-1);	outb (0x07, dev->fx_dsp_page);	outb (0x43, dev->fx_dsp_addr);	outb (0x00, dev->fx_dsp_msb);	outb (0x00, dev->fx_dsp_lsb);	if (!wavefront_fx_idle (dev)) return (-1);	outb (0x07, dev->fx_dsp_page);	outb (0x7c, dev->fx_dsp_addr);	outb (0x00, dev->fx_dsp_msb);	outb (0x00, dev->fx_dsp_lsb);	if (!wavefront_fx_idle (dev)) return (-1);	outb (0x07, dev->fx_dsp_page);	outb (0x7e, dev->fx_dsp_addr);	outb (0x00, dev->fx_dsp_msb);	outb (0x00, dev->fx_dsp_lsb);	if (!wavefront_fx_idle (dev)) return (-1);	outb (0x07, dev->fx_dsp_page);	outb (0x46, dev->fx_dsp_addr);	outb (0x00, dev->fx_dsp_msb);	outb (0x00, dev->fx_dsp_lsb);	if (!wavefront_fx_idle (dev)) return (-1);	outb (0x07, dev->fx_dsp_page);	outb (0x49, dev->fx_dsp_addr);	outb (0x00, dev->fx_dsp_msb);	outb (0x00, dev->fx_dsp_lsb);	if (!wavefront_fx_idle (dev)) return (-1);	outb (0x07, dev->fx_dsp_page);	outb (0x47, dev->fx_dsp_addr);	outb (0x00, dev->fx_dsp_msb);	outb (0x00, dev->fx_dsp_lsb);	if (!wavefront_fx_idle (dev)) return (-1);	outb (0x07, dev->fx_dsp_page);	outb (0x4a, dev->fx_dsp_addr);	outb (0x00, dev->fx_dsp_msb);	outb (0x00, dev->fx_dsp_lsb);	/* either because of stupidity by TB's programmers, or because it	   actually does something, rezero the MOD page.	*/	for (i = 0x10; i <= 0xff; i++) {			if (!wavefront_fx_idle (dev)) {			return (-1);		}			outb (i, dev->fx_mod_addr);		outb (0x0, dev->fx_mod_data);	}	/* load page zero */	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);	outb (0x00, dev->fx_dsp_page);	outb (0x00, dev->fx_dsp_addr);	for (i = 0; i < sizeof (page_zero); i += 2) {		outb (page_zero[i], dev->fx_dsp_msb);		outb (page_zero[i+1], dev->fx_dsp_lsb);		if (!wavefront_fx_idle (dev)) return (-1);	}	/* Now load page one */	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);	outb (0x01, dev->fx_dsp_page);	outb (0x00, dev->fx_dsp_addr);	for (i = 0; i < sizeof (page_one); i += 2) {		outb (page_one[i], dev->fx_dsp_msb);		outb (page_one[i+1], dev->fx_dsp_lsb);		if (!wavefront_fx_idle (dev)) return (-1);	}    	outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);	outb (0x02, dev->fx_dsp_page);	outb (0x00, dev->fx_dsp_addr);	for (i = 0; i < sizeof (page_two); i++) {		outb (page_two[i], dev->fx_dsp_lsb);		if (!wavefront_fx_idle (dev)) return (-1);	}    

⌨️ 快捷键说明

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