首页 > 代码库 > 一步步写 CMOS 驱动模块 <ELDD 学习笔记> (最近更新,写到open release为止)

一步步写 CMOS 驱动模块 <ELDD 学习笔记> (最近更新,写到open release为止)

一步步写 CMOS 驱动模块


 Let‘s implement a char driver to access the system CMOS.




首先仅仅是创建设备模块,最简单的,类似于前面hello world模块一样的东东,从最简单的框架慢慢搭


/************************************************************
code writer : EOF
code date : 2014.08.15
code file : cmos_demo.c
e-mail:	jasonleaster@gmail.com

code purpose:
	This code is a demo for how to build a CMOS-driver
step by step.

	If there is something wrong with my code, please touch
me by e-mail. Thank you.

************************************************************/
#include <linux/module.h>
#include <linux/moduleparam.h>

#include <linux/fs.h>
#include <linux/init.h> 
#include <linux/cdev.h>  
#include <linux/slab.h> /* kmalloc() */
#include <linux/kernel.h> /* printk */
#include <linux/device.h>
#include <linux/ioport.h>
#include <linux/kdev_t.h>

int cmos_major = 0;//defualt
int cmos_minor = 0;

module_param(cmos_major,int,S_IRUGO);
module_param(cmos_minor,int,S_IRUGO);

//static dev_t	cmos_dev_number;	/* Allocated device number */
struct class	*cmos_class;	/* Tie with the device model */

#define NUM_CMOS_BANKS	2	
#define CMOS_BANK_SIZE	(0xFF*8)
#define DEVICE_NAME	"Jason_cmos"

#define CMOS_BANK0_INDEX_PORT	0x70
#define CMOS_BANK0_DATA_PORT	0x71
#define CMOS_BANK1_INDEX_PORT	0x72
#define CMOS_BANK1_DATA_PORT	0x73

unsigned char addrports[NUM_CMOS_BANKS] = {CMOS_BANK0_INDEX_PORT,CMOS_BANK1_INDEX_PORT};
unsigned char dataports[NUM_CMOS_BANKS] = {CMOS_BANK0_DATA_PORT,CMOS_BANK1_DATA_PORT};

MODULE_AUTHOR("Jason Leaster");
MODULE_LICENSE("Dual BSD/GPL");


struct cmos_dev
{
	unsigned short current_pointer; /*Current point within the bank*/
	
	unsigned int size;	/*size of the bank*/
	int bank_number;	/*Size of bank*/
	struct cdev cdev;
	char name[10];		/*Name of I/O regeion*/
	
	/* ... */
	
}*cmos_devp;
 
static struct file_operations cmos_fops = 
{
	.owner	=	THIS_MODULE,
};

int  cmos_init(void)
{
	int i;

	dev_t dev = 0;
	
	if(alloc_chrdev_region(&dev,cmos_minor,NUM_CMOS_BANKS,DEVICE_NAME) < 0)
	{
		printk(KERN_DEBUG "Can't regiester device\n");
		return -1;
	}

	cmos_major = MAJOR(dev);
	
	/*********I don't know what this is************/
	cmos_class = class_create(THIS_MODULE,DEVICE_NAME);
	
	release_region(0x70,0x8);

	for(i = 0;i < NUM_CMOS_BANKS;i++)
	{
		cmos_devp = kmalloc(sizeof(struct cmos_dev),GFP_KERNEL);
		if(!cmos_devp)
		{
			printk("Bad Kmalloc\n");
			return 1;
		}

		sprintf(cmos_devp->name,"cmos%d",i);
	
		if(!(request_region(addrports[i],2,cmos_devp->name)))
		{
			printk("cmos: I/O port 0x%x is not free.\n",addrports[i]);

			return -EIO;
		}

		cmos_devp->bank_number = i;

		cdev_init(&cmos_devp->cdev,&cmos_fops);
		cmos_devp->cdev.owner = THIS_MODULE;

		if(cdev_add(&cmos_devp->cdev,(dev + i),1))
		{
			printk("Bad cdev\n");

			return 1;
		}

		device_create(cmos_class,NULL,(dev + i),NULL,"cmos%d",i);
	}

	printk("CMOS Driver Initialized.\n");

	return 0;
}

void cmos_cleanup(void)
{
	int i;
	
	dev_t  devno = MKDEV(cmos_major,cmos_minor);
	
	cdev_del(&cmos_devp->cdev);
	
	unregister_chrdev_region(devno,NUM_CMOS_BANKS);
	
	for(i = 0;i < NUM_CMOS_BANKS;i++)
	{
		device_destroy(cmos_class,MKDEV(MAJOR(devno),i));
		
		release_region(addrports[i],2);
	}

	class_destroy(cmos_class);
	
	return ;
}

module_init(cmos_init);
module_exit(cmos_cleanup);

这里还每个给出open,writer,read,release的实现,仅仅是实现注册模块的部分。不过,感觉不错~






待更新...






平凡着的,在路上的