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