#include "char.h" #include #include #include #include #include #include "doomdev.h" #include "harddoom.h" #include "util.h" #include "pci.h" #include "surface.h" #define DOOMDEV_COUNT 256 #define DOOMDEV_NAME "doom" dev_t first; int major; bool minors[DOOMDEV_COUNT]; long do_new_surface(struct file *filp, unsigned long arg) { struct doomdev_ioctl_create_surface param; int not_copied; int err; not_copied = copy_from_user(¶m, (void __iomem *) arg, sizeof(param)); if (not_copied) { err = -EFAULT; goto error_param; } err = new_surface(filp, ¶m); error_param: return err; } long do_new_texture(struct file *filp, unsigned long arg) { struct doomdev_ioctl_create_texture param; int not_copied; int err; not_copied = copy_from_user(¶m, (void __iomem *) arg, sizeof(param)); if (not_copied) { err = -EFAULT; goto error_param; } err = new_texture(filp, ¶m); error_param: return err; } long do_new_flat(struct file *filp, unsigned long arg) { struct doomdev_ioctl_create_flat param; int not_copied; int err; not_copied = copy_from_user(¶m, (void __iomem *) arg, sizeof(param)); if (not_copied) { err = -EFAULT; goto error_param; } err = new_flat(filp, ¶m); error_param: return err; } long do_new_colors(struct file *filp, unsigned long arg) { struct doomdev_ioctl_create_colormaps param; int not_copied; int err; not_copied = copy_from_user(¶m, (void __iomem *) arg, sizeof(param)); if (not_copied) { err = -EFAULT; goto error_param; } err = new_colors(filp, ¶m); error_param: return err; } long doom_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { switch (cmd) { case DOOMDEV_IOCTL_CREATE_SURFACE: return do_new_surface(filp, arg); case DOOMDEV_IOCTL_CREATE_TEXTURE: return do_new_texture(filp, arg); case DOOMDEV_IOCTL_CREATE_FLAT: return do_new_flat(filp, arg); case DOOMDEV_IOCTL_CREATE_COLORMAPS: return do_new_colors(filp, arg); default: return -ENOTTY; } } int doom_open(struct inode *inode, struct file *filp) { return 0; } struct file_operations doomdev_fops = { .owner = THIS_MODULE, .unlocked_ioctl = doom_ioctl, .compat_ioctl = doom_ioctl, .open = doom_open }; struct class *doom_class; int alloc_minor(void) { int i; for (i = 0; i < DOOMDEV_COUNT; i++) { if (!minors[i]) { minors[i] = true; return i; } } return -EOVERFLOW; } void free_minor(int minor) { minors[minor] = false; } int new_doomdev(struct pci_dev *dev) { int err = 0; int minor; struct doom_data *doom_data; dev_t devt; doom_data = pci_get_drvdata(dev); cdev_init(&doom_data->cdev, &doomdev_fops); ORFAIL(cdev_add(&doom_data->cdev, first, 1), error_add); minor = alloc_minor(); ORFAIL(minor, error_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); return 0; error_create: free_minor(minor); error_minor: cdev_del(&doom_data->cdev); error_add: return err; } void destroy_doomdev(struct doom_data *doom_data) { free_minor(MINOR(doom_data->device->devt)); device_destroy(doom_class, doom_data->device->devt); cdev_del(&doom_data->cdev); } 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); }