This source file includes following definitions.
- get_device_list
- get_blkfops
- get_chrfops
- register_chrdev
- register_blkdev
- unregister_chrdev
- unregister_blkdev
- check_disk_change
- blkdev_open
- chrdev_open
1
2
3
4
5
6
7
8
9 #include <linux/fs.h>
10 #include <linux/major.h>
11 #include <linux/string.h>
12 #include <linux/sched.h>
13 #include <linux/ext_fs.h>
14 #include <linux/stat.h>
15 #include <linux/fcntl.h>
16 #include <linux/errno.h>
17
18 struct device_struct {
19 const char * name;
20 struct file_operations * fops;
21 };
22
23 static struct device_struct chrdevs[MAX_CHRDEV] = {
24 { NULL, NULL },
25 };
26
27 static struct device_struct blkdevs[MAX_BLKDEV] = {
28 { NULL, NULL },
29 };
30
31 int get_device_list(char * page)
32 {
33 int i;
34 int len;
35
36 len = sprintf(page, "Character devices:\n");
37 for (i = 0; i < MAX_CHRDEV ; i++) {
38 if (chrdevs[i].fops) {
39 len += sprintf(page+len, "%2d %s\n", i, chrdevs[i].name);
40 }
41 }
42 len += sprintf(page+len, "\nBlock devices:\n");
43 for (i = 0; i < MAX_BLKDEV ; i++) {
44 if (blkdevs[i].fops) {
45 len += sprintf(page+len, "%2d %s\n", i, blkdevs[i].name);
46 }
47 }
48 return len;
49 }
50
51 struct file_operations * get_blkfops(unsigned int major)
52 {
53 if (major >= MAX_BLKDEV)
54 return NULL;
55 return blkdevs[major].fops;
56 }
57
58 struct file_operations * get_chrfops(unsigned int major)
59 {
60 if (major >= MAX_CHRDEV)
61 return NULL;
62 return chrdevs[major].fops;
63 }
64
65 int register_chrdev(unsigned int major, const char * name, struct file_operations *fops)
66 {
67 if (major == 0) {
68 for (major = MAX_CHRDEV-1; major > 0; major--) {
69 if (chrdevs[major].fops == fops)
70 return major;
71 }
72 for (major = MAX_CHRDEV-1; major > 0; major--) {
73 if (chrdevs[major].fops == NULL) {
74 chrdevs[major].name = name;
75 chrdevs[major].fops = fops;
76 return major;
77 }
78 }
79 return -EBUSY;
80 }
81 if (major >= MAX_CHRDEV)
82 return -EINVAL;
83 if (chrdevs[major].fops && chrdevs[major].fops != fops)
84 return -EBUSY;
85 chrdevs[major].name = name;
86 chrdevs[major].fops = fops;
87 return 0;
88 }
89
90 int register_blkdev(unsigned int major, const char * name, struct file_operations *fops)
91 {
92 if (major == 0) {
93 for (major = MAX_BLKDEV-1; major > 0; major--) {
94 if (blkdevs[major].fops == fops)
95 return major;
96 }
97 for (major = MAX_BLKDEV-1; major > 0; major--) {
98 if (blkdevs[major].fops == NULL) {
99 blkdevs[major].name = name;
100 blkdevs[major].fops = fops;
101 return major;
102 }
103 }
104 return -EBUSY;
105 }
106 if (major >= MAX_BLKDEV)
107 return -EINVAL;
108 if (blkdevs[major].fops && blkdevs[major].fops != fops)
109 return -EBUSY;
110 blkdevs[major].name = name;
111 blkdevs[major].fops = fops;
112 return 0;
113 }
114
115 int unregister_chrdev(unsigned int major, const char * name)
116 {
117 if (major >= MAX_CHRDEV)
118 return -EINVAL;
119 if (!chrdevs[major].fops)
120 return -EINVAL;
121 if (strcmp(chrdevs[major].name, name))
122 return -EINVAL;
123 chrdevs[major].name = NULL;
124 chrdevs[major].fops = NULL;
125 return 0;
126 }
127
128 int unregister_blkdev(unsigned int major, const char * name)
129 {
130 if (major >= MAX_BLKDEV)
131 return -EINVAL;
132 if (!blkdevs[major].fops)
133 return -EINVAL;
134 if (strcmp(blkdevs[major].name, name))
135 return -EINVAL;
136 blkdevs[major].name = NULL;
137 blkdevs[major].fops = NULL;
138 return 0;
139 }
140
141
142
143
144
145
146
147
148
149
150 int check_disk_change(dev_t dev)
151 {
152 int i;
153 struct file_operations * fops;
154
155 i = MAJOR(dev);
156 if (i >= MAX_BLKDEV || (fops = blkdevs[i].fops) == NULL)
157 return 0;
158 if (fops->check_media_change == NULL)
159 return 0;
160 if (!fops->check_media_change(dev))
161 return 0;
162
163 printk("VFS: Disk change detected on device %d/%d\n",
164 MAJOR(dev), MINOR(dev));
165 for (i=0 ; i<NR_SUPER ; i++)
166 if (super_blocks[i].s_dev == dev)
167 put_super(super_blocks[i].s_dev);
168 invalidate_inodes(dev);
169 invalidate_buffers(dev);
170
171 if (fops->revalidate)
172 fops->revalidate(dev);
173 return 1;
174 }
175
176
177
178
179 int blkdev_open(struct inode * inode, struct file * filp)
180 {
181 int i;
182
183 i = MAJOR(inode->i_rdev);
184 if (i >= MAX_BLKDEV || !blkdevs[i].fops)
185 return -ENODEV;
186 filp->f_op = blkdevs[i].fops;
187 if (filp->f_op->open)
188 return filp->f_op->open(inode,filp);
189 return 0;
190 }
191
192
193
194
195
196
197 struct file_operations def_blk_fops = {
198 NULL,
199 NULL,
200 NULL,
201 NULL,
202 NULL,
203 NULL,
204 NULL,
205 blkdev_open,
206 NULL,
207 };
208
209 struct inode_operations blkdev_inode_operations = {
210 &def_blk_fops,
211 NULL,
212 NULL,
213 NULL,
214 NULL,
215 NULL,
216 NULL,
217 NULL,
218 NULL,
219 NULL,
220 NULL,
221 NULL,
222 NULL,
223 NULL,
224 NULL
225 };
226
227
228
229
230 int chrdev_open(struct inode * inode, struct file * filp)
231 {
232 int i;
233
234 i = MAJOR(inode->i_rdev);
235 if (i >= MAX_CHRDEV || !chrdevs[i].fops)
236 return -ENODEV;
237 filp->f_op = chrdevs[i].fops;
238 if (filp->f_op->open)
239 return filp->f_op->open(inode,filp);
240 return 0;
241 }
242
243
244
245
246
247
248 struct file_operations def_chr_fops = {
249 NULL,
250 NULL,
251 NULL,
252 NULL,
253 NULL,
254 NULL,
255 NULL,
256 chrdev_open,
257 NULL,
258 };
259
260 struct inode_operations chrdev_inode_operations = {
261 &def_chr_fops,
262 NULL,
263 NULL,
264 NULL,
265 NULL,
266 NULL,
267 NULL,
268 NULL,
269 NULL,
270 NULL,
271 NULL,
272 NULL,
273 NULL,
274 NULL,
275 NULL
276 };