?? rtl_fifo.c
字號:
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 + -