]>
Commit | Line | Data |
---|---|---|
c3e6af00 | 1 | diff -Nru a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c |
2 | --- a/drivers/char/vc_screen.c Mon Dec 22 16:02:06 2003 | |
3 | +++ b/drivers/char/vc_screen.c Mon Dec 22 16:02:06 2003 | |
4 | @@ -36,6 +36,7 @@ | |
5 | #include <linux/kbd_kern.h> | |
6 | #include <linux/console.h> | |
7 | #include <linux/smp_lock.h> | |
8 | +#include <linux/device.h> | |
9 | #include <asm/uaccess.h> | |
10 | #include <asm/byteorder.h> | |
11 | #include <asm/unaligned.h> | |
12 | @@ -469,6 +470,85 @@ | |
13 | .open = vcs_open, | |
14 | }; | |
15 | ||
16 | +/* vc class implementation */ | |
17 | + | |
18 | +struct vc_dev { | |
19 | + struct list_head node; | |
20 | + dev_t dev; | |
21 | + struct class_device class_dev; | |
22 | +}; | |
23 | +#define to_vc_dev(d) container_of(d, struct vc_dev, class_dev) | |
24 | + | |
25 | +static LIST_HEAD(vc_dev_list); | |
26 | +static spinlock_t vc_dev_list_lock = SPIN_LOCK_UNLOCKED; | |
27 | + | |
28 | +static void release_vc_dev(struct class_device *class_dev) | |
29 | +{ | |
30 | + struct vc_dev *vc_dev = to_vc_dev(class_dev); | |
31 | + kfree(vc_dev); | |
32 | +} | |
33 | + | |
34 | +static struct class vc_class = { | |
35 | + .name = "vc", | |
36 | + .release = &release_vc_dev, | |
37 | +}; | |
38 | + | |
39 | +static ssize_t show_dev(struct class_device *class_dev, char *buf) | |
40 | +{ | |
41 | + struct vc_dev *vc_dev = to_vc_dev(class_dev); | |
42 | + return print_dev_t(buf, vc_dev->dev); | |
43 | +} | |
44 | +static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL); | |
45 | + | |
46 | +static int vc_add_class_device(dev_t dev, char *name, int minor) | |
47 | +{ | |
48 | + struct vc_dev *vc_dev = NULL; | |
49 | + int retval; | |
50 | + | |
51 | + vc_dev = kmalloc(sizeof(*vc_dev), GFP_KERNEL); | |
52 | + if (!vc_dev) | |
53 | + return -ENOMEM; | |
54 | + memset(vc_dev, 0x00, sizeof(*vc_dev)); | |
55 | + | |
56 | + vc_dev->dev = dev; | |
57 | + vc_dev->class_dev.class = &vc_class; | |
58 | + snprintf(vc_dev->class_dev.class_id, BUS_ID_SIZE, name, minor); | |
59 | + retval = class_device_register(&vc_dev->class_dev); | |
60 | + if (retval) | |
61 | + goto error; | |
62 | + class_device_create_file(&vc_dev->class_dev, &class_device_attr_dev); | |
63 | + spin_lock(&vc_dev_list_lock); | |
64 | + list_add(&vc_dev->node, &vc_dev_list); | |
65 | + spin_unlock(&vc_dev_list_lock); | |
66 | + return 0; | |
67 | +error: | |
68 | + kfree(vc_dev); | |
69 | + return retval; | |
70 | +} | |
71 | + | |
72 | +static void vc_remove_class_device(int minor) | |
73 | +{ | |
74 | + struct vc_dev *vc_dev = NULL; | |
75 | + struct list_head *tmp; | |
76 | + int found = 0; | |
77 | + | |
78 | + spin_lock(&vc_dev_list_lock); | |
79 | + list_for_each(tmp, &vc_dev_list) { | |
80 | + vc_dev = list_entry(tmp, struct vc_dev, node); | |
81 | + if (MINOR(vc_dev->dev) == minor) { | |
82 | + found = 1; | |
83 | + break; | |
84 | + } | |
85 | + } | |
86 | + if (found) { | |
87 | + list_del(&vc_dev->node); | |
88 | + spin_unlock(&vc_dev_list_lock); | |
89 | + class_device_unregister(&vc_dev->class_dev); | |
90 | + } else { | |
91 | + spin_unlock(&vc_dev_list_lock); | |
92 | + } | |
93 | +} | |
94 | + | |
95 | void vcs_make_devfs(struct tty_struct *tty) | |
96 | { | |
97 | devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 1), | |
98 | @@ -477,19 +557,26 @@ | |
99 | devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 129), | |
100 | S_IFCHR|S_IRUSR|S_IWUSR, | |
101 | "vcc/a%u", tty->index + 1); | |
102 | + vc_add_class_device(MKDEV(VCS_MAJOR, tty->index + 1), "vcs%u", tty->index + 1); | |
103 | + vc_add_class_device(MKDEV(VCS_MAJOR, tty->index + 129), "vcsa%u", tty->index + 1); | |
104 | } | |
105 | void vcs_remove_devfs(struct tty_struct *tty) | |
106 | { | |
107 | devfs_remove("vcc/%u", tty->index + 1); | |
108 | devfs_remove("vcc/a%u", tty->index + 1); | |
109 | + vc_remove_class_device(tty->index + 1); | |
110 | + vc_remove_class_device(tty->index + 129); | |
111 | } | |
112 | ||
113 | int __init vcs_init(void) | |
114 | { | |
115 | if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops)) | |
116 | panic("unable to get major %d for vcs device", VCS_MAJOR); | |
117 | + class_register(&vc_class); | |
118 | ||
119 | devfs_mk_cdev(MKDEV(VCS_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/0"); | |
120 | devfs_mk_cdev(MKDEV(VCS_MAJOR, 128), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/a0"); | |
121 | + vc_add_class_device(MKDEV(VCS_MAJOR, 0), "vcs", 0); | |
122 | + vc_add_class_device(MKDEV(VCS_MAJOR, 128), "vcsa", 128); | |
123 | return 0; | |
124 | } |