TextModeConsole.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <Kernel/Graphics/Console/TextModeConsole.h>
  7. #include <Kernel/Graphics/GraphicsManagement.h>
  8. #include <Kernel/IO.h>
  9. #include <Kernel/Sections.h>
  10. namespace Kernel::Graphics {
  11. UNMAP_AFTER_INIT NonnullRefPtr<TextModeConsole> TextModeConsole::initialize(const VGACompatibleAdapter& adapter)
  12. {
  13. return adopt_ref(*new TextModeConsole(adapter));
  14. }
  15. UNMAP_AFTER_INIT TextModeConsole::TextModeConsole(const VGACompatibleAdapter& adapter)
  16. : VGAConsole(adapter, VGAConsole::Mode::TextMode, 80, 25)
  17. , m_current_vga_window(m_vga_region->vaddr().offset(0x18000).as_ptr())
  18. {
  19. for (size_t index = 0; index < height(); index++) {
  20. clear_vga_row(index);
  21. }
  22. dbgln("Text mode console initialized!");
  23. }
  24. enum VGAColor : u8 {
  25. Black = 0,
  26. Blue,
  27. Green,
  28. Cyan,
  29. Red,
  30. Magenta,
  31. Brown,
  32. LightGray,
  33. DarkGray,
  34. BrightBlue,
  35. BrightGreen,
  36. BrightCyan,
  37. BrightRed,
  38. BrightMagenta,
  39. Yellow,
  40. White,
  41. };
  42. [[maybe_unused]] static inline VGAColor convert_standard_color_to_vga_color(Console::Color color)
  43. {
  44. switch (color) {
  45. case Console::Color::Black:
  46. return VGAColor::Black;
  47. case Console::Color::Red:
  48. return VGAColor::Red;
  49. case Console::Color::Brown:
  50. return VGAColor::Brown;
  51. case Console::Color::Blue:
  52. return VGAColor::Blue;
  53. case Console::Color::Magenta:
  54. return VGAColor::Magenta;
  55. case Console::Color::Green:
  56. return VGAColor::Green;
  57. case Console::Color::Cyan:
  58. return VGAColor::Cyan;
  59. case Console::Color::LightGray:
  60. return VGAColor::LightGray;
  61. case Console::Color::DarkGray:
  62. return VGAColor::DarkGray;
  63. case Console::Color::BrightRed:
  64. return VGAColor::BrightRed;
  65. case Console::Color::BrightGreen:
  66. return VGAColor::BrightGreen;
  67. case Console::Color::Yellow:
  68. return VGAColor::Yellow;
  69. case Console::Color::BrightBlue:
  70. return VGAColor::BrightBlue;
  71. case Console::Color::BrightMagenta:
  72. return VGAColor::BrightMagenta;
  73. case Console::Color::BrightCyan:
  74. return VGAColor::BrightCyan;
  75. case Console::Color::White:
  76. return VGAColor::White;
  77. default:
  78. VERIFY_NOT_REACHED();
  79. }
  80. }
  81. void TextModeConsole::set_cursor(size_t x, size_t y)
  82. {
  83. SpinlockLocker main_lock(GraphicsManagement::the().main_vga_lock());
  84. SpinlockLocker lock(m_vga_lock);
  85. m_cursor_x = x;
  86. m_cursor_y = y;
  87. u16 value = m_current_vga_start_address + (y * width() + x);
  88. IO::out8(0x3d4, 0x0e);
  89. IO::out8(0x3d5, MSB(value));
  90. IO::out8(0x3d4, 0x0f);
  91. IO::out8(0x3d5, LSB(value));
  92. }
  93. void TextModeConsole::hide_cursor()
  94. {
  95. SpinlockLocker main_lock(GraphicsManagement::the().main_vga_lock());
  96. SpinlockLocker lock(m_vga_lock);
  97. IO::out8(0x3D4, 0xA);
  98. IO::out8(0x3D5, 0x20);
  99. }
  100. void TextModeConsole::show_cursor()
  101. {
  102. SpinlockLocker main_lock(GraphicsManagement::the().main_vga_lock());
  103. SpinlockLocker lock(m_vga_lock);
  104. IO::out8(0x3D4, 0xA);
  105. IO::out8(0x3D5, 0x20);
  106. }
  107. void TextModeConsole::clear(size_t x, size_t y, size_t length)
  108. {
  109. SpinlockLocker lock(m_vga_lock);
  110. auto* buf = (u16*)(m_current_vga_window + (x * 2) + (y * width() * 2));
  111. for (size_t index = 0; index < length; index++) {
  112. buf[index] = 0x0720;
  113. }
  114. }
  115. void TextModeConsole::write(size_t x, size_t y, char ch, bool critical)
  116. {
  117. write(x, y, ch, m_default_background_color, m_default_foreground_color, critical);
  118. }
  119. void TextModeConsole::write(size_t x, size_t y, char ch, Color background, Color foreground, bool critical)
  120. {
  121. SpinlockLocker lock(m_vga_lock);
  122. // If we are in critical printing mode, we need to handle new lines here
  123. // because there's no other responsible object to do that in the print call path
  124. if (critical && (ch == '\r' || ch == '\n')) {
  125. // Disable hardware VGA cursor
  126. SpinlockLocker main_lock(GraphicsManagement::the().main_vga_lock());
  127. IO::out8(0x3D4, 0xA);
  128. IO::out8(0x3D5, 0x20);
  129. m_x = 0;
  130. m_y += 1;
  131. if (m_y >= max_row())
  132. m_y = 0;
  133. return;
  134. }
  135. auto* buf = (u16*)(m_current_vga_window + (x * 2) + (y * width() * 2));
  136. *buf = foreground << 8 | background << 12 | ch;
  137. m_x = x + 1;
  138. if (m_x >= max_column()) {
  139. m_x = 0;
  140. m_y = y + 1;
  141. if (m_y >= max_row())
  142. m_y = 0;
  143. }
  144. }
  145. void TextModeConsole::clear_vga_row(u16 row)
  146. {
  147. clear(row * width(), width(), width());
  148. }
  149. void TextModeConsole::set_vga_start_row(u16 row)
  150. {
  151. SpinlockLocker lock(m_vga_lock);
  152. m_vga_start_row = row;
  153. m_current_vga_start_address = row * width();
  154. m_current_vga_window = m_current_vga_window + row * width() * bytes_per_base_glyph();
  155. IO::out8(0x3d4, 0x0c);
  156. IO::out8(0x3d5, MSB(m_current_vga_start_address));
  157. IO::out8(0x3d4, 0x0d);
  158. IO::out8(0x3d5, LSB(m_current_vga_start_address));
  159. }
  160. void TextModeConsole::write(char ch, bool critical)
  161. {
  162. write(m_x, m_y, ch, critical);
  163. }
  164. }