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

📄 cmpci.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
		break;					case MT_5MUTE:	default:		rl = 100 - 3 * ((l >> 3) & 31);		rr = 100 - 3 * ((r >> 3) & 31);		break;					case MT_6MUTE:		rl = 100 - 3 * (l & 63) / 2;		rr = 100 - 3 * (r & 63) / 2;		break;	}	if (l & 0x80)		rl = 0;	if (r & 0x80)		rr = 0;	return put_user((rr << 8) | rl, arg);}#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */static const unsigned char volidx[SOUND_MIXER_NRDEVICES] = {	[SOUND_MIXER_CD]     = 1,	[SOUND_MIXER_LINE]   = 2,	[SOUND_MIXER_MIC]    = 3,	[SOUND_MIXER_SYNTH]  = 4,	[SOUND_MIXER_VOLUME] = 5,	[SOUND_MIXER_PCM]    = 6};#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */static unsigned mixer_recmask(struct cm_state *s){	unsigned long flags;	int i, j, k;	spin_lock_irqsave(&s->lock, flags);	j = rdmixer(s, DSP_MIX_ADCMIXIDX_L);	spin_unlock_irqrestore(&s->lock, flags);	j &= 0x7f;	for (k = i = 0; i < SOUND_MIXER_NRDEVICES; i++)		if (j & mixtable[i].rec)			k |= 1 << i;	return k;}static int mixer_ioctl(struct cm_state *s, unsigned int cmd, unsigned long arg){	unsigned long flags;	int i, val, j;	unsigned char l, r, rl, rr;	VALIDATE_STATE(s);        if (cmd == SOUND_MIXER_INFO) {		mixer_info info;		strncpy(info.id, "cmpci", sizeof(info.id));		strncpy(info.name, "C-Media PCI", sizeof(info.name));		info.modify_counter = s->mix.modcnt;		if (copy_to_user((void *)arg, &info, sizeof(info)))			return -EFAULT;		return 0;	}	if (cmd == SOUND_OLD_MIXER_INFO) {		_old_mixer_info info;		strncpy(info.id, "cmpci", sizeof(info.id));		strncpy(info.name, "C-Media cmpci", sizeof(info.name));		if (copy_to_user((void *)arg, &info, sizeof(info)))			return -EFAULT;		return 0;	}	if (cmd == OSS_GETVERSION)		return put_user(SOUND_VERSION, (int *)arg);	if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int))                return -EINVAL;        if (_SIOC_DIR(cmd) == _SIOC_READ) {                switch (_IOC_NR(cmd)) {                case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */			return put_user(mixer_recmask(s), (int *)arg);			                case SOUND_MIXER_OUTSRC: /* Arg contains a bit for each recording source */			return put_user(mixer_recmask(s), (int *)arg);//need fix			                case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */			for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++)				if (mixtable[i].type)					val |= 1 << i;			return put_user(val, (int *)arg);                case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */			for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++)				if (mixtable[i].rec)					val |= 1 << i;			return put_user(val, (int *)arg);			                case SOUND_MIXER_OUTMASK: /* Arg contains a bit for each supported recording source */			for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++)				if (mixtable[i].play)					val |= 1 << i;			return put_user(val, (int *)arg);			                 case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */			for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++)				if (mixtable[i].type && mixtable[i].type != MT_4MUTEMONO)					val |= 1 << i;			return put_user(val, (int *)arg);			                case SOUND_MIXER_CAPS:			return put_user(0, (int *)arg);		default:			i = _IOC_NR(cmd);                        if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type)                                return -EINVAL;#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS			return return_mixval(s, i, (int *)arg);#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */			if (!volidx[i])				return -EINVAL;			return put_user(s->mix.vol[volidx[i]-1], (int *)arg);#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */		}	}        if (_SIOC_DIR(cmd) != (_SIOC_READ|_SIOC_WRITE)) 		return -EINVAL;	s->mix.modcnt++;	switch (_IOC_NR(cmd)) {	case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */		if (get_user(val, (int *)arg))			return -EFAULT;		i = hweight32(val);		for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) {			if (!(val & (1 << i)))				continue;			if (!mixtable[i].rec) {				val &= ~(1 << i);				continue;			}			j |= mixtable[i].rec;		}		spin_lock_irqsave(&s->lock, flags);		wrmixer(s, DSP_MIX_ADCMIXIDX_L, j);		wrmixer(s, DSP_MIX_ADCMIXIDX_R, (j & 1) | (j>>1));		spin_unlock_irqrestore(&s->lock, flags);		return 0;	case SOUND_MIXER_OUTSRC: /* Arg contains a bit for each recording source */		if (get_user(val, (int *)arg))			return -EFAULT;		for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) {			if (!(val & (1 << i)))				continue;			if (!mixtable[i].play) {				val &= ~(1 << i);				continue;			}			j |= mixtable[i].play;		}		spin_lock_irqsave(&s->lock, flags);		frobindir(s, DSP_MIX_OUTMIXIDX, 0x1f, j);		spin_unlock_irqrestore(&s->lock, flags);		return 0;		default:		i = _IOC_NR(cmd);		if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type)			return -EINVAL;		if (get_user(val, (int *)arg))			return -EFAULT;		l = val & 0xff;		r = (val >> 8) & 0xff;		if (l > 100)			l = 100;		if (r > 100)			r = 100;		spin_lock_irqsave(&s->lock, flags);		switch (mixtable[i].type) {		case MT_4:			if (l >= 10)				l -= 10;			if (r >= 10)				r -= 10;			frobindir(s, mixtable[i].left, 0xf0, l / 6);			frobindir(s, mixtable[i].right, 0xf0, l / 6);			break;		case MT_4MUTEMONO:			rl = (l < 4 ? 0 : (l - 5) / 3) & 31;			rr = (rl >> 2) & 7;			wrmixer(s, mixtable[i].left, rl<<3);			outb((inb(s->iobase + CODEC_CMI_MIXER2) & ~0x0e) | rr<<1, s->iobase + CODEC_CMI_MIXER2);			break;					case MT_5MUTEMONO:			r = l;			rl = l < 4 ? 0 : (l - 5) / 3;			rr = rl >> 2; 			wrmixer(s, mixtable[i].left, rl<<3);			outb((inb(s->iobase + CODEC_CMI_MIXER2) & ~0x0e) | rr<<1, s->iobase + CODEC_CMI_MIXER2);			break;						case MT_5MUTE:			rl = l < 4 ? 0 : (l - 5) / 3;			rr = r < 4 ? 0 : (r - 5) / 3; 			wrmixer(s, mixtable[i].left, rl<<3);			wrmixer(s, mixtable[i].right, rr<<3);			break;						case MT_6MUTE:			if (l < 6)				rl = 0x00;			else				rl = l * 2 / 3;			if (r < 6)				rr = 0x00;			else				rr = r * 2 / 3;			wrmixer(s, mixtable[i].left, rl);			wrmixer(s, mixtable[i].right, rr);			break;		}		spin_unlock_irqrestore(&s->lock, flags);#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS                return return_mixval(s, i, (int *)arg);#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */		if (!volidx[i])			return -EINVAL;		s->mix.vol[volidx[i]-1] = val;		return put_user(s->mix.vol[volidx[i]-1], (int *)arg);#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */	}}/* --------------------------------------------------------------------- */static loff_t cm_llseek(struct file *file, loff_t offset, int origin){	return -ESPIPE;}/* --------------------------------------------------------------------- */static int cm_open_mixdev(struct inode *inode, struct file *file){	int minor = MINOR(inode->i_rdev);	struct cm_state *s = devs;	while (s && s->dev_mixer != minor)		s = s->next;	if (!s)		return -ENODEV;       	VALIDATE_STATE(s);	file->private_data = s;	return 0;}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:		cm_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);                        current->state = TASK_RUNNING;                        return -EBUSY;                }		tmo = (count * HZ) / s->ratedac;		tmo >>= sample_shift[(s->fmt >> CM_CFMT_DACSHIFT) & CM_CFMT_MASK];		if (!schedule_timeout(tmo ? : 1) && tmo)			printk(KERN_DEBUG "cmpci: dma timed out??\n");        }        remove_wait_queue(&s->dma_dac.wait, &wait);        current->state = TASK_RUNNING;        if (signal_pending(current))                return -ERESTARTSYS;        return 0;}/* --------------------------------------------------------------------- */static ssize_t cm_read(struct file *file, char *buffer, size_t count, loff_t *ppos){	struct cm_state *s = (struct cm_state *)file->private_data;	ssize_t ret;	unsigned long flags;	unsigned swptr;	int cnt;	VALIDATE_STATE(s);	if (ppos != &file->f_pos)		return -ESPIPE;	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;#if 0   spin_lock_irqsave(&s->lock, flags);   cm_update_ptr(s);   spin_unlock_irqrestore(&s->lock, flags);#endif	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;		spin_unlock_irqrestore(&s->lock, flags);		if (cnt > count)			cnt = count;		if (cnt <= 0) {			start_adc(s);			if (file->f_flags & O_NONBLOCK)				return ret ? ret : -EAGAIN;			if (!interruptible_sleep_on_timeout(&s->dma_adc.wait, 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);				stop_adc(s);				spin_lock_irqsave(&s->lock, flags);				set_dmaadc(s, virt_to_bus(s->dma_adc.rawbuf), s->dma_adc.dmasamples);				/* program sample counts */				outw(s->dma_adc.fragsamples-1, s->iobase + CODEC_CMI_CH1_FRAME2 + 2);				s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0;				spin_unlock_irqrestore(&s->lock, flags);			}			if (signal_pending(current))				return ret ? ret : -ERESTARTSYS;			continue;		}		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))			return ret ? ret : -EFAULT;		swptr = (swptr + cnt) % s->dma_adc.dmasize;		spin_lock_irqsave(&s->lock, flags);		s->dma_adc.swptr = swptr;		s->dma_adc.count -= cnt;		spin_unlock_irqrestore(&s->lock, flags);		count -= cnt;		buffer += cnt;		ret += cnt;		start_adc(s);	}	return ret;}static ssize_t cm_write(struct file *file, const char *buffer, size_t count, loff_t *ppos){	struct cm_state *s = (struct cm_state *)file->private_data;	ssize_t ret;	unsigned long flags;	unsigned swptr;	int cnt;	VALIDATE_STATE(s);	if (ppos != &file->f_pos)		return -ESPIPE;	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;	ret = 0;#if 0   spin_lock_irqsave(&s->lock, flags);   cm_update_ptr(s);   spin_unlock_irqrestore(&s->lock, flags);#endif	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;		}		swptr = s->dma_dac.swptr;		cnt = s->dma_dac.dmasize-swptr;		if (s->dma_dac.count + cnt > s->dma_dac.dmasize)			cnt = s->dma_dac.dmasize - s->dma_dac.count;		spin_unlock_irqrestore(&s->lock, flags);		if (cnt > count)			cnt = count;		if (cnt <= 0) {			start_dac(s);			if (file->f_flags & O_NONBLOCK)				return ret ? ret : -EAGAIN;			if (!interruptible_sleep_on_timeout(&s->dma_dac.wait, 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);				stop_dac(s);				spin_lock_irqsave(&s->lock, flags);				set_dmadac(s, virt_to_bus(s->dma_dac.rawbuf), s->dma_dac.dmasamples);				/* program sample counts */				outw(s->dma_dac.fragsamples-1, s->iobase + CODEC_CMI_CH0_FRAME2 + 2);				s->dma_dac.count = s->dma_dac.hwptr = s->dma_dac.swptr = 0;				spin_unlock_irqrestore(&s->lock, flags);			}			if (signal_pending(current))				return ret ? ret : -ERESTARTSYS;			continue;		}		if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt))			return ret ? ret : -EFAULT;		swptr = (swptr + cnt) % s->dma_dac.dmasize;		spin_lock_irqsave(&s->lock, flags);		s->dma_dac.swptr = swptr;		s->dma_dac.count += cnt;		s->dma_dac.endcleared = 0;		spin_unlock_irqrestore(&s->lock, flags);		count -= cnt;		buffer += cnt;		ret += cnt;		start_dac(s);	}	return ret;

⌨️ 快捷键说明

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