首页 / 操作系统 / Linux / Linux Kernel 2.6.38内核驱动globalmem--添加中断机制和udev机制
- //这个驱动网上有例子,但是很多机制在新的内核里面已经过时了,所以我重写了一下,尽量使用了一些最近内核里面的机制。
- //创建设备节点,使用的udev机制;
- //注册中断向量的时候使用了新的接口函数,包括了ISR的接口的改变。
-
-
-
- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/fs.h>
- #include <linux/errno.h>
- #include <linux/mm.h>
- #include <linux/sched.h>
- #include <linux/init.h>
- #include <linux/cdev.h>
- #include <linux/device.h>
-
- //使用中断机制添加头文件
- #include <linux/sched.h>
- #include <asm/signal.h>
- #include <linux/interrupt.h>
-
- //使用udev机制添加的头文件
- #include <linux/slab.h>
-
- #ifdef CONFIG_SLUB
- #include <linux/slub_def.h>
- #elif defined CONFIG_SLOB
- #include <linux/slob_def.h>
- #else
- #include <linux/slab_def.h>
- #endif
-
-
- #include <asm/io.h>
- #include <asm/system.h>
- #include <asm/uaccess.h>
-
- //swliao:memory size 4K.
- #define MEMS_SIZE 0x1000
-
- //#define MEMS_CLEAR 0x1
-
-
- #define MEMS_MAJOR 300
-
- static struct class *my_class;
-
- static int mems_major = MEMS_MAJOR;
- static unsigned int mems_irq = 1;
- static char* interface = "mems-test";
-
- //module_param()添加模块支持参数,每行设置一个参数
- module_param(mems_irq,int,S_IRUGO);
- module_param(interface,charp,S_IRUGO);
-
-
- //声明设备结构体
- struct mems_dev
- {
- struct cdev cdev;
- unsigned char mems[MEMS_SIZE];
- };
-
- struct mems_dev *mems_devp;
-
-
- //对应的中断向量的ISR
- static irqreturn_t mems_irq_handler(int irq,void *dev_id)
- {
- printk(KERN_INFO "Interrupt handler...............................%d
",irq);
- return IRQ_HANDLED;
- }
-
- //swliao:open function in file_operation.
- int mems_open(struct inode *inode,struct file *filp)
- {
- filp->private_data = mems_devp;
- return 0;
- }
-
- //close()
- int mems_release(struct inode *inode,struct file *filp)
- {
- return 0;
- }
-
-
-
- //swliao:read() function in file_operations.
- static ssize_t mems_read(struct file *filp,char __user *buf,size_t size,loff_t *ppos)
- {
- unsigned long p =*ppos;
- unsigned int count = size;
- int ret = 0;
-
- struct mems_dev *dev = filp->private_data;
-
- if(p >= MEMS_SIZE)
- return count ? -ENXIO : 0;
- if(count > MEMS_SIZE-p)
- count = MEMS_SIZE - p;
-
- if(copy_to_user(buf,(void *)(dev->mems + p),count))
- {
- ret = -EFAULT;
- }
- else
- {
- *ppos += count;
- ret = count;
-
- printk(KERN_INFO "Liaosw read %d bytes.
",count);
- }
-
- return ret;
- }
-
- static ssize_t mems_write(struct file *filp,const char __user *buf,size_t size,loff_t *ppos)
- {
- unsigned long p = *ppos;
- unsigned int count = size;
- int ret = 0;
- struct mems_dev *dev = filp->private_data;
-
- if(p >= MEMS_SIZE)
- return count ? -ENXIO : 0;
- if(count > MEMS_SIZE -p)
- count = MEMS_SIZE - p;
-
- if(copy_from_user(dev->mems+p,buf,count))
- {
- ret = -EFAULT;
- }
- else
- {
- *ppos += count;
- ret = count;
-
- printk(KERN_INFO "Liaosw written %d bytes.
",count);
- }
-
- return ret;
- }
-
-
-
- //swliao:very important file_operations structure.
- //字符驱动的主体实现部分:对应设备文件的file_operations结构体
- static const struct file_operations mems_fops =
- {
- .owner = THIS_MODULE,
- .read = mems_read,
- .write = mems_write,
- .open = mems_open,
- .release = mems_release,
- };
-
- static void mems_setup_cdev(struct mems_dev *dev,int index)
- {
- int devno = MKDEV(mems_major,index);
-
- cdev_init(&dev->cdev,&mems_fops);
- dev->cdev.owner = THIS_MODULE;
- dev->cdev.ops = &mems_fops;
-
- int err = cdev_add(&dev->cdev,devno,1);
- if(err)
- printk(KERN_NOTICE "Error %d addint cdev %d.
",err,index);
- }
-
-
-
- //内核模块的入口函数
- //字符设备驱动程序三步:创建分配,初始化,安装注册
- int mems_init()
- {
-
- printk(KERN_INFO "Install the driver to kernel space.
");
-
- int result = 0;
- dev_t devno = MKDEV(mems_major,0);
-
- if(mems_major)
- result = register_chrdev_region(devno,1,"mem-test");
- else
- {
- result = alloc_chrdev_region(&devno,0,1,"mem-test");
- mems_major = MAJOR(devno);
- }
-
- if(result < 0)
- return result;
-
- mems_devp = kmalloc(sizeof(struct mems_dev),GFP_KERNEL);
- if(!mems_devp)
- {
- result = -ENOMEM;
- goto fail_malloc;
- }
-
- memset(mems_devp,0,sizeof(struct mems_dev));
-
- mems_setup_cdev(mems_devp,0);
-
- my_class = class_create(THIS_MODULE,"my_class");
- if(IS_ERR(my_class))
- {
- printk("Err:failed in creating class.
");
- return -1;
- }
- device_create(my_class,NULL,MKDEV(mems_major,0),NULL,"mem-test",0);
-
- //register interrupt.
- //请求分配中断向量
- int flagnum;
- if(!(flagnum = request_irq(mems_irq,&mems_irq_handler,IRQF_SHARED,interface,mems_devp)))
- {
- printk(KERN_INFO "Register interrupt correctly..
");
- goto fail_malloc;
- }
- else
- printk(KERN_INFO "Error was happened here...%d
",flagnum);
-
- return 0;
-
- fail_malloc:
- unregister_chrdev_region(devno,1);
- return result;
- }
-
- void mems_exit()
- {
- cdev_del(&mems_devp->cdev);
-
- //udev的退出清理
- device_destroy(my_class,MKDEV(mems_major,0));
- class_destroy(my_class);
-
- kfree(mems_devp);
-
- //释放设备号和中断向量
- free_irq(mems_irq,mems_devp);
- unregister_chrdev_region(MKDEV(mems_major,0),1);
- printk(KERN_INFO "Test module quit kernel space.
");
- }
-
-
- MODULE_AUTHOR("LiaoSW");
- MODULE_LICENSE("GPL");
-
- module_init(mems_init);
- module_exit(mems_exit);
-
-
-
-
-
- 希望对大家有帮助,转载请注明出处,谢谢。