/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 2008 THALES Communications, All Rights Reserved. * Author: F. LAMBERT */ #include #include #include #include #include #include #include #include #include #define DEBUG #undef DEBUG #define HRTIMER_BASE_ADDR na_hrtimer_0 #define HRTIMER_SIZE 4 MODULE_AUTHOR("Frederic LAMBERT"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Module for HiRes timer /dev/hrtimer"); MODULE_SUPPORTED_DEVICE("none"); #define HRTIMER_MAJOR 251 #define HRTIMER_MINOR 0 static int hrtimer_open(struct inode*, struct file*); static int hrtimer_release(struct inode*, struct file*); static int hrtimer_mmap(struct file *file, struct vm_area_struct * vma); static unsigned long hrtimer_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags); static struct hrtimer_dev_t { int __iomem* membase; struct cdev cdev; } s_hrtimer_dev; /* definitions, which functions are called for /dev/hrtimer */ static struct file_operations fops_hrtimer = { .mmap = hrtimer_mmap, .open = hrtimer_open, .release = hrtimer_release, .get_unmapped_area = hrtimer_get_unmapped_area, }; /* called when data device file is opened */ static int hrtimer_open(struct inode *inode, struct file *filp) { struct hrtimer_dev_t *dev = container_of(inode->i_cdev, struct hrtimer_dev_t, cdev); filp->private_data = dev; return 0; } /* called when process closes data device file */ static int hrtimer_release(struct inode *inode, struct file *filp) { return 0; } /* called when a process mmap from data file */ static int hrtimer_mmap(struct file *filp, struct vm_area_struct * vma) { struct hrtimer_dev_t *dev = (struct hrtimer_dev_t*)filp->private_data; vma->vm_flags |= VM_MAYSHARE | VM_SHARED; vma->vm_start = (unsigned long)dev->membase; vma->vm_end = vma->vm_start + HRTIMER_SIZE; return 0; } static unsigned long hrtimer_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { return pgoff << PAGE_SHIFT; } static int __init mod_init(void) { int res; dev_t devno = MKDEV(HRTIMER_MAJOR, HRTIMER_MINOR); struct hrtimer_dev_t *dev = &s_hrtimer_dev; cdev_init(&dev->cdev, &fops_hrtimer); dev->cdev.owner = THIS_MODULE; dev->membase = ioremap(HRTIMER_BASE_ADDR, HRTIMER_SIZE); res = register_chrdev_region(devno, 1, "hrtimer"); if (res) { printk(KERN_NOTICE "Can't get major %d for HRTIMER", HRTIMER_MAJOR); return res; } res = cdev_add(&dev->cdev, devno, 1); if (res) { printk(KERN_NOTICE "Error %d adding HRTIMER", res); unregister_chrdev_region(devno, 1); return res; } printk(KERN_INFO "hrtimer: HiRes timer driver v0.0 (aug 2008) by frd66 at 0x%p\n", dev->membase); return res; } /* exit the module */ static void __exit mod_exit(void) { cdev_del(&s_hrtimer_dev.cdev); unregister_chrdev_region(MKDEV(HRTIMER_MAJOR, HRTIMER_MINOR), 1); } /* what are the module init/exit functions */ module_init(mod_init); module_exit(mod_exit);