易网时代-编程资源站
Welcome
微信登录
编程资源
图片资源库
蚂蚁家优选
PDF转换器
软件资源
软件开发
、
小程序制作
、
系统集成与运维
、
空间租用
、
硬件开发
、
视频监控
、
技术咨询与支持
——联系电话:0311-88999002/88999003
首页
/
操作系统
/
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);
希望对大家有帮助,转载请注明出处,谢谢。
收藏该网址
版权所有©石家庄振强科技有限公司2024
冀ICP备08103738号-5
网站地图