4 * (C) 1993 Matthias Urlichs -- collected common code and tables.
6 * Copyright (C) 1991, 1992 Linus Torvalds
8 * Added kerneld support: Jacques Gelinas and Bjorn Ekwall
12 #include <linux/config.h>
14 #include <linux/major.h>
15 #include <linux/string.h>
16 #include <linux/sched.h>
17 #include <linux/stat.h>
18 #include <linux/fcntl.h>
19 #include <linux/errno.h>
21 #include <linux/kmod.h>
23 #include <linux/tty.h>
25 /* serial module kmod load support */
26 struct tty_driver
*get_tty_driver(kdev_t device
);
27 #define isa_tty_dev(ma) (ma == TTY_MAJOR || ma == TTYAUX_MAJOR)
28 #define need_serial(ma,mi) (get_tty_driver(MKDEV(ma,mi)) == NULL)
31 struct device_struct
{
33 struct file_operations
* fops
;
36 static struct device_struct chrdevs
[MAX_CHRDEV
] = {
40 static struct device_struct blkdevs
[MAX_BLKDEV
] = {
44 int get_device_list(char * page
)
49 len
= sprintf(page
, "Character devices:\n");
50 for (i
= 0; i
< MAX_CHRDEV
; i
++) {
51 if (chrdevs
[i
].fops
) {
52 len
+= sprintf(page
+len
, "%3d %s\n", i
, chrdevs
[i
].name
);
55 len
+= sprintf(page
+len
, "\nBlock devices:\n");
56 for (i
= 0; i
< MAX_BLKDEV
; i
++) {
57 if (blkdevs
[i
].fops
) {
58 len
+= sprintf(page
+len
, "%3d %s\n", i
, blkdevs
[i
].name
);
65 Return the function table of a device.
66 Load the driver if needed.
68 static struct file_operations
* get_fops(
72 const char *mangle
, /* String to use to build the module name */
73 struct device_struct tb
[])
75 struct file_operations
*ret
= NULL
;
80 * I do get request for device 0. I have no idea why. It happen
81 * at shutdown time for one. Without the following test, the
82 * kernel will happily trigger a request_module() which will
83 * trigger kmod and modprobe for nothing (since there
84 * is no device with major number == 0. And furthermore
85 * it locks the reboot process :-(
87 * Jacques Gelinas (jacques@solucorp.qc.ca)
89 * A. Haritsis <ah@doc.ic.ac.uk>: fix for serial module
90 * though we need the minor here to check if serial dev,
91 * we pass only the normal major char dev to kmod
92 * as there is no other loadable dev on these majors
94 if ((isa_tty_dev(major
) && need_serial(major
,minor
)) ||
95 (major
!= 0 && !tb
[major
].fops
)) {
97 sprintf(name
, mangle
, major
);
101 ret
= tb
[major
].fops
;
108 Return the function table of a device.
109 Load the driver if needed.
111 struct file_operations
* get_blkfops(unsigned int major
)
113 return get_fops (major
,0,MAX_BLKDEV
,"block-major-%d",blkdevs
);
116 struct file_operations
* get_chrfops(unsigned int major
, unsigned int minor
)
118 return get_fops (major
,minor
,MAX_CHRDEV
,"char-major-%d",chrdevs
);
121 int register_chrdev(unsigned int major
, const char * name
, struct file_operations
*fops
)
124 for (major
= MAX_CHRDEV
-1; major
> 0; major
--) {
125 if (chrdevs
[major
].fops
== NULL
) {
126 chrdevs
[major
].name
= name
;
127 chrdevs
[major
].fops
= fops
;
133 if (major
>= MAX_CHRDEV
)
135 if (chrdevs
[major
].fops
&& chrdevs
[major
].fops
!= fops
)
137 chrdevs
[major
].name
= name
;
138 chrdevs
[major
].fops
= fops
;
142 int register_blkdev(unsigned int major
, const char * name
, struct file_operations
*fops
)
145 for (major
= MAX_BLKDEV
-1; major
> 0; major
--) {
146 if (blkdevs
[major
].fops
== NULL
) {
147 blkdevs
[major
].name
= name
;
148 blkdevs
[major
].fops
= fops
;
154 if (major
>= MAX_BLKDEV
)
156 if (blkdevs
[major
].fops
&& blkdevs
[major
].fops
!= fops
)
158 blkdevs
[major
].name
= name
;
159 blkdevs
[major
].fops
= fops
;
163 int unregister_chrdev(unsigned int major
, const char * name
)
165 if (major
>= MAX_CHRDEV
)
167 if (!chrdevs
[major
].fops
)
169 if (strcmp(chrdevs
[major
].name
, name
))
171 chrdevs
[major
].name
= NULL
;
172 chrdevs
[major
].fops
= NULL
;
176 int unregister_blkdev(unsigned int major
, const char * name
)
178 if (major
>= MAX_BLKDEV
)
180 if (!blkdevs
[major
].fops
)
182 if (strcmp(blkdevs
[major
].name
, name
))
184 blkdevs
[major
].name
= NULL
;
185 blkdevs
[major
].fops
= NULL
;
190 * This routine checks whether a removable media has been changed,
191 * and invalidates all buffer-cache-entries in that case. This
192 * is a relatively slow routine, so we have to try to minimize using
193 * it. Thus it is called only upon a 'mount' or 'open'. This
194 * is the best way of combining speed and utility, I think.
195 * People changing diskettes in the middle of an operation deserve
198 int check_disk_change(kdev_t dev
)
201 struct file_operations
* fops
;
202 struct super_block
* sb
;
205 if (i
>= MAX_BLKDEV
|| (fops
= blkdevs
[i
].fops
) == NULL
)
207 if (fops
->check_media_change
== NULL
)
209 if (!fops
->check_media_change(dev
))
212 printk(KERN_DEBUG
"VFS: Disk change detected on device %s\n",
216 if (sb
&& invalidate_inodes(sb
))
217 printk("VFS: busy inodes on changed media.\n");
219 invalidate_buffers(dev
);
221 if (fops
->revalidate
)
222 fops
->revalidate(dev
);
227 * Called every time a block special file is opened
229 int blkdev_open(struct inode
* inode
, struct file
* filp
)
232 filp
->f_op
= get_blkfops(MAJOR(inode
->i_rdev
));
233 if (filp
->f_op
!= NULL
){
235 if (filp
->f_op
->open
!= NULL
)
236 ret
= filp
->f_op
->open(inode
,filp
);
241 int blkdev_release(struct inode
* inode
)
243 struct file_operations
*fops
= get_blkfops(MAJOR(inode
->i_rdev
));
244 if (fops
&& fops
->release
)
245 return fops
->release(inode
,NULL
);
251 * Dummy default file-operations: the only thing this does
252 * is contain the open that then fills in the correct operations
253 * depending on the special file...
255 struct file_operations def_blk_fops
= {
263 blkdev_open
, /* open */
268 struct inode_operations blkdev_inode_operations
= {
269 &def_blk_fops
, /* default file operations */
280 NULL
, /* follow_link */
281 NULL
, /* get_block */
283 NULL
, /* writepage */
285 NULL
, /* permission */
286 NULL
/* revalidate */
290 * Called every time a character special file is opened
292 int chrdev_open(struct inode
* inode
, struct file
* filp
)
296 filp
->f_op
= get_chrfops(MAJOR(inode
->i_rdev
), MINOR(inode
->i_rdev
));
297 if (filp
->f_op
!= NULL
){
299 if (filp
->f_op
->open
!= NULL
)
300 ret
= filp
->f_op
->open(inode
,filp
);
306 * Dummy default file-operations: the only thing this does
307 * is contain the open that then fills in the correct operations
308 * depending on the special file...
310 struct file_operations def_chr_fops
= {
318 chrdev_open
, /* open */
323 struct inode_operations chrdev_inode_operations
= {
324 &def_chr_fops
, /* default file operations */
335 NULL
, /* follow_link */
336 NULL
, /* get_block */
338 NULL
, /* writepage */
340 NULL
, /* permission */
341 NULL
/* revalidate */
345 * Print device name (in decimal, hexadecimal or symbolic)
346 * Note: returns pointer to static data!
348 char * kdevname(kdev_t dev
)
350 static char buffer
[32];
351 sprintf(buffer
, "%02x:%02x", MAJOR(dev
), MINOR(dev
));
355 char * bdevname(kdev_t dev
)
357 static char buffer
[32];
358 const char * name
= blkdevs
[MAJOR(dev
)].name
;
361 name
= "unknown-block";
363 sprintf(buffer
, "%s(%d,%d)", name
, MAJOR(dev
), MINOR(dev
));
367 char * cdevname(kdev_t dev
)
369 static char buffer
[32];
370 const char * name
= chrdevs
[MAJOR(dev
)].name
;
373 name
= "unknown-char";
374 sprintf(buffer
, "%s(%d,%d)", name
, MAJOR(dev
), MINOR(dev
));
378 void init_special_inode(struct inode
*inode
, umode_t mode
, int rdev
)
380 inode
->i_mode
= mode
;
383 inode
->i_op
= &chrdev_inode_operations
;
384 inode
->i_rdev
= to_kdev_t(rdev
);
385 } else if (S_ISBLK(mode
)) {
386 inode
->i_op
= &blkdev_inode_operations
;
387 inode
->i_rdev
= to_kdev_t(rdev
);
388 } else if (S_ISFIFO(mode
))
390 else if (S_ISSOCK(mode
))
393 printk(KERN_DEBUG
"init_special_inode: bogus imode (%o)\n", mode
);