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