diff options
author | Milton Miller <miltonm@bga.com> | 2005-07-07 20:56:16 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-07 21:23:38 -0400 |
commit | 837dcfaf46d147f1d2c64cbbecb832dd9075c39d (patch) | |
tree | 4b8199609f63ee07126c6940c71d9a6f14bca4ec | |
parent | 5cee73fa04758f52b7404b93a02edf74649370ab (diff) |
[PATCH] hvc_console: Rearrange code
Milton Miller has done a lot of work to clean up our hvc_console code.
One of the important things the following patch series does is separate the
VIO layer from the hvc_console code. With the VIO specific code removed any
ppc64 platform, or even any architecture, can use hvc_console as a generic
polling console. You simply have to supply a get_chars and put_chars method
and hvc_console does the rest of the work. You can even use it for an
interrupt driven console.
This patch:
Rearrange the code in drivers/char/hvc_console.c to make future patches
smaller. No actual code changes, just ordering of the functions in the file.
Signed-off-by: Milton Miller <miltonm@bga.com>
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/char/hvc_console.c | 284 |
1 files changed, 142 insertions, 142 deletions
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 88cd858f74d0..f0a1456a597e 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
@@ -61,16 +61,21 @@ | |||
61 | */ | 61 | */ |
62 | #define HVC_ALLOC_TTY_ADAPTERS 8 | 62 | #define HVC_ALLOC_TTY_ADAPTERS 8 |
63 | 63 | ||
64 | static struct tty_driver *hvc_driver; | ||
65 | #ifdef CONFIG_MAGIC_SYSRQ | ||
66 | static int sysrq_pressed; | ||
67 | #endif | ||
68 | |||
69 | #define N_OUTBUF 16 | 64 | #define N_OUTBUF 16 |
70 | #define N_INBUF 16 | 65 | #define N_INBUF 16 |
71 | 66 | ||
72 | #define __ALIGNED__ __attribute__((__aligned__(8))) | 67 | #define __ALIGNED__ __attribute__((__aligned__(8))) |
73 | 68 | ||
69 | static struct tty_driver *hvc_driver; | ||
70 | static struct task_struct *hvc_task; | ||
71 | |||
72 | /* Picks up late kicks after list walk but before schedule() */ | ||
73 | static int hvc_kicked; | ||
74 | |||
75 | #ifdef CONFIG_MAGIC_SYSRQ | ||
76 | static int sysrq_pressed; | ||
77 | #endif | ||
78 | |||
74 | struct hvc_struct { | 79 | struct hvc_struct { |
75 | spinlock_t lock; | 80 | spinlock_t lock; |
76 | int index; | 81 | int index; |
@@ -97,6 +102,41 @@ static struct list_head hvc_structs = LIST_HEAD_INIT(hvc_structs); | |||
97 | static DEFINE_SPINLOCK(hvc_structs_lock); | 102 | static DEFINE_SPINLOCK(hvc_structs_lock); |
98 | 103 | ||
99 | /* | 104 | /* |
105 | * This value is used to associate a tty->index value to a hvc_struct based | ||
106 | * upon order of exposure via hvc_probe(). | ||
107 | */ | ||
108 | static int hvc_count = -1; | ||
109 | |||
110 | /* | ||
111 | * Do not call this function with either the hvc_strucst_lock or the hvc_struct | ||
112 | * lock held. If successful, this function increments the kobject reference | ||
113 | * count against the target hvc_struct so it should be released when finished. | ||
114 | */ | ||
115 | struct hvc_struct *hvc_get_by_index(int index) | ||
116 | { | ||
117 | struct hvc_struct *hp; | ||
118 | unsigned long flags; | ||
119 | |||
120 | spin_lock(&hvc_structs_lock); | ||
121 | |||
122 | list_for_each_entry(hp, &hvc_structs, next) { | ||
123 | spin_lock_irqsave(&hp->lock, flags); | ||
124 | if (hp->index == index) { | ||
125 | kobject_get(&hp->kobj); | ||
126 | spin_unlock_irqrestore(&hp->lock, flags); | ||
127 | spin_unlock(&hvc_structs_lock); | ||
128 | return hp; | ||
129 | } | ||
130 | spin_unlock_irqrestore(&hp->lock, flags); | ||
131 | } | ||
132 | hp = NULL; | ||
133 | |||
134 | spin_unlock(&hvc_structs_lock); | ||
135 | return hp; | ||
136 | } | ||
137 | |||
138 | |||
139 | /* | ||
100 | * Initial console vtermnos for console API usage prior to full console | 140 | * Initial console vtermnos for console API usage prior to full console |
101 | * initialization. Any vty adapter outside this range will not have usable | 141 | * initialization. Any vty adapter outside this range will not have usable |
102 | * console interfaces but can still be used as a tty device. This has to be | 142 | * console interfaces but can still be used as a tty device. This has to be |
@@ -107,16 +147,98 @@ static uint32_t vtermnos[MAX_NR_HVC_CONSOLES]; | |||
107 | /* Used for accounting purposes */ | 147 | /* Used for accounting purposes */ |
108 | static int num_vterms = 0; | 148 | static int num_vterms = 0; |
109 | 149 | ||
110 | static struct task_struct *hvc_task; | 150 | /* |
151 | * Console APIs, NOT TTY. These APIs are available immediately when | ||
152 | * hvc_console_setup() finds adapters. | ||
153 | */ | ||
154 | |||
155 | void hvc_console_print(struct console *co, const char *b, unsigned count) | ||
156 | { | ||
157 | char c[16] __ALIGNED__; | ||
158 | unsigned i = 0, n = 0; | ||
159 | int r, donecr = 0; | ||
160 | |||
161 | /* Console access attempt outside of acceptable console range. */ | ||
162 | if (co->index >= MAX_NR_HVC_CONSOLES) | ||
163 | return; | ||
164 | |||
165 | /* This console adapter was removed so it is not useable. */ | ||
166 | if (vtermnos[co->index] < 0) | ||
167 | return; | ||
168 | |||
169 | while (count > 0 || i > 0) { | ||
170 | if (count > 0 && i < sizeof(c)) { | ||
171 | if (b[n] == '\n' && !donecr) { | ||
172 | c[i++] = '\r'; | ||
173 | donecr = 1; | ||
174 | } else { | ||
175 | c[i++] = b[n++]; | ||
176 | donecr = 0; | ||
177 | --count; | ||
178 | } | ||
179 | } else { | ||
180 | r = hvc_put_chars(vtermnos[co->index], c, i); | ||
181 | if (r < 0) { | ||
182 | /* throw away chars on error */ | ||
183 | i = 0; | ||
184 | } else if (r > 0) { | ||
185 | i -= r; | ||
186 | if (i > 0) | ||
187 | memmove(c, c+r, i); | ||
188 | } | ||
189 | } | ||
190 | } | ||
191 | } | ||
192 | |||
193 | static struct tty_driver *hvc_console_device(struct console *c, int *index) | ||
194 | { | ||
195 | *index = c->index; | ||
196 | return hvc_driver; | ||
197 | } | ||
198 | |||
199 | static int __init hvc_console_setup(struct console *co, char *options) | ||
200 | { | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | struct console hvc_con_driver = { | ||
205 | .name = "hvc", | ||
206 | .write = hvc_console_print, | ||
207 | .device = hvc_console_device, | ||
208 | .setup = hvc_console_setup, | ||
209 | .flags = CON_PRINTBUFFER, | ||
210 | .index = -1, | ||
211 | }; | ||
212 | |||
213 | /* Early console initialization. Preceeds driver initialization. */ | ||
214 | static int __init hvc_console_init(void) | ||
215 | { | ||
216 | int i; | ||
217 | |||
218 | for (i=0; i<MAX_NR_HVC_CONSOLES; i++) | ||
219 | vtermnos[i] = -1; | ||
220 | num_vterms = hvc_find_vtys(); | ||
221 | register_console(&hvc_con_driver); | ||
222 | return 0; | ||
223 | } | ||
224 | console_initcall(hvc_console_init); | ||
111 | 225 | ||
112 | /* | 226 | /* |
113 | * This value is used to associate a tty->index value to a hvc_struct based | 227 | * hvc_instantiate() is an early console discovery method which locates consoles |
114 | * upon order of exposure via hvc_probe(). | 228 | * prior to the vio subsystem discovering them. Hotplugged vty adapters do NOT |
229 | * get an hvc_instantiate() callback since the appear after early console init. | ||
115 | */ | 230 | */ |
116 | static int hvc_count = -1; | 231 | int hvc_instantiate(uint32_t vtermno, int index) |
232 | { | ||
233 | if (index < 0 || index >= MAX_NR_HVC_CONSOLES) | ||
234 | return -1; | ||
117 | 235 | ||
118 | /* Picks up late kicks after list walk but before schedule() */ | 236 | if (vtermnos[index] != -1) |
119 | static int hvc_kicked; | 237 | return -1; |
238 | |||
239 | vtermnos[index] = vtermno; | ||
240 | return 0; | ||
241 | } | ||
120 | 242 | ||
121 | /* Wake the sleeping khvcd */ | 243 | /* Wake the sleeping khvcd */ |
122 | static void hvc_kick(void) | 244 | static void hvc_kick(void) |
@@ -141,34 +263,6 @@ static void hvc_unthrottle(struct tty_struct *tty) | |||
141 | } | 263 | } |
142 | 264 | ||
143 | /* | 265 | /* |
144 | * Do not call this function with either the hvc_strucst_lock or the hvc_struct | ||
145 | * lock held. If successful, this function increments the kobject reference | ||
146 | * count against the target hvc_struct so it should be released when finished. | ||
147 | */ | ||
148 | struct hvc_struct *hvc_get_by_index(int index) | ||
149 | { | ||
150 | struct hvc_struct *hp; | ||
151 | unsigned long flags; | ||
152 | |||
153 | spin_lock(&hvc_structs_lock); | ||
154 | |||
155 | list_for_each_entry(hp, &hvc_structs, next) { | ||
156 | spin_lock_irqsave(&hp->lock, flags); | ||
157 | if (hp->index == index) { | ||
158 | kobject_get(&hp->kobj); | ||
159 | spin_unlock_irqrestore(&hp->lock, flags); | ||
160 | spin_unlock(&hvc_structs_lock); | ||
161 | return hp; | ||
162 | } | ||
163 | spin_unlock_irqrestore(&hp->lock, flags); | ||
164 | } | ||
165 | hp = NULL; | ||
166 | |||
167 | spin_unlock(&hvc_structs_lock); | ||
168 | return hp; | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * The TTY interface won't be used until after the vio layer has exposed the vty | 266 | * The TTY interface won't be used until after the vio layer has exposed the vty |
173 | * adapter to the kernel. | 267 | * adapter to the kernel. |
174 | */ | 268 | */ |
@@ -577,14 +671,6 @@ static struct tty_operations hvc_ops = { | |||
577 | .chars_in_buffer = hvc_chars_in_buffer, | 671 | .chars_in_buffer = hvc_chars_in_buffer, |
578 | }; | 672 | }; |
579 | 673 | ||
580 | char hvc_driver_name[] = "hvc_console"; | ||
581 | |||
582 | static struct vio_device_id hvc_driver_table[] __devinitdata= { | ||
583 | {"serial", "hvterm1"}, | ||
584 | { NULL, } | ||
585 | }; | ||
586 | MODULE_DEVICE_TABLE(vio, hvc_driver_table); | ||
587 | |||
588 | /* callback when the kboject ref count reaches zero. */ | 674 | /* callback when the kboject ref count reaches zero. */ |
589 | static void destroy_hvc_struct(struct kobject *kobj) | 675 | static void destroy_hvc_struct(struct kobject *kobj) |
590 | { | 676 | { |
@@ -674,6 +760,14 @@ static int __devexit hvc_remove(struct vio_dev *dev) | |||
674 | return 0; | 760 | return 0; |
675 | } | 761 | } |
676 | 762 | ||
763 | char hvc_driver_name[] = "hvc_console"; | ||
764 | |||
765 | static struct vio_device_id hvc_driver_table[] __devinitdata= { | ||
766 | {"serial", "hvterm1"}, | ||
767 | { NULL, } | ||
768 | }; | ||
769 | MODULE_DEVICE_TABLE(vio, hvc_driver_table); | ||
770 | |||
677 | static struct vio_driver hvc_vio_driver = { | 771 | static struct vio_driver hvc_vio_driver = { |
678 | .name = hvc_driver_name, | 772 | .name = hvc_driver_name, |
679 | .id_table = hvc_driver_table, | 773 | .id_table = hvc_driver_table, |
@@ -721,6 +815,7 @@ int __init hvc_init(void) | |||
721 | 815 | ||
722 | return rc; | 816 | return rc; |
723 | } | 817 | } |
818 | module_init(hvc_init); | ||
724 | 819 | ||
725 | /* This isn't particularily necessary due to this being a console driver but it | 820 | /* This isn't particularily necessary due to this being a console driver but it |
726 | * is nice to be thorough */ | 821 | * is nice to be thorough */ |
@@ -733,99 +828,4 @@ static void __exit hvc_exit(void) | |||
733 | /* return tty_struct instances allocated in hvc_init(). */ | 828 | /* return tty_struct instances allocated in hvc_init(). */ |
734 | put_tty_driver(hvc_driver); | 829 | put_tty_driver(hvc_driver); |
735 | } | 830 | } |
736 | |||
737 | /* | ||
738 | * Console APIs, NOT TTY. These APIs are available immediately when | ||
739 | * hvc_console_setup() finds adapters. | ||
740 | */ | ||
741 | |||
742 | /* | ||
743 | * hvc_instantiate() is an early console discovery method which locates consoles | ||
744 | * prior to the vio subsystem discovering them. Hotplugged vty adapters do NOT | ||
745 | * get an hvc_instantiate() callback since the appear after early console init. | ||
746 | */ | ||
747 | int hvc_instantiate(uint32_t vtermno, int index) | ||
748 | { | ||
749 | if (index < 0 || index >= MAX_NR_HVC_CONSOLES) | ||
750 | return -1; | ||
751 | |||
752 | if (vtermnos[index] != -1) | ||
753 | return -1; | ||
754 | |||
755 | vtermnos[index] = vtermno; | ||
756 | return 0; | ||
757 | } | ||
758 | |||
759 | void hvc_console_print(struct console *co, const char *b, unsigned count) | ||
760 | { | ||
761 | char c[16] __ALIGNED__; | ||
762 | unsigned i = 0, n = 0; | ||
763 | int r, donecr = 0; | ||
764 | |||
765 | /* Console access attempt outside of acceptable console range. */ | ||
766 | if (co->index >= MAX_NR_HVC_CONSOLES) | ||
767 | return; | ||
768 | |||
769 | /* This console adapter was removed so it is not useable. */ | ||
770 | if (vtermnos[co->index] < 0) | ||
771 | return; | ||
772 | |||
773 | while (count > 0 || i > 0) { | ||
774 | if (count > 0 && i < sizeof(c)) { | ||
775 | if (b[n] == '\n' && !donecr) { | ||
776 | c[i++] = '\r'; | ||
777 | donecr = 1; | ||
778 | } else { | ||
779 | c[i++] = b[n++]; | ||
780 | donecr = 0; | ||
781 | --count; | ||
782 | } | ||
783 | } else { | ||
784 | r = hvc_put_chars(vtermnos[co->index], c, i); | ||
785 | if (r < 0) { | ||
786 | /* throw away chars on error */ | ||
787 | i = 0; | ||
788 | } else if (r > 0) { | ||
789 | i -= r; | ||
790 | if (i > 0) | ||
791 | memmove(c, c+r, i); | ||
792 | } | ||
793 | } | ||
794 | } | ||
795 | } | ||
796 | |||
797 | static struct tty_driver *hvc_console_device(struct console *c, int *index) | ||
798 | { | ||
799 | *index = c->index; | ||
800 | return hvc_driver; | ||
801 | } | ||
802 | |||
803 | static int __init hvc_console_setup(struct console *co, char *options) | ||
804 | { | ||
805 | return 0; | ||
806 | } | ||
807 | |||
808 | struct console hvc_con_driver = { | ||
809 | .name = "hvc", | ||
810 | .write = hvc_console_print, | ||
811 | .device = hvc_console_device, | ||
812 | .setup = hvc_console_setup, | ||
813 | .flags = CON_PRINTBUFFER, | ||
814 | .index = -1, | ||
815 | }; | ||
816 | |||
817 | /* Early console initialization. Preceeds driver initialization. */ | ||
818 | static int __init hvc_console_init(void) | ||
819 | { | ||
820 | int i; | ||
821 | |||
822 | for (i=0; i<MAX_NR_HVC_CONSOLES; i++) | ||
823 | vtermnos[i] = -1; | ||
824 | num_vterms = hvc_find_vtys(); | ||
825 | register_console(&hvc_con_driver); | ||
826 | return 0; | ||
827 | } | ||
828 | console_initcall(hvc_console_init); | ||
829 | |||
830 | module_init(hvc_init); | ||
831 | module_exit(hvc_exit); | 831 | module_exit(hvc_exit); |