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

📄 msnd_pinnacle.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
			spin_unlock_irqrestore(&dev.lock, flags);			return n;		}		spin_unlock_irqrestore(&dev.lock, flags);		buf += n;		count -= n;		if (!test_bit(F_WRITING, &dev.flags) && (dev.mode & FMODE_WRITE)) {			dev.last_playbank = -1;			if (pack_DAPF_to_DAPQ(1) > 0)				set_bit(F_WRITING, &dev.flags);		}		if (dev.play_ndelay)			return count == len ? -EAGAIN : len - count;		if (count > 0) {			set_bit(F_WRITEBLOCK, &dev.flags);			interruptible_sleep_on_timeout(				&dev.writeblock,				get_play_delay_jiffies(DAP_BUFF_SIZE));			clear_bit(F_WRITEBLOCK, &dev.flags);			if (signal_pending(current))				return -EINTR;		}	}	return len - count;}static ssize_t dev_read(struct file *file, char *buf, size_t count, loff_t *off){	int minor = MINOR(file->f_dentry->d_inode->i_rdev);	if (minor == dev.dsp_minor)		return dsp_read(buf, count);	else		return -EINVAL;}static ssize_t dev_write(struct file *file, const char *buf, size_t count, loff_t *off){	int minor = MINOR(file->f_dentry->d_inode->i_rdev);	if (minor == dev.dsp_minor)		return dsp_write(buf, count);	else		return -EINVAL;}static __inline__ void eval_dsp_msg(register WORD wMessage){	switch (HIBYTE(wMessage)) {	case HIMT_PLAY_DONE:		if (dev.last_playbank == LOBYTE(wMessage) || !test_bit(F_WRITING, &dev.flags))			break;		dev.last_playbank = LOBYTE(wMessage);		if (pack_DAPF_to_DAPQ(0) <= 0) {			if (!test_bit(F_WRITEBLOCK, &dev.flags)) {				if (test_and_clear_bit(F_WRITEFLUSH, &dev.flags))					wake_up_interruptible(&dev.writeflush);			}			clear_bit(F_WRITING, &dev.flags);		}		if (test_bit(F_WRITEBLOCK, &dev.flags))			wake_up_interruptible(&dev.writeblock);		break;	case HIMT_RECORD_DONE:		if (dev.last_recbank == LOBYTE(wMessage))			break;		dev.last_recbank = LOBYTE(wMessage);		pack_DARQ_to_DARF(dev.last_recbank);		if (test_bit(F_READBLOCK, &dev.flags))			wake_up_interruptible(&dev.readblock);		break;	case HIMT_DSP:		switch (LOBYTE(wMessage)) {#ifndef MSND_CLASSIC		case HIDSP_PLAY_UNDER:#endif		case HIDSP_INT_PLAY_UNDER:/*			printk(KERN_DEBUG LOGNAME ": Play underflow\n"); */			clear_bit(F_WRITING, &dev.flags);			break;		case HIDSP_INT_RECORD_OVER:/*			printk(KERN_DEBUG LOGNAME ": Record overflow\n"); */			clear_bit(F_READING, &dev.flags);			break;		default:/*			printk(KERN_DEBUG LOGNAME ": DSP message %d 0x%02x\n",			LOBYTE(wMessage), LOBYTE(wMessage)); */			break;		}		break;        case HIMT_MIDI_IN_UCHAR:		if (dev.midi_in_interrupt)			(*dev.midi_in_interrupt)(&dev);		break;	default:/*		printk(KERN_DEBUG LOGNAME ": HIMT message %d 0x%02x\n", HIBYTE(wMessage), HIBYTE(wMessage)); */		break;	}}static void intr(int irq, void *dev_id, struct pt_regs *regs){	/* Send ack to DSP */	inb(dev.io + HP_RXL);	/* Evaluate queued DSP messages */	while (isa_readw(dev.DSPQ + JQS_wTail) != isa_readw(dev.DSPQ + JQS_wHead)) {		register WORD wTmp;		eval_dsp_msg(isa_readw(dev.pwDSPQData + 2*isa_readw(dev.DSPQ + JQS_wHead)));		if ((wTmp = isa_readw(dev.DSPQ + JQS_wHead) + 1) > isa_readw(dev.DSPQ + JQS_wSize))			isa_writew(0, dev.DSPQ + JQS_wHead);		else			isa_writew(wTmp, dev.DSPQ + JQS_wHead);	}}static struct file_operations dev_fileops = {	owner:		THIS_MODULE,	read:		dev_read,	write:		dev_write,	ioctl:		dev_ioctl,	open:		dev_open,	release:	dev_release,};static int reset_dsp(void){	int timeout = 100;	outb(HPDSPRESET_ON, dev.io + HP_DSPR);	mdelay(1);#ifndef MSND_CLASSIC	dev.info = inb(dev.io + HP_INFO);#endif	outb(HPDSPRESET_OFF, dev.io + HP_DSPR);	mdelay(1);	while (timeout-- > 0) {		if (inb(dev.io + HP_CVR) == HP_CVR_DEF)			return 0;		mdelay(1);	}	printk(KERN_ERR LOGNAME ": Cannot reset DSP\n");	return -EIO;}static int __init probe_multisound(void){#ifndef MSND_CLASSIC	char *xv, *rev = NULL;	char *pin = "Pinnacle", *fiji = "Fiji";	char *pinfiji = "Pinnacle/Fiji";#endif	if (check_region(dev.io, dev.numio)) {		printk(KERN_ERR LOGNAME ": I/O port conflict\n");		return -ENODEV;	}	request_region(dev.io, dev.numio, "probing");	if (reset_dsp() < 0) {		release_region(dev.io, dev.numio);		return -ENODEV;	}#ifdef MSND_CLASSIC	dev.name = "Classic/Tahiti/Monterey";	printk(KERN_INFO LOGNAME ": %s, "#else	switch (dev.info >> 4) {	case 0xf: xv = "<= 1.15"; break;	case 0x1: xv = "1.18/1.2"; break;	case 0x2: xv = "1.3"; break;	case 0x3: xv = "1.4"; break;	default: xv = "unknown"; break;	}	switch (dev.info & 0x7) {	case 0x0: rev = "I"; dev.name = pin; break;	case 0x1: rev = "F"; dev.name = pin; break;	case 0x2: rev = "G"; dev.name = pin; break;	case 0x3: rev = "H"; dev.name = pin; break;	case 0x4: rev = "E"; dev.name = fiji; break;	case 0x5: rev = "C"; dev.name = fiji; break;	case 0x6: rev = "D"; dev.name = fiji; break;	case 0x7:		rev = "A-B (Fiji) or A-E (Pinnacle)";		dev.name = pinfiji;		break;	}	printk(KERN_INFO LOGNAME ": %s revision %s, Xilinx version %s, "#endif /* MSND_CLASSIC */	       "I/O 0x%x-0x%x, IRQ %d, memory mapped to 0x%lX-0x%lX\n",	       dev.name,#ifndef MSND_CLASSIC	       rev, xv,#endif	       dev.io, dev.io + dev.numio - 1,	       dev.irq,	       dev.base, dev.base + 0x7fff);	release_region(dev.io, dev.numio);	return 0;}static int init_sma(void){	static int initted;	WORD mastVolLeft, mastVolRight;	unsigned long flags;#ifdef MSND_CLASSIC	outb(dev.memid, dev.io + HP_MEMM);#endif	outb(HPBLKSEL_0, dev.io + HP_BLKS);	if (initted) {		mastVolLeft = isa_readw(dev.SMA + SMA_wCurrMastVolLeft);		mastVolRight = isa_readw(dev.SMA + SMA_wCurrMastVolRight);	} else		mastVolLeft = mastVolRight = 0;	isa_memset_io(dev.base, 0, 0x8000);	/* Critical section: bank 1 access */	spin_lock_irqsave(&dev.lock, flags);	outb(HPBLKSEL_1, dev.io + HP_BLKS);	isa_memset_io(dev.base, 0, 0x8000);	outb(HPBLKSEL_0, dev.io + HP_BLKS);	spin_unlock_irqrestore(&dev.lock, flags);	dev.pwDSPQData = (dev.base + DSPQ_DATA_BUFF);	dev.pwMODQData = (dev.base + MODQ_DATA_BUFF);	dev.pwMIDQData = (dev.base + MIDQ_DATA_BUFF);	/* Motorola 56k shared memory base */	dev.SMA = dev.base + SMA_STRUCT_START;	/* Digital audio play queue */	dev.DAPQ = dev.base + DAPQ_OFFSET;	msnd_init_queue(dev.DAPQ, DAPQ_DATA_BUFF, DAPQ_BUFF_SIZE);	/* Digital audio record queue */	dev.DARQ = dev.base + DARQ_OFFSET;	msnd_init_queue(dev.DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE);	/* MIDI out queue */	dev.MODQ = dev.base + MODQ_OFFSET;	msnd_init_queue(dev.MODQ, MODQ_DATA_BUFF, MODQ_BUFF_SIZE);	/* MIDI in queue */	dev.MIDQ = dev.base + MIDQ_OFFSET;	msnd_init_queue(dev.MIDQ, MIDQ_DATA_BUFF, MIDQ_BUFF_SIZE);	/* DSP -> host message queue */	dev.DSPQ = dev.base + DSPQ_OFFSET;	msnd_init_queue(dev.DSPQ, DSPQ_DATA_BUFF, DSPQ_BUFF_SIZE);	/* Setup some DSP values */#ifndef MSND_CLASSIC	isa_writew(1, dev.SMA + SMA_wCurrPlayFormat);	isa_writew(dev.play_sample_size, dev.SMA + SMA_wCurrPlaySampleSize);	isa_writew(dev.play_channels, dev.SMA + SMA_wCurrPlayChannels);	isa_writew(dev.play_sample_rate, dev.SMA + SMA_wCurrPlaySampleRate);#endif	isa_writew(dev.play_sample_rate, dev.SMA + SMA_wCalFreqAtoD);	isa_writew(mastVolLeft, dev.SMA + SMA_wCurrMastVolLeft);	isa_writew(mastVolRight, dev.SMA + SMA_wCurrMastVolRight);#ifndef MSND_CLASSIC	isa_writel(0x00010000, dev.SMA + SMA_dwCurrPlayPitch);	isa_writel(0x00000001, dev.SMA + SMA_dwCurrPlayRate);#endif	isa_writew(0x303, dev.SMA + SMA_wCurrInputTagBits);	initted = 1;	return 0;}static int __init calibrate_adc(WORD srate){	isa_writew(srate, dev.SMA + SMA_wCalFreqAtoD);	if (dev.calibrate_signal == 0)		isa_writew(isa_readw(dev.SMA + SMA_wCurrHostStatusFlags)		       | 0x0001, dev.SMA + SMA_wCurrHostStatusFlags);	else		isa_writew(isa_readw(dev.SMA + SMA_wCurrHostStatusFlags)		       & ~0x0001, dev.SMA + SMA_wCurrHostStatusFlags);	if (msnd_send_word(&dev, 0, 0, HDEXAR_CAL_A_TO_D) == 0 &&	    chk_send_dsp_cmd(&dev, HDEX_AUX_REQ) == 0) {		current->state = TASK_INTERRUPTIBLE;		schedule_timeout(HZ / 3);		return 0;	}	printk(KERN_WARNING LOGNAME ": ADC calibration failed\n");	return -EIO;}static int upload_dsp_code(void){	outb(HPBLKSEL_0, dev.io + HP_BLKS);#ifndef HAVE_DSPCODEH	INITCODESIZE = mod_firmware_load(INITCODEFILE, &INITCODE);	if (!INITCODE) {		printk(KERN_ERR LOGNAME ": Error loading " INITCODEFILE);		return -EBUSY;	}	PERMCODESIZE = mod_firmware_load(PERMCODEFILE, &PERMCODE);	if (!PERMCODE) {		printk(KERN_ERR LOGNAME ": Error loading " PERMCODEFILE);		vfree(INITCODE);		return -EBUSY;	}#endif	isa_memcpy_toio(dev.base, PERMCODE, PERMCODESIZE);	if (msnd_upload_host(&dev, INITCODE, INITCODESIZE) < 0) {		printk(KERN_WARNING LOGNAME ": Error uploading to DSP\n");		return -ENODEV;	}#ifdef HAVE_DSPCODEH	printk(KERN_INFO LOGNAME ": DSP firmware uploaded (resident)\n");#else	printk(KERN_INFO LOGNAME ": DSP firmware uploaded\n");#endif#ifndef HAVE_DSPCODEH	vfree(INITCODE);	vfree(PERMCODE);#endif	return 0;}#ifdef MSND_CLASSICstatic void reset_proteus(void){	outb(HPPRORESET_ON, dev.io + HP_PROR);	mdelay(TIME_PRO_RESET);	outb(HPPRORESET_OFF, dev.io + HP_PROR);	mdelay(TIME_PRO_RESET_DONE);}#endifstatic int initialize(void){	int err, timeout;#ifdef MSND_CLASSIC	outb(HPWAITSTATE_0, dev.io + HP_WAIT);	outb(HPBITMODE_16, dev.io + HP_BITM);	reset_proteus();#endif	if ((err = init_sma()) < 0) {		printk(KERN_WARNING LOGNAME ": Cannot initialize SMA\n");		return err;	}	if ((err = reset_dsp()) < 0)		return err;	if ((err = upload_dsp_code()) < 0) {		printk(KERN_WARNING LOGNAME ": Cannot upload DSP code\n");		return err;	}	timeout = 200;	while (isa_readw(dev.base)) {		mdelay(1);		if (!timeout--) {			printk(KERN_DEBUG LOGNAME ": DSP reset timeout\n");			return -EIO;		}	}	mixer_setup();	return 0;}static int dsp_full_reset(void){	int rv;	if (test_bit(F_RESETTING, &dev.flags) || ++dev.nresets > 10)		return 0;	set_bit(F_RESETTING, &dev.flags);	printk(KERN_INFO LOGNAME ": DSP reset\n");	dsp_halt(NULL);			/* Unconditionally halt */	if ((rv = initialize()))		printk(KERN_WARNING LOGNAME ": DSP reset failed\n");	force_recsrc(dev.recsrc);	dsp_open(NULL);	clear_bit(F_RESETTING, &dev.flags);	return rv;}static int __init attach_multisound(void){	int err;	if ((err = request_irq(dev.irq, intr, 0, dev.name, &dev)) < 0) {		printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", dev.irq);		return err;	}	request_region(dev.io, dev.numio, dev.name);        if ((err = dsp_full_reset()) < 0) {		release_region(dev.io, dev.numio);		free_irq(dev.irq, &dev);		return err;	}	if ((err = msnd_register(&dev)) < 0) {		printk(KERN_ERR LOGNAME ": Unable to register MultiSound\n");		release_region(dev.io, dev.numio);		free_irq(dev.irq, &dev);		return err;	}	if ((dev.dsp_minor = register_sound_dsp(&dev_fileops, -1)) < 0) {		printk(KERN_ERR LOGNAME ": Unable to register DSP operations\n");		msnd_unregister(&dev);		release_region(dev.io, dev.numio);		free_irq(dev.irq, &dev);		return dev.dsp_minor;	}	if ((dev.mixer_minor = register_sound_mixer(&dev_fileops, -1)) < 0) {		printk(KERN_ERR LOGNAME ": Unable to register mixer operations\n");		unregister_sound_mixer(dev.mixer_minor);		msnd_unregister(&dev);		release_region(dev.io, dev.numio);		free_irq(dev.irq, &dev);		return dev.mixer_minor;	}	dev.ext_midi_dev = dev.hdr_midi_dev = -1;	disable_irq(dev.irq);	calibrate_adc(dev.play_sample_rate);#ifndef MSND_CLASSIC	force_recsrc(SOUND_MASK_IMIX);#endif	return 0;}static void __exit unload_multisound(void){	release_region(dev.io, dev.numio);	free_irq(dev.irq, &dev);	unregister_sound_mixer(dev.mixer_minor);	unregister_sound_dsp(dev.dsp_minor);	msnd_unregister(&dev);}#ifndef MSND_CLASSIC

⌨️ 快捷键说明

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