diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-29 11:28:30 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-29 11:28:30 -0800 |
commit | 76babde121d2ffef04ca692ce64ef9f8a9866086 (patch) | |
tree | 294923bbb4974258d86d223e35eee691abacdfb1 /drivers/char/hvc_rtas.c | |
parent | e71ac6032edf77a1e4a81f3e3b260807e94b37a5 (diff) | |
parent | 15e812ad849e142e3dfc984d33c4d8042389f148 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (67 commits)
[PATCH] powerpc: Remove oprofile spinlock backtrace code
[PATCH] powerpc: Add oprofile calltrace support to all powerpc cpus
[PATCH] powerpc: Add oprofile calltrace support
[PATCH] for_each_possible_cpu: ppc
[PATCH] for_each_possible_cpu: powerpc
[PATCH] lock PTE before updating it in 440/BookE page fault handler
[PATCH] powerpc: Kill _machine and hard-coded platform numbers
ppc: Fix compile error in arch/ppc/lib/strcase.c
[PATCH] git-powerpc: WARN was a dumb idea
[PATCH] powerpc: a couple of trivial compile warning fixes
powerpc: remove OCP references
powerpc: Make uImage default build output for MPC8540 ADS
powerpc: move math-emu over to arch/powerpc
powerpc: use memparse() for mem= command line parsing
ppc: fix strncasecmp prototype
[PATCH] powerpc: make ISA floppies work again
[PATCH] powerpc: Fix some initcall return values
[PATCH] powerpc: Workaround for pSeries RTAS bug
[PATCH] spufs: fix __init/__exit annotations
[PATCH] powerpc: add hvc backend for rtas
...
Diffstat (limited to 'drivers/char/hvc_rtas.c')
-rw-r--r-- | drivers/char/hvc_rtas.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/drivers/char/hvc_rtas.c b/drivers/char/hvc_rtas.c new file mode 100644 index 000000000000..83364ea63cba --- /dev/null +++ b/drivers/char/hvc_rtas.c @@ -0,0 +1,138 @@ +/* + * IBM RTAS driver interface to hvc_console.c + * + * (C) Copyright IBM Corporation 2001-2005 + * (C) Copyright Red Hat, Inc. 2005 + * + * Author(s): Maximino Augilar <IBM STI Design Center> + * : Ryan S. Arnold <rsa@us.ibm.com> + * : Utz Bacher <utz.bacher@de.ibm.com> + * : David Woodhouse <dwmw2@infradead.org> + * + * inspired by drivers/char/hvc_console.c + * written by Anton Blanchard and Paul Mackerras + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/console.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/moduleparam.h> +#include <linux/types.h> + +#include <asm/irq.h> +#include <asm/rtas.h> +#include "hvc_console.h" + +#define hvc_rtas_cookie 0x67781e15 +struct hvc_struct *hvc_rtas_dev; + +#define RTASCONS_PUT_ATTEMPTS 16 + +static int rtascons_put_char_token = RTAS_UNKNOWN_SERVICE; +static int rtascons_get_char_token = RTAS_UNKNOWN_SERVICE; +static int rtascons_put_delay = 100; +module_param_named(put_delay, rtascons_put_delay, int, 0644); + +static inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf, int count) +{ + int done; + + /* if there is more than one character to be displayed, wait a bit */ + for (done = 0; done < count; done++) { + int result; + result = rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[done]); + if (result) + break; + } + /* the calling routine expects to receive the number of bytes sent */ + return done; +} + +static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count) +{ + int i; + + for (i = 0; i < count; i++) { + int c, err; + + err = rtas_call(rtascons_get_char_token, 0, 2, &c); + if (err) + break; + + buf[i] = c; + } + + return i; +} + +static struct hv_ops hvc_rtas_get_put_ops = { + .get_chars = hvc_rtas_read_console, + .put_chars = hvc_rtas_write_console, +}; + +static int hvc_rtas_init(void) +{ + struct hvc_struct *hp; + + if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) + rtascons_put_char_token = rtas_token("put-term-char"); + if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) + return -EIO; + + if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE) + rtascons_get_char_token = rtas_token("get-term-char"); + if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE) + return -EIO; + + BUG_ON(hvc_rtas_dev); + + /* Allocate an hvc_struct for the console device we instantiated + * earlier. Save off hp so that we can return it on exit */ + hp = hvc_alloc(hvc_rtas_cookie, NO_IRQ, &hvc_rtas_get_put_ops); + if (IS_ERR(hp)) + return PTR_ERR(hp); + hvc_rtas_dev = hp; + return 0; +} +module_init(hvc_rtas_init); + +/* This will tear down the tty portion of the driver */ +static void __exit hvc_rtas_exit(void) +{ + /* Really the fun isn't over until the worker thread breaks down and the + * tty cleans up */ + if (hvc_rtas_dev) + hvc_remove(hvc_rtas_dev); +} +module_exit(hvc_rtas_exit); + +/* This will happen prior to module init. There is no tty at this time? */ +static int hvc_rtas_console_init(void) +{ + rtascons_put_char_token = rtas_token("put-term-char"); + if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) + return -EIO; + rtascons_get_char_token = rtas_token("get-term-char"); + if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE) + return -EIO; + + hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops ); + add_preferred_console("hvc", 0, NULL); + return 0; +} +console_initcall(hvc_rtas_console_init); |