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

📄 cs46xx.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		SGarray[4] = *(ptmp+2);                                             		SGarray[5] = 0x80000010;                                            		SGarray[6] = *ptmp;                                                 		SGarray[7] = *(ptmp+2);                                             		SGarray[8] = (virt_to_bus(dmabuf->pbuf) & 0xffff000) | 0x10;        		if (dmabuf->SGok) {                                                 			dmabuf->numfrag = nSGpages;                                 			dmabuf->fragsize = 4096;                                    			dmabuf->fragsamples = 4096 >> sample_shift[dmabuf->fmt];    			dmabuf->fragshift = 12;                                     			dmabuf->dmasize = dmabuf->numfrag*4096;                     		}                                                                   		else {                                                              			SGarray[0] = 0xf2c0000f;                                    			SGarray[1] = 0x00000200;                                    			SGarray[2] = 0;                                             			SGarray[3] = 0x00010600;                                    			SGarray[4]=SGarray[5]=SGarray[6]=SGarray[7]=SGarray[8] = 0; 			dmabuf->numfrag = 2;                                        			dmabuf->fragsize = 2048;                                    			dmabuf->fragsamples = 2048 >> sample_shift[dmabuf->fmt];    			dmabuf->dmasize = 4096;                                     			dmabuf->fragshift = 11;                                     		}		for(tmp1 = 0; tmp1 < sizeof(SGarray)/4; tmp1++)                     			cs461x_poke( state->card, BA1_PDTC+tmp1*4, SGarray[tmp1]);  		memset(dmabuf->rawbuf, (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80,		       dmabuf->dmasize);		/*		 *      Now set up the ring		 */		spin_lock_irqsave(&state->card->lock, flags);		cs_play_setup(state);		spin_unlock_irqrestore(&state->card->lock, flags);		/* set the ready flag for the dma buffer */		dmabuf->ready = 1;		CS_DBGOUT(CS_PARMS, 4, printk(			"cs461x: prog_dmabuf(): PLAYBACK rate=%d fmt=0x%x numfrag=%d "			"fragsize=%d dmasize=%d\n",			    dmabuf->rate, dmabuf->fmt, dmabuf->numfrag,			    dmabuf->fragsize, dmabuf->dmasize) );		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- \n"));		return 0;	}	else	{		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- Invalid Type %d\n",			dmabuf->type));	}	return 1;}static void cs_clear_tail(struct cs_state *state){}static int drain_dac(struct cs_state *state, int nonblock){	DECLARE_WAITQUEUE(wait, current);	struct dmabuf *dmabuf = &state->dmabuf;	unsigned long flags;	unsigned long tmo;	int count;	if (dmabuf->mapped || !dmabuf->ready)		return 0;	add_wait_queue(&dmabuf->wait, &wait);	for (;;) {		/* It seems that we have to set the current state to TASK_INTERRUPTIBLE		   every time to make the process really go to sleep */		current->state = TASK_INTERRUPTIBLE;		spin_lock_irqsave(&state->card->lock, flags);		count = dmabuf->count;		spin_unlock_irqrestore(&state->card->lock, flags);		if (count <= 0)			break;		if (signal_pending(current))			break;		if (nonblock) {			remove_wait_queue(&dmabuf->wait, &wait);			current->state = TASK_RUNNING;			return -EBUSY;		}		tmo = (dmabuf->dmasize * HZ) / dmabuf->rate;		tmo >>= sample_shift[dmabuf->fmt];		tmo += (2048*HZ)/dmabuf->rate;				if (!schedule_timeout(tmo ? tmo : 1) && tmo){			printk(KERN_ERR "cs461x: drain_dac, dma timeout? %d\n", count);			break;		}	}	remove_wait_queue(&dmabuf->wait, &wait);	current->state = TASK_RUNNING;	if (signal_pending(current))		return -ERESTARTSYS;	return 0;}/* update buffer manangement pointers, especially, dmabuf->count and dmabuf->hwptr */static void cs_update_ptr(void){	struct cs_card *card=devs;	struct cs_state *state;	struct dmabuf *dmabuf;	unsigned hwptr;	int diff;	/* error handling and process wake up for ADC */	state = card->states[0];	if(state)	{		dmabuf = &state->dmabuf;		if (dmabuf->enable & ADC_RUNNING) {			/* update hardware pointer */			hwptr = cs_get_dma_addr(state);			diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;			CS_DBGOUT(CS_PARMS, 9, printk(				"cs46xx: cs_update_ptr()+ ADC hwptr=%d diff=%d\n", 				hwptr,diff) );			dmabuf->hwptr = hwptr;			dmabuf->total_bytes += diff;			dmabuf->count += diff;			if (dmabuf->count > dmabuf->dmasize)				dmabuf->count = dmabuf->dmasize;			if(dmabuf->mapped)			{				if (dmabuf->count >= (signed)dmabuf->fragsize)					wake_up(&dmabuf->wait);			} else 			{				if (dmabuf->count > 0)					wake_up(&dmabuf->wait);			}		}	}/* * Now the DAC */	state = card->states[1];	if(state)	{		dmabuf = &state->dmabuf;		/* error handling and process wake up for DAC */		if (dmabuf->enable & DAC_RUNNING) {			/* update hardware pointer */			hwptr = cs_get_dma_addr(state);			diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;			CS_DBGOUT(CS_PARMS, 9, printk(				"cs46xx: cs_update_ptr()+ DAC hwptr=%d diff=%d\n", 				hwptr,diff) );			dmabuf->hwptr = hwptr;			dmabuf->total_bytes += diff;			if (dmabuf->mapped) {				dmabuf->count += diff;				if (dmabuf->count >= (signed)dmabuf->fragsize)					wake_up(&dmabuf->wait);				/*				 * other drivers use fragsize, but don't see any sense				 * in that, since dmasize is the buffer asked for				 * via mmap.				 */				if( dmabuf->count > dmabuf->dmasize)					dmabuf->count &= dmabuf->dmasize-1;			} else {				dmabuf->count -= diff;				/*				 * backfill with silence and clear out the last 				 * "diff" number of bytes.				 */				if(hwptr >= diff)				{					memset(dmabuf->rawbuf + hwptr - diff, 						(dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, diff);				}				else				{					memset(dmabuf->rawbuf, 						(dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80,						(unsigned)hwptr);					memset((void *)((unsigned)dmabuf->rawbuf + 							dmabuf->dmasize + hwptr - diff),						(dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, 						diff - hwptr); 				}				if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) {					CS_DBGOUT(CS_ERROR, 2, printk(					  "cs46xx: ERROR DAC count<0 or count > dmasize (%d)\n",					  	dmabuf->count));					/* 					* buffer underrun or buffer overrun, reset the					* count of bytes written back to 0.					*/					if(dmabuf->count < 0)						dmabuf->underrun=1;					dmabuf->count = 0;					dmabuf->error++;				}				if (dmabuf->count < (signed)dmabuf->dmasize/2)					wake_up(&dmabuf->wait);			}		}	}}/* hold spinlock for the following! */static void cs_handle_midi(struct cs_card *card){        unsigned char ch;        int wake;        unsigned temp1;        wake = 0;        while (!(cs461x_peekBA0(card,  BA0_MIDSR) & MIDSR_RBE)) {                ch = cs461x_peekBA0(card, BA0_MIDRP);                if (card->midi.icnt < CS_MIDIINBUF) {                        card->midi.ibuf[card->midi.iwr] = ch;                        card->midi.iwr = (card->midi.iwr + 1) % CS_MIDIINBUF;                        card->midi.icnt++;                }                wake = 1;        }        if (wake)                wake_up(&card->midi.iwait);        wake = 0;        while (!(cs461x_peekBA0(card,  BA0_MIDSR) & MIDSR_TBF) && card->midi.ocnt > 0) {                temp1 = ( card->midi.obuf[card->midi.ord] ) & 0x000000ff;                cs461x_pokeBA0(card, BA0_MIDWP,temp1);                card->midi.ord = (card->midi.ord + 1) % CS_MIDIOUTBUF;                card->midi.ocnt--;                if (card->midi.ocnt < CS_MIDIOUTBUF-16)                        wake = 1;        }        if (wake)                wake_up(&card->midi.owait);}static void cs_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct cs_card *card = (struct cs_card *)dev_id;	/* Single channel card */	struct cs_state *recstate = card->channel[0].state;	struct cs_state *playstate = card->channel[1].state;	u32 status;	CS_DBGOUT(CS_INTERRUPT, 4, printk("cs46xx: cs_interrupt()+ \n"));	spin_lock(&card->lock);	status = cs461x_peekBA0(card, BA0_HISR);		if ((status & 0x7fffffff) == 0)	{		cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV);		spin_unlock(&card->lock);		return;	}		/*	 * check for playback or capture interrupt only	 */	if( ((status & HISR_VC0) && playstate && playstate->dmabuf.ready) || 	    (((status & HISR_VC1) && recstate && recstate->dmabuf.ready)) )	{		CS_DBGOUT(CS_INTERRUPT, 8, printk(			"cs46xx: cs_interrupt() interrupt bit(s) set (0x%x)\n",status));		cs_update_ptr();	}        if( status & HISR_MIDI )                cs_handle_midi(card);	 	/* clear 'em */	cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV);	spin_unlock(&card->lock);	CS_DBGOUT(CS_INTERRUPT, 4, printk("cs46xx: cs_interrupt()- \n"));}/**********************************************************************/static ssize_t cs_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos){        struct cs_card *card = (struct cs_card *)file->private_data;        ssize_t ret;        unsigned long flags;        unsigned ptr;        int cnt;        if (ppos != &file->f_pos)                return -ESPIPE;        if (!access_ok(VERIFY_WRITE, buffer, count))                return -EFAULT;        ret = 0;        while (count > 0) {                spin_lock_irqsave(&card->lock, flags);                ptr = card->midi.ird;                cnt = CS_MIDIINBUF - ptr;                if (card->midi.icnt < cnt)                        cnt = card->midi.icnt;                spin_unlock_irqrestore(&card->lock, flags);                if (cnt > count)                        cnt = count;                if (cnt <= 0) {                        if (file->f_flags & O_NONBLOCK)                                return ret ? ret : -EAGAIN;                        interruptible_sleep_on(&card->midi.iwait);                        if (signal_pending(current))                                return ret ? ret : -ERESTARTSYS;                        continue;                }                if (copy_to_user(buffer, card->midi.ibuf + ptr, cnt))                        return ret ? ret : -EFAULT;                ptr = (ptr + cnt) % CS_MIDIINBUF;                spin_lock_irqsave(&card->lock, flags);                card->midi.ird = ptr;                card->midi.icnt -= cnt;                spin_unlock_irqrestore(&card->lock, flags);                count -= cnt;                buffer += cnt;                ret += cnt;        }        return ret;}static ssize_t cs_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos){        struct cs_card *card = (struct cs_card *)file->private_data;        ssize_t ret;        unsigned long flags;        unsigned ptr;        int cnt;        if (ppos != &file->f_pos)                return -ESPIPE;        if (!access_ok(VERIFY_READ, buffer, count))                return -EFAULT;        ret = 0;        while (count > 0) {                spin_lock_irqsave(&card->lock, flags);                ptr = card->midi.owr;                cnt = CS_MIDIOUTBUF - ptr;                if (card->midi.ocnt + cnt > CS_MIDIOUTBUF)                        cnt = CS_MIDIOUTBUF - card->midi.ocnt;                if (cnt <= 0)                        cs_handle_midi(card);                spin_unlock_irqrestore(&card->lock, flags);                if (cnt > count)                        cnt = count;                if (cnt <= 0) {                        if (file->f_flags & O_NONBLOCK)                                return ret ? ret : -EAGAIN;                        interruptible_sleep_on(&card->midi.owait);                        if (signal_pending(current))                                return ret ? ret : -ERESTARTSYS;                        continue;                }                if (copy_from_user(card->midi.obuf + ptr, buffer, cnt))                        return ret ? ret : -EFAULT;                ptr = (ptr + cnt) % CS_MIDIOUTBUF;                spin_lock_irqsave(&card->lock, flags);                card->midi.owr = ptr;                card->midi.ocnt += cnt;                spin_unlock_irqrestore(&card->lock, flags);                count -= cnt;                buffer += cnt;                ret += cnt;                spin_lock_irqsave(&card->lock, flags);                cs_handle_midi(card);                spin_unlock_irqrestore(&card->lock, flags);        }        return ret;}static unsigned int cs_midi_poll(struct file *file, struct poll_table_struct *wait){        struct cs_card *card = (struct cs_card *)file->private_data;        unsigned long flags;        unsigned int mask = 0;        if (file->f_flags & FMODE_WRITE)                poll_wait(file, &card->midi.owait, wait);        if (file->f_flags & FMODE_READ)                poll_wait(file, &card->midi.iwait, wait);        spin_lock_irqsave(&card->lock, flags);        if (file->f_flags & FMODE_READ) {                if (card->midi.icnt > 0)                        mask |= POLLIN | POLLRDNORM;        }        if (file->f_flags & FMODE_WRITE) {                if (card->midi.ocnt < CS_MIDIOUTBUF)                        mask |= POLLOUT | POLLWRNORM;        }        spin_unlock_irqrestore(&card->lock, flags);        return mask;}

⌨️ 快捷键说明

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