📄 io_irq.c
字号:
#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <linux/kernel.h> /* printk() */#include <linux/slab.h> /* kmalloc() */#include <linux/fs.h> /* everything... */#include <linux/errno.h> /* error codes */#include <linux/types.h> /* size_t */#include <linux/proc_fs.h>#include <linux/fcntl.h> /* O_ACCMODE */#include <linux/seq_file.h>#include <linux/cdev.h>#include <linux/kfifo.h>#include <linux/sched.h> /* current and everything *///#include <linux/delay.h> /* udelay */#include <asm/system.h> /* cli(), *_flags */#include <asm/uaccess.h> /* copy_*_user */#include <asm/atomic.h>#include "IO_irq.h" /* local definitions *//* * Our parameters which can be set at load time. */int IO_irq_major = 0;int IO_irq_minor = 0;module_param(IO_irq_major, int, S_IRUGO);module_param(IO_irq_minor, int, S_IRUGO);struct IO_irq_dev *IO_irq_devices; /* allocated in scull_init_module */static atomic_t IO_irq_available = ATOMIC_INIT(1);static spinlock_t IO_irq_lock = SPIN_LOCK_UNLOCKED;static DECLARE_WAIT_QUEUE_HEAD(IO_irq_wait);static unsigned long prevjiffies = 0;static unsigned int prevkey = 0;static struct IO_irq_key key1;static struct IO_irq_key key2;static struct IO_irq_key key3;static struct IO_irq_key key4;struct workqueue_struct *tekkamanwork;static struct delayed_work irq_work_delay;static struct work_struct irq_work;static struct tasklet_struct keytask;struct kfifo *tekkamanfifo;static spinlock_t tekkamanlock= SPIN_LOCK_UNLOCKED;static unsigned char *tekkamantmp;static unsigned char *tekkamanbuf ;/*key1_tasklet*/void key1_tasklet(unsigned long arg){ struct IO_irq_key *data = (struct IO_irq_key *)arg; unsigned long j=0; printk("\n**************key1_tasklet_start*****************\n"); j = jiffies; printk("time:%08lx delta:%3li inirq:%i pid:%3i cpu:%i command:%s\n", j, j - data->prevjiffies, in_interrupt() ? 1 : 0, current->pid, smp_processor_id(), current->comm); printk("\n**************key1_tasklet_end*****************\n");}/*key2-3_work_fn*/void irq_work_delay_fn(void *arg){ struct IO_irq_key *data = &key2; unsigned long j=0; printk("\n**************key2_workqueue_start*****************\n"); j = jiffies; printk("time:%08lx delta:%3li inirq:%i pid:%3i cpu:%i command:%s\n", j, j - data->prevjiffies, in_interrupt() ? 1 : 0, current->pid, smp_processor_id(), current->comm); printk("\n**************key2_workqueu_end*****************\n");}void irq_work_fn(void *arg){ struct IO_irq_key *data = &key3; unsigned long j=0; printk("\n**************key3_workqueue_start*****************\n"); j = jiffies; printk("time:%08lx delta:%3li inirq:%i pid:%3i cpu:%i command:%s\n", j, j - data->prevjiffies, in_interrupt() ? 1 : 0, current->pid, smp_processor_id(), current->comm); printk("\n**************key3_workqueu_end*****************\n");}/* * irq handled */static irqreturn_t IO_irq_interrupt1(int irq, void *dev_id, struct pt_regs *regs){ unsigned long j =0; j = jiffies; printk("\n**************KEY = 1*****************\n"); if (!prevkey) printk("NO prevkey\nnow jiffies =0x%08lx\ncount = %d\n", j , ++key1.count); else if (!key1.prevjiffies) printk("prevkey=%d at 0x%08lx\nNO prekey1\nnow jiffies =0x%08lx\ncount = %d\n" , prevkey , prevjiffies , j, ++key1.count); else printk("prevkey=%d at 0x%08lx\nprekey1 at 0x%08lx\nnow jiffies =0x%08lx\ncount = %d\n" , prevkey , prevjiffies , key1.prevjiffies , j, ++key1.count); prevkey = 1; prevjiffies = key1.prevjiffies =j; tasklet_schedule(&keytask); printk("\n**************KEY = 1 END*****************\n"); return IRQ_HANDLED;}static irqreturn_t IO_irq_interrupt2(int irq, void *dev_id, struct pt_regs *regs){ unsigned long j =0; int result = 0; j = jiffies; printk("\n**************KEY = 2*****************\n"); if (!prevkey) printk("NO prevkey\nnow jiffies =0x%08lx\ncount = %d\n", j , ++key2.count); else if (!key2.prevjiffies) printk("prevkey=%d at 0x%08lx\nNO prekey2\nnow jiffies =0x%08lx\ncount = %d\n" , prevkey , prevjiffies , j, ++key2.count); else printk("prevkey=%d at 0x%08lx\nprekey2 at 0x%08lx\nnow jiffies =0x%08lx\ncount = %d\n" , prevkey , prevjiffies , key2.prevjiffies , j, ++key2.count); prevkey = 2; prevjiffies = key2.prevjiffies =j; if ((result =queue_delayed_work(tekkamanwork , &irq_work_delay, DELAY))!=1) printk("IO_irq_interrupt2 cannot add work ! "); printk("result = %d ",result); printk("\n**************KEY = 2 END*****************\n"); return IRQ_HANDLED;}static irqreturn_t IO_irq_interrupt3(int irq, void *dev_id, struct pt_regs *regs){ unsigned long j =0; int result = 0; j = jiffies; printk("\n**************KEY = 3*****************\n"); if (!prevkey) printk("NO prevkey\nnow jiffies =0x%08lx\ncount = %d\n", j , ++key3.count); else if (!key3.prevjiffies) printk("prevkey=%d at 0x%08lx\nNO prekey3\nnow jiffies =0x%08lx\ncount = %d\n" , prevkey , prevjiffies , j, ++key3.count); else printk("prevkey=%d at 0x%08lx\nprekey3 at 0x%08lx\nnow jiffies =0x%08lx\ncount = %d\n" , prevkey , prevjiffies , key3.prevjiffies , j, ++key3.count); prevkey = 3; prevjiffies = key3.prevjiffies =j; if ((result = schedule_work(&irq_work))!=1) printk("IO_irq_interrupt3 cannot add work sharequeue ! "); printk("result = %d ",result); printk("\n**************KEY = 3 END*****************\n"); return IRQ_HANDLED;}static irqreturn_t IO_irq_interrupt4(int irq, void *dev_id, struct pt_regs *regs){ unsigned int len = 0; unsigned long j =0; j = jiffies; if (!prevkey) len = sprintf(tekkamanbuf,"\n**********KEY = 4**********\nNO prevkey\nnow jiffies =0x%08lx\ncount = %d\n*********KEY = 4 END***********\n", j , ++key4.count); else if (!key4.prevjiffies) len = sprintf(tekkamanbuf,"\n**********KEY = 4**********\nprevkey=%d at 0x%08lx\nNO prekey4\nnow jiffies =0x%08lx\ncount = %d\n*********KEY = 4 END***********\n" , prevkey , prevjiffies , j, ++key4.count); else len = sprintf(tekkamanbuf,"\n**********KEY = 4**********\nprevkey=%d at 0x%08lx\nprekey4 at 0x%08lx\nnow jiffies =0x%08lx\ncount = %d\n*********KEY = 4 END***********\n" , prevkey , prevjiffies , key4.prevjiffies , j, ++key4.count); prevkey = 4; prevjiffies = key4.prevjiffies =j; kfifo_put(tekkamanfifo, tekkamanbuf, len); return IRQ_HANDLED;}/* * Open and close */int IO_irq_open(struct inode *inode, struct file *filp){ struct IO_irq_dev *dev; /* device information */ int result1,result2,result3,result4; spin_lock(&IO_irq_lock); while (! atomic_dec_and_test (&IO_irq_available)) { atomic_inc(&IO_irq_available); spin_unlock(&IO_irq_lock); if (filp->f_flags & O_NONBLOCK) return -EAGAIN; if (wait_event_interruptible (IO_irq_wait, atomic_read (&IO_irq_available))) return -ERESTARTSYS; /* tell the fs layer to handle it */ spin_lock(&IO_irq_lock); } spin_unlock(&IO_irq_lock); dev = container_of(inode->i_cdev, struct IO_irq_dev, cdev); if ((dev->IO_irq1 >= IRQ_EINT0)&&(dev->IO_irq2 >= IRQ_EINT0)&&(dev->IO_irq3 >= IRQ_EINT0)&&(dev->IO_irq4 >= IRQ_EINT0)) { result1 = request_irq(dev->IO_irq1, IO_irq_interrupt1, 0 , "IO_irq1", (void *)NULL); result2 = request_irq(dev->IO_irq2, IO_irq_interrupt2, 0 , "IO_irq2", (void *)NULL); result3 = request_irq(dev->IO_irq3, IO_irq_interrupt3, 0 , "IO_irq3", (void *)NULL); result4 = request_irq(dev->IO_irq4, IO_irq_interrupt4, 0 , "IO_irq4", (void *)NULL); if (result1 || result2 || result3 || result4 ) { printk( "IO_irq: can't get assigned one of irq \n"); if (!result1) free_irq(IO_irq_devices->IO_irq1, NULL); if (!result2) free_irq(IO_irq_devices->IO_irq2, NULL); if (!result3) free_irq(IO_irq_devices->IO_irq3, NULL); if (!result4) free_irq(IO_irq_devices->IO_irq4, NULL); return -EAGAIN; } else { s3c2410_gpio_cfgpin(S3C2410_GPG11, S3C2410_GPG11_EINT19); s3c2410_gpio_pullup(S3C2410_GPG11, 0); s3c2410_gpio_cfgpin(S3C2410_GPG3, S3C2410_GPG3_EINT11); s3c2410_gpio_pullup(S3C2410_GPG3, 0); s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_EINT2); s3c2410_gpio_pullup(S3C2410_GPF2, 0); s3c2410_gpio_cfgpin(S3C2410_GPF0, S3C2410_GPF0_EINT0); s3c2410_gpio_pullup(S3C2410_GPF0, 0); dev->IO_status = 0x1f ; } } else { printk("IO_irq: get IRQ failed !\n"); return -EAGAIN; } filp->private_data = dev; /* for other methods */ tasklet_init(&keytask , key1_tasklet , (unsigned long)&key1); tekkamanwork = create_workqueue("tekkamanwork"); INIT_DELAYED_WORK(&irq_work_delay, irq_work_delay_fn); INIT_WORK(&irq_work, irq_work_fn); tekkamantmp = kmalloc(512, GFP_KERNEL); tekkamanbuf = kmalloc (512 , GFP_KERNEL); tekkamanfifo = kfifo_alloc(512, GFP_KERNEL, &tekkamanlock); printk( "IO_irq: opened ! \n"); return nonseekable_open(inode, filp); /* success */}int IO_irq_release(struct inode *inode, struct file *filp){ free_irq(IO_irq_devices->IO_irq1, NULL); free_irq(IO_irq_devices->IO_irq2, NULL); free_irq(IO_irq_devices->IO_irq3, NULL); free_irq(IO_irq_devices->IO_irq4, NULL); s3c2410_gpio_cfgpin(S3C2410_GPG11, S3C2410_GPG11_INP); s3c2410_gpio_cfgpin(S3C2410_GPG3, S3C2410_GPG3_INP); s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_INP); s3c2410_gpio_cfgpin(S3C2410_GPF0, S3C2410_GPF0_INP); IO_irq_devices->IO_status = 0 ; tasklet_kill(&keytask);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -