m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
path: root/char.c
blob: 881c3d031c064cd089282611f5f80c082a2f40af (plain)
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include "char.h"

#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h>

#include "doomdev.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_create_surface(struct file *filp, unsigned long arg)
{
	struct doomdev_ioctl_create_surface *params;
	params = (struct doomdev_ioctl_create_surface *)arg;
	return new_surface(params);
}

long doom_create_texture(struct file *filp, unsigned long arg)
{
	return -1;
}

long doom_create_flat(struct file *filp, unsigned long arg)
{
	return -1;
}

long doom_create_colormaps(struct file *filp, unsigned long arg)
{
	return -1;
}

long doom_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	switch (cmd) {
	case DOOMDEV_IOCTL_CREATE_SURFACE:
		return doom_create_surface(filp, arg);
	case DOOMDEV_IOCTL_CREATE_TEXTURE:
		return doom_create_texture(filp, arg);
	case DOOMDEV_IOCTL_CREATE_FLAT:
		return doom_create_flat(filp, arg);
	case DOOMDEV_IOCTL_CREATE_COLORMAPS:
		return doom_create_colormaps(filp, arg);
	default:
		return -EINVAL;
	}
}

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 -ENOMEM;
	}

	doom_data = pci_get_drvdata(dev);

	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);

	return 0;

error_create:
	cdev_del(doom_data->cdev);
error_add:
error_cdev:
	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);
}