#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/mm.h>
#include <linux/kdev_t.h>
#define DEVICE "sky"
struct sky_struct
{
dev_t devno;
struct cdev cdev;
};
struct sky_struct sky;
static void vm_ops_open(struct vm_area_struct *area)
{
printk(KERN_ALERT "vm_ops_open\n");
}
static void vm_ops_close(struct vm_area_struct *area)
{
printk(KERN_ALERT "vm_ops_close\n");
}
static struct vm_operations_struct vm_ops =
{
.open = vm_ops_open,
.close = vm_ops_close,
};
static int sky_mmap(struct file *filp, struct vm_area_struct *vm)
{
unsigned long start, end, size, pfn;
pgprot_t prot;
start = vm->vm_start;
end = vm->vm_end;
size = end - start;
pfn = vm->vm_pgoff;
prot = vm->vm_page_prot;
if (remap_pfn_range(vm, start, pfn, size, prot) < 0)
{
goto remap_err;
}
vm->vm_ops = &vm_ops;
vm_ops_open(vm);
return 0;
remap_err:
return -1;
}
static struct file_operations fops =
{
.mmap = sky_mmap,
};
static int __init sky_init(void)
{
if (alloc_chrdev_region(&sky.devno, 0, 1, DEVICE) < 0)
{
goto alloc_err;
}
cdev_init(&sky.cdev, &fops);
sky.cdev.owner = THIS_MODULE;
sky.cdev.ops = &fops;
if (cdev_add(&sky.cdev, sky.devno, 1) < 0)
{
goto add_err;
}
return 0;
add_err:
unregister_chrdev_region(sky.devno, 1);
alloc_err:
return -1;
}
static void __exit sky_exit(void)
{
cdev_del(&sky.cdev);
unregister_chrdev_region(sky.devno, 1);
}
MODULE_LICENSE("GPL");
module_init(sky_init);
module_exit(sky_exit);
|