1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#include "char.h"
#include <linux/anon_inodes.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#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;
int next_minor = 0;
long doom_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
switch (cmd) {
case DOOMDEV_IOCTL_CREATE_SURFACE:
return new_surface(filp,
(struct doomdev_ioctl_create_surface *) arg);
case DOOMDEV_IOCTL_CREATE_TEXTURE:
return new_texture(filp,
(struct doomdev_ioctl_create_texture *) arg);
case DOOMDEV_IOCTL_CREATE_FLAT:
return new_flat(filp,
(struct doomdev_ioctl_create_flat *) arg);
case DOOMDEV_IOCTL_CREATE_COLORMAPS:
return new_colors(filp,
(struct doomdev_ioctl_create_colormaps *) 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 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 -EOVERFLOW;
}
doom_data = pci_get_drvdata(dev);
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);
return 0;
error_create:
cdev_del(&doom_data->cdev);
error_add:
return err;
}
void destroy_doomdev(struct doom_data *doom_data)
{
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);
}
|