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

📄 wavefront_synth.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
				   Don't fetch unsupplied data from				   user space, just continue with				   whatever the final value was.				*/			}	    			if (i < blocksize - 1) {				outw (sample_short, dev->block_port);			} else {				outw (sample_short, dev->last_block_port);			}		}		/* Get "DMA page acknowledge", even though its really		   nothing to do with DMA at all.		*/			if ((dma_ack = wavefront_read (dev)) != WF_DMA_ACK) {			if (dma_ack == -1) {				snd_printk ("upload sample "					    "DMA ack timeout\n");				return -(EIO);			} else {				snd_printk ("upload sample "					    "DMA ack error 0x%x\n",					    dma_ack);				return -(EIO);			}		}	}	dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_SAMPLE);	/* Note, label is here because sending the sample header shouldn't	   alter the sample_status info at all.	*/ sent:	return (0);}static intwavefront_send_alias (snd_wavefront_t *dev, wavefront_patch_info *header){	unsigned char alias_hdr[WF_ALIAS_BYTES];	DPRINT (WF_DEBUG_LOAD_PATCH, "download alias, %d is "				      "alias for %d\n",				      header->number,				      header->hdr.a.OriginalSample);    	munge_int32 (header->number, &alias_hdr[0], 2);	munge_int32 (header->hdr.a.OriginalSample, &alias_hdr[2], 2);	munge_int32 (*((unsigned int *)&header->hdr.a.sampleStartOffset),		     &alias_hdr[4], 4);	munge_int32 (*((unsigned int *)&header->hdr.a.loopStartOffset),		     &alias_hdr[8], 4);	munge_int32 (*((unsigned int *)&header->hdr.a.loopEndOffset),		     &alias_hdr[12], 4);	munge_int32 (*((unsigned int *)&header->hdr.a.sampleEndOffset),		     &alias_hdr[16], 4);	munge_int32 (header->hdr.a.FrequencyBias, &alias_hdr[20], 3);	munge_int32 (*(&header->hdr.a.FrequencyBias+1), &alias_hdr[23], 2);	if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_SAMPLE_ALIAS, NULL, alias_hdr)) {		snd_printk ("download alias failed.\n");		return -(EIO);	}	dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_ALIAS);	return (0);}static intwavefront_send_multisample (snd_wavefront_t *dev, wavefront_patch_info *header){	int i;	int num_samples;	unsigned char *msample_hdr;	msample_hdr = kmalloc(sizeof(WF_MSAMPLE_BYTES), GFP_KERNEL);	if (! msample_hdr)		return -ENOMEM;	munge_int32 (header->number, &msample_hdr[0], 2);	/* You'll recall at this point that the "number of samples" value	   in a wavefront_multisample struct is actually the log2 of the	   real number of samples.	*/	num_samples = (1<<(header->hdr.ms.NumberOfSamples&7));	msample_hdr[2] = (unsigned char) header->hdr.ms.NumberOfSamples;	DPRINT (WF_DEBUG_LOAD_PATCH, "multi %d with %d=%d samples\n",				      header->number,				      header->hdr.ms.NumberOfSamples,				      num_samples);	for (i = 0; i < num_samples; i++) {		DPRINT(WF_DEBUG_LOAD_PATCH|WF_DEBUG_DATA, "sample[%d] = %d\n",		       i, header->hdr.ms.SampleNumber[i]);		munge_int32 (header->hdr.ms.SampleNumber[i],		     &msample_hdr[3+(i*2)], 2);	}    	/* Need a hack here to pass in the number of bytes	   to be written to the synth. This is ugly, and perhaps	   one day, I'll fix it.	*/	if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_MULTISAMPLE, 			   (unsigned char *) (long) ((num_samples*2)+3),			   msample_hdr)) {		snd_printk ("download of multisample failed.\n");		kfree(msample_hdr);		return -(EIO);	}	dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_MULTISAMPLE);	kfree(msample_hdr);	return (0);}static intwavefront_fetch_multisample (snd_wavefront_t *dev, 			     wavefront_patch_info *header){	int i;	unsigned char log_ns[1];	unsigned char number[2];	int num_samples;	munge_int32 (header->number, number, 2);    	if (snd_wavefront_cmd (dev, WFC_UPLOAD_MULTISAMPLE, log_ns, number)) {		snd_printk ("upload multisample failed.\n");		return -(EIO);	}    	DPRINT (WF_DEBUG_DATA, "msample %d has %d samples\n",				header->number, log_ns[0]);	header->hdr.ms.NumberOfSamples = log_ns[0];	/* get the number of samples ... */	num_samples = (1 << log_ns[0]);    	for (i = 0; i < num_samples; i++) {		char d[2];		int val;			if ((val = wavefront_read (dev)) == -1) {			snd_printk ("upload multisample failed "				    "during sample loop.\n");			return -(EIO);		}		d[0] = val;		if ((val = wavefront_read (dev)) == -1) {			snd_printk ("upload multisample failed "				    "during sample loop.\n");			return -(EIO);		}		d[1] = val;			header->hdr.ms.SampleNumber[i] =			demunge_int32 ((unsigned char *) d, 2);			DPRINT (WF_DEBUG_DATA, "msample sample[%d] = %d\n",					i, header->hdr.ms.SampleNumber[i]);	}	return (0);}static intwavefront_send_drum (snd_wavefront_t *dev, wavefront_patch_info *header){	unsigned char drumbuf[WF_DRUM_BYTES];	wavefront_drum *drum = &header->hdr.d;	int i;	DPRINT (WF_DEBUG_LOAD_PATCH, "downloading edrum for MIDI "		"note %d, patch = %d\n", 		header->number, drum->PatchNumber);	drumbuf[0] = header->number & 0x7f;	for (i = 0; i < 4; i++) {		munge_int32 (((unsigned char *)drum)[i], &drumbuf[1+(i*2)], 2);	}	if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_EDRUM_PROGRAM, NULL, drumbuf)) {		snd_printk ("download drum failed.\n");		return -(EIO);	}	return (0);}static int wavefront_find_free_sample (snd_wavefront_t *dev){	int i;	for (i = 0; i < WF_MAX_SAMPLE; i++) {		if (!(dev->sample_status[i] & WF_SLOT_FILLED)) {			return i;		}	}	snd_printk ("no free sample slots!\n");	return -1;}#if 0static int wavefront_find_free_patch (snd_wavefront_t *dev){	int i;	for (i = 0; i < WF_MAX_PATCH; i++) {		if (!(dev->patch_status[i] & WF_SLOT_FILLED)) {			return i;		}	}	snd_printk ("no free patch slots!\n");	return -1;}#endifstatic intwavefront_load_patch (snd_wavefront_t *dev, const char __user *addr){	wavefront_patch_info *header;	int err;		header = kmalloc(sizeof(*header), GFP_KERNEL);	if (! header)		return -ENOMEM;	if (copy_from_user (header, addr, sizeof(wavefront_patch_info) -			    sizeof(wavefront_any))) {		snd_printk ("bad address for load patch.\n");		err = -EFAULT;		goto __error;	}	DPRINT (WF_DEBUG_LOAD_PATCH, "download "				      "Sample type: %d "				      "Sample number: %d "				      "Sample size: %d\n",				      header->subkey,				      header->number,				      header->size);	switch (header->subkey) {	case WF_ST_SAMPLE:  /* sample or sample_header, based on patch->size */		if (copy_from_user (&header->hdr.s, header->hdrptr,				    sizeof (wavefront_sample))) {			err = -EFAULT;			break;		}		err = wavefront_send_sample (dev, header, header->dataptr, 0);		break;	case WF_ST_MULTISAMPLE:		if (copy_from_user (&header->hdr.s, header->hdrptr,				    sizeof (wavefront_multisample))) {			err = -EFAULT;			break;		}		err = wavefront_send_multisample (dev, header);		break;	case WF_ST_ALIAS:		if (copy_from_user (&header->hdr.a, header->hdrptr,				    sizeof (wavefront_alias))) {			err = -EFAULT;			break;		}		err = wavefront_send_alias (dev, header);		break;	case WF_ST_DRUM:		if (copy_from_user (&header->hdr.d, header->hdrptr,				    sizeof (wavefront_drum))) {			err = -EFAULT;			break;		}		err = wavefront_send_drum (dev, header);		break;	case WF_ST_PATCH:		if (copy_from_user (&header->hdr.p, header->hdrptr,				    sizeof (wavefront_patch))) {			err = -EFAULT;			break;		}				err = wavefront_send_patch (dev, header);		break;	case WF_ST_PROGRAM:		if (copy_from_user (&header->hdr.pr, header->hdrptr,				    sizeof (wavefront_program))) {			err = -EFAULT;			break;		}		err = wavefront_send_program (dev, header);		break;	default:		snd_printk ("unknown patch type %d.\n",			    header->subkey);		err = -EINVAL;		break;	} __error:	kfree(header);	return err;}/***********************************************************************WaveFront: hardware-dependent interface***********************************************************************/static voidprocess_sample_hdr (u8 *buf){	wavefront_sample s;	u8 *ptr;	ptr = buf;	/* The board doesn't send us an exact copy of a "wavefront_sample"	   in response to an Upload Sample Header command. Instead, we 	   have to convert the data format back into our data structure,	   just as in the Download Sample command, where we have to do	   something very similar in the reverse direction.	*/	*((u32 *) &s.sampleStartOffset) = demunge_int32 (ptr, 4); ptr += 4;	*((u32 *) &s.loopStartOffset) = demunge_int32 (ptr, 4); ptr += 4;	*((u32 *) &s.loopEndOffset) = demunge_int32 (ptr, 4); ptr += 4;	*((u32 *) &s.sampleEndOffset) = demunge_int32 (ptr, 4); ptr += 4;	*((u32 *) &s.FrequencyBias) = demunge_int32 (ptr, 3); ptr += 3;	s.SampleResolution = *ptr & 0x3;	s.Loop = *ptr & 0x8;	s.Bidirectional = *ptr & 0x10;	s.Reverse = *ptr & 0x40;	/* Now copy it back to where it came from */	memcpy (buf, (unsigned char *) &s, sizeof (wavefront_sample));}static intwavefront_synth_control (snd_wavefront_card_t *acard, 			 wavefront_control *wc){	snd_wavefront_t *dev = &acard->wavefront;	unsigned char patchnumbuf[2];	int i;	DPRINT (WF_DEBUG_CMD, "synth control with "		"cmd 0x%x\n", wc->cmd);	/* Pre-handling of or for various commands */	switch (wc->cmd) {			case WFC_DISABLE_INTERRUPTS:		snd_printk ("interrupts disabled.\n");		outb (0x80|0x20, dev->control_port);		dev->interrupts_are_midi = 1;		return 0;	case WFC_ENABLE_INTERRUPTS:		snd_printk ("interrupts enabled.\n");		outb (0x80|0x40|0x20, dev->control_port);		dev->interrupts_are_midi = 1;		return 0;	case WFC_INTERRUPT_STATUS:		wc->rbuf[0] = dev->interrupts_are_midi;		return 0;	case WFC_ROMSAMPLES_RDONLY:		dev->rom_samples_rdonly = wc->wbuf[0];		wc->status = 0;		return 0;	case WFC_IDENTIFY_SLOT_TYPE:		i = wc->wbuf[0] | (wc->wbuf[1] << 7);		if (i <0 || i >= WF_MAX_SAMPLE) {			snd_printk ("invalid slot ID %d\n",				i);			wc->status = EINVAL;			return -EINVAL;		}		wc->rbuf[0] = dev->sample_status[i];		wc->status = 0;		return 0;	case WFC_DEBUG_DRIVER:		dev->debug = wc->wbuf[0];		snd_printk ("debug = 0x%x\n", dev->debug);		return 0;	case WFC_UPLOAD_PATCH:		munge_int32 (*((u32 *) wc->wbuf), patchnumbuf, 2);		memcpy (wc->wbuf, patchnumbuf, 2);		break;	case WFC_UPLOAD_MULTISAMPLE:		/* multisamples have to be handled differently, and		   cannot be dealt with properly by snd_wavefront_cmd() alone.		*/		wc->status = wavefront_fetch_multisample			(dev, (wavefront_patch_info *) wc->rbuf);		return 0;	case WFC_UPLOAD_SAMPLE_ALIAS:		snd_printk ("support for sample alias upload "			"being considered.\n");		wc->status = EINVAL;		return -EINVAL;	}	wc->status = snd_wavefront_cmd (dev, wc->cmd, wc->rbuf, wc->wbuf);	/* Post-handling of certain commands.	   In particular, if the command was an upload, demunge the data	   so that the user-level doesn't have to think about it.	*/	if (wc->status == 0) {		switch (wc->cmd) {			/* intercept any freemem requests so that we know			   we are always current with the user-level view			   of things.			*/		case WFC_REPORT_FREE_MEMORY:			dev->freemem = demunge_int32 (wc->rbuf, 4);			break;		case WFC_UPLOAD_PATCH:			demunge_buf (wc->rbuf, wc->rbuf, WF_PATCH_BYTES);			break;		case WFC_UPLOAD_PROGRAM:			demunge_buf (wc->rbuf, wc->rbuf, WF_PROGRAM_BYTES);			break;		case WFC_UPLOAD_EDRUM_PROGRAM:			demunge_buf (wc->rbuf, wc->rbuf, WF_DRUM_BYTES - 1);			break;		case WFC_UPLOAD_SAMPLE_HEADER:			process_sample_hdr (wc->rbuf);			break;		case WFC_UPLOAD_SAMPLE_ALIAS:			snd_printk ("support for "				    "sample aliases still "				    "being considered.\n");			break;		case WFC_VMIDI_OFF:			snd_wavefront_midi_disable_virtual (acard);			break;		case WFC_VMIDI_ON:			snd_wavefront_midi_enable_virtual (acard);			break;		}	}	return 0;}int snd_wavefront_synth_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_synth_release (snd_hwdep_t *hw, struct file *file){	module_put(hw->card->module);	return 0;}intsnd_wavefront_synth_ioctl (snd_hwdep_t *hw, struct file *file,			   unsigned int cmd, unsigned long arg){	snd_card_t *card;	snd_wavefront_t *dev;	snd_wavefront_card_t *acard;	wavefront_control *wc;	void __user *argp = (void __user *)arg;	int err;	card = (snd_card_t *) hw->card;	snd_assert(card != NULL, return -ENODEV);	snd_assert(card->private_data != NULL, return -ENODEV);	acard = card->private_data;	dev = &acard->wavefront;		switch (cmd) {	case WFCTL_LOAD_SPP:		if (wavefront_load_patch (dev, argp) != 0) {			return -EIO;		}		break;	case WFCTL_WFCMD:		wc = kmalloc(sizeof(*wc), GFP_KERNEL);		if (! wc)			return -ENOMEM;		if (copy_from_user (wc, argp, sizeof (*wc)))			err = -EFAULT;		else if (wavefront_synth_control (acard, wc) < 0)			err = -EIO;		else if (copy_to_user (argp, wc, sizeof (*wc)))			err = -EFAULT;		else

⌨️ 快捷键说明

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