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

📄 cmpci.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
static /*const*/ struct file_operations cm_audio_fops = {	owner:		THIS_MODULE,	llseek:		cm_llseek,	read:		cm_read,	write:		cm_write,	poll:		cm_poll,	ioctl:		cm_ioctl,	mmap:		cm_mmap,	open:		cm_open,	release:	cm_release,};/* --------------------------------------------------------------------- */static ssize_t cm_midi_read(struct file *file, char *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 ptr;	int cnt;	VALIDATE_STATE(s);	if (ppos != &file->f_pos)		return -ESPIPE;	if (!access_ok(VERIFY_WRITE, buffer, count))		return -EFAULT;	if (count == 0)		return 0;	ret = 0;	add_wait_queue(&s->midi.iwait, &wait);	while (count > 0) {		set_current_state(TASK_INTERRUPTIBLE);		spin_lock_irqsave(&s->lock, flags);		ptr = s->midi.ird;		cnt = MIDIINBUF - ptr;		if (s->midi.icnt < cnt)			cnt = s->midi.icnt;		spin_unlock_irqrestore(&s->lock, flags);		if (cnt > count)			cnt = count;		if (cnt <= 0) {			if (file->f_flags & O_NONBLOCK) 			{				if (!ret)					ret = -EAGAIN;				break;			}			schedule();			if (signal_pending(current)) 			{				if (!ret)					ret = -ERESTARTSYS;				break;			}			continue;		}		if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt)) {			if (!ret)				ret = -EFAULT;			break;		}		ptr = (ptr + cnt) % MIDIINBUF;		spin_lock_irqsave(&s->lock, flags);		s->midi.ird = ptr;		s->midi.icnt -= cnt;		spin_unlock_irqrestore(&s->lock, flags);		count -= cnt;		buffer += cnt;		ret += cnt;		break;	}	__set_current_state(TASK_RUNNING);	remove_wait_queue(&s->midi.iwait, &wait);	return ret;}static ssize_t cm_midi_write(struct file *file, const char *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 ptr;	int cnt;	VALIDATE_STATE(s);	if (ppos != &file->f_pos)		return -ESPIPE;	if (!access_ok(VERIFY_READ, buffer, count))		return -EFAULT;	if (count == 0)		return 0;	ret = 0;	add_wait_queue(&s->midi.owait, &wait);	while (count > 0) {		set_current_state(TASK_INTERRUPTIBLE);		spin_lock_irqsave(&s->lock, flags);		ptr = s->midi.owr;		cnt = MIDIOUTBUF - ptr;		if (s->midi.ocnt + cnt > MIDIOUTBUF)			cnt = MIDIOUTBUF - s->midi.ocnt;		if (cnt <= 0)			cm_handle_midi(s);		spin_unlock_irqrestore(&s->lock, flags);		if (cnt > count)			cnt = count;		if (cnt <= 0) {			if (file->f_flags & O_NONBLOCK) {				if (!ret)					ret = -EAGAIN;				break;			}			schedule();			if (signal_pending(current)) {				if (!ret)					ret = -ERESTARTSYS;				break;			}			continue;		}		if (copy_from_user(s->midi.obuf + ptr, buffer, cnt)) {			if (!ret)				ret = -EFAULT;			break;		}		ptr = (ptr + cnt) % MIDIOUTBUF;		spin_lock_irqsave(&s->lock, flags);		s->midi.owr = ptr;		s->midi.ocnt += cnt;		spin_unlock_irqrestore(&s->lock, flags);		count -= cnt;		buffer += cnt;		ret += cnt;		spin_lock_irqsave(&s->lock, flags);		cm_handle_midi(s);		spin_unlock_irqrestore(&s->lock, flags);	}	__set_current_state(TASK_RUNNING);	remove_wait_queue(&s->midi.owait, &wait);	return ret;}static unsigned int cm_midi_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)		poll_wait(file, &s->midi.owait, wait);	if (file->f_mode & FMODE_READ)		poll_wait(file, &s->midi.iwait, wait);	spin_lock_irqsave(&s->lock, flags);	if (file->f_mode & FMODE_READ) {		if (s->midi.icnt > 0)			mask |= POLLIN | POLLRDNORM;	}	if (file->f_mode & FMODE_WRITE) {		if (s->midi.ocnt < MIDIOUTBUF)			mask |= POLLOUT | POLLWRNORM;	}	spin_unlock_irqrestore(&s->lock, flags);	return mask;}static int cm_midi_open(struct inode *inode, struct file *file){	int minor = MINOR(inode->i_rdev);	struct cm_state *s = devs;	unsigned long flags;	while (s && s->dev_midi != minor)		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 << FMODE_MIDI_SHIFT)) {		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);	}	spin_lock_irqsave(&s->lock, flags);	if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {		s->midi.ird = s->midi.iwr = s->midi.icnt = 0;		s->midi.ord = s->midi.owr = s->midi.ocnt = 0;		/* enable MPU-401 */		outb(inb(s->iobase + CODEC_CMI_FUNCTRL1) | 4, s->iobase + CODEC_CMI_FUNCTRL1);		outb(0xff, s->iomidi+1); /* reset command */		if (!(inb(s->iomidi+1) & 0x80))			inb(s->iomidi);		outb(0x3f, s->iomidi+1); /* uart command */		if (!(inb(s->iomidi+1) & 0x80))			inb(s->iomidi);		s->midi.ird = s->midi.iwr = s->midi.icnt = 0;		init_timer(&s->midi.timer);		s->midi.timer.expires = jiffies+1;		s->midi.timer.data = (unsigned long)s;		s->midi.timer.function = cm_midi_timer;		add_timer(&s->midi.timer);	}	if (file->f_mode & FMODE_READ) {		s->midi.ird = s->midi.iwr = s->midi.icnt = 0;	}	if (file->f_mode & FMODE_WRITE) {		s->midi.ord = s->midi.owr = s->midi.ocnt = 0;	}	spin_unlock_irqrestore(&s->lock, flags);	s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE);	up(&s->open_sem);	return 0;}static int cm_midi_release(struct inode *inode, struct file *file){	struct cm_state *s = (struct cm_state *)file->private_data;        DECLARE_WAITQUEUE(wait, current);	unsigned long flags;	unsigned count, tmo;	VALIDATE_STATE(s);	lock_kernel();	if (file->f_mode & FMODE_WRITE) {		add_wait_queue(&s->midi.owait, &wait);		for (;;) {			set_current_state(TASK_INTERRUPTIBLE);			spin_lock_irqsave(&s->lock, flags);			count = s->midi.ocnt;			spin_unlock_irqrestore(&s->lock, flags);			if (count <= 0)				break;			if (signal_pending(current))				break;			if (file->f_flags & O_NONBLOCK) {				remove_wait_queue(&s->midi.owait, &wait);				set_current_state(TASK_RUNNING);				return -EBUSY;			}			tmo = (count * HZ) / 3100;			if (!schedule_timeout(tmo ? : 1) && tmo)				printk(KERN_DEBUG "cmpci: midi timed out??\n");		}		remove_wait_queue(&s->midi.owait, &wait);		set_current_state(TASK_RUNNING);	}	down(&s->open_sem);	s->open_mode &= (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE);	spin_lock_irqsave(&s->lock, flags);	if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {		del_timer(&s->midi.timer);				outb(0xff, s->iomidi+1); /* reset command */		if (!(inb(s->iomidi+1) & 0x80))			inb(s->iomidi);		/* disable MPU-401 */		outb(inb(s->iobase + CODEC_CMI_FUNCTRL1) & ~4, s->iobase + CODEC_CMI_FUNCTRL1);	}	spin_unlock_irqrestore(&s->lock, flags);	up(&s->open_sem);	wake_up(&s->open_wait);	unlock_kernel();	return 0;}static /*const*/ struct file_operations cm_midi_fops = {	owner:		THIS_MODULE,	llseek:		cm_llseek,	read:		cm_midi_read,	write:		cm_midi_write,	poll:		cm_midi_poll,	open:		cm_midi_open,	release:	cm_midi_release,};/* --------------------------------------------------------------------- */static int cm_dmfm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	static const unsigned char op_offset[18] = {		0x00, 0x01, 0x02, 0x03, 0x04, 0x05,		0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,		0x10, 0x11, 0x12, 0x13, 0x14, 0x15	};	struct cm_state *s = (struct cm_state *)file->private_data;	struct dm_fm_voice v;	struct dm_fm_note n;	struct dm_fm_params p;	unsigned int io;	unsigned int regb;	switch (cmd) {			case FM_IOCTL_RESET:		for (regb = 0xb0; regb < 0xb9; regb++) {			outb(regb, s->iosynth);			outb(0, s->iosynth+1);			outb(regb, s->iosynth+2);			outb(0, s->iosynth+3);		}		return 0;	case FM_IOCTL_PLAY_NOTE:		if (copy_from_user(&n, (void *)arg, sizeof(n)))			return -EFAULT;		if (n.voice >= 18)			return -EINVAL;		if (n.voice >= 9) {			regb = n.voice - 9;			io = s->iosynth+2;		} else {			regb = n.voice;			io = s->iosynth;		}		outb(0xa0 + regb, io);		outb(n.fnum & 0xff, io+1);		outb(0xb0 + regb, io);		outb(((n.fnum >> 8) & 3) | ((n.octave & 7) << 2) | ((n.key_on & 1) << 5), io+1);		return 0;	case FM_IOCTL_SET_VOICE:		if (copy_from_user(&v, (void *)arg, sizeof(v)))			return -EFAULT;		if (v.voice >= 18)			return -EINVAL;		regb = op_offset[v.voice];		io = s->iosynth + ((v.op & 1) << 1);		outb(0x20 + regb, io);		outb(((v.am & 1) << 7) | ((v.vibrato & 1) << 6) | ((v.do_sustain & 1) << 5) | 		     ((v.kbd_scale & 1) << 4) | (v.harmonic & 0xf), io+1);		outb(0x40 + regb, io);		outb(((v.scale_level & 0x3) << 6) | (v.volume & 0x3f), io+1);		outb(0x60 + regb, io);		outb(((v.attack & 0xf) << 4) | (v.decay & 0xf), io+1);		outb(0x80 + regb, io);		outb(((v.sustain & 0xf) << 4) | (v.release & 0xf), io+1);		outb(0xe0 + regb, io);		outb(v.waveform & 0x7, io+1);		if (n.voice >= 9) {			regb = n.voice - 9;			io = s->iosynth+2;		} else {			regb = n.voice;			io = s->iosynth;		}		outb(0xc0 + regb, io);		outb(((v.right & 1) << 5) | ((v.left & 1) << 4) | ((v.feedback & 7) << 1) |		     (v.connection & 1), io+1);		return 0;			case FM_IOCTL_SET_PARAMS:		if (copy_from_user(&p, (void *)arg, sizeof(p)))			return -EFAULT;		outb(0x08, s->iosynth);		outb((p.kbd_split & 1) << 6, s->iosynth+1);		outb(0xbd, s->iosynth);		outb(((p.am_depth & 1) << 7) | ((p.vib_depth & 1) << 6) | ((p.rhythm & 1) << 5) | ((p.bass & 1) << 4) |		     ((p.snare & 1) << 3) | ((p.tomtom & 1) << 2) | ((p.cymbal & 1) << 1) | (p.hihat & 1), s->iosynth+1);		return 0;	case FM_IOCTL_SET_OPL:		outb(4, s->iosynth+2);		outb(arg, s->iosynth+3);		return 0;	case FM_IOCTL_SET_MODE:		outb(5, s->iosynth+2);		outb(arg & 1, s->iosynth+3);		return 0;	default:		return -EINVAL;	}}static int cm_dmfm_open(struct inode *inode, struct file *file){	int minor = MINOR(inode->i_rdev);	struct cm_state *s = devs;	while (s && s->dev_dmfm != minor)		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 & FMODE_DMFM) {		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);	}	/* init the stuff */	outb(1, s->iosynth);	outb(0x20, s->iosynth+1); /* enable waveforms */	outb(4, s->iosynth+2);	outb(0, s->iosynth+3);  /* no 4op enabled */	outb(5, s->iosynth+2);	outb(1, s->iosynth+3);  /* enable OPL3 */	s->open_mode |= FMODE_DMFM;	up(&s->open_sem);	return 0;}static int cm_dmfm_release(struct inode *inode, struct file *file){	struct cm_state *s = (struct cm_state *)file->private_data;	unsigned int regb;	VALIDATE_STATE(s);	lock_kernel();	down(&s->open_sem);	s->open_mode &= ~FMODE_DMFM;	for (regb = 0xb0; regb < 0xb9; regb++) {		outb(regb, s->iosynth);		outb(0, s->iosynth+1);		outb(regb, s->iosynth+2);		outb(0, s->iosynth+3);	}	up(&s->open_sem);	wake_up(&s->open_wait);	unlock_kernel();	return 0;}static /*const*/ struct file_operations cm_dmfm_fops = {	owner:		THIS_MODULE,	llseek:		cm_llseek,	ioctl:		cm_dmfm_ioctl,	open:		cm_dmfm_open,	release:	cm_dmfm_release,};/* --------------------------------------------------------------------- *//* maximum number of device

⌨️ 快捷键说明

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