2 * arch/v850/kernel/simcons.c -- Console I/O for GDB v850e simulator
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
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.
11 * Written by Miles Bader <miles@gnu.org>
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>
22 #include <asm/string.h>
23 #include <asm/simsyscall.h>
26 /* Low-level console. */
28 static void simcons_write (struct console
*co
, const char *buf
, unsigned len
)
30 V850_SIM_SYSCALL (write
, 1, buf
, len
);
33 static int simcons_read (struct console
*co
, char *buf
, unsigned len
)
35 return V850_SIM_SYSCALL (read
, 0, buf
, len
);
38 static struct tty_driver
*tty_driver
;
39 static struct tty_driver
*simcons_device (struct console
*c
, int *index
)
45 static struct console simcons
=
48 .write
= simcons_write
,
50 .device
= simcons_device
,
51 .flags
= CON_PRINTBUFFER
,
55 /* Higher level TTY interface. */
57 int simcons_tty_open (struct tty_struct
*tty
, struct file
*filp
)
62 int simcons_tty_write (struct tty_struct
*tty
,
63 const unsigned char *buf
, int count
)
65 return V850_SIM_SYSCALL (write
, 1, buf
, count
);
68 int simcons_tty_write_room (struct tty_struct
*tty
)
70 /* Completely arbitrary. */
74 int simcons_tty_chars_in_buffer (struct tty_struct
*tty
)
76 /* We have no buffer. */
80 static const 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
,
87 int __init
simcons_tty_init (void)
89 struct tty_driver
*driver
= alloc_tty_driver(1);
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
);
101 put_tty_driver(driver
);
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. */
114 late_initcall(simcons_tty_init
);
116 /* Poll for input on the console, and if there's any, deliver it to the
118 void simcons_poll_tty (struct tty_struct
*tty
)
120 char buf
[32]; /* Not the nicest way to do it but I need it correct first */
121 int flip
= 0, send_break
= 0;
126 if (V850_SIM_SYSCALL (poll
, &pfd
, 1, 0) > 0) {
127 if (pfd
.revents
& POLLIN
) {
128 /* Real block hardware knows the transfer size before
129 transfer so the new tty buffering doesn't try to handle
130 this rather weird simulator specific case well */
131 int rd
= V850_SIM_SYSCALL (read
, 0, buf
, 32);
133 tty_insert_flip_string(tty
, buf
, rd
);
137 } else if (pfd
.revents
& POLLERR
)
142 tty_insert_flip_char (tty
, 0, TTY_BREAK
);
147 tty_schedule_flip (tty
);
150 void simcons_poll_ttys (void)
152 if (tty_driver
&& tty_driver
->ttys
[0])
153 simcons_poll_tty (tty_driver
->ttys
[0]);
156 void simcons_setup (void)
158 V850_SIM_SYSCALL (make_raw
, 0);
159 register_console (&simcons
);
160 printk (KERN_INFO
"Console: GDB V850E simulator stdio\n");