| xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 | 
|  | 2 | #include <linux/fs.h> | 
|  | 3 | #include <linux/init.h> | 
|  | 4 | #include <linux/proc_fs.h> | 
|  | 5 | #include <linux/seq_file.h> | 
|  | 6 |  | 
|  | 7 | static int devinfo_show(struct seq_file *f, void *v) | 
|  | 8 | { | 
|  | 9 | int i = *(loff_t *) v; | 
|  | 10 |  | 
|  | 11 | if (i < CHRDEV_MAJOR_MAX) { | 
|  | 12 | if (i == 0) | 
|  | 13 | seq_puts(f, "Character devices:\n"); | 
|  | 14 | chrdev_show(f, i); | 
|  | 15 | } | 
|  | 16 | #ifdef CONFIG_BLOCK | 
|  | 17 | else { | 
|  | 18 | i -= CHRDEV_MAJOR_MAX; | 
|  | 19 | if (i == 0) | 
|  | 20 | seq_puts(f, "\nBlock devices:\n"); | 
|  | 21 | blkdev_show(f, i); | 
|  | 22 | } | 
|  | 23 | #endif | 
|  | 24 | return 0; | 
|  | 25 | } | 
|  | 26 |  | 
|  | 27 | static void *devinfo_start(struct seq_file *f, loff_t *pos) | 
|  | 28 | { | 
|  | 29 | if (*pos < (BLKDEV_MAJOR_MAX + CHRDEV_MAJOR_MAX)) | 
|  | 30 | return pos; | 
|  | 31 | return NULL; | 
|  | 32 | } | 
|  | 33 |  | 
|  | 34 | static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos) | 
|  | 35 | { | 
|  | 36 | (*pos)++; | 
|  | 37 | if (*pos >= (BLKDEV_MAJOR_MAX + CHRDEV_MAJOR_MAX)) | 
|  | 38 | return NULL; | 
|  | 39 | return pos; | 
|  | 40 | } | 
|  | 41 |  | 
|  | 42 | static void devinfo_stop(struct seq_file *f, void *v) | 
|  | 43 | { | 
|  | 44 | /* Nothing to do */ | 
|  | 45 | } | 
|  | 46 |  | 
|  | 47 | static const struct seq_operations devinfo_ops = { | 
|  | 48 | .start = devinfo_start, | 
|  | 49 | .next  = devinfo_next, | 
|  | 50 | .stop  = devinfo_stop, | 
|  | 51 | .show  = devinfo_show | 
|  | 52 | }; | 
|  | 53 |  | 
|  | 54 | static int __init proc_devices_init(void) | 
|  | 55 | { | 
|  | 56 | proc_create_seq("devices", 0, NULL, &devinfo_ops); | 
|  | 57 | return 0; | 
|  | 58 | } | 
|  | 59 | fs_initcall(proc_devices_init); |