linux 3.0字符设备驱动程序,linux 3.0.35下globalmem 字符设备驱动实现

#include #include#include#include#include#include#include#include#include#include#include#include

#define GLOBALMEM_SIZE 0x1000 //4KB

//create device node in the board side.//mknod /dev/globalmem c 120 0

#define GLOBALMEM_MAJOR 120 //preset major number

//define ioctl cmd

#define GLOBALMEM_MAGIC 0x01

#define MEM_CLEAR _IO(GLOBALMEM_MAGIC, 0)

static int globalmem_major =GLOBALMEM_MAJOR;//globalmem struct

structglobalmem_dev {struct cdev cdev; //cdev struct

unsigned char mem[GLOBALMEM_SIZE]; //global memory

};struct globalmem_dev *globalmem_devp; //device struct instance

int globalmem_open(struct inode *inode, struct file *filp)

{//set device struct pointer to file privatedata pointer

filp->private_data =globalmem_devp;return 0;

}int globalmem_release(struct inode *inode, struct file *filp)

{return 0;

}static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size,

loff_t*ppos)

{

unsignedlong p = *ppos;

unsignedint count =size;int ret = 0;struct globalmem_dev *dev = filp->private_data; //get device struct pointer//analysis and get valid read length

if (p >= GLOBALMEM_SIZE) //overflow

return 0;if (count > GLOBALMEM_SIZE - p) //count is too large

count = GLOBALMEM_SIZE -p;//kernel buf -> user buf

if (copy_to_user(buf, (void *)(dev->mem +p), count))

ret= -EFAULT;else{*ppos +=count;

ret=count;

printk(KERN_INFO"read %d bytes from %ld\n", count, p);

}returnret;

}static ssize_t globalmem_write(struct file *filp, const char __user *buf,

size_t size, loff_t*ppos)

{

unsignedlong p = *ppos;

unsignedint count =size;int ret = 0;struct globalmem_dev *dev = filp->private_data; //get device stuct pointer//analysis and get valid write length

if (p >= GLOBALMEM_SIZE) //write overflow

return 0;if (count > GLOBALMEM_SIZE - p) //write count is too large

count = GLOBALMEM_SIZE -p;//user buf -> kernel buf

if (copy_from_user(dev->mem +p, buf, count))

ret= -EFAULT;else{*ppos +=count;

ret=count;

printk(KERN_INFO"written %d bytes from %ld\n", count, p);

}returnret;

}static loff_t globalmem_llseek(struct file *filp, loff_t offset, intorig)

{

loff_t ret= 0;switch(orig) {case 0: //from the file head

if (offset < 0 || ((unsigned int) offset >GLOBALMEM_SIZE)) {

ret= -EINVAL;break;

}

filp->f_pos = (unsigned int) offset;

ret= filp->f_pos;break;case 1: //from current position

if ((filp->f_pos + offset) > GLOBALMEM_SIZE || (filp->f_pos + offset) < 0) {

ret= -EINVAL;break;

}

filp->f_pos +=offset;

ret= filp->f_pos;break;

}returnret;

}static long globalmem_ioctl(struct file *filp, unsigned int cmd, unsigned longarg)

{struct globalmem_dev *dev = filp->private_data; //get device stuct pointer

switch(cmd) {caseMEM_CLEAR:

memset(dev->mem, 0, GLOBALMEM_SIZE);

printk(KERN_INFO"globalmem is set to zero\n");break;default:return -EINVAL; //not supported

}return 0;

}//file operations struct

static const struct file_operations globalmem_fops ={

.owner=THIS_MODULE,

.llseek=globalmem_llseek,

.read=globalmem_read,

.write=globalmem_write,

.unlocked_ioctl=globalmem_ioctl,

.open=globalmem_open,

.release=globalmem_release,

};//init and add cdev struct

static void globalmem_setup_cdev(struct globalmem_dev * dev, intindex)

{interr;int devno = MKDEV(globalmem_major, 0);

cdev_init(&dev->cdev, &globalmem_fops);

err= cdev_add(&dev->cdev, devno, 1);if(err)

printk(KERN_NOTICE"Error %d adding globalmem", err);

}//globalmem device init function

int globalmem_init(void)

{intresult;

dev_t devno= MKDEV(globalmem_major, 0);//apply globalmem device kernel region

if(globalmem_major)

result= register_chrdev_region(devno, 1, "globalmem");else{//get major no dynamically

result = alloc_chrdev_region(&devno, 0, 1, "globalmem");

globalmem_major=MAJOR(devno);

}if (result < 0)returnresult;//apply device struct memory

globalmem_devp = kmalloc(sizeof(structglobalmem_dev), GFP_KERNEL);if (!globalmem_devp) {

result= -ENOMEM;gotofail_malloc;

}

memset(globalmem_devp,0, sizeof(structglobalmem_dev));

globalmem_setup_cdev(globalmem_devp,0);return 0;

fail_malloc:

unregister_chrdev_region(devno,1);returnresult;

}//globalmem device exit function

void globalmem_exit(void)

{//del cdev struct

cdev_del(&globalmem_devp->cdev);//free device struct memory

kfree(globalmem_devp);//unregister device region

unregister_chrdev_region(MKDEV(globalmem_major, 0), 1);

}

module_param(globalmem_major,int, S_IRUGO);

module_init(globalmem_init);

module_exit(globalmem_exit);

MODULE_AUTHOR("");

MODULE_LICENSE("Dual BSD/GPL");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值