Merge tag 'x86_urgent_for_v5.13_rc6' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / fs / proc / consoles.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2010 Werner Fink, Jiri Slaby
4  */
5
6 #include <linux/console.h>
7 #include <linux/kernel.h>
8 #include <linux/proc_fs.h>
9 #include <linux/seq_file.h>
10 #include <linux/tty_driver.h>
11
12 /*
13  * This is handler for /proc/consoles
14  */
15 static int show_console_dev(struct seq_file *m, void *v)
16 {
17         static const struct {
18                 short flag;
19                 char name;
20         } con_flags[] = {
21                 { CON_ENABLED,          'E' },
22                 { CON_CONSDEV,          'C' },
23                 { CON_BOOT,             'B' },
24                 { CON_PRINTBUFFER,      'p' },
25                 { CON_BRL,              'b' },
26                 { CON_ANYTIME,          'a' },
27         };
28         char flags[ARRAY_SIZE(con_flags) + 1];
29         struct console *con = v;
30         unsigned int a;
31         dev_t dev = 0;
32
33         if (con->device) {
34                 const struct tty_driver *driver;
35                 int index;
36                 driver = con->device(con, &index);
37                 if (driver) {
38                         dev = MKDEV(driver->major, driver->minor_start);
39                         dev += index;
40                 }
41         }
42
43         for (a = 0; a < ARRAY_SIZE(con_flags); a++)
44                 flags[a] = (con->flags & con_flags[a].flag) ?
45                         con_flags[a].name : ' ';
46         flags[a] = 0;
47
48         seq_setwidth(m, 21 - 1);
49         seq_printf(m, "%s%d", con->name, con->index);
50         seq_pad(m, ' ');
51         seq_printf(m, "%c%c%c (%s)", con->read ? 'R' : '-',
52                         con->write ? 'W' : '-', con->unblank ? 'U' : '-',
53                         flags);
54         if (dev)
55                 seq_printf(m, " %4d:%d", MAJOR(dev), MINOR(dev));
56
57         seq_putc(m, '\n');
58         return 0;
59 }
60
61 static void *c_start(struct seq_file *m, loff_t *pos)
62 {
63         struct console *con;
64         loff_t off = 0;
65
66         console_lock();
67         for_each_console(con)
68                 if (off++ == *pos)
69                         break;
70
71         return con;
72 }
73
74 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
75 {
76         struct console *con = v;
77         ++*pos;
78         return con->next;
79 }
80
81 static void c_stop(struct seq_file *m, void *v)
82 {
83         console_unlock();
84 }
85
86 static const struct seq_operations consoles_op = {
87         .start  = c_start,
88         .next   = c_next,
89         .stop   = c_stop,
90         .show   = show_console_dev
91 };
92
93 static int __init proc_consoles_init(void)
94 {
95         proc_create_seq("consoles", 0, NULL, &consoles_op);
96         return 0;
97 }
98 fs_initcall(proc_consoles_init);