hvc_rtas.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * IBM RTAS driver interface to hvc_console.c
  4. *
  5. * (C) Copyright IBM Corporation 2001-2005
  6. * (C) Copyright Red Hat, Inc. 2005
  7. *
  8. * Author(s): Maximino Augilar <IBM STI Design Center>
  9. * : Ryan S. Arnold <rsa@us.ibm.com>
  10. * : Utz Bacher <utz.bacher@de.ibm.com>
  11. * : David Woodhouse <dwmw2@infradead.org>
  12. *
  13. * inspired by drivers/char/hvc_console.c
  14. * written by Anton Blanchard and Paul Mackerras
  15. */
  16. #include <linux/console.h>
  17. #include <linux/delay.h>
  18. #include <linux/err.h>
  19. #include <linux/init.h>
  20. #include <linux/moduleparam.h>
  21. #include <linux/types.h>
  22. #include <asm/irq.h>
  23. #include <asm/rtas.h>
  24. #include "hvc_console.h"
  25. #define hvc_rtas_cookie 0x67781e15
  26. static struct hvc_struct *hvc_rtas_dev;
  27. static int rtascons_put_char_token = RTAS_UNKNOWN_SERVICE;
  28. static int rtascons_get_char_token = RTAS_UNKNOWN_SERVICE;
  29. static ssize_t hvc_rtas_write_console(uint32_t vtermno, const u8 *buf,
  30. size_t count)
  31. {
  32. size_t i;
  33. for (i = 0; i < count; i++) {
  34. if (rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[i]))
  35. break;
  36. }
  37. return i;
  38. }
  39. static ssize_t hvc_rtas_read_console(uint32_t vtermno, u8 *buf, size_t count)
  40. {
  41. size_t i;
  42. int c;
  43. for (i = 0; i < count; i++) {
  44. if (rtas_call(rtascons_get_char_token, 0, 2, &c))
  45. break;
  46. buf[i] = c;
  47. }
  48. return i;
  49. }
  50. static const struct hv_ops hvc_rtas_get_put_ops = {
  51. .get_chars = hvc_rtas_read_console,
  52. .put_chars = hvc_rtas_write_console,
  53. };
  54. static int __init hvc_rtas_init(void)
  55. {
  56. struct hvc_struct *hp;
  57. if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
  58. rtascons_put_char_token = rtas_token("put-term-char");
  59. if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
  60. return -EIO;
  61. if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
  62. rtascons_get_char_token = rtas_token("get-term-char");
  63. if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
  64. return -EIO;
  65. BUG_ON(hvc_rtas_dev);
  66. /* Allocate an hvc_struct for the console device we instantiated
  67. * earlier. Save off hp so that we can return it on exit */
  68. hp = hvc_alloc(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops, 16);
  69. if (IS_ERR(hp))
  70. return PTR_ERR(hp);
  71. hvc_rtas_dev = hp;
  72. return 0;
  73. }
  74. device_initcall(hvc_rtas_init);
  75. /* This will happen prior to module init. There is no tty at this time? */
  76. static int __init hvc_rtas_console_init(void)
  77. {
  78. rtascons_put_char_token = rtas_token("put-term-char");
  79. if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
  80. return -EIO;
  81. rtascons_get_char_token = rtas_token("get-term-char");
  82. if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
  83. return -EIO;
  84. hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops);
  85. add_preferred_console("hvc", 0, NULL);
  86. return 0;
  87. }
  88. console_initcall(hvc_rtas_console_init);