📄 io_irq.c
字号:
if(!cancel_delayed_work(&irq_work_delay)) flush_workqueue(tekkamanwork); destroy_workqueue(tekkamanwork); kfifo_free(tekkamanfifo); kfree(tekkamantmp); kfree(tekkamanbuf); atomic_inc(&IO_irq_available); /* release the device */ wake_up_interruptible_sync(&IO_irq_wait); /* awake other uid's */ printk( "IO_irq: release ! \n"); return 0;}/* * The ioctl() implementation */ssize_t IO_irq_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos){ struct IO_irq_dev *dev = filp->private_data; ssize_t retval = 0; if (down_interruptible(&dev->sem)) return -ERESTARTSYS; if (count > kfifo_len(tekkamanfifo)) count = kfifo_len(tekkamanfifo); count = kfifo_get(tekkamanfifo,tekkamantmp, count); if (copy_to_user(buf, tekkamantmp, count)) { retval = -EFAULT; goto out; } retval = count; out: up(&dev->sem); return retval;}#if 1int IO_irq_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ //int err = 0; int retval = 0; //unsigned int current_status; /* * extract the type and number bitfields, and don't decode * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok() */ if (_IOC_TYPE(cmd) != IO_IRQ_MAGIC) return -ENOTTY; if (_IOC_NR(cmd) > IO_IRQ_MAXNR) return -ENOTTY; /* * the direction is a bitmask, and VERIFY_WRITE catches R/W * transfers. `Type' is user-oriented, while * access_ok is kernel-oriented, so the concept of "read" and * "write" is reversed */ switch(cmd) { case IO_IRQ_1: if (IO_irq_devices->IO_status&IO_IRQ1_MASK) { disable_irq(IO_IRQ1); IO_irq_devices->IO_status &= ~IO_IRQ1_MASK; printk(KERN_NOTICE "disable_irq IO_IRQ_1 !\n"); } else { enable_irq(IO_IRQ1); IO_irq_devices->IO_status |= IO_IRQ1_MASK; printk(KERN_NOTICE "enable_irq IO_IRQ_1 !\n"); } break; case IO_IRQ_2: /* Set: arg points to the value */ if (IO_irq_devices->IO_status&IO_IRQ2_MASK) { disable_irq(IO_IRQ2); IO_irq_devices->IO_status &= ~IO_IRQ2_MASK; printk(KERN_NOTICE "disable_irq IO_IRQ_2 !\n"); } else { enable_irq(IO_IRQ2); IO_irq_devices->IO_status |= IO_IRQ2_MASK; printk(KERN_NOTICE "enable_irq IO_IRQ_2 !\n"); } break; case IO_IRQ_3: /* Tell: arg is the value */ if (IO_irq_devices->IO_status&IO_IRQ3_MASK) { disable_irq(IO_IRQ3); IO_irq_devices->IO_status &= ~IO_IRQ3_MASK; printk(KERN_NOTICE "disable_irq IO_IRQ_3 !\n"); } else { enable_irq(IO_IRQ3); IO_irq_devices->IO_status |= IO_IRQ3_MASK; printk(KERN_NOTICE "enable_irq IO_IRQ_3 !\n"); } break; case IO_IRQ_4: /* Get: arg is pointer to result */ if (IO_irq_devices->IO_status&IO_IRQ4_MASK) { disable_irq(IO_IRQ4); IO_irq_devices->IO_status &= ~IO_IRQ4_MASK; printk(KERN_NOTICE "disable_irq IO_IRQ_4 !\n"); } else { enable_irq(IO_IRQ4); IO_irq_devices->IO_status |= IO_IRQ4_MASK; printk(KERN_NOTICE "enable_irq IO_IRQ_4 !\n"); } break; case IO_IRQ_ALL: /* eXchange: use arg as pointer */ if (IO_irq_devices->IO_status&IO_IRQ_ALL_MASK) { if (IO_irq_devices->IO_status&IO_IRQ1_MASK) disable_irq(IO_IRQ1); if (IO_irq_devices->IO_status&IO_IRQ2_MASK) disable_irq(IO_IRQ2); if (IO_irq_devices->IO_status&IO_IRQ3_MASK) disable_irq(IO_IRQ3); if (IO_irq_devices->IO_status&IO_IRQ4_MASK) disable_irq(IO_IRQ4); IO_irq_devices->IO_status &= ~IO_IRQ_ALL_MASK; printk(KERN_NOTICE "disable_irq IO_IRQ_ALL !\n"); } else { if (IO_irq_devices->IO_status&IO_IRQ1_MASK) enable_irq(IO_IRQ1); if (IO_irq_devices->IO_status&IO_IRQ2_MASK) enable_irq(IO_IRQ2); if (IO_irq_devices->IO_status&IO_IRQ3_MASK) enable_irq(IO_IRQ3); if (IO_irq_devices->IO_status&IO_IRQ4_MASK) enable_irq(IO_IRQ4); IO_irq_devices->IO_status |= IO_IRQ_ALL_MASK; printk(KERN_NOTICE "enable_irq IO_IRQ_ALL !\n"); } break; case IO_KFIFO_SIZE: return (int) kfifo_len(tekkamanfifo); case IO_KFIFO_RESET: kfifo_reset(tekkamanfifo); break; default: /* redundant, as cmd was checked against MAXNR */ return -ENOTTY; } printk(KERN_NOTICE "IO_status= %x !\n",IO_irq_devices->IO_status); return retval;}#endifstruct file_operations IO_irq_fops = { .owner = THIS_MODULE, .ioctl = IO_irq_ioctl, .open = IO_irq_open, .release = IO_irq_release, .llseek = no_llseek, .read = IO_irq_read,};/* * Finally, the module stuff *//* * The cleanup function is used to handle initialization failures as well. * Thefore, it must be careful to work correctly even if some of the items * have not been initialized */void IO_irq_cleanup_module(void){ dev_t devno = MKDEV(IO_irq_major, IO_irq_minor); /* Get rid of our char dev entries */ if (IO_irq_devices) { cdev_del(&IO_irq_devices->cdev); kfree(IO_irq_devices); } /* cleanup_module is never called if registering failed */ unregister_chrdev_region(devno, 1);}/* * Set up the char_dev structure for this device. */static void IO_irq_setup_cdev(struct IO_irq_dev *dev){ int err, devno = MKDEV(IO_irq_major, IO_irq_minor); cdev_init(&dev->cdev, &IO_irq_fops); dev->cdev.owner = THIS_MODULE; err = cdev_add (&dev->cdev, devno, 1); /* Fail gracefully if need be */ if (err) printk(KERN_NOTICE "Error %d adding IO_irq", err);}int IO_irq_init_module(void){ int result; dev_t dev = 0;/* * Get a range of minor numbers to work with, asking for a dynamic * major unless directed otherwise at load time. */ if (IO_irq_major) { dev = MKDEV(IO_irq_major, IO_irq_minor); result = register_chrdev_region(dev, 1, "IO_irq"); } else { result = alloc_chrdev_region(&dev, IO_irq_minor, 1, "IO_irq"); IO_irq_major = MAJOR(dev); } if (result < 0) { printk(KERN_WARNING "IO_irq: can't get major %d\n", IO_irq_major); return result; } /* * allocate the devices -- we can't have them static, as the number * can be specified at load time */ IO_irq_devices = kmalloc(sizeof(struct IO_irq_dev), GFP_KERNEL); if (!IO_irq_devices) { result = -ENOMEM; goto fail; /* Make this more graceful */ } memset(IO_irq_devices, 0, sizeof(struct IO_irq_dev)); /* Initialize each device. */ init_MUTEX(&IO_irq_devices->sem); IO_irq_devices->IO_irq1 = (unsigned int) IO_IRQ1; IO_irq_devices->IO_irq2 = (unsigned int) IO_IRQ2; IO_irq_devices->IO_irq3 = (unsigned int) IO_IRQ3; IO_irq_devices->IO_irq4 = (unsigned int) IO_IRQ4; IO_irq_devices->IO_status = 0 ; IO_irq_setup_cdev(IO_irq_devices); set_irq_type(IO_IRQ1,IRQ_TYPE_EDGE_RISING ); set_irq_type(IO_IRQ2,IRQ_TYPE_EDGE_FALLING ); set_irq_type(IO_IRQ3,IRQ_TYPE_EDGE_RISING ); set_irq_type(IO_IRQ4,IRQ_TYPE_EDGE_FALLING ); return 0; /* succeed */ fail: IO_irq_cleanup_module(); return result;}module_init(IO_irq_init_module);module_exit(IO_irq_cleanup_module);MODULE_AUTHOR("Tekkaman Ninja");MODULE_LICENSE("Dual BSD/GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -