#include <linux/version.h> #include <linux/config.h> #include <linux/module.h> #include <linux/vmalloc.h>
#include <linux/sched.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/proc_fs.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/proc_fs.h> #include <linux/fcntl.h> /* O_ACCMODE */ #include <linux/seq_file.h> #include <linux/cdev.h>
#include <asm/page.h> #include <asm/io.h>
#include "hpialloc.h"
int hpialloc_major = HPIALLOC_MAJOR; int hpialloc_minor = 0; int hpialloc_nr_devs = HPIALLOC_NR_DEVS;
module_param(hpialloc_major, int, S_IRUGO); module_param(hpialloc_minor, int, S_IRUGO); module_param(hpialloc_nr_devs, int, S_IRUGO);
MODULE_AUTHOR("Bozhidar Bastov"); MODULE_LICENSE("GPL");
struct hpialloc_dev *hpialloc_devices;
/* * Open and close */
int hpialloc_open(struct inode *inode, struct file *filp) { struct hpialloc_dev *dev; /* device information */
dev = container_of(inode->i_cdev, struct hpialloc_dev, cdev); filp->private_data = dev; /* for other methods */
return 0; /* success */ }
int hpialloc_release(struct inode *inode, struct file *filp) { return 0; }
struct file_operations hpialloc_fops = { .owner = THIS_MODULE, .llseek = NULL, .read = NULL, .write = NULL, .ioctl = NULL, .open = hpialloc_open, .release = hpialloc_release, };
/* * Finally, the module stuff */
/* * The cleanup function is used to handle initialization failures as well. * Thefore, it must be careful to work correctly even if some of the items * have not been initialized */
void hpialloc_cleanup_module(void) { int i; dev_t devno = MKDEV(hpialloc_major, hpialloc_minor);
/* Get rid of our char dev entries */ if (hpialloc_devices) { for (i = 0; i < hpialloc_nr_devs; i++) { cdev_del(&hpialloc_devices[i].cdev); } kfree(hpialloc_devices); }
/* cleanup_module is never called if registering failed */ unregister_chrdev_region(devno, hpialloc_nr_devs);
printk(KERN_WARNING "hpialloc: smpd module unloaded!\n");
}
/* * Set up the char_dev structure for this device. */
static void hpialloc_setup_cdev(struct hpialloc_dev *dev, int index) { int err, devno = MKDEV(hpialloc_major, hpialloc_minor + index); cdev_init(&dev->cdev, &hpialloc_fops); dev->cdev.owner = THIS_MODULE; dev->cdev.ops = &hpialloc_fops; err = cdev_add (&dev->cdev, devno, 1); /* Fail gracefully if need be */ if (err) printk(KERN_NOTICE "Error %d adding hpialloc%d", err, index); }
int hpialloc_init_module(void) { int result, i; dev_t dev = 0; volatile void *remapped; unsigned long trial_size = 0x100000; // 1MB char test_string[] = "0123456789abcde"; // 16 bytes
/* * Get a range of minor numbers to work with, asking for a dynamic * major unless directed otherwise at load time. */ if (hpialloc_major) { dev = MKDEV(hpialloc_major, hpialloc_minor); result = register_chrdev_region(dev, hpialloc_nr_devs, "hpialloc"); } else { result = alloc_chrdev_region(&dev, hpialloc_minor, hpialloc_nr_devs, "hpialloc"); hpialloc_major = MAJOR(dev); } if (result < 0) { printk(KERN_WARNING "hpialloc: can't get major %d\n", hpialloc_major); return result; }
/* * allocate the devices -- we can't have them static, as the number * can be specified at load time */ hpialloc_devices = kmalloc(hpialloc_nr_devs * sizeof(struct hpialloc_dev), GFP_KERNEL); if (!hpialloc_devices) { result = -ENOMEM; goto fail; /* Make this more graceful */ } memset(hpialloc_devices, 0, hpialloc_nr_devs * sizeof(struct hpialloc_dev));
/* Initialize each device. */ for (i = 0; i < hpialloc_nr_devs; i++) { hpialloc_setup_cdev(&hpialloc_devices[i], i); } printk(KERN_WARNING "hpialloc: hpialloc module loaded!\n");
remapped = ioremap(0xA1E00000, trial_size);
if (!remapped) return -1;
printk(KERN_INFO "hpialloc: hpialloc module mapped memory successfully!\n");
for (i = 0; i < trial_size; i += 16) { strcpy((char *)(remapped) + i, test_string); if (strcmp((char *)(remapped) + i, test_string)) { printk(KERN_INFO "Compare failure, i = %d!\n", i); printk(KERN_INFO "remapped : %s\n", (char *)remapped); break; } }
for (i = 0; i < trial_size; i += 16) { strncpy(test_string, (char *)(remapped) + i, 16); if (strcmp((char *)(remapped) + i, test_string)) { printk(KERN_INFO "Compare failure, i = %d!\n", i); printk(KERN_INFO "remapped : %s\n", (char *)remapped); break; } }
//iounmap((void *)remapped); return 0; /* succeed */
fail: hpialloc_cleanup_module(); return result; }
module_init(hpialloc_init_module); module_exit(hpialloc_cleanup_module);
|