kernel-2.6.38内核驱动globalmem--添加中断机制和udev机制

21 篇文章 0 订阅
//这个驱动网上有例子,但是很多机制在新的内核里面已经过时了,所以我重写了一下,尽量使用了一些最近内核里面的机制。
//创建设备节点,使用的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\n",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.\n",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.\n",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.\n",err,index);
}



//内核模块的入口函数
//字符设备驱动程序三步:创建分配,初始化,安装注册
int mems_init()
{

	printk(KERN_INFO "Install the driver to kernel space.\n");

	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.\n");
		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..\n");
		goto fail_malloc;
	}
	else
		printk(KERN_INFO "Error was happened here...%d\n",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.\n");
}


MODULE_AUTHOR("LiaoSW");
MODULE_LICENSE("GPL");

module_init(mems_init);
module_exit(mems_exit);





希望对大家有帮助,转载请注明出处,谢谢。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值