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

📄 cmpci.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
}/* No kernel lock - fine (we have our own spinlock) */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_dmabuf(s, 1)) != 0)			goto out;		db = &s->dma_dac;	} else if (vma->vm_flags & VM_READ) {		if ((ret = prog_dmabuf(s, 0)) != 0)			goto out;		db = &s->dma_adc;	} else 		goto out;	ret = -EINVAL;	if (vma->vm_pgoff != 0)		goto out;	size = vma->vm_end - vma->vm_start;	if (size > (PAGE_SIZE << db->buforder))		goto out;	ret = -EAGAIN;	if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))		goto out;	db->mapped = 1;	ret = 0;out:	unlock_kernel();	return ret;}static int cm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	struct cm_state *s = (struct cm_state *)file->private_data;	unsigned long flags;        audio_buf_info abinfo;        count_info cinfo;	int val, mapped, ret;	unsigned char fmtm, fmtd;	VALIDATE_STATE(s);        mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) ||		((file->f_mode & FMODE_READ) && s->dma_adc.mapped);	switch (cmd) {	case OSS_GETVERSION:		return put_user(SOUND_VERSION, (int *)arg);	case SNDCTL_DSP_SYNC:		if (file->f_mode & FMODE_WRITE)			return drain_dac(s, 0/*file->f_flags & O_NONBLOCK*/);		return 0;			case SNDCTL_DSP_SETDUPLEX:		return 0;	case SNDCTL_DSP_GETCAPS:		return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg);		        case SNDCTL_DSP_RESET:		if (file->f_mode & FMODE_WRITE) {			stop_dac(s);			synchronize_irq();			s->dma_dac.swptr = s->dma_dac.hwptr = s->dma_dac.count = s->dma_dac.total_bytes = 0;		}		if (file->f_mode & FMODE_READ) {			stop_adc(s);			synchronize_irq();			s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = s->dma_adc.total_bytes = 0;		}		return 0;        case SNDCTL_DSP_SPEED:                if (get_user(val, (int *)arg))			return -EFAULT;		if (val >= 0) {			if (file->f_mode & FMODE_READ) {				stop_adc(s);				s->dma_adc.ready = 0;				set_adc_rate(s, val);			}			if (file->f_mode & FMODE_WRITE) {				stop_dac(s);				s->dma_dac.ready = 0;				set_dac_rate(s, val);			}		}		return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);		        case SNDCTL_DSP_STEREO:                if (get_user(val, (int *)arg))			return -EFAULT;		fmtd = 0;		fmtm = ~0;		if (file->f_mode & FMODE_READ) {			stop_adc(s);			s->dma_adc.ready = 0;			if (val)				fmtd |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT;			else				fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_ADCSHIFT);		}		if (file->f_mode & FMODE_WRITE) {			stop_dac(s);			s->dma_dac.ready = 0;			if (val)				fmtd |= CM_CFMT_STEREO << CM_CFMT_DACSHIFT;			else				fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_DACSHIFT);		}		set_fmt(s, fmtm, fmtd);		return 0;        case SNDCTL_DSP_CHANNELS:                if (get_user(val, (int *)arg))			return -EFAULT;		if (val != 0) {			fmtd = 0;			fmtm = ~0;			if (file->f_mode & FMODE_READ) {				stop_adc(s);				s->dma_adc.ready = 0;				if (val >= 2)					fmtd |= CM_CFMT_STEREO << CM_CFMT_ADCSHIFT;				else					fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_ADCSHIFT);			}			if (file->f_mode & FMODE_WRITE) {				stop_dac(s);				s->dma_dac.ready = 0;				if (val >= 2)					fmtd |= CM_CFMT_STEREO << CM_CFMT_DACSHIFT;				else					fmtm &= ~(CM_CFMT_STEREO << CM_CFMT_DACSHIFT);			}			set_fmt(s, fmtm, fmtd);		}		return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_STEREO << CM_CFMT_ADCSHIFT) 					   : (CM_CFMT_STEREO << CM_CFMT_DACSHIFT))) ? 2 : 1, (int *)arg);			case SNDCTL_DSP_GETFMTS: /* Returns a mask */                return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);			case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/		if (get_user(val, (int *)arg))			return -EFAULT;		if (val != AFMT_QUERY) {			fmtd = 0;			fmtm = ~0;			if (file->f_mode & FMODE_READ) {				stop_adc(s);				s->dma_adc.ready = 0;				if (val == AFMT_S16_LE)					fmtd |= CM_CFMT_16BIT << CM_CFMT_ADCSHIFT;				else					fmtm &= ~(CM_CFMT_16BIT << CM_CFMT_ADCSHIFT);			}			if (file->f_mode & FMODE_WRITE) {				stop_dac(s);				s->dma_dac.ready = 0;				if (val == AFMT_S16_LE)					fmtd |= CM_CFMT_16BIT << CM_CFMT_DACSHIFT;				else					fmtm &= ~(CM_CFMT_16BIT << CM_CFMT_DACSHIFT);			}			set_fmt(s, fmtm, fmtd);		}		return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_16BIT << CM_CFMT_ADCSHIFT) 					   : (CM_CFMT_16BIT << CM_CFMT_DACSHIFT))) ? AFMT_S16_LE : AFMT_U8, (int *)arg);			case SNDCTL_DSP_POST:                return 0;        case SNDCTL_DSP_GETTRIGGER:		val = 0;		if (file->f_mode & FMODE_READ && s->enable & CM_CENABLE_RE) 			val |= PCM_ENABLE_INPUT;		if (file->f_mode & FMODE_WRITE && s->enable & CM_CENABLE_PE) 			val |= PCM_ENABLE_OUTPUT;		return put_user(val, (int *)arg);			case SNDCTL_DSP_SETTRIGGER:		if (get_user(val, (int *)arg))			return -EFAULT;		if (file->f_mode & FMODE_READ) {			if (val & PCM_ENABLE_INPUT) {				if (!s->dma_adc.ready && (ret =  prog_dmabuf(s, 1)))					return ret;				start_adc(s);			} else				stop_adc(s);		}		if (file->f_mode & FMODE_WRITE) {			if (val & PCM_ENABLE_OUTPUT) {				if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))					return ret;				start_dac(s);			} else				stop_dac(s);		}		return 0;	case SNDCTL_DSP_GETOSPACE:		if (!(file->f_mode & FMODE_WRITE))			return -EINVAL;		if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))			return ret;		spin_lock_irqsave(&s->lock, flags);		cm_update_ptr(s);		abinfo.fragsize = s->dma_dac.fragsize;                abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count;                abinfo.fragstotal = s->dma_dac.numfrag;                abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;      		spin_unlock_irqrestore(&s->lock, flags);		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;	case SNDCTL_DSP_GETISPACE:		if (!(file->f_mode & FMODE_READ))			return -EINVAL;		if (!s->dma_adc.ready && (ret =  prog_dmabuf(s, 1)))			return ret;		spin_lock_irqsave(&s->lock, flags);		cm_update_ptr(s);		abinfo.fragsize = s->dma_adc.fragsize;                abinfo.bytes = s->dma_adc.count;                abinfo.fragstotal = s->dma_adc.numfrag;                abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;      		spin_unlock_irqrestore(&s->lock, flags);		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;		        case SNDCTL_DSP_NONBLOCK:                file->f_flags |= O_NONBLOCK;                return 0;        case SNDCTL_DSP_GETODELAY:		if (!(file->f_mode & FMODE_WRITE))			return -EINVAL;		if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))			return ret;		spin_lock_irqsave(&s->lock, flags);		cm_update_ptr(s);                val = s->dma_dac.count;		spin_unlock_irqrestore(&s->lock, flags);		return put_user(val, (int *)arg);        case SNDCTL_DSP_GETIPTR:		if (!(file->f_mode & FMODE_READ))			return -EINVAL;		if (!s->dma_adc.ready && (ret =  prog_dmabuf(s, 1)))			return ret;		spin_lock_irqsave(&s->lock, flags);		cm_update_ptr(s);                cinfo.bytes = s->dma_adc.total_bytes;                cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;                cinfo.ptr = s->dma_adc.hwptr;		if (s->dma_adc.mapped)			s->dma_adc.count &= s->dma_adc.fragsize-1;		spin_unlock_irqrestore(&s->lock, flags);                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));        case SNDCTL_DSP_GETOPTR:		if (!(file->f_mode & FMODE_WRITE))			return -EINVAL;		if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))			return ret;		spin_lock_irqsave(&s->lock, flags);		cm_update_ptr(s);                cinfo.bytes = s->dma_dac.total_bytes;                cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift;                cinfo.ptr = s->dma_dac.hwptr;		if (s->dma_dac.mapped)			s->dma_dac.count &= s->dma_dac.fragsize-1;		spin_unlock_irqrestore(&s->lock, flags);                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));        case SNDCTL_DSP_GETBLKSIZE:		if (file->f_mode & FMODE_WRITE) {			if ((val = prog_dmabuf(s, 0)))				return val;			return put_user(s->dma_dac.fragsize, (int *)arg);		}		if ((val = prog_dmabuf(s, 1)))			return val;		return put_user(s->dma_adc.fragsize, (int *)arg);        case SNDCTL_DSP_SETFRAGMENT:                if (get_user(val, (int *)arg))			return -EFAULT;		if (file->f_mode & FMODE_READ) {			s->dma_adc.ossfragshift = val & 0xffff;			s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;			if (s->dma_adc.ossfragshift < 4)				s->dma_adc.ossfragshift = 4;			if (s->dma_adc.ossfragshift > 15)				s->dma_adc.ossfragshift = 15;			if (s->dma_adc.ossmaxfrags < 4)				s->dma_adc.ossmaxfrags = 4;		}		if (file->f_mode & FMODE_WRITE) {			s->dma_dac.ossfragshift = val & 0xffff;			s->dma_dac.ossmaxfrags = (val >> 16) & 0xffff;			if (s->dma_dac.ossfragshift < 4)				s->dma_dac.ossfragshift = 4;			if (s->dma_dac.ossfragshift > 15)				s->dma_dac.ossfragshift = 15;			if (s->dma_dac.ossmaxfrags < 4)				s->dma_dac.ossmaxfrags = 4;		}		return 0;        case SNDCTL_DSP_SUBDIVIDE:		if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||		    (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision))			return -EINVAL;                if (get_user(val, (int *)arg))			return -EFAULT;		if (val != 1 && val != 2 && val != 4)			return -EINVAL;		if (file->f_mode & FMODE_READ)			s->dma_adc.subdivision = val;		if (file->f_mode & FMODE_WRITE)			s->dma_dac.subdivision = val;		return 0;        case SOUND_PCM_READ_RATE:		return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);        case SOUND_PCM_READ_CHANNELS:		return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_STEREO << CM_CFMT_ADCSHIFT) : (CM_CFMT_STEREO << CM_CFMT_DACSHIFT))) ? 2 : 1, (int *)arg);        case SOUND_PCM_READ_BITS:		return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (CM_CFMT_16BIT << CM_CFMT_ADCSHIFT) : (CM_CFMT_16BIT << CM_CFMT_DACSHIFT))) ? 16 : 8, (int *)arg);        case SOUND_PCM_READ_FILTER:		return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);        case SOUND_PCM_WRITE_FILTER:        case SNDCTL_DSP_SETSYNCRO:                return -EINVAL;			}	return mixer_ioctl(s, cmd, arg);}static int cm_open(struct inode *inode, struct file *file){	int minor = MINOR(inode->i_rdev);	struct cm_state *s = devs;	unsigned char fmtm = ~0, fmts = 0;	while (s && ((s->dev_audio ^ minor) & ~0xf))		s = s->next;	if (!s)		return -ENODEV;       	VALIDATE_STATE(s);	file->private_data = s;	/* wait for device to become free */	down(&s->open_sem);	while (s->open_mode & file->f_mode) {		if (file->f_flags & O_NONBLOCK) {			up(&s->open_sem);			return -EBUSY;		}		up(&s->open_sem);		interruptible_sleep_on(&s->open_wait);		if (signal_pending(current))			return -ERESTARTSYS;		down(&s->open_sem);	}	if (file->f_mode & FMODE_READ) {		fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_ADCSHIFT);		if ((minor & 0xf) == SND_DEV_DSP16)			fmts |= CM_CFMT_16BIT << CM_CFMT_ADCSHIFT;		s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0;		set_adc_rate(s, 8000);	}	if (file->f_mode & FMODE_WRITE) {		fmtm &= ~((CM_CFMT_STEREO | CM_CFMT_16BIT) << CM_CFMT_DACSHIFT);		if ((minor & 0xf) == SND_DEV_DSP16)			fmts |= CM_CFMT_16BIT << CM_CFMT_DACSHIFT;		s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = s->dma_dac.subdivision = 0;		set_dac_rate(s, 8000);	}	set_fmt(s, fmtm, fmts);	s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);	up(&s->open_sem);	return 0;}static int cm_release(struct inode *inode, struct file *file){	struct cm_state *s = (struct cm_state *)file->private_data;	VALIDATE_STATE(s);	lock_kernel();	if (file->f_mode & FMODE_WRITE)		drain_dac(s, file->f_flags & O_NONBLOCK);	down(&s->open_sem);	if (file->f_mode & FMODE_WRITE) {		stop_dac(s);		dealloc_dmabuf(&s->dma_dac);	}	if (file->f_mode & FMODE_READ) {		stop_adc(s);		dealloc_dmabuf(&s->dma_adc);	}	s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);	up(&s->open_sem);	wake_up(&s->open_wait);	unlock_kernel();	return 0;}

⌨️ 快捷键说明

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