#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");