Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * IBM RTAS driver interface to hvc_console.c
0004  *
0005  * (C) Copyright IBM Corporation 2001-2005
0006  * (C) Copyright Red Hat, Inc. 2005
0007  *
0008  * Author(s): Maximino Augilar <IBM STI Design Center>
0009  *      : Ryan S. Arnold <rsa@us.ibm.com>
0010  *      : Utz Bacher <utz.bacher@de.ibm.com>
0011  *      : David Woodhouse <dwmw2@infradead.org>
0012  *
0013  *    inspired by drivers/char/hvc_console.c
0014  *    written by Anton Blanchard and Paul Mackerras
0015  */
0016 
0017 #include <linux/console.h>
0018 #include <linux/delay.h>
0019 #include <linux/err.h>
0020 #include <linux/init.h>
0021 #include <linux/moduleparam.h>
0022 #include <linux/types.h>
0023 
0024 #include <asm/irq.h>
0025 #include <asm/rtas.h>
0026 #include "hvc_console.h"
0027 
0028 #define hvc_rtas_cookie 0x67781e15
0029 struct hvc_struct *hvc_rtas_dev;
0030 
0031 static int rtascons_put_char_token = RTAS_UNKNOWN_SERVICE;
0032 static int rtascons_get_char_token = RTAS_UNKNOWN_SERVICE;
0033 
0034 static inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf,
0035         int count)
0036 {
0037     int i;
0038 
0039     for (i = 0; i < count; i++) {
0040         if (rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[i]))
0041             break;
0042     }
0043 
0044     return i;
0045 }
0046 
0047 static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count)
0048 {
0049     int i, c;
0050 
0051     for (i = 0; i < count; i++) {
0052         if (rtas_call(rtascons_get_char_token, 0, 2, &c))
0053             break;
0054 
0055         buf[i] = c;
0056     }
0057 
0058     return i;
0059 }
0060 
0061 static const struct hv_ops hvc_rtas_get_put_ops = {
0062     .get_chars = hvc_rtas_read_console,
0063     .put_chars = hvc_rtas_write_console,
0064 };
0065 
0066 static int __init hvc_rtas_init(void)
0067 {
0068     struct hvc_struct *hp;
0069 
0070     if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
0071         rtascons_put_char_token = rtas_token("put-term-char");
0072     if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
0073         return -EIO;
0074 
0075     if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
0076         rtascons_get_char_token = rtas_token("get-term-char");
0077     if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
0078         return -EIO;
0079 
0080     BUG_ON(hvc_rtas_dev);
0081 
0082     /* Allocate an hvc_struct for the console device we instantiated
0083      * earlier.  Save off hp so that we can return it on exit */
0084     hp = hvc_alloc(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops, 16);
0085     if (IS_ERR(hp))
0086         return PTR_ERR(hp);
0087 
0088     hvc_rtas_dev = hp;
0089 
0090     return 0;
0091 }
0092 device_initcall(hvc_rtas_init);
0093 
0094 /* This will happen prior to module init.  There is no tty at this time? */
0095 static int __init hvc_rtas_console_init(void)
0096 {
0097     rtascons_put_char_token = rtas_token("put-term-char");
0098     if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
0099         return -EIO;
0100 
0101     rtascons_get_char_token = rtas_token("get-term-char");
0102     if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
0103         return -EIO;
0104 
0105     hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops);
0106     add_preferred_console("hvc", 0, NULL);
0107 
0108     return 0;
0109 }
0110 console_initcall(hvc_rtas_console_init);