aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc/kernel
diff options
context:
space:
mode:
authorGuy Martin <gmsoft@tuxicoman.be>2010-06-14 13:24:41 -0400
committerKyle McMartin <kyle@mcmartin.ca>2010-10-21 21:27:18 -0400
commit650a35f868f809aade56ef960d8a465f57ac74e2 (patch)
tree7e7156d125f7344635eb11d19bad325517fc0a99 /arch/parisc/kernel
parentf8301041d7bdca3197d718518242eeba0c75352f (diff)
parisc: add tty driver to PDC console
This patch adds a tty driver to the PDC console. It allows the use of ports not supported by linux as a console (e.g. serial port on C8000.) The tty driver will not register the ttyB device if PDC console driver has been unregistered. This happens when the early printk console is disabled as it has not been selected as the primary console. Signed-off-by: Guy Martin <gmsoft@tuxicoman.be> Signed-off-by: Kyle McMartin <kyle@redhat.com>
Diffstat (limited to 'arch/parisc/kernel')
-rw-r--r--arch/parisc/kernel/pdc_cons.c141
1 files changed, 134 insertions, 7 deletions
diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c
index 1ff366cb9685..66d1f17fdb94 100644
--- a/arch/parisc/kernel/pdc_cons.c
+++ b/arch/parisc/kernel/pdc_cons.c
@@ -12,6 +12,7 @@
12 * Copyright (C) 2001 Helge Deller <deller at parisc-linux.org> 12 * Copyright (C) 2001 Helge Deller <deller at parisc-linux.org>
13 * Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org> 13 * Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
14 * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org> 14 * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
15 * Copyright (C) 2010 Guy Martin <gmsoft at tuxicoman.be>
15 * 16 *
16 * 17 *
17 * This program is free software; you can redistribute it and/or modify 18 * This program is free software; you can redistribute it and/or modify
@@ -31,12 +32,11 @@
31 32
32/* 33/*
33 * The PDC console is a simple console, which can be used for debugging 34 * The PDC console is a simple console, which can be used for debugging
34 * boot related problems on HP PA-RISC machines. 35 * boot related problems on HP PA-RISC machines. It is also useful when no
36 * other console works.
35 * 37 *
36 * This code uses the ROM (=PDC) based functions to read and write characters 38 * This code uses the ROM (=PDC) based functions to read and write characters
37 * from and to PDC's boot path. 39 * from and to PDC's boot path.
38 * Since all character read from that path must be polled, this code never
39 * can or will be a fully functional linux console.
40 */ 40 */
41 41
42/* Define EARLY_BOOTUP_DEBUG to debug kernel related boot problems. 42/* Define EARLY_BOOTUP_DEBUG to debug kernel related boot problems.
@@ -53,6 +53,7 @@
53#include <asm/pdc.h> /* for iodc_call() proto and friends */ 53#include <asm/pdc.h> /* for iodc_call() proto and friends */
54 54
55static DEFINE_SPINLOCK(pdc_console_lock); 55static DEFINE_SPINLOCK(pdc_console_lock);
56static struct console pdc_cons;
56 57
57static void pdc_console_write(struct console *co, const char *s, unsigned count) 58static void pdc_console_write(struct console *co, const char *s, unsigned count)
58{ 59{
@@ -85,12 +86,138 @@ static int pdc_console_setup(struct console *co, char *options)
85 86
86#if defined(CONFIG_PDC_CONSOLE) 87#if defined(CONFIG_PDC_CONSOLE)
87#include <linux/vt_kern.h> 88#include <linux/vt_kern.h>
89#include <linux/tty_flip.h>
90
91#define PDC_CONS_POLL_DELAY (30 * HZ / 1000)
92
93static struct timer_list pdc_console_timer;
94
95extern struct console * console_drivers;
96
97static int pdc_console_tty_open(struct tty_struct *tty, struct file *filp)
98{
99
100 mod_timer(&pdc_console_timer, jiffies + PDC_CONS_POLL_DELAY);
101
102 return 0;
103}
104
105static void pdc_console_tty_close(struct tty_struct *tty, struct file *filp)
106{
107 if (!tty->count)
108 del_timer(&pdc_console_timer);
109}
110
111static int pdc_console_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
112{
113 pdc_console_write(NULL, buf, count);
114 return count;
115}
116
117static int pdc_console_tty_write_room(struct tty_struct *tty)
118{
119 return 32768; /* no limit, no buffer used */
120}
121
122static int pdc_console_tty_chars_in_buffer(struct tty_struct *tty)
123{
124 return 0; /* no buffer */
125}
126
127static struct tty_driver *pdc_console_tty_driver;
128
129static const struct tty_operations pdc_console_tty_ops = {
130 .open = pdc_console_tty_open,
131 .close = pdc_console_tty_close,
132 .write = pdc_console_tty_write,
133 .write_room = pdc_console_tty_write_room,
134 .chars_in_buffer = pdc_console_tty_chars_in_buffer,
135};
136
137static void pdc_console_poll(unsigned long unused)
138{
139
140 int data, count = 0;
141
142 struct tty_struct *tty = pdc_console_tty_driver->ttys[0];
143
144 if (!tty)
145 return;
146
147 while (1) {
148 data = pdc_console_poll_key(NULL);
149 if (data == -1)
150 break;
151 tty_insert_flip_char(tty, data & 0xFF, TTY_NORMAL);
152 count ++;
153 }
154
155 if (count)
156 tty_flip_buffer_push(tty);
157
158 if (tty->count && (pdc_cons.flags & CON_ENABLED))
159 mod_timer(&pdc_console_timer, jiffies + PDC_CONS_POLL_DELAY);
160}
161
162static int __init pdc_console_tty_driver_init(void)
163{
164
165 int err;
166 struct tty_driver *drv;
167
168 /* Check if the console driver is still registered.
169 * It is unregistered if the pdc console was not selected as the
170 * primary console. */
171
172 struct console *tmp = console_drivers;
173
174 for (tmp = console_drivers; tmp; tmp = tmp->next)
175 if (tmp == &pdc_cons)
176 break;
177
178 if (!tmp) {
179 printk(KERN_INFO "PDC console driver not registered anymore, not creating %s\n", pdc_cons.name);
180 return -ENODEV;
181 }
182
183 printk(KERN_INFO "The PDC console driver is still registered, removing CON_BOOT flag\n");
184 pdc_cons.flags &= ~CON_BOOT;
185
186 drv = alloc_tty_driver(1);
187
188 if (!drv)
189 return -ENOMEM;
190
191 drv->driver_name = "pdc_cons";
192 drv->name = "ttyB";
193 drv->major = MUX_MAJOR;
194 drv->minor_start = 0;
195 drv->type = TTY_DRIVER_TYPE_SYSTEM;
196 drv->init_termios = tty_std_termios;
197 drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
198 tty_set_operations(drv, &pdc_console_tty_ops);
199
200 err = tty_register_driver(drv);
201 if (err) {
202 printk(KERN_ERR "Unable to register the PDC console TTY driver\n");
203 return err;
204 }
205
206 pdc_console_tty_driver = drv;
207
208 /* No need to initialize the pdc_console_timer if tty isn't allocated */
209 init_timer(&pdc_console_timer);
210 pdc_console_timer.function = pdc_console_poll;
211
212 return 0;
213}
214
215module_init(pdc_console_tty_driver_init);
88 216
89static struct tty_driver * pdc_console_device (struct console *c, int *index) 217static struct tty_driver * pdc_console_device (struct console *c, int *index)
90{ 218{
91 extern struct tty_driver console_driver; 219 *index = c->index;
92 *index = c->index ? c->index-1 : fg_console; 220 return pdc_console_tty_driver;
93 return &console_driver;
94} 221}
95#else 222#else
96#define pdc_console_device NULL 223#define pdc_console_device NULL
@@ -101,7 +228,7 @@ static struct console pdc_cons = {
101 .write = pdc_console_write, 228 .write = pdc_console_write,
102 .device = pdc_console_device, 229 .device = pdc_console_device,
103 .setup = pdc_console_setup, 230 .setup = pdc_console_setup,
104 .flags = CON_BOOT | CON_PRINTBUFFER | CON_ENABLED, 231 .flags = CON_BOOT | CON_PRINTBUFFER,
105 .index = -1, 232 .index = -1,
106}; 233};
107 234