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

📄 cmpci.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
		s->mix.vol[volidx[i]-1] = val;		return put_user(s->mix.vol[volidx[i]-1], p);	}}/* --------------------------------------------------------------------- */static int cm_open_mixdev(struct inode *inode, struct file *file){	int minor = iminor(inode);	struct list_head *list;	struct cm_state *s;	for (list = devs.next; ; list = list->next) {		if (list == &devs)			return -ENODEV;		s = list_entry(list, struct cm_state, devs);		if (s->dev_mixer == minor)			break;	}       	VALIDATE_STATE(s);	file->private_data = s;	return nonseekable_open(inode, file);}static int cm_release_mixdev(struct inode *inode, struct file *file){	struct cm_state *s = (struct cm_state *)file->private_data;	VALIDATE_STATE(s);	return 0;}static int cm_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	return mixer_ioctl((struct cm_state *)file->private_data, cmd, arg);}static /*const*/ struct file_operations cm_mixer_fops = {	.owner	 = THIS_MODULE,	.llseek	 = no_llseek,	.ioctl	 = cm_ioctl_mixdev,	.open	 = cm_open_mixdev,	.release = cm_release_mixdev,};/* --------------------------------------------------------------------- */static int drain_dac(struct cm_state *s, int nonblock){	DECLARE_WAITQUEUE(wait, current);	unsigned long flags;	int count, tmo;	if (s->dma_dac.mapped || !s->dma_dac.ready)		return 0;        add_wait_queue(&s->dma_dac.wait, &wait);        for (;;) {        	__set_current_state(TASK_INTERRUPTIBLE);                spin_lock_irqsave(&s->lock, flags);		count = s->dma_dac.count;                spin_unlock_irqrestore(&s->lock, flags);		if (count <= 0)			break;		if (signal_pending(current))                        break;                if (nonblock) {                        remove_wait_queue(&s->dma_dac.wait, &wait);                        set_current_state(TASK_RUNNING);                        return -EBUSY;                }		tmo = 3 * HZ * (count + s->dma_dac.fragsize) / 2 / s->ratedac;		tmo >>= sample_shift[(s->fmt >> CM_CFMT_DACSHIFT) & CM_CFMT_MASK];		if (!schedule_timeout(tmo + 1))			DBG(printk(KERN_DEBUG "cmpci: dma timed out??\n");)        }        remove_wait_queue(&s->dma_dac.wait, &wait);        set_current_state(TASK_RUNNING);        if (signal_pending(current))                return -ERESTARTSYS;        return 0;}/* --------------------------------------------------------------------- */static ssize_t cm_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos){	struct cm_state *s = (struct cm_state *)file->private_data;	DECLARE_WAITQUEUE(wait, current);	ssize_t ret;	unsigned long flags;	unsigned swptr;	int cnt;	VALIDATE_STATE(s);	if (s->dma_adc.mapped)		return -ENXIO;	if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1)))		return ret;	if (!access_ok(VERIFY_WRITE, buffer, count))		return -EFAULT;	ret = 0;        add_wait_queue(&s->dma_adc.wait, &wait);	while (count > 0) {		spin_lock_irqsave(&s->lock, flags);		swptr = s->dma_adc.swptr;		cnt = s->dma_adc.dmasize-swptr;		if (s->dma_adc.count < cnt)			cnt = s->dma_adc.count;		if (cnt <= 0)			__set_current_state(TASK_INTERRUPTIBLE);		spin_unlock_irqrestore(&s->lock, flags);		if (cnt > count)			cnt = count;		if (cnt <= 0) {			if (s->dma_adc.enabled)				start_adc(s);			if (file->f_flags & O_NONBLOCK) {				if (!ret)					ret = -EAGAIN;				goto out;			}			if (!schedule_timeout(HZ)) {				printk(KERN_DEBUG "cmpci: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",				       s->dma_adc.dmasize, s->dma_adc.fragsize, s->dma_adc.count,				       s->dma_adc.hwptr, s->dma_adc.swptr);				spin_lock_irqsave(&s->lock, flags);				stop_adc_unlocked(s);				set_dmaadc(s, s->dma_adc.dmaaddr, s->dma_adc.dmasamples);				/* program sample counts */				set_countadc(s, s->dma_adc.fragsamples);				s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0;				spin_unlock_irqrestore(&s->lock, flags);			}			if (signal_pending(current)) {				if (!ret)					ret = -ERESTARTSYS;				goto out;			}			continue;		}		if (s->status & DO_BIGENDIAN_R) {			int	i, err;			unsigned char *src;			char __user *dst = buffer;			unsigned char data[2];			src = (unsigned char *) (s->dma_adc.rawbuf + swptr);			// copy left/right sample at one time			for (i = 0; i < cnt / 2; i++) {				data[0] = src[1];				data[1] = src[0];				if ((err = __put_user(data[0], dst++))) {					ret = err;					goto out;				}				if ((err = __put_user(data[1], dst++))) {					ret = err;					goto out;				}				src += 2;			}		} else if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {			if (!ret)				ret = -EFAULT;			goto out;		}		swptr = (swptr + cnt) % s->dma_adc.dmasize;		spin_lock_irqsave(&s->lock, flags);		s->dma_adc.swptr = swptr;		s->dma_adc.count -= cnt;		count -= cnt;		buffer += cnt;		ret += cnt;		if (s->dma_adc.enabled)			start_adc_unlocked(s);		spin_unlock_irqrestore(&s->lock, flags);	}out:        remove_wait_queue(&s->dma_adc.wait, &wait);	set_current_state(TASK_RUNNING);	return ret;}static ssize_t cm_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos){	struct cm_state *s = (struct cm_state *)file->private_data;	DECLARE_WAITQUEUE(wait, current);	ssize_t ret;	unsigned long flags;	unsigned swptr;	int cnt;	VALIDATE_STATE(s);	if (s->dma_dac.mapped)		return -ENXIO;	if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))		return ret;	if (!access_ok(VERIFY_READ, buffer, count))		return -EFAULT;	if (s->status & DO_DUAL_DAC) {		if (s->dma_adc.mapped)			return -ENXIO;		if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1)))			return ret;	}	if (!access_ok(VERIFY_READ, buffer, count))		return -EFAULT;	ret = 0;        add_wait_queue(&s->dma_dac.wait, &wait);	while (count > 0) {		spin_lock_irqsave(&s->lock, flags);		if (s->dma_dac.count < 0) {			s->dma_dac.count = 0;			s->dma_dac.swptr = s->dma_dac.hwptr;		}		if (s->status & DO_DUAL_DAC) {			s->dma_adc.swptr = s->dma_dac.swptr;			s->dma_adc.count = s->dma_dac.count;			s->dma_adc.endcleared = s->dma_dac.endcleared;		}		swptr = s->dma_dac.swptr;		cnt = s->dma_dac.dmasize-swptr;		if (s->status & DO_AC3_SW) {			if (s->dma_dac.count + 2 * cnt > s->dma_dac.dmasize)				cnt = (s->dma_dac.dmasize - s->dma_dac.count) / 2;		} else {			if (s->dma_dac.count + cnt > s->dma_dac.dmasize)				cnt = s->dma_dac.dmasize - s->dma_dac.count;		}		if (cnt <= 0)			__set_current_state(TASK_INTERRUPTIBLE);		spin_unlock_irqrestore(&s->lock, flags);		if (cnt > count)			cnt = count;		if ((s->status & DO_DUAL_DAC) && (cnt > count / 2))		    cnt = count / 2;		if (cnt <= 0) {			if (s->dma_dac.enabled)				start_dac(s);			if (file->f_flags & O_NONBLOCK) {				if (!ret)					ret = -EAGAIN;				goto out;			}			if (!schedule_timeout(HZ)) {				printk(KERN_DEBUG "cmpci: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",				       s->dma_dac.dmasize, s->dma_dac.fragsize, s->dma_dac.count,				       s->dma_dac.hwptr, s->dma_dac.swptr);				spin_lock_irqsave(&s->lock, flags);				stop_dac_unlocked(s);				set_dmadac(s, s->dma_dac.dmaaddr, s->dma_dac.dmasamples);				/* program sample counts */				set_countdac(s, s->dma_dac.fragsamples);				s->dma_dac.count = s->dma_dac.hwptr = s->dma_dac.swptr = 0;				if (s->status & DO_DUAL_DAC)  {					set_dmadac1(s, s->dma_adc.dmaaddr, s->dma_adc.dmasamples);					s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0;				}				spin_unlock_irqrestore(&s->lock, flags);			}			if (signal_pending(current)) {				if (!ret)					ret = -ERESTARTSYS;				goto out;			}			continue;		}		if (s->status & DO_AC3_SW) {			int err;			// clip exceeded data, caught by 033 and 037			if (swptr + 2 * cnt > s->dma_dac.dmasize)				cnt = (s->dma_dac.dmasize - swptr) / 2;			if ((err = trans_ac3(s, s->dma_dac.rawbuf + swptr, buffer, cnt))) {				ret = err;				goto out;			}			swptr = (swptr + 2 * cnt) % s->dma_dac.dmasize;		} else if ((s->status & DO_DUAL_DAC) && (s->status & DO_BIGENDIAN_W)) {			int	i, err;			const char __user *src = buffer;			unsigned char *dst0, *dst1;			unsigned char data[8];			dst0 = (unsigned char *) (s->dma_dac.rawbuf + swptr);			dst1 = (unsigned char *) (s->dma_adc.rawbuf + swptr);			// copy left/right sample at one time			for (i = 0; i < cnt / 4; i++) {				if ((err = __get_user(data[0], src++))) {					ret = err;					goto out;				}				if ((err = __get_user(data[1], src++))) {					ret = err;					goto out;				}				if ((err = __get_user(data[2], src++))) {					ret = err;					goto out;				}				if ((err = __get_user(data[3], src++))) {					ret = err;					goto out;				}				if ((err = __get_user(data[4], src++))) {					ret = err;					goto out;				}				if ((err = __get_user(data[5], src++))) {					ret = err;					goto out;				}				if ((err = __get_user(data[6], src++))) {					ret = err;					goto out;				}				if ((err = __get_user(data[7], src++))) {					ret = err;					goto out;				}				dst0[0] = data[1];				dst0[1] = data[0];				dst0[2] = data[3];				dst0[3] = data[2];				dst1[0] = data[5];				dst1[1] = data[4];				dst1[2] = data[7];				dst1[3] = data[6];				dst0 += 4;				dst1 += 4;			}			swptr = (swptr + cnt) % s->dma_dac.dmasize;		} else if (s->status & DO_DUAL_DAC) {			int	i, err;			unsigned long __user *src = (unsigned long __user *) buffer;			unsigned long *dst0, *dst1;			dst0 = (unsigned long *) (s->dma_dac.rawbuf + swptr);			dst1 = (unsigned long *) (s->dma_adc.rawbuf + swptr);			// copy left/right sample at one time			for (i = 0; i < cnt / 4; i++) {				if ((err = __get_user(*dst0++, src++))) {					ret = err;					goto out;				}				if ((err = __get_user(*dst1++, src++))) {					ret = err;					goto out;				}			}			swptr = (swptr + cnt) % s->dma_dac.dmasize;		} else if (s->status & DO_BIGENDIAN_W) {			int	i, err;			const char __user *src = buffer;			unsigned char *dst;			unsigned char data[2];			dst = (unsigned char *) (s->dma_dac.rawbuf + swptr);			// swap hi/lo bytes for each sample			for (i = 0; i < cnt / 2; i++) {				if ((err = __get_user(data[0], src++))) {					ret = err;					goto out;				}				if ((err = __get_user(data[1], src++))) {					ret = err;					goto out;				}				dst[0] = data[1];				dst[1] = data[0];				dst += 2;			}			swptr = (swptr + cnt) % s->dma_dac.dmasize;		} else {			if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) {				if (!ret)					ret = -EFAULT;				goto out;			}			swptr = (swptr + cnt) % s->dma_dac.dmasize;		}		spin_lock_irqsave(&s->lock, flags);		s->dma_dac.swptr = swptr;		s->dma_dac.count += cnt;		if (s->status & DO_AC3_SW)			s->dma_dac.count += cnt;		s->dma_dac.endcleared = 0;		spin_unlock_irqrestore(&s->lock, flags);		count -= cnt;		buffer += cnt;		ret += cnt;		if (s->status & DO_DUAL_DAC) {			count -= cnt;			buffer += cnt;			ret += cnt;		}		if (s->dma_dac.enabled)			start_dac(s);	}out:        remove_wait_queue(&s->dma_dac.wait, &wait);	set_current_state(TASK_RUNNING);	return ret;}static unsigned int cm_poll(struct file *file, struct poll_table_struct *wait){	struct cm_state *s = (struct cm_state *)file->private_data;	unsigned long flags;	unsigned int mask = 0;	VALIDATE_STATE(s);	if (file->f_mode & FMODE_WRITE) {		if (!s->dma_dac.ready && prog_dmabuf(s, 0))			return 0;		poll_wait(file, &s->dma_dac.wait, wait);	}	if (file->f_mode & FMODE_READ) {		if (!s->dma_adc.ready && prog_dmabuf(s, 1))			return 0;		poll_wait(file, &s->dma_adc.wait, wait);	}	spin_lock_irqsave(&s->lock, flags);	cm_update_ptr(s);	if (file->f_mode & FMODE_READ) {		if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)			mask |= POLLIN | POLLRDNORM;	}	if (file->f_mode & FMODE_WRITE) {		if (s->dma_dac.mapped) {			if (s->dma_dac.count >= (signed)s->dma_dac.fragsize)				mask |= POLLOUT | POLLWRNORM;		} else {			if ((signed)s->dma_dac.dmasize >= s->dma_dac.count + (signed)s->dma_dac.fragsize)				mask |= POLLOUT | POLLWRNORM;		}	}	spin_unlock_irqrestore(&s->lock, flags);	return mask;}static int cm_mmap(struct file *file, struct vm_area_struct *vma){	struct cm_state *s = (struct cm_state *)file->private_data;	struct dmabuf *db;	int ret = -EINVAL;	unsigned long size;	VALIDATE_STATE(s);	lock_kernel();	if (vma->vm_flags & VM_WRITE) {		if ((ret = prog_

⌨️ 快捷键说明

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