aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/hvc_console.c284
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
64static struct tty_driver *hvc_driver;
65#ifdef CONFIG_MAGIC_SYSRQ
66static 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
69static struct tty_driver *hvc_driver;
70static struct task_struct *hvc_task;
71
72/* Picks up late kicks after list walk but before schedule() */
73static int hvc_kicked;
74
75#ifdef CONFIG_MAGIC_SYSRQ
76static int sysrq_pressed;
77#endif
78
74struct hvc_struct { 79struct 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);
97static DEFINE_SPINLOCK(hvc_structs_lock); 102static 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 */
108static 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 */
115struct 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 */
108static int num_vterms = 0; 148static int num_vterms = 0;
109 149
110static 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
155void 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
193static struct tty_driver *hvc_console_device(struct console *c, int *index)
194{
195 *index = c->index;
196 return hvc_driver;
197}
198
199static int __init hvc_console_setup(struct console *co, char *options)
200{
201 return 0;
202}
203
204struct 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. */
214static 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}
224console_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 */
116static int hvc_count = -1; 231int 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)
119static 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 */
122static void hvc_kick(void) 244static 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 */
148struct 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
580char hvc_driver_name[] = "hvc_console";
581
582static struct vio_device_id hvc_driver_table[] __devinitdata= {
583 {"serial", "hvterm1"},
584 { NULL, }
585};
586MODULE_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. */
589static void destroy_hvc_struct(struct kobject *kobj) 675static 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
763char hvc_driver_name[] = "hvc_console";
764
765static struct vio_device_id hvc_driver_table[] __devinitdata= {
766 {"serial", "hvterm1"},
767 { NULL, }
768};
769MODULE_DEVICE_TABLE(vio, hvc_driver_table);
770
677static struct vio_driver hvc_vio_driver = { 771static 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}
818module_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 */
747int 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
759void 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
797static struct tty_driver *hvc_console_device(struct console *c, int *index)
798{
799 *index = c->index;
800 return hvc_driver;
801}
802
803static int __init hvc_console_setup(struct console *co, char *options)
804{
805 return 0;
806}
807
808struct 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. */
818static 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}
828console_initcall(hvc_console_init);
829
830module_init(hvc_init);
831module_exit(hvc_exit); 831module_exit(hvc_exit);