aboutsummaryrefslogtreecommitdiffstats
path: root/arch/v850/kernel/simcons.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/v850/kernel/simcons.c')
-rw-r--r--arch/v850/kernel/simcons.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/arch/v850/kernel/simcons.c b/arch/v850/kernel/simcons.c
new file mode 100644
index 000000000000..7f0efaa025c9
--- /dev/null
+++ b/arch/v850/kernel/simcons.c
@@ -0,0 +1,166 @@
1/*
2 * arch/v850/kernel/simcons.c -- Console I/O for GDB v850e simulator
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/kernel.h>
15#include <linux/console.h>
16#include <linux/tty.h>
17#include <linux/tty_flip.h>
18#include <linux/tty_driver.h>
19#include <linux/init.h>
20
21#include <asm/poll.h>
22#include <asm/string.h>
23#include <asm/simsyscall.h>
24
25
26/* Low-level console. */
27
28static void simcons_write (struct console *co, const char *buf, unsigned len)
29{
30 V850_SIM_SYSCALL (write, 1, buf, len);
31}
32
33static int simcons_read (struct console *co, char *buf, unsigned len)
34{
35 return V850_SIM_SYSCALL (read, 0, buf, len);
36}
37
38static struct tty_driver *tty_driver;
39static struct tty_driver *simcons_device (struct console *c, int *index)
40{
41 *index = c->index;
42 return tty_driver;
43}
44
45static struct console simcons =
46{
47 .name = "simcons",
48 .write = simcons_write,
49 .read = simcons_read,
50 .device = simcons_device,
51 .flags = CON_PRINTBUFFER,
52 .index = -1,
53};
54
55/* Higher level TTY interface. */
56
57int simcons_tty_open (struct tty_struct *tty, struct file *filp)
58{
59 return 0;
60}
61
62int simcons_tty_write (struct tty_struct *tty,
63 const unsigned char *buf, int count)
64{
65 return V850_SIM_SYSCALL (write, 1, buf, count);
66}
67
68int simcons_tty_write_room (struct tty_struct *tty)
69{
70 /* Completely arbitrary. */
71 return 0x100000;
72}
73
74int simcons_tty_chars_in_buffer (struct tty_struct *tty)
75{
76 /* We have no buffer. */
77 return 0;
78}
79
80static struct tty_operations ops = {
81 .open = simcons_tty_open,
82 .write = simcons_tty_write,
83 .write_room = simcons_tty_write_room,
84 .chars_in_buffer = simcons_tty_chars_in_buffer,
85};
86
87int __init simcons_tty_init (void)
88{
89 struct tty_driver *driver = alloc_tty_driver(1);
90 int err;
91 if (!driver)
92 return -ENOMEM;
93 driver->name = "simcons";
94 driver->major = TTY_MAJOR;
95 driver->minor_start = 64;
96 driver->type = TTY_DRIVER_TYPE_SYSCONS;
97 driver->init_termios = tty_std_termios;
98 tty_set_operations(driver, &ops);
99 err = tty_register_driver(driver);
100 if (err) {
101 put_tty_driver(driver);
102 return err;
103 }
104 tty_driver = driver;
105 return 0;
106}
107/* We use `late_initcall' instead of just `__initcall' as a workaround for
108 the fact that (1) simcons_tty_init can't be called before tty_init,
109 (2) tty_init is called via `module_init', (3) if statically linked,
110 module_init == device_init, and (4) there's no ordering of init lists.
111 We can do this easily because simcons is always statically linked, but
112 other tty drivers that depend on tty_init and which must use
113 `module_init' to declare their init routines are likely to be broken. */
114late_initcall(simcons_tty_init);
115
116/* Poll for input on the console, and if there's any, deliver it to the
117 tty driver. */
118void simcons_poll_tty (struct tty_struct *tty)
119{
120 int flip = 0, send_break = 0;
121 struct pollfd pfd;
122 pfd.fd = 0;
123 pfd.events = POLLIN;
124
125 if (V850_SIM_SYSCALL (poll, &pfd, 1, 0) > 0) {
126 if (pfd.revents & POLLIN) {
127 int left = TTY_FLIPBUF_SIZE - tty->flip.count;
128
129 if (left > 0) {
130 unsigned char *buf = tty->flip.char_buf_ptr;
131 int rd = V850_SIM_SYSCALL (read, 0, buf, left);
132
133 if (rd > 0) {
134 tty->flip.count += rd;
135 tty->flip.char_buf_ptr += rd;
136 memset (tty->flip.flag_buf_ptr, 0, rd);
137 tty->flip.flag_buf_ptr += rd;
138 flip = 1;
139 } else
140 send_break = 1;
141 }
142 } else if (pfd.revents & POLLERR)
143 send_break = 1;
144 }
145
146 if (send_break) {
147 tty_insert_flip_char (tty, 0, TTY_BREAK);
148 flip = 1;
149 }
150
151 if (flip)
152 tty_schedule_flip (tty);
153}
154
155void simcons_poll_ttys (void)
156{
157 if (tty_driver && tty_driver->ttys[0])
158 simcons_poll_tty (tty_driver->ttys[0]);
159}
160
161void simcons_setup (void)
162{
163 V850_SIM_SYSCALL (make_raw, 0);
164 register_console (&simcons);
165 printk (KERN_INFO "Console: GDB V850E simulator stdio\n");
166}