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

📄 cs46xx.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
static int cs_midi_open(struct inode *inode, struct file *file){        int minor = MINOR(inode->i_rdev);        struct cs_card *card = devs;        unsigned long flags;        while (card && card->dev_midi != minor)                card = card->next;        if (!card)                return -ENODEV;        file->private_data = card;        /* wait for device to become free */        down(&card->midi.open_sem);        while (card->midi.open_mode & file->f_mode) {                if (file->f_flags & O_NONBLOCK) {                        up(&card->midi.open_sem);                        return -EBUSY;                }                up(&card->midi.open_sem);                interruptible_sleep_on(&card->midi.open_wait);                if (signal_pending(current))                        return -ERESTARTSYS;                down(&card->midi.open_sem);        }        spin_lock_irqsave(&card->midi.lock, flags);        if (!(card->midi.open_mode & (FMODE_READ | FMODE_WRITE))) {                card->midi.ird = card->midi.iwr = card->midi.icnt = 0;                card->midi.ord = card->midi.owr = card->midi.ocnt = 0;                card->midi.ird = card->midi.iwr = card->midi.icnt = 0;                cs461x_pokeBA0(card, BA0_MIDCR, 0x0000000f);            /* Enable xmit, rcv. */                cs461x_pokeBA0(card, BA0_HICR, HICR_IEV | HICR_CHGM);   /* Enable interrupts */        }        if (file->f_mode & FMODE_READ) {                card->midi.ird = card->midi.iwr = card->midi.icnt = 0;        }        if (file->f_mode & FMODE_WRITE) {                card->midi.ord = card->midi.owr = card->midi.ocnt = 0;        }        spin_unlock_irqrestore(&card->midi.lock, flags);        card->midi.open_mode |= (file->f_mode & (FMODE_READ | FMODE_WRITE));        up(&card->midi.open_sem);        MOD_INC_USE_COUNT;        return 0;}static int cs_midi_release(struct inode *inode, struct file *file){        struct cs_card *card = (struct cs_card *)file->private_data;        DECLARE_WAITQUEUE(wait, current);        unsigned long flags;        unsigned count, tmo;        if (file->f_mode & FMODE_WRITE) {                current->state = TASK_INTERRUPTIBLE;                add_wait_queue(&card->midi.owait, &wait);                for (;;) {                        spin_lock_irqsave(&card->midi.lock, flags);                        count = card->midi.ocnt;                        spin_unlock_irqrestore(&card->midi.lock, flags);                        if (count <= 0)                                break;                        if (signal_pending(current))                                break;                        if (file->f_flags & O_NONBLOCK) {                                remove_wait_queue(&card->midi.owait, &wait);                                current->state = TASK_RUNNING;                                return -EBUSY;                        }                                              tmo = (count * HZ) / 3100;                        if (!schedule_timeout(tmo ? : 1) && tmo)                                printk(KERN_DEBUG "cs46xx: midi timed out??\n");                }                remove_wait_queue(&card->midi.owait, &wait);                current->state = TASK_RUNNING;        }        down(&card->midi.open_sem);        card->midi.open_mode &= (~(file->f_mode & (FMODE_READ | FMODE_WRITE)));        up(&card->midi.open_sem);        wake_up(&card->midi.open_wait);        MOD_DEC_USE_COUNT;        return 0;}/* *   Midi file operations struct. */static /*const*/ struct file_operations cs_midi_fops = {        llseek:		cs_llseek,        read:		cs_midi_read,        write:		cs_midi_write,        poll:		cs_midi_poll,        open:		cs_midi_open,        release:	cs_midi_release,};static loff_t cs_llseek(struct file *file, loff_t offset, int origin){	return -ESPIPE;}/* * * CopySamples copies 16-bit stereo signed samples from the source to the * destination, possibly converting down to unsigned 8-bit and/or mono. * count specifies the number of output bytes to write. * *  Arguments: * *  dst             - Pointer to a destination buffer. *  src             - Pointer to a source buffer *  count           - The number of bytes to copy into the destination buffer. *  fmt             - CS_FMT_16BIT and/or CS_FMT_STEREO bits *  dmabuf          - pointer to the dma buffer structure * * NOTES: only call this routine if the output desired is not 16 Signed Stereo * 	 * */static void CopySamples(char *dst, char *src, int count, unsigned fmt, 		struct dmabuf *dmabuf){    s32 s32AudioSample;    s16 *psSrc=(s16 *)src;    s16 *psDst=(s16 *)dst;    u8 *pucDst=(u8 *)dst;    CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs4281: CopySamples()+ ") );    CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO	" dst=0x%x src=0x%x count=%d fmt=0x%x\n",	(unsigned)dst,(unsigned)src,(unsigned)count,(unsigned)fmt) );    /*     * See if the data should be output as 8-bit unsigned stereo.     */    if((fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT))    {        /*         * Convert each 16-bit signed stereo sample to 8-bit unsigned 	 * stereo using rounding.         */        psSrc = (s16 *)src;	count = count/2;        while(count--)        {            *(pucDst++) = (u8)(((s16)(*psSrc++) + (s16)0x8000) >> 8);        }    }    /*     * See if the data should be output at 8-bit unsigned mono.     */    else if(!(fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT))    {        /*         * Convert each 16-bit signed stereo sample to 8-bit unsigned 	 * mono using averaging and rounding.         */        psSrc = (s16 *)src;	count = count/2;        while(count--)        {	    s32AudioSample = ((*psSrc)+(*(psSrc + 1)))/2 + (s32)0x80;	    if(s32AudioSample > 0x7fff)	    	s32AudioSample = 0x7fff;            *(pucDst++) = (u8)(((s16)s32AudioSample + (s16)0x8000) >> 8);	    psSrc += 2;        }    }    /*     * See if the data should be output at 16-bit signed mono.     */    else if(!(fmt & CS_FMT_STEREO) && (fmt & CS_FMT_16BIT))    {        /*         * Convert each 16-bit signed stereo sample to 16-bit signed 	 * mono using averaging.         */        psSrc = (s16 *)src;	count = count/2;        while(count--)        {            *(psDst++) = (s16)((*psSrc)+(*(psSrc + 1)))/2;	    psSrc += 2;        }    }}/* * cs_copy_to_user() * replacement for the standard copy_to_user, to allow for a conversion from * 16 bit to 8 bit and from stereo to mono, if the record conversion is active.   * The current CS46xx/CS4280 static image only records in 16bit unsigned Stereo,  * so we convert from any of the other format combinations. */static unsigned cs_copy_to_user(	struct cs_state *s, 	void *dest, 	void *hwsrc, 	unsigned cnt, 	unsigned *copied){	struct dmabuf *dmabuf = &s->dmabuf;	void *src = hwsrc;  /* default to the standard destination buffer addr */	CS_DBGOUT(CS_FUNCTION, 6, printk(KERN_INFO 		"cs_copy_to_user()+ fmt=0x%x cnt=%d dest=0x%.8x\n",		dmabuf->fmt,(unsigned)cnt,(unsigned)dest) );	if(cnt > dmabuf->dmasize)	{		cnt = dmabuf->dmasize;	}	if(!cnt)	{		*copied = 0;		return 0;	}	if(dmabuf->divisor != 1)	{		if(!dmabuf->tmpbuff)		{			*copied = cnt/dmabuf->divisor;			return 0;		}		CopySamples((char *)dmabuf->tmpbuff, (char *)hwsrc, cnt, 			dmabuf->fmt, dmabuf);		src = dmabuf->tmpbuff;		cnt = cnt/dmabuf->divisor;	}        if (copy_to_user(dest, src, cnt))	{		CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR 			"cs4281: cs_copy_to_user()- fault dest=0x%x src=0x%x cnt=%d\n",				(unsigned)dest,(unsigned)src,cnt) );		*copied = 0;		return -EFAULT;	}	*copied = cnt;	CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO 		"cs4281: cs_copy_to_user()- copied bytes is %d \n",cnt) );	return 0;}/* in this loop, dmabuf.count signifies the amount of data that is waiting to be copied to   the user's buffer.  it is filled by the dma machine and drained by this loop. */static ssize_t cs_read(struct file *file, char *buffer, size_t count, loff_t *ppos){	struct cs_card *card=devs;	struct cs_state *state;	DECLARE_WAITQUEUE(wait, current);	struct dmabuf *dmabuf;	ssize_t ret = 0;	unsigned long flags;	unsigned swptr;	int cnt;	unsigned copied=0;	CS_DBGOUT(CS_WAVE_READ, 4, printk("cs461x: cs_read()+ %d\n",count) );	state = (struct cs_state *)card->states[0];	if(!state)		return -ENODEV;	dmabuf = &state->dmabuf;	if (ppos != &file->f_pos)		return -ESPIPE;	if (dmabuf->mapped)		return -ENXIO;	if (!dmabuf->ready && (ret = prog_dmabuf(state)))		return ret;	if (!access_ok(VERIFY_WRITE, buffer, count))		return -EFAULT;	add_wait_queue(&state->dmabuf.wait, &wait);	while (count > 0) {		spin_lock_irqsave(&state->card->lock, flags);		swptr = dmabuf->swptr;		cnt = dmabuf->dmasize - swptr;		if (dmabuf->count < cnt)			cnt = dmabuf->count;		if (cnt <= 0)			__set_current_state(TASK_INTERRUPTIBLE);		spin_unlock_irqrestore(&state->card->lock, flags);		if (cnt > (count * dmabuf->divisor))			cnt = count * dmabuf->divisor;		if (cnt <= 0) {			/* buffer is empty, start the dma machine and wait for data to be			   recorded */			start_adc(state);			if (file->f_flags & O_NONBLOCK) {				if (!ret) ret = -EAGAIN;				break; 			}			schedule();			if (signal_pending(current)) {				ret = ret ? ret : -ERESTARTSYS;				break;			}			continue;		}		CS_DBGOUT(CS_WAVE_READ, 2, printk(KERN_INFO 			"_read() copy_to cnt=%d count=%d ", cnt,count) );		CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO 			" .dmasize=%d .count=%d buffer=0x%.8x ret=%d\n",			dmabuf->dmasize,dmabuf->count,(unsigned)buffer,ret) );                if (cs_copy_to_user(state, buffer, 			(void *)((unsigned)dmabuf->rawbuf + swptr), cnt, &copied))		{			if (!ret) ret = -EFAULT;			break;		}                swptr = (swptr + cnt) % dmabuf->dmasize;                spin_lock_irqsave(&card->lock, flags);                dmabuf->swptr = swptr;                dmabuf->count -= cnt;                spin_unlock_irqrestore(&card->lock, flags);                count -= copied;                buffer += copied;                ret += copied;                start_adc(state);	}	remove_wait_queue(&state->dmabuf.wait, &wait);	set_current_state(TASK_RUNNING);	CS_DBGOUT(CS_WAVE_READ, 4, printk("cs461x: cs_read()- %d\n",ret) );	return ret;}/* in this loop, dmabuf.count signifies the amount of data that is waiting to be dma to   the soundcard.  it is drained by the dma machine and filled by this loop. */static ssize_t cs_write(struct file *file, const char *buffer, size_t count, loff_t *ppos){	struct cs_card *card=devs;	struct cs_state *state;	DECLARE_WAITQUEUE(wait, current);	struct dmabuf *dmabuf;	ssize_t ret = 0;	unsigned long flags;	unsigned swptr;	int cnt;	CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 4,		printk("cs461x: cs_write called, count = %d\n", count) );	state = (struct cs_state *)card->states[1];	if(!state)		return -ENODEV;	dmabuf = &state->dmabuf;	if (ppos != &file->f_pos)		return -ESPIPE;	if (dmabuf->mapped)		return -ENXIO;	if (!dmabuf->ready && (ret = prog_dmabuf(state)))		return ret;	if (!access_ok(VERIFY_READ, buffer, count))		return -EFAULT;	add_wait_queue(&state->dmabuf.wait, &wait);	while (count > 0) {		spin_lock_irqsave(&state->card->lock, flags);		if (dmabuf->count < 0) {			/* buffer underrun, we are recovering from sleep_on_timeout,			   resync hwptr and swptr */			dmabuf->count = 0;			dmabuf->swptr = dmabuf->hwptr;		}		if (dmabuf->underrun)		{			dmabuf->underrun = 0;			dmabuf->hwptr = cs_get_dma_addr(state);			dmabuf->swptr = dmabuf->hwptr;		}		swptr = dmabuf->swptr;		cnt = dmabuf->dmasize - swptr;		if (dmabuf->count + cnt > dmabuf->dmasize)			cnt = dmabuf->dmasize - dmabuf->count;		if (cnt <= 0)			__set_current_state(TASK_INTERRUPTIBLE);		spin_unlock_irqrestore(&state->card->lock, flags);		if (cnt > count)			cnt = count;		if (cnt <= 0) {			/* buffer is full, start the dma machine and wait for data to be			   played */			start_dac(state);			if (file->f_flags & O_NONBLOCK) {				if (!ret) ret = -EAGAIN;				break; 			}			schedule(); 			if (signal_pending(current)) {				ret = ret ? ret : -ERESTARTSYS;				break; 			} 			continue; 		}		if (copy_from_user(dmabuf->rawbuf + swptr, buffer, cnt)) {			if (!ret) ret = -EFAULT;			return ret;		}		swptr = (swptr + cnt) % dmabuf->dmasize;		spin_lock_irqsave(&state->card->lock, flags);		dmabuf->swptr = swptr;		dmabuf->count += cnt;		if(dmabuf->count > dmabuf->dmasize)		{			CS_DBGOUT(CS_WAVE_WRITE | CS_ERROR, 2, printk(			    "cs46xx: cs_write() d->count > dmasize - resetting\n"));			dmabuf->count = dmabuf->dmasize;		}		dmabuf->en

⌨️ 快捷键说明

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