1728674a7SGreg Kroah-Hartman /* 2728674a7SGreg Kroah-Hartman * IBM RTAS driver interface to hvc_console.c 3728674a7SGreg Kroah-Hartman * 4728674a7SGreg Kroah-Hartman * (C) Copyright IBM Corporation 2001-2005 5728674a7SGreg Kroah-Hartman * (C) Copyright Red Hat, Inc. 2005 6728674a7SGreg Kroah-Hartman * 7728674a7SGreg Kroah-Hartman * Author(s): Maximino Augilar <IBM STI Design Center> 8728674a7SGreg Kroah-Hartman * : Ryan S. Arnold <rsa@us.ibm.com> 9728674a7SGreg Kroah-Hartman * : Utz Bacher <utz.bacher@de.ibm.com> 10728674a7SGreg Kroah-Hartman * : David Woodhouse <dwmw2@infradead.org> 11728674a7SGreg Kroah-Hartman * 12728674a7SGreg Kroah-Hartman * inspired by drivers/char/hvc_console.c 13728674a7SGreg Kroah-Hartman * written by Anton Blanchard and Paul Mackerras 14728674a7SGreg Kroah-Hartman * 15728674a7SGreg Kroah-Hartman * This program is free software; you can redistribute it and/or modify 16728674a7SGreg Kroah-Hartman * it under the terms of the GNU General Public License as published by 17728674a7SGreg Kroah-Hartman * the Free Software Foundation; either version 2 of the License, or 18728674a7SGreg Kroah-Hartman * (at your option) any later version. 19728674a7SGreg Kroah-Hartman * 20728674a7SGreg Kroah-Hartman * This program is distributed in the hope that it will be useful, 21728674a7SGreg Kroah-Hartman * but WITHOUT ANY WARRANTY; without even the implied warranty of 22728674a7SGreg Kroah-Hartman * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23728674a7SGreg Kroah-Hartman * GNU General Public License for more details. 24728674a7SGreg Kroah-Hartman * 25728674a7SGreg Kroah-Hartman * You should have received a copy of the GNU General Public License 26728674a7SGreg Kroah-Hartman * along with this program; if not, write to the Free Software 27728674a7SGreg Kroah-Hartman * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 28728674a7SGreg Kroah-Hartman */ 29728674a7SGreg Kroah-Hartman 30728674a7SGreg Kroah-Hartman #include <linux/console.h> 31728674a7SGreg Kroah-Hartman #include <linux/delay.h> 32728674a7SGreg Kroah-Hartman #include <linux/err.h> 33728674a7SGreg Kroah-Hartman #include <linux/init.h> 34728674a7SGreg Kroah-Hartman #include <linux/moduleparam.h> 35728674a7SGreg Kroah-Hartman #include <linux/types.h> 36728674a7SGreg Kroah-Hartman 37728674a7SGreg Kroah-Hartman #include <asm/irq.h> 38728674a7SGreg Kroah-Hartman #include <asm/rtas.h> 39728674a7SGreg Kroah-Hartman #include "hvc_console.h" 40728674a7SGreg Kroah-Hartman 41728674a7SGreg Kroah-Hartman #define hvc_rtas_cookie 0x67781e15 42728674a7SGreg Kroah-Hartman struct hvc_struct *hvc_rtas_dev; 43728674a7SGreg Kroah-Hartman 44728674a7SGreg Kroah-Hartman static int rtascons_put_char_token = RTAS_UNKNOWN_SERVICE; 45728674a7SGreg Kroah-Hartman static int rtascons_get_char_token = RTAS_UNKNOWN_SERVICE; 46728674a7SGreg Kroah-Hartman 47728674a7SGreg Kroah-Hartman static inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf, 48728674a7SGreg Kroah-Hartman int count) 49728674a7SGreg Kroah-Hartman { 50728674a7SGreg Kroah-Hartman int i; 51728674a7SGreg Kroah-Hartman 52728674a7SGreg Kroah-Hartman for (i = 0; i < count; i++) { 53728674a7SGreg Kroah-Hartman if (rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[i])) 54728674a7SGreg Kroah-Hartman break; 55728674a7SGreg Kroah-Hartman } 56728674a7SGreg Kroah-Hartman 57728674a7SGreg Kroah-Hartman return i; 58728674a7SGreg Kroah-Hartman } 59728674a7SGreg Kroah-Hartman 60728674a7SGreg Kroah-Hartman static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count) 61728674a7SGreg Kroah-Hartman { 62728674a7SGreg Kroah-Hartman int i, c; 63728674a7SGreg Kroah-Hartman 64728674a7SGreg Kroah-Hartman for (i = 0; i < count; i++) { 65728674a7SGreg Kroah-Hartman if (rtas_call(rtascons_get_char_token, 0, 2, &c)) 66728674a7SGreg Kroah-Hartman break; 67728674a7SGreg Kroah-Hartman 68728674a7SGreg Kroah-Hartman buf[i] = c; 69728674a7SGreg Kroah-Hartman } 70728674a7SGreg Kroah-Hartman 71728674a7SGreg Kroah-Hartman return i; 72728674a7SGreg Kroah-Hartman } 73728674a7SGreg Kroah-Hartman 74728674a7SGreg Kroah-Hartman static const struct hv_ops hvc_rtas_get_put_ops = { 75728674a7SGreg Kroah-Hartman .get_chars = hvc_rtas_read_console, 76728674a7SGreg Kroah-Hartman .put_chars = hvc_rtas_write_console, 77728674a7SGreg Kroah-Hartman }; 78728674a7SGreg Kroah-Hartman 79728674a7SGreg Kroah-Hartman static int __init hvc_rtas_init(void) 80728674a7SGreg Kroah-Hartman { 81728674a7SGreg Kroah-Hartman struct hvc_struct *hp; 82728674a7SGreg Kroah-Hartman 83728674a7SGreg Kroah-Hartman if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) 84728674a7SGreg Kroah-Hartman rtascons_put_char_token = rtas_token("put-term-char"); 85728674a7SGreg Kroah-Hartman if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) 86728674a7SGreg Kroah-Hartman return -EIO; 87728674a7SGreg Kroah-Hartman 88728674a7SGreg Kroah-Hartman if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE) 89728674a7SGreg Kroah-Hartman rtascons_get_char_token = rtas_token("get-term-char"); 90728674a7SGreg Kroah-Hartman if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE) 91728674a7SGreg Kroah-Hartman return -EIO; 92728674a7SGreg Kroah-Hartman 93728674a7SGreg Kroah-Hartman BUG_ON(hvc_rtas_dev); 94728674a7SGreg Kroah-Hartman 95728674a7SGreg Kroah-Hartman /* Allocate an hvc_struct for the console device we instantiated 96728674a7SGreg Kroah-Hartman * earlier. Save off hp so that we can return it on exit */ 97728674a7SGreg Kroah-Hartman hp = hvc_alloc(hvc_rtas_cookie, NO_IRQ, &hvc_rtas_get_put_ops, 16); 98728674a7SGreg Kroah-Hartman if (IS_ERR(hp)) 99728674a7SGreg Kroah-Hartman return PTR_ERR(hp); 100728674a7SGreg Kroah-Hartman 101728674a7SGreg Kroah-Hartman hvc_rtas_dev = hp; 102728674a7SGreg Kroah-Hartman 103728674a7SGreg Kroah-Hartman return 0; 104728674a7SGreg Kroah-Hartman } 105728674a7SGreg Kroah-Hartman module_init(hvc_rtas_init); 106728674a7SGreg Kroah-Hartman 107728674a7SGreg Kroah-Hartman /* This will tear down the tty portion of the driver */ 108728674a7SGreg Kroah-Hartman static void __exit hvc_rtas_exit(void) 109728674a7SGreg Kroah-Hartman { 110728674a7SGreg Kroah-Hartman /* Really the fun isn't over until the worker thread breaks down and 111728674a7SGreg Kroah-Hartman * the tty cleans up */ 112728674a7SGreg Kroah-Hartman if (hvc_rtas_dev) 113728674a7SGreg Kroah-Hartman hvc_remove(hvc_rtas_dev); 114728674a7SGreg Kroah-Hartman } 115728674a7SGreg Kroah-Hartman module_exit(hvc_rtas_exit); 116728674a7SGreg Kroah-Hartman 117728674a7SGreg Kroah-Hartman /* This will happen prior to module init. There is no tty at this time? */ 118728674a7SGreg Kroah-Hartman static int __init hvc_rtas_console_init(void) 119728674a7SGreg Kroah-Hartman { 120728674a7SGreg Kroah-Hartman rtascons_put_char_token = rtas_token("put-term-char"); 121728674a7SGreg Kroah-Hartman if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) 122728674a7SGreg Kroah-Hartman return -EIO; 123728674a7SGreg Kroah-Hartman 124728674a7SGreg Kroah-Hartman rtascons_get_char_token = rtas_token("get-term-char"); 125728674a7SGreg Kroah-Hartman if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE) 126728674a7SGreg Kroah-Hartman return -EIO; 127728674a7SGreg Kroah-Hartman 128728674a7SGreg Kroah-Hartman hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops); 129728674a7SGreg Kroah-Hartman add_preferred_console("hvc", 0, NULL); 130728674a7SGreg Kroah-Hartman 131728674a7SGreg Kroah-Hartman return 0; 132728674a7SGreg Kroah-Hartman } 133728674a7SGreg Kroah-Hartman console_initcall(hvc_rtas_console_init); 134