diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2007-07-19 04:49:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-19 13:04:52 -0400 |
commit | 3f8c4d3f82c564e5e27c6375fe17544f694359dc (patch) | |
tree | c3c28fcea5bfcb1b6c8456ae9d27eb9611a7d33c /drivers | |
parent | 709e89266b60eff444fc512400321eb02d2474eb (diff) |
lguest: the console driver
A simple console driver for lguest.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/Makefile | 1 | ||||
-rw-r--r-- | drivers/char/hvc_lguest.c | 102 |
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 | |||
42 | obj-$(CONFIG_N_HDLC) += n_hdlc.o | 42 | obj-$(CONFIG_N_HDLC) += n_hdlc.o |
43 | obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o | 43 | obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o |
44 | obj-$(CONFIG_SX) += sx.o generic_serial.o | 44 | obj-$(CONFIG_SX) += sx.o generic_serial.o |
45 | obj-$(CONFIG_LGUEST_GUEST) += hvc_lguest.o | ||
45 | obj-$(CONFIG_RIO) += rio/ generic_serial.o | 46 | obj-$(CONFIG_RIO) += rio/ generic_serial.o |
46 | obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o | 47 | obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o |
47 | obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o | 48 | obj-$(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 | |||
24 | static char inbuf[256]; | ||
25 | static struct lguest_dma cons_input = { .used_len = 0, | ||
26 | .addr[0] = __pa(inbuf), | ||
27 | .len[0] = sizeof(inbuf), | ||
28 | .len[1] = 0 }; | ||
29 | |||
30 | static 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 | |||
43 | static 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 | |||
62 | static struct hv_ops lguest_cons = { | ||
63 | .get_chars = get_chars, | ||
64 | .put_chars = put_chars, | ||
65 | }; | ||
66 | |||
67 | static 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 | } | ||
74 | console_initcall(cons_init); | ||
75 | |||
76 | static 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 | |||
91 | static 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 | |||
98 | static int __init hvc_lguest_init(void) | ||
99 | { | ||
100 | return register_lguest_driver(&lguestcons_drv); | ||
101 | } | ||
102 | module_init(hvc_lguest_init); | ||