您的位置:首页 > 运维架构 > Linux

Linux 内核空间与用户空间异步通信机制

2016-09-22 10:36 267 查看
/*
* @file	exirq.c
* @author	fzs
* @date	2016-12-13
*/

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/nmi.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/irqreturn.h>
#include <linux/spinlock.h>

#include <asm/io.h>
#include <asm/irq.h>

volatile unsigned int *pic_vaddr6 = NULL, *pic_vaddr5 = NULL;
extern void open_softirq(int nr, void (*action)(struct softirq_action *));
extern phys_addr_t get_immrbase(void);

static atomic_t ex_interrupt_has_happen = ATOMIC_INIT(0);
static wait_queue_head_t ex_interrupt;

#define MPC85xx_PIC_EIVPR6		0x500c0
#define WAIT_FOR_EXTERN_INTERRUPT	0x1

#if 1
static irqreturn_t exirq_process ( int irq, void *dev_id )
{
int handled = 0;
u32 regdata;

//	printk("come in irq_process \n");
#if 1
regdata = in_be32(pic_vaddr6);

//printk("pic_eivpr6 value = %x \n", regdata);
if(regdata & 0x40000000)
{
atomic_set(&ex_interrupt_has_happen, 1);
wake_up_interruptible(&ex_interrupt);
}
#endif

//spin_lock(&i->lock);
handled = 1;

//spin_unlock(&i->lock);

return IRQ_RETVAL(handled);
}
#endif

static long exirq_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{

switch (cmd)
{
case WAIT_FOR_EXTERN_INTERRUPT:
//printk("wait for extern interrupt\n");

wait_event_interruptible(ex_interrupt,
atomic_read(&ex_interrupt_has_happen)!=0);
atomic_set(&ex_interrupt_has_happen, 0);

//printk("get an interrupt\n");
break;
default:
printk("cmd=%d error\n",cmd);
break;
}
return 0;
}
#if 0
static struct timer_list test_timer;
static void timer_action(unsigned long aa)
{
atomic_set(&ex_interrupt_has_happen, 1);
wake_up_interruptible(&ex_interrupt);

test_timer.expires = jiffies+(HZ*10);
add_timer(&test_timer);
}
#endif
static struct file_operations exirq_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = exirq_ioctl
};

struct cdev exirq_cdev;
int major;
int exirq_int_init(void)
{
unsigned int regdata = 0;
int ret = 0;

init_waitqueue_head(&ex_interrupt);
atomic_set(&ex_interrupt_has_happen, 0);
#if 1
pic_vaddr6 = ioremap(get_immrbase() + MPC85xx_PIC_EIVPR6, 64);

/* init EIVPR4 to 0x80000 */
regdata = 0x80000; /* priority=8; vector=0 */
//	regdata |= 1<<22;
out_be32(pic_vaddr6, regdata);

/* init EIDR4 to let core process the int*/
regdata  = 2;
out_be32((pic_vaddr6+4), regdata);
#endif
/* we must use IRQF_SHARED mode. here IRQF_SHARED=0x80 */
ret = request_irq(16, exirq_process, 0x80, "IRQ4",1);
if (ret < 0)
printk("irq4 request fail.\n");
else
printk("irq4 request success.\n");
#if 0
init_timer(&test_timer);

test_timer.function = timer_action;

test_timer.expires = jiffies + (HZ * 10);

add_timer(&test_timer);
#endif
return 0;
}

static struct class *exirq_cls;
dev_t dev_id;
static int __init exirq_init(void)
{
printk("exirq init...\n");

exirq_int_init();

alloc_chrdev_region(&dev_id, 0, 1, "exirq");
major = MAJOR(dev_id);

cdev_init(&exirq_cdev, &exirq_fops);
cdev_add(&exirq_cdev, dev_id, 1);

exirq_cls = class_create(THIS_MODULE, "exirq");

device_create(exirq_cls, NULL, dev_id, NULL, "exirq");
/* for test */
/*
fpga_int_register_callback(0,test1);
fpga_int_register_callback(1,test2);
*/

return 0;
}

static void __exit exirq_exit(void)
{
printk(KERN_ALERT "exirq driver exit\n");

device_destroy(exirq_cls, MKDEV(major, 0));
class_destroy(exirq_cls);

/* 3.3 删除cdev*/
cdev_del(&exirq_cdev);

/* 3.4 释放设备号*/
unregister_chrdev_region(MKDEV(major, 0), 1);
free_irq(16,1);
}

module_init(exirq_init);
module_exit(exirq_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("fzs");


/*
* @file	exirq.c
* @author	fzs
* @date	2016-12-13
*/

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/nmi.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/irqreturn.h>
#include <linux/spinlock.h>

#include <asm/io.h>
#include <asm/irq.h>

volatile unsigned int *pic_vaddr6 = NULL, *pic_vaddr5 = NULL;
extern void open_softirq(int nr, void (*action)(struct softirq_action *));
extern phys_addr_t get_immrbase(void);

static atomic_t ex_interrupt_has_happen = ATOMIC_INIT(0);
static wait_queue_head_t ex_interrupt;

#define MPC85xx_PIC_EIVPR6		0x500c0
#define WAIT_FOR_EXTERN_INTERRUPT	0x1

#if 1
static irqreturn_t exirq_process ( int irq, void *dev_id )
{
int handled = 0;
u32 regdata;

//	printk("come in irq_process \n");
#if 1
regdata = in_be32(pic_vaddr6);

//printk("pic_eivpr6 value = %x \n", regdata);
if(regdata & 0x40000000)
{
atomic_set(&ex_interrupt_has_happen, 1);
wake_up_interruptible(&ex_interrupt);
}
#endif

//spin_lock(&i->lock);
handled = 1;

//spin_unlock(&i->lock);

return IRQ_RETVAL(handled);
}
#endif

static long exirq_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{

switch (cmd)
{
case WAIT_FOR_EXTERN_INTERRUPT:
//printk("wait for extern interrupt\n");

wait_event_interruptible(ex_interrupt,
atomic_read(&ex_interrupt_has_happen)!=0);
atomic_set(&ex_interrupt_has_happen, 0);

//printk("get an interrupt\n");
break;
default:
printk("cmd=%d error\n",cmd);
break;
}
return 0;
}
#if 0
static struct timer_list test_timer;
static void timer_action(unsigned long aa)
{
atomic_set(&ex_interrupt_has_happen, 1);
wake_up_interruptible(&ex_interrupt);

test_timer.expires = jiffies+(HZ*10);
add_timer(&test_timer);
}
#endif
static struct file_operations exirq_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = exirq_ioctl
};

struct cdev exirq_cdev;
int major;
int exirq_int_init(void)
{
unsigned int regdata = 0;
int ret = 0;

init_waitqueue_head(&ex_interrupt);
atomic_set(&ex_interrupt_has_happen, 0);
#if 1
pic_vaddr6 = ioremap(get_immrbase() + MPC85xx_PIC_EIVPR6, 64);

/* init EIVPR4 to 0x80000 */
regdata = 0x80000; /* priority=8; vector=0 */
//	regdata |= 1<<22;
out_be32(pic_vaddr6, regdata);

/* init EIDR4 to let core process the int*/
regdata  = 2;
out_be32((pic_vaddr6+4), regdata);
#endif
/* we must use IRQF_SHARED mode. here IRQF_SHARED=0x80 */
ret = request_irq(16, exirq_process, 0x80, "IRQ4",1);
if (ret < 0)
printk("irq4 request fail.\n");
else
printk("irq4 request success.\n");
#if 0
init_timer(&test_timer);

test_timer.function = timer_action;

test_timer.expires = jiffies + (HZ * 10);

add_timer(&test_timer);
#endif
return 0;
}

static struct class *exirq_cls;
dev_t dev_id;
static int __init exirq_init(void)
{
printk("exirq init...\n");

exirq_int_init();

alloc_chrdev_region(&dev_id, 0, 1, "exirq");
major = MAJOR(dev_id);

cdev_init(&exirq_cdev, &exirq_fops);
cdev_add(&exirq_cdev, dev_id, 1);

exirq_cls = class_create(THIS_MODULE, "exirq");

device_create(exirq_cls, NULL, dev_id, NULL, "exirq");
/* for test */
/*
fpga_int_register_callback(0,test1);
fpga_int_register_callback(1,test2);
*/

return 0;
}

static void __exit exirq_exit(void)
{
printk(KERN_ALERT "exirq driver exit\n");

device_destroy(exirq_cls, MKDEV(major, 0));
class_destroy(exirq_cls);

/* 3.3 删除cdev*/
cdev_del(&exirq_cdev);

/* 3.4 释放设备号*/
unregister_chrdev_region(MKDEV(major, 0), 1);
free_irq(16,1);
}

module_init(exirq_init);
module_exit(exirq_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("fzs");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: