hvc_rtas.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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 <[email protected]>
  10. * : Utz Bacher <[email protected]>
  11. * : David Woodhouse <[email protected]>
  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. 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 inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf,
  30. int count)
  31. {
  32. int 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 int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count)
  40. {
  41. int i, c;
  42. for (i = 0; i < count; i++) {
  43. if (rtas_call(rtascons_get_char_token, 0, 2, &c))
  44. break;
  45. buf[i] = c;
  46. }
  47. return i;
  48. }
  49. static const struct hv_ops hvc_rtas_get_put_ops = {
  50. .get_chars = hvc_rtas_read_console,
  51. .put_chars = hvc_rtas_write_console,
  52. };
  53. static int __init hvc_rtas_init(void)
  54. {
  55. struct hvc_struct *hp;
  56. if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
  57. rtascons_put_char_token = rtas_token("put-term-char");
  58. if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
  59. return -EIO;
  60. if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
  61. rtascons_get_char_token = rtas_token("get-term-char");
  62. if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
  63. return -EIO;
  64. BUG_ON(hvc_rtas_dev);
  65. /* Allocate an hvc_struct for the console device we instantiated
  66. * earlier. Save off hp so that we can return it on exit */
  67. hp = hvc_alloc(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops, 16);
  68. if (IS_ERR(hp))
  69. return PTR_ERR(hp);
  70. hvc_rtas_dev = hp;
  71. return 0;
  72. }
  73. device_initcall(hvc_rtas_init);
  74. /* This will happen prior to module init. There is no tty at this time? */
  75. static int __init hvc_rtas_console_init(void)
  76. {
  77. rtascons_put_char_token = rtas_token("put-term-char");
  78. if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
  79. return -EIO;
  80. rtascons_get_char_token = rtas_token("get-term-char");
  81. if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
  82. return -EIO;
  83. hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops);
  84. add_preferred_console("hvc", 0, NULL);
  85. return 0;
  86. }
  87. console_initcall(hvc_rtas_console_init);