Current Cell hardware is using the console through a set of rtas calls. This driver is needed to get console output on those boards. Signed-off-by: Arnd Bergmann Index: linux-2.6.15-rc/drivers/char/hvc_rtas.c =================================================================== --- /dev/null +++ linux-2.6.15-rc/drivers/char/hvc_rtas.c @@ -0,0 +1,154 @@ +/* + * IBM RTAS driver interface to hvc_console.c + * + * (C) Copyright IBM Corporation 2001-2005 + * (C) Copyright Red Hat, Inc. 2005 + * + * Author(s): Maximino Augilar + * : Ryan S. Arnold + * : Utz Bacher + * : David Woodhouse + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#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(rtascons_put_delay, int, 0644); + +static inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf, int count) +{ + int attempts = RTASCONS_PUT_ATTEMPTS; + int result; + int done; + + /* if there is more than one character to be displayed, wait a bit */ + for (done = 0; done < count && attempts; udelay(rtascons_put_delay)) { + attempts--; + result = rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[done]); + + if (!result) { + attempts = RTASCONS_PUT_ATTEMPTS; + done++; + } + } + /* the calling routine expects to receive the number of bytes sent */ + return done ?: 0; +} + +static inline int rtascons_get_char(void) +{ + int result; + + if (rtas_call(rtascons_get_char_token, 0, 2, &result)) + result = -1; + + return result; +} + +static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count) +{ + unsigned long got; + int c; + int i; + + for (got = 0, i = 0; i < count; i++) { + + if (( c = rtascons_get_char() ) != -1) { + buf[i] = c; + ++got; + } + else + break; + } + return got; +} + +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); /* before drivers/char/hvc_console.c */ + +/* 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); Index: linux-2.6.15-rc/drivers/char/Makefile =================================================================== --- linux-2.6.15-rc.orig/drivers/char/Makefile +++ linux-2.6.15-rc/drivers/char/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_RIO) += rio/ generic_seria obj-$(CONFIG_HVC_DRIVER) += hvc_console.o obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o obj-$(CONFIG_HVC_FSS) += hvc_fss.o +obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o obj-$(CONFIG_MMTIMER) += mmtimer.o Index: linux-2.6.15-rc/drivers/char/Kconfig =================================================================== --- linux-2.6.15-rc.orig/drivers/char/Kconfig +++ linux-2.6.15-rc/drivers/char/Kconfig @@ -578,6 +578,13 @@ config HVC_FSS IBM Full System Simulator Console device driver which makes use of the HVC_DRIVER front end. +config HVC_RTAS + bool "IBM RTAS Console support" + depends on PPC_RTAS + select HVC_DRIVER + help + IBM Console device driver which makes use of RTAS + config HVCS tristate "IBM Hypervisor Virtual Console Server support" depends on PPC_PSERIES --