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

📄 wavfront.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	char rbuf[8];	if (wavefront_cmd (WFC_REPORT_FREE_MEMORY, rbuf, 0)) {		printk (KERN_WARNING LOGNAME "can't get memory stats.\n");		return -1;	} else {		return demunge_int32 (rbuf, 4);	}}static intwavefront_send_sample (wavefront_patch_info *header,		       UINT16 *dataptr,		       int data_is_unsigned){	/* samples are downloaded via a 16-bit wide i/o port	   (you could think of it as 2 adjacent 8-bit wide ports	   but its less efficient that way). therefore, all	   the blocksizes and so forth listed in the documentation,	   and used conventionally to refer to sample sizes,	   which are given in 8-bit units (bytes), need to be	   divided by 2.        */	UINT16 sample_short;	UINT32 length;	UINT16 *data_end = 0;	unsigned int i;	const int max_blksize = 4096/2;	unsigned int written;	unsigned int blocksize;	int dma_ack;	int blocknum;	unsigned char sample_hdr[WF_SAMPLE_HDR_BYTES];	unsigned char *shptr;	int skip = 0;	int initial_skip = 0;	DPRINT (WF_DEBUG_LOAD_PATCH, "sample %sdownload for slot %d, "				      "type %d, %d bytes from 0x%x\n",				      header->size ? "" : "header ", 				      header->number, header->subkey,				      header->size,				      (int) header->dataptr);	if (header->number == WAVEFRONT_FIND_FREE_SAMPLE_SLOT) {		int x;		if ((x = wavefront_find_free_sample ()) < 0) {			return -ENOMEM;		}		printk (KERN_DEBUG LOGNAME "unspecified sample => %d\n", x);		header->number = x;	}	if (header->size) {		/* XXX its a debatable point whether or not RDONLY semantics		   on the ROM samples should cover just the sample data or		   the sample header. For now, it only covers the sample data,		   so anyone is free at all times to rewrite sample headers.		   My reason for this is that we have the sample headers		   available in the WFB file for General MIDI, and so these		   can always be reset if needed. The sample data, however,		   cannot be recovered without a complete reset and firmware		   reload of the ICS2115, which is a very expensive operation.		   So, doing things this way allows us to honor the notion of		   "RESETSAMPLES" reasonably cheaply. Note however, that this		   is done purely at user level: there is no WFB parser in		   this driver, and so a complete reset (back to General MIDI,		   or theoretically some other configuration) is the		   responsibility of the user level library. 		   To try to do this in the kernel would be a little		   crazy: we'd need 158K of kernel space just to hold		   a copy of the patch/program/sample header data.		*/		if (dev.rom_samples_rdonly) {			if (dev.sample_status[header->number] & WF_SLOT_ROM) {				printk (KERN_ERR LOGNAME "sample slot %d "					"write protected\n",					header->number);				return -EACCES;			}		}		wavefront_delete_sample (header->number);	}	if (header->size) {		dev.freemem = wavefront_freemem ();		if (dev.freemem < header->size) {			printk (KERN_ERR LOGNAME				"insufficient memory to "				"load %d byte sample.\n",				header->size);			return -ENOMEM;		}		}	skip = WF_GET_CHANNEL(&header->hdr.s);	if (skip > 0 && header->hdr.s.SampleResolution != LINEAR_16BIT) {		printk (KERN_ERR LOGNAME "channel selection only "			"possible on 16-bit samples");		return -(EINVAL);	}	switch (skip) {	case 0:		initial_skip = 0;		skip = 1;		break;	case 1:		initial_skip = 0;		skip = 2;		break;	case 2:		initial_skip = 1;		skip = 2;		break;	case 3:		initial_skip = 2;		skip = 3;		break;	case 4:		initial_skip = 3;		skip = 4;		break;	case 5:		initial_skip = 4;		skip = 5;		break;	case 6:		initial_skip = 5;		skip = 6;		break;	}	DPRINT (WF_DEBUG_LOAD_PATCH, "channel selection: %d => "				      "initial skip = %d, skip = %d\n",				      WF_GET_CHANNEL (&header->hdr.s),				      initial_skip, skip);    	/* Be safe, and zero the "Unused" bits ... */	WF_SET_CHANNEL(&header->hdr.s, 0);	/* adjust size for 16 bit samples by dividing by two.  We always	   send 16 bits per write, even for 8 bit samples, so the length	   is always half the size of the sample data in bytes.	*/	length = header->size / 2;	/* the data we're sent has not been munged, and in fact, the	   header we have to send isn't just a munged copy either.	   so, build the sample header right here.	*/	shptr = &sample_hdr[0];	shptr = munge_int32 (header->number, shptr, 2);	if (header->size) {		shptr = munge_int32 (length, shptr, 4);	}	/* Yes, a 4 byte result doesn't contain all of the offset bits,	   but the offset only uses 24 bits.	*/	shptr = munge_int32 (*((UINT32 *) &header->hdr.s.sampleStartOffset),			     shptr, 4);	shptr = munge_int32 (*((UINT32 *) &header->hdr.s.loopStartOffset),			     shptr, 4);	shptr = munge_int32 (*((UINT32 *) &header->hdr.s.loopEndOffset),			     shptr, 4);	shptr = munge_int32 (*((UINT32 *) &header->hdr.s.sampleEndOffset),			     shptr, 4);		/* This one is truly wierd. What kind of wierdo decided that in	   a system dominated by 16 and 32 bit integers, they would use	   a just 12 bits ?	*/		shptr = munge_int32 (header->hdr.s.FrequencyBias, shptr, 3);		/* Why is this nybblified, when the MSB is *always* zero ? 	   Anyway, we can't take address of bitfield, so make a	   good-faith guess at where it starts.	*/		shptr = munge_int32 (*(&header->hdr.s.FrequencyBias+1),			     shptr, 2);	if (wavefront_cmd (header->size ?			   WFC_DOWNLOAD_SAMPLE : WFC_DOWNLOAD_SAMPLE_HEADER,			   0, sample_hdr)) {		printk (KERN_WARNING LOGNAME "sample %sdownload refused.\n",			header->size ? "" : "header ");		return -(EIO);	}	if (header->size == 0) {		goto sent; /* Sorry. Just had to have one somewhere */	}    	data_end = dataptr + length;	/* Do any initial skip over an unused channel's data */	dataptr += initial_skip;    	for (written = 0, blocknum = 0;	     written < length; written += max_blksize, blocknum++) {			if ((length - written) > max_blksize) {			blocksize = max_blksize;		} else {			/* round to nearest 16-byte value */			blocksize = ((length-written+7)&~0x7);		}		if (wavefront_cmd (WFC_DOWNLOAD_BLOCK, 0, 0)) {			printk (KERN_WARNING LOGNAME "download block "				"request refused.\n");			return -(EIO);		}		for (i = 0; i < blocksize; i++) {			if (dataptr < data_end) {						__get_user (sample_short, dataptr);				dataptr += skip;						if (data_is_unsigned) { /* GUS ? */					if (WF_SAMPLE_IS_8BIT(&header->hdr.s)) {									/* 8 bit sample						 resolution, sign						 extend both bytes.						*/									((unsigned char*)						 &sample_short)[0] += 0x7f;						((unsigned char*)						 &sample_short)[1] += 0x7f;								} else {									/* 16 bit sample						 resolution, sign						 extend the MSB.						*/									sample_short += 0x7fff;					}				}			} else {				/* In padding section of final block:				   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 ()) != WF_DMA_ACK) {			if (dma_ack == -1) {				printk (KERN_ERR LOGNAME "upload sample "					"DMA ack timeout\n");				return -(EIO);			} else {				printk (KERN_ERR LOGNAME "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 (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 (wavefront_cmd (WFC_DOWNLOAD_SAMPLE_ALIAS, 0, alias_hdr)) {		printk (KERN_ERR LOGNAME "download alias failed.\n");		return -(EIO);	}	dev.sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_ALIAS);	return (0);}static intwavefront_send_multisample (wavefront_patch_info *header){	int i;	int num_samples;	unsigned char msample_hdr[WF_MSAMPLE_BYTES];	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 (wavefront_cmd (WFC_DOWNLOAD_MULTISAMPLE, 			   (unsigned char *) ((num_samples*2)+3),			   msample_hdr)) {		printk (KERN_ERR LOGNAME "download of multisample failed.\n");		return -(EIO);	}	dev.sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_MULTISAMPLE);	return (0);}static intwavefront_fetch_multisample (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 (wavefront_cmd (WFC_UPLOAD_MULTISAMPLE, log_ns, number)) {		printk (KERN_ERR LOGNAME "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];			if ((d[0] = wavefront_read ()) == -1) {			printk (KERN_ERR LOGNAME "upload multisample failed "				"during sample loop.\n");			return -(EIO);		}		if ((d[1] = wavefront_read ()) == -1) {			printk (KERN_ERR LOGNAME "upload multisample failed "				"during sample loop.\n");			return -(EIO);		}			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 (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 (wavefront_cmd (WFC_DOWNLOAD_EDRUM_PROGRAM, 0, drumbuf)) {		printk (KERN_ERR LOGNAME "download drum failed.\n");		return -(EIO);	}	return (0);}static int wavefront_find_free_sample (void){	int i;	for (i = 0; i < WF_MAX_SAMPLE; i++) {		if (!(dev.sample_status[i] & WF_SLOT_FILLED)) {			return i;		}	}	printk (KERN_WARNING LOGNAME "no free sample slots!\n");	return -1;}static int wavefront_find_free_patch (void){	int i;	for (i = 0; i < WF_MAX_PATCH; i++) {		if (!(dev.patch_status[i] & WF_SLOT_FILLED)) {			return i;		}	}	printk (KERN_WARNING LOGNAME "no free patch slots!\n");	return -1;}static int log2_2048(int n){	int tbl[]={0, 0, 2048, 3246, 4096, 4755, 5294, 5749, 6143,		   6492, 6803, 7084, 7342, 7578, 7797, 8001, 8192,		   8371, 8540, 8699, 8851, 8995, 9132, 9264, 9390,		   9510, 9626, 9738, 9845, 9949, 10049, 10146};	int i;	/* Returns 2048*log2(n) */	/* FIXME: this is like doing integer math	   on quantum particles (RuN) */

⌨️ 快捷键说明

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