VGATextModeConsole.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <Kernel/Arch/x86/IO.h>
  7. #include <Kernel/Graphics/Console/VGATextModeConsole.h>
  8. #include <Kernel/Graphics/GraphicsManagement.h>
  9. #include <Kernel/Sections.h>
  10. namespace Kernel::Graphics {
  11. UNMAP_AFTER_INIT NonnullRefPtr<VGATextModeConsole> VGATextModeConsole::initialize()
  12. {
  13. auto vga_window_size = MUST(Memory::page_round_up(0xc0000 - 0xa0000));
  14. auto vga_window_region = MUST(MM.allocate_kernel_region(PhysicalAddress(0xa0000), vga_window_size, "VGA Display"sv, Memory::Region::Access::ReadWrite));
  15. return adopt_ref(*new (nothrow) VGATextModeConsole(move(vga_window_region)));
  16. }
  17. UNMAP_AFTER_INIT VGATextModeConsole::VGATextModeConsole(NonnullOwnPtr<Memory::Region> vga_window_region)
  18. : Console(80, 25)
  19. , m_vga_window_region(move(vga_window_region))
  20. , m_current_vga_window(m_vga_window_region->vaddr().offset(0x18000).as_ptr())
  21. {
  22. for (size_t index = 0; index < height(); index++) {
  23. clear_vga_row(index);
  24. }
  25. dbgln("VGA Text mode console initialized!");
  26. }
  27. enum VGAColor : u8 {
  28. Black = 0,
  29. Blue,
  30. Green,
  31. Cyan,
  32. Red,
  33. Magenta,
  34. Brown,
  35. LightGray,
  36. DarkGray,
  37. BrightBlue,
  38. BrightGreen,
  39. BrightCyan,
  40. BrightRed,
  41. BrightMagenta,
  42. Yellow,
  43. White,
  44. };
  45. [[maybe_unused]] static inline VGAColor convert_standard_color_to_vga_color(Console::Color color)
  46. {
  47. switch (color) {
  48. case Console::Color::Black:
  49. return VGAColor::Black;
  50. case Console::Color::Red:
  51. return VGAColor::Red;
  52. case Console::Color::Brown:
  53. return VGAColor::Brown;
  54. case Console::Color::Blue:
  55. return VGAColor::Blue;
  56. case Console::Color::Magenta:
  57. return VGAColor::Magenta;
  58. case Console::Color::Green:
  59. return VGAColor::Green;
  60. case Console::Color::Cyan:
  61. return VGAColor::Cyan;
  62. case Console::Color::LightGray:
  63. return VGAColor::LightGray;
  64. case Console::Color::DarkGray:
  65. return VGAColor::DarkGray;
  66. case Console::Color::BrightRed:
  67. return VGAColor::BrightRed;
  68. case Console::Color::BrightGreen:
  69. return VGAColor::BrightGreen;
  70. case Console::Color::Yellow:
  71. return VGAColor::Yellow;
  72. case Console::Color::BrightBlue:
  73. return VGAColor::BrightBlue;
  74. case Console::Color::BrightMagenta:
  75. return VGAColor::BrightMagenta;
  76. case Console::Color::BrightCyan:
  77. return VGAColor::BrightCyan;
  78. case Console::Color::White:
  79. return VGAColor::White;
  80. default:
  81. VERIFY_NOT_REACHED();
  82. }
  83. }
  84. void VGATextModeConsole::set_cursor(size_t x, size_t y)
  85. {
  86. SpinlockLocker lock(m_vga_lock);
  87. GraphicsManagement::the().set_vga_text_mode_cursor(width(), x, y);
  88. m_x = x;
  89. m_y = y;
  90. }
  91. void VGATextModeConsole::hide_cursor()
  92. {
  93. SpinlockLocker lock(m_vga_lock);
  94. GraphicsManagement::the().disable_vga_text_mode_console_cursor();
  95. }
  96. void VGATextModeConsole::show_cursor()
  97. {
  98. set_cursor(m_x, m_y);
  99. }
  100. void VGATextModeConsole::clear(size_t x, size_t y, size_t length)
  101. {
  102. SpinlockLocker lock(m_vga_lock);
  103. auto* buf = (u16*)m_current_vga_window.offset((x * 2) + (y * width() * 2)).as_ptr();
  104. for (size_t index = 0; index < length; index++) {
  105. buf[index] = 0x0720;
  106. }
  107. }
  108. void VGATextModeConsole::write(size_t x, size_t y, char ch, bool critical)
  109. {
  110. write(x, y, ch, m_default_background_color, m_default_foreground_color, critical);
  111. }
  112. void VGATextModeConsole::write(size_t x, size_t y, char ch, Color background, Color foreground, bool critical)
  113. {
  114. SpinlockLocker lock(m_vga_lock);
  115. // If we are in critical printing mode, we need to handle new lines here
  116. // because there's no other responsible object to do that in the print call path
  117. if (critical && (ch == '\r' || ch == '\n')) {
  118. // Disable hardware VGA cursor
  119. GraphicsManagement::the().disable_vga_text_mode_console_cursor();
  120. m_x = 0;
  121. m_y += 1;
  122. if (m_y >= max_row())
  123. m_y = 0;
  124. return;
  125. }
  126. auto* buf = (u16*)m_current_vga_window.offset((x * 2) + (y * width() * 2)).as_ptr();
  127. *buf = foreground << 8 | background << 12 | ch;
  128. m_x = x + 1;
  129. if (m_x >= max_column()) {
  130. m_x = 0;
  131. m_y = y + 1;
  132. if (m_y >= max_row())
  133. m_y = 0;
  134. }
  135. }
  136. void VGATextModeConsole::clear_vga_row(u16 row)
  137. {
  138. clear(0, row, width());
  139. }
  140. void VGATextModeConsole::write(char ch, bool critical)
  141. {
  142. write(m_x, m_y, ch, critical);
  143. }
  144. }