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
- kdevname
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 == NULL) {
70 chrdevs[major].name = name;
71 chrdevs[major].fops = fops;
72 return major;
73 }
74 }
75 return -EBUSY;
76 }
77 if (major >= MAX_CHRDEV)
78 return -EINVAL;
79 if (chrdevs[major].fops && chrdevs[major].fops != fops)
80 return -EBUSY;
81 chrdevs[major].name = name;
82 chrdevs[major].fops = fops;
83 return 0;
84 }
85
86 int register_blkdev(unsigned int major, const char * name, struct file_operations *fops)
87 {
88 if (major == 0) {
89 for (major = MAX_BLKDEV-1; major > 0; major--) {
90 if (blkdevs[major].fops == NULL) {
91 blkdevs[major].name = name;
92 blkdevs[major].fops = fops;
93 return major;
94 }
95 }
96 return -EBUSY;
97 }
98 if (major >= MAX_BLKDEV)
99 return -EINVAL;
100 if (blkdevs[major].fops && blkdevs[major].fops != fops)
101 return -EBUSY;
102 blkdevs[major].name = name;
103 blkdevs[major].fops = fops;
104 return 0;
105 }
106
107 int unregister_chrdev(unsigned int major, const char * name)
108 {
109 if (major >= MAX_CHRDEV)
110 return -EINVAL;
111 if (!chrdevs[major].fops)
112 return -EINVAL;
113 if (strcmp(chrdevs[major].name, name))
114 return -EINVAL;
115 chrdevs[major].name = NULL;
116 chrdevs[major].fops = NULL;
117 return 0;
118 }
119
120 int unregister_blkdev(unsigned int major, const char * name)
121 {
122 if (major >= MAX_BLKDEV)
123 return -EINVAL;
124 if (!blkdevs[major].fops)
125 return -EINVAL;
126 if (strcmp(blkdevs[major].name, name))
127 return -EINVAL;
128 blkdevs[major].name = NULL;
129 blkdevs[major].fops = NULL;
130 return 0;
131 }
132
133
134
135
136
137
138
139
140
141
142 int check_disk_change(kdev_t dev)
143 {
144 int i;
145 struct file_operations * fops;
146
147 i = MAJOR(dev);
148 if (i >= MAX_BLKDEV || (fops = blkdevs[i].fops) == NULL)
149 return 0;
150 if (fops->check_media_change == NULL)
151 return 0;
152 if (!fops->check_media_change(dev))
153 return 0;
154
155 printk(KERN_DEBUG "VFS: Disk change detected on device %s\n",
156 kdevname(dev));
157 for (i=0 ; i<NR_SUPER ; i++)
158 if (super_blocks[i].s_dev == dev)
159 put_super(super_blocks[i].s_dev);
160 invalidate_inodes(dev);
161 invalidate_buffers(dev);
162
163 if (fops->revalidate)
164 fops->revalidate(dev);
165 return 1;
166 }
167
168
169
170
171 int blkdev_open(struct inode * inode, struct file * filp)
172 {
173 int i;
174
175 i = MAJOR(inode->i_rdev);
176 if (i >= MAX_BLKDEV || !blkdevs[i].fops)
177 return -ENODEV;
178 filp->f_op = blkdevs[i].fops;
179 if (filp->f_op->open)
180 return filp->f_op->open(inode,filp);
181 return 0;
182 }
183
184
185
186
187
188
189 struct file_operations def_blk_fops = {
190 NULL,
191 NULL,
192 NULL,
193 NULL,
194 NULL,
195 NULL,
196 NULL,
197 blkdev_open,
198 NULL,
199 };
200
201 struct inode_operations blkdev_inode_operations = {
202 &def_blk_fops,
203 NULL,
204 NULL,
205 NULL,
206 NULL,
207 NULL,
208 NULL,
209 NULL,
210 NULL,
211 NULL,
212 NULL,
213 NULL,
214 NULL,
215 NULL,
216 NULL
217 };
218
219
220
221
222 int chrdev_open(struct inode * inode, struct file * filp)
223 {
224 int i;
225
226 i = MAJOR(inode->i_rdev);
227 if (i >= MAX_CHRDEV || !chrdevs[i].fops)
228 return -ENODEV;
229 filp->f_op = chrdevs[i].fops;
230 if (filp->f_op->open)
231 return filp->f_op->open(inode,filp);
232 return 0;
233 }
234
235
236
237
238
239
240 struct file_operations def_chr_fops = {
241 NULL,
242 NULL,
243 NULL,
244 NULL,
245 NULL,
246 NULL,
247 NULL,
248 chrdev_open,
249 NULL,
250 };
251
252 struct inode_operations chrdev_inode_operations = {
253 &def_chr_fops,
254 NULL,
255 NULL,
256 NULL,
257 NULL,
258 NULL,
259 NULL,
260 NULL,
261 NULL,
262 NULL,
263 NULL,
264 NULL,
265 NULL,
266 NULL,
267 NULL
268 };
269
270
271
272
273
274
275 char * kdevname(kdev_t dev)
276 {
277 static char buffer[32];
278 sprintf(buffer, "%02x:%02x", MAJOR(dev), MINOR(dev));
279 return buffer;
280 }