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

📄 rtl_fifo.c

📁 fsmlabs的real time linux的内核
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (RTF_USER_OPEN(minor)) {		fifo_wake_sleepers(minor);	}	return read;}/* these are RTL-FIFO internal functions */static int rtf_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){	unsigned int minor = MINOR(inode->i_rdev);	int val;	if (RTF_USER_IOCTL(minor)) {		return (*RTF_USER_IOCTL(minor)) (minor, cmd, arg);	} else {		switch (cmd) {			case FIONREAD:				val = RTF_LEN(minor);				put_user(val, (int *) arg);				break;			default:				break;		}		return 0;	}}static void fifo_setup_sleep(unsigned int minor){/* 	clear_bit(0,&rtl_fifo_to_wakeup[minor]); */}static void fifo_wake_sleepers(int minor){	if (waitqueue_active(&RTF_WAIT(minor))) {		set_bit(0, &rtl_fifo_to_wakeup[minor]);		if (rtl_fifo_irq > 0) {			rtl_global_pend_irq(rtl_fifo_irq);		}	}}static void fifo_irq_handler (int irq, void *dev_id, struct pt_regs *p){	int minor;	for(minor=0; minor < RTF_MAX_FIFO; minor++) {		if (test_and_clear_bit(0,&rtl_fifo_to_wakeup[minor])) {			rtf_wake_up(RTF_ADDR(minor));		}	}}/*  * these are file_operations functions * called by user tasks via the fops structure  */static int rtf_open(struct inode *inode, struct file *filp){	unsigned int minor = MINOR(inode->i_rdev);	if (minor >= RTF_MAX_FIFO)		return -ENODEV;	if (!RTF_ALLOCATED(minor)) {		return -ENODEV;	}	if (RTF_USER_OPEN(minor) && current != RTF_OPENER(minor)) {		return -EACCES;	}	RTF_OPENER(minor) = current;	RTF_USER_OPEN(minor)++;	if (RTF_ADDR(minor)->creator) {		__MOD_INC_USE_COUNT(RTF_ADDR(minor)->creator);	}	return 0;}static int rtf_release(struct inode *inode, struct file *file){	unsigned int minor = MINOR(inode->i_rdev);#if 0	if (!RTF_USER_OPEN(minor)) {		printk("rtf: release on a not opened descriptor inode=%d\n",(int)inode->i_ino);		return 0;  /* that was just a warning */	}#endif	RTF_USER_OPEN(minor)--;	if (RTF_ADDR(minor)->creator) {		__MOD_DEC_USE_COUNT(RTF_ADDR(minor)->creator);	}	return 0;}static loff_t rtf_llseek(struct file *file, loff_t offset, int origin){	return -ESPIPE;}#define RTL_FIFO_TIMEOUT (HZ/10)static ssize_t rtf_read(struct file *filp, char *buf, size_t count, loff_t* ppos){	struct inode* inode = filp->f_dentry->d_inode;	unsigned int minor = MINOR(inode->i_rdev);	rtl_irqstate_t interrupt_state;	int result;	int chars = 0, size = 0, read = 0;	char *pipebuf;	minor = minor + RTF_BI(minor);	if (filp->f_flags & O_NONBLOCK) {		/*      if (RTF_LOCK(minor))		   return -EAGAIN;		 */		if (RTF_EMPTY(minor))			return 0;	} else		while (RTF_EMPTY(minor)  ) {			if (signal_pending(current))				return -ERESTARTSYS;			fifo_setup_sleep(minor);			interruptible_sleep_on_timeout(&RTF_WAIT(minor),					RTL_FIFO_TIMEOUT);		}/*      RTF_LOCK(minor)++; */	while (count > 0 && (size = RTF_LEN(minor))) {		chars = RTF_MAX_RCHUNK(minor);		if (chars > count)			chars = count;		if (chars > size)			chars = size;		read += chars;		pipebuf = RTF_BASE(minor) + RTF_START(minor);		count -= chars;		copy_to_user(buf, pipebuf, chars); 		rtl_spin_lock_irqsave(&RTF_SPIN(minor), interrupt_state);		RTF_START(minor) += chars;		RTF_START(minor) = RTF_WRAP(minor, RTF_START(minor));		RTF_LEN(minor) -= chars;		rtl_spin_unlock_irqrestore(&RTF_SPIN(minor), interrupt_state);		buf += chars;	}/*      RTF_LOCK(minor)--; */	if (read) {		inode->i_atime = CURRENT_TIME;		if ((result = (*RTF_HANDLER(minor)) (minor)) < 0) {			return result;		}		return read;	}	return 0;}static ssize_t rtf_write(struct file *filp, const char *buf, size_t count, loff_t* ppos){	struct inode* inode = filp->f_dentry->d_inode;	unsigned int minor = MINOR(inode->i_rdev);	rtl_irqstate_t interrupt_state;	int chars = 0, free = 0, written = 0;	char *pipebuf;	int result;	if (count <= RTF_BUF(minor))		free = count;	else		free = 1;	while (count > 0) {		while (RTF_FREE(minor) < free)  {			if (signal_pending(current))				return written ? : -ERESTARTSYS;			if (filp->f_flags & O_NONBLOCK)				return written ? : -EAGAIN;			fifo_setup_sleep(minor);			interruptible_sleep_on_timeout(&RTF_WAIT(minor),					RTL_FIFO_TIMEOUT);		}		/*      RTF_LOCK(minor)++; */		while (count > 0 && (free = RTF_FREE(minor))) {			chars = RTF_MAX_WCHUNK(minor);			if (chars > count)				chars = count;			if (chars > free)				chars = free;			rtl_spin_lock_irqsave(&RTF_SPIN(minor), interrupt_state);			pipebuf = RTF_BASE(minor) + RTF_END(minor);			rtl_spin_unlock_irqrestore(&RTF_SPIN(minor), interrupt_state);			count -= chars;			written += chars;			copy_from_user(pipebuf, buf, chars);			rtl_spin_lock_irqsave(&RTF_SPIN(minor), interrupt_state);			RTF_LEN(minor) += chars;			rtl_spin_unlock_irqrestore(&RTF_SPIN(minor), interrupt_state);			buf += chars;		}		/*      RTF_LOCK(minor)--; */		free = 1;	}	inode->i_ctime = inode->i_mtime = CURRENT_TIME;	if ((result = (*RTF_HANDLER(minor)) (minor)) < 0) {		return result;	}	return written;}static	unsigned int rtf_poll(struct file *filp, poll_table *wait){	int ret = 0;	struct inode* inode = filp->f_dentry->d_inode;	unsigned int minor = MINOR(inode->i_rdev);	fifo_setup_sleep(minor);	poll_wait(filp, &RTF_WAIT(minor), wait);	if (!RTF_EMPTY(minor + RTF_BI(minor))) {		ret |= POLLIN | POLLRDNORM;	}	if (!RTF_FULL(minor)) {		ret |= POLLOUT | POLLWRNORM;	}	return ret;}static struct file_operations rtf_fops ={llseek: rtf_llseek,read: rtf_read,write: rtf_write,poll: rtf_poll,ioctl: rtf_ioctl,open: rtf_open,release: rtf_release,};int rtf_init (void){	int irq = -1;	int i;	if (register_chrdev (RTF_MAJOR, "rtf", &rtf_fops)) {		printk ("RT-FIFO: unable to get major %d\n", RTF_MAJOR);		return -EIO;	}	for (i = 0; i < RTF_MAX_FIFO; i++) {		rtl_fifo_to_wakeup[i] = 0;	}	irq = rtl_get_soft_irq (fifo_irq_handler, "RTLinux FIFO");	if (irq > 0) {		rtl_fifo_irq = irq;	} else {		unregister_chrdev (RTF_MAJOR, "rtf");		printk ("Can't get an irq for rt fifos");		return -EIO;	/* should have a different return */	}	return 0;}		void rtf_uninit(void){	if (rtl_fifo_irq) {		rtl_free_soft_irq(rtl_fifo_irq);	}	unregister_chrdev(RTF_MAJOR, "rtf");}#ifdef CONFIG_RTL_POSIX_IO#include <rtl_posixio.h>#define RTF_DEFAULT_SIZE PREALLOC_SIZEstatic int rtl_rtf_open (struct rtl_file *filp){	if (!(filp->f_flags & O_NONBLOCK)) {		return -EACCES; /* TODO: implement blocking IO */	}	if( (filp->f_flags & O_CREAT) &&  !RTF_ALLOCATED(filp->f_minor))	{		/* better be calling from Linux and not RT mode unless		   there are preallocted fifos still */		__rtf_create(filp->f_minor, RTF_DEFAULT_SIZE, &__this_module);	}	if(!RTF_ALLOCATED(filp->f_minor)){		return -EUNATCH; // protocol driver not attached	}	return 0;}static int rtl_rtf_release (struct rtl_file *filp){	int minor = filp->f_minor;	char *old = RTF_BASE(minor);	if (RTF_ALLOCATED(minor) && old && find_prealloc(old)) {		rtf_destroy(minor);	}	return 0;}static ssize_t rtl_rtf_write(struct rtl_file *filp, const char *buf, size_t count, loff_t* ppos){	return rtf_put(RTL_MINOR_FROM_FILEPTR(filp), (char *) buf, count);	}static ssize_t rtl_rtf_read(struct rtl_file *filp, char *buf, size_t count, loff_t* ppos){	return rtf_get(RTL_MINOR_FROM_FILEPTR(filp), buf, count);	}static int rtl_rtf_ioctl (struct rtl_file *filp, unsigned int req, unsigned long arg){	int minor = RTL_MINOR_FROM_FILEPTR(filp);	if (!RTF_ALLOCATED(minor)) {		return -EINVAL;	}	if (req == RTF_SETSIZE) {		if (rtf_resize(minor, arg) < 0) {			return -EINVAL;		}	} else {		return -EINVAL;	}	return 0;}static struct rtl_file_operations rtl_fifo_fops = {       	NULL,	rtl_rtf_read,	rtl_rtf_write,	rtl_rtf_ioctl,	NULL,	rtl_rtf_open,	rtl_rtf_release};#endif#ifdef MODULEint init_module(void){	int ret;	ret = rtf_init();	if (ret < 0) {		return ret;	}#ifdef CONFIG_RTL_POSIX_IO	if (rtl_register_chrdev (RTF_MAJOR, "rtf", &rtl_fifo_fops)) {		printk ("RT-FIFO: unable to get RTLinux major %d\n", RTF_MAJOR);		rtf_uninit();		return -EIO;	}#endif	return 0;}void cleanup_module(void){#ifdef CONFIG_RTL_POSIX_IO	rtl_unregister_chrdev(RTF_MAJOR, "rtf");#endif	rtf_uninit();}#endif				/* MODULE */

⌨️ 快捷键说明

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