tty.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* -*- linux-c -*- ------------------------------------------------------- *
  3. *
  4. * Copyright (C) 1991, 1992 Linus Torvalds
  5. * Copyright 2007 rPath, Inc. - All Rights Reserved
  6. * Copyright 2009 Intel Corporation; author H. Peter Anvin
  7. *
  8. * ----------------------------------------------------------------------- */
  9. /*
  10. * Very simple screen and serial I/O
  11. */
  12. #include "boot.h"
  13. int early_serial_base;
  14. #define XMTRDY 0x20
  15. #define TXR 0 /* Transmit register (WRITE) */
  16. #define LSR 5 /* Line Status */
  17. /*
  18. * These functions are in .inittext so they can be used to signal
  19. * error during initialization.
  20. */
  21. static void __section(".inittext") serial_putchar(int ch)
  22. {
  23. unsigned timeout = 0xffff;
  24. while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
  25. cpu_relax();
  26. outb(ch, early_serial_base + TXR);
  27. }
  28. static void __section(".inittext") bios_putchar(int ch)
  29. {
  30. struct biosregs ireg;
  31. initregs(&ireg);
  32. ireg.bx = 0x0007;
  33. ireg.cx = 0x0001;
  34. ireg.ah = 0x0e;
  35. ireg.al = ch;
  36. intcall(0x10, &ireg, NULL);
  37. }
  38. void __section(".inittext") putchar(int ch)
  39. {
  40. if (ch == '\n')
  41. putchar('\r'); /* \n -> \r\n */
  42. bios_putchar(ch);
  43. if (early_serial_base != 0)
  44. serial_putchar(ch);
  45. }
  46. void __section(".inittext") puts(const char *str)
  47. {
  48. while (*str)
  49. putchar(*str++);
  50. }
  51. /*
  52. * Read the CMOS clock through the BIOS, and return the
  53. * seconds in BCD.
  54. */
  55. static u8 gettime(void)
  56. {
  57. struct biosregs ireg, oreg;
  58. initregs(&ireg);
  59. ireg.ah = 0x02;
  60. intcall(0x1a, &ireg, &oreg);
  61. return oreg.dh;
  62. }
  63. /*
  64. * Read from the keyboard
  65. */
  66. int getchar(void)
  67. {
  68. struct biosregs ireg, oreg;
  69. initregs(&ireg);
  70. /* ireg.ah = 0x00; */
  71. intcall(0x16, &ireg, &oreg);
  72. return oreg.al;
  73. }
  74. static int kbd_pending(void)
  75. {
  76. struct biosregs ireg, oreg;
  77. initregs(&ireg);
  78. ireg.ah = 0x01;
  79. intcall(0x16, &ireg, &oreg);
  80. return !(oreg.eflags & X86_EFLAGS_ZF);
  81. }
  82. void kbd_flush(void)
  83. {
  84. for (;;) {
  85. if (!kbd_pending())
  86. break;
  87. getchar();
  88. }
  89. }
  90. int getchar_timeout(void)
  91. {
  92. int cnt = 30;
  93. int t0, t1;
  94. t0 = gettime();
  95. while (cnt) {
  96. if (kbd_pending())
  97. return getchar();
  98. t1 = gettime();
  99. if (t0 != t1) {
  100. cnt--;
  101. t0 = t1;
  102. }
  103. }
  104. return 0; /* Timeout! */
  105. }