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 NULL,
218 NULL
219 };
220
221
222
223
224 int chrdev_open(struct inode * inode, struct file * filp)
225 {
226 int i;
227
228 i = MAJOR(inode->i_rdev);
229 if (i >= MAX_CHRDEV || !chrdevs[i].fops)
230 return -ENODEV;
231 filp->f_op = chrdevs[i].fops;
232 if (filp->f_op->open)
233 return filp->f_op->open(inode,filp);
234 return 0;
235 }
236
237
238
239
240
241
242 struct file_operations def_chr_fops = {
243 NULL,
244 NULL,
245 NULL,
246 NULL,
247 NULL,
248 NULL,
249 NULL,
250 chrdev_open,
251 NULL,
252 };
253
254 struct inode_operations chrdev_inode_operations = {
255 &def_chr_fops,
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 NULL,
269 NULL,
270 NULL,
271 NULL
272 };
273
274
275
276
277
278
279 char * kdevname(kdev_t dev)
280 {
281 static char buffer[32];
282 sprintf(buffer, "%02x:%02x", MAJOR(dev), MINOR(dev));
283 return buffer;
284 }