aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/hvc_lguest.c102
2 files changed, 103 insertions, 0 deletions
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 8852b8d643cf..4e6f387fd189 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o
42obj-$(CONFIG_N_HDLC) += n_hdlc.o 42obj-$(CONFIG_N_HDLC) += n_hdlc.o
43obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o 43obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
44obj-$(CONFIG_SX) += sx.o generic_serial.o 44obj-$(CONFIG_SX) += sx.o generic_serial.o
45obj-$(CONFIG_LGUEST_GUEST) += hvc_lguest.o
45obj-$(CONFIG_RIO) += rio/ generic_serial.o 46obj-$(CONFIG_RIO) += rio/ generic_serial.o
46obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o 47obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o
47obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o 48obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o
diff --git a/drivers/char/hvc_lguest.c b/drivers/char/hvc_lguest.c
new file mode 100644
index 000000000000..e7b889e404a7
--- /dev/null
+++ b/drivers/char/hvc_lguest.c
@@ -0,0 +1,102 @@
1/* Simple console for lguest.
2 *
3 * Copyright (C) 2006 Rusty Russell, IBM Corporation
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <linux/err.h>
20#include <linux/init.h>
21#include <linux/lguest_bus.h>
22#include "hvc_console.h"
23
24static char inbuf[256];
25static struct lguest_dma cons_input = { .used_len = 0,
26 .addr[0] = __pa(inbuf),
27 .len[0] = sizeof(inbuf),
28 .len[1] = 0 };
29
30static int put_chars(u32 vtermno, const char *buf, int count)
31{
32 struct lguest_dma dma;
33
34 /* FIXME: what if it's over a page boundary? */
35 dma.len[0] = count;
36 dma.len[1] = 0;
37 dma.addr[0] = __pa(buf);
38
39 lguest_send_dma(LGUEST_CONSOLE_DMA_KEY, &dma);
40 return count;
41}
42
43static int get_chars(u32 vtermno, char *buf, int count)
44{
45 static int cons_offset;
46
47 if (!cons_input.used_len)
48 return 0;
49
50 if (cons_input.used_len - cons_offset < count)
51 count = cons_input.used_len - cons_offset;
52
53 memcpy(buf, inbuf + cons_offset, count);
54 cons_offset += count;
55 if (cons_offset == cons_input.used_len) {
56 cons_offset = 0;
57 cons_input.used_len = 0;
58 }
59 return count;
60}
61
62static struct hv_ops lguest_cons = {
63 .get_chars = get_chars,
64 .put_chars = put_chars,
65};
66
67static int __init cons_init(void)
68{
69 if (strcmp(paravirt_ops.name, "lguest") != 0)
70 return 0;
71
72 return hvc_instantiate(0, 0, &lguest_cons);
73}
74console_initcall(cons_init);
75
76static int lguestcons_probe(struct lguest_device *lgdev)
77{
78 int err;
79
80 lgdev->private = hvc_alloc(0, lgdev_irq(lgdev), &lguest_cons, 256);
81 if (IS_ERR(lgdev->private))
82 return PTR_ERR(lgdev->private);
83
84 err = lguest_bind_dma(LGUEST_CONSOLE_DMA_KEY, &cons_input, 1,
85 lgdev_irq(lgdev));
86 if (err)
87 printk("lguest console: failed to bind buffer.\n");
88 return err;
89}
90
91static struct lguest_driver lguestcons_drv = {
92 .name = "lguestcons",
93 .owner = THIS_MODULE,
94 .device_type = LGUEST_DEVICE_T_CONSOLE,
95 .probe = lguestcons_probe,
96};
97
98static int __init hvc_lguest_init(void)
99{
100 return register_lguest_driver(&lguestcons_drv);
101}
102module_init(hvc_lguest_init);