#include "char.h" #include #include #include #include "util.h" #include "pci.h" #define DOOMDEV_COUNT 256 #define DOOMDEV_NAME "doom" dev_t first; int major; int next_minor = 0; long doom_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { return -1; } int doom_open(struct inode *inode, struct file *filp) { return -1; } struct file_operations doomdev_fops = { .owner = THIS_MODULE, .unlocked_ioctl = doom_ioctl, .compat_ioctl = doom_ioctl, .open = doom_open }; struct class *doom_class; int new_doomdev(struct pci_dev *dev) { int err = 0; int minor; struct doom_data *doom_data; dev_t devt; if (next_minor >= DOOMDEV_COUNT) { return -ENOMEM; } doom_data = kmalloc(sizeof(*doom_data), GFP_KERNEL); if (doom_data == NULL) { err = -ENOMEM; goto error_kmalloc; } doom_data->cdev = cdev_alloc(); if (doom_data->cdev == NULL) { err = -ENOMEM; goto error_cdev; } cdev_init(doom_data->cdev, &doomdev_fops); ORFAIL(cdev_add(doom_data->cdev, first, 1), error_add); minor = next_minor++; devt = MKDEV(major, minor); doom_data->device = device_create(doom_class, &dev->dev, devt, NULL, "doom%d", minor), ORFAIL_PTR(doom_data->device, error_create); pci_set_drvdata(dev, doom_data); return 0; error_create: cdev_del(doom_data->cdev); error_add: error_cdev: kfree(doom_data); error_kmalloc: return err; } void destroy_doomdev(struct pci_dev *dev) { struct doom_data *data; data = pci_get_drvdata(dev); device_destroy(doom_class, data->device->devt); cdev_del(data->cdev); kfree(data); } int char_init(void) { int err = 0; ORFAIL(alloc_chrdev_region(&first, 0, DOOMDEV_COUNT, DOOMDEV_NAME), error_region); major = MAJOR(first); doom_class = class_create(THIS_MODULE, "doom"); ORFAIL_PTR(doom_class, error_create); return 0; error_create: unregister_chrdev_region(first, DOOMDEV_COUNT); error_region: return err; } void char_cleanup(void) { unregister_chrdev_region(first, DOOMDEV_COUNT); class_unregister(doom_class); class_destroy(doom_class); }