| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <Kernel/Graphics/Console/TextModeConsole.h>
 | 
					
						
							|  |  |  | #include <Kernel/Graphics/GraphicsManagement.h>
 | 
					
						
							|  |  |  | #include <Kernel/IO.h>
 | 
					
						
							| 
									
										
										
										
											2021-06-22 17:40:16 +02:00
										 |  |  | #include <Kernel/Sections.h>
 | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace Kernel::Graphics { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | UNMAP_AFTER_INIT NonnullRefPtr<TextModeConsole> TextModeConsole::initialize(const VGACompatibleAdapter& adapter) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return adopt_ref(*new TextModeConsole(adapter)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | UNMAP_AFTER_INIT TextModeConsole::TextModeConsole(const VGACompatibleAdapter& adapter) | 
					
						
							|  |  |  |     : VGAConsole(adapter, VGAConsole::Mode::TextMode, 80, 25) | 
					
						
							|  |  |  |     , m_current_vga_window(m_vga_region->vaddr().offset(0x18000).as_ptr()) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     for (size_t index = 0; index < height(); index++) { | 
					
						
							|  |  |  |         clear_vga_row(index); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     dbgln("Text mode console initialized!"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum VGAColor : u8 { | 
					
						
							|  |  |  |     Black = 0, | 
					
						
							|  |  |  |     Blue, | 
					
						
							|  |  |  |     Green, | 
					
						
							|  |  |  |     Cyan, | 
					
						
							|  |  |  |     Red, | 
					
						
							|  |  |  |     Magenta, | 
					
						
							|  |  |  |     Brown, | 
					
						
							|  |  |  |     LightGray, | 
					
						
							|  |  |  |     DarkGray, | 
					
						
							|  |  |  |     BrightBlue, | 
					
						
							|  |  |  |     BrightGreen, | 
					
						
							|  |  |  |     BrightCyan, | 
					
						
							|  |  |  |     BrightRed, | 
					
						
							|  |  |  |     BrightMagenta, | 
					
						
							|  |  |  |     Yellow, | 
					
						
							|  |  |  |     White, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline VGAColor convert_standard_color_to_vga_color(Console::Color color) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (color) { | 
					
						
							|  |  |  |     case Console::Color::Black: | 
					
						
							|  |  |  |         return VGAColor::Black; | 
					
						
							|  |  |  |     case Console::Color::Red: | 
					
						
							|  |  |  |         return VGAColor::Red; | 
					
						
							|  |  |  |     case Console::Color::Brown: | 
					
						
							|  |  |  |         return VGAColor::Brown; | 
					
						
							|  |  |  |     case Console::Color::Blue: | 
					
						
							|  |  |  |         return VGAColor::Blue; | 
					
						
							|  |  |  |     case Console::Color::Magenta: | 
					
						
							|  |  |  |         return VGAColor::Magenta; | 
					
						
							|  |  |  |     case Console::Color::Green: | 
					
						
							|  |  |  |         return VGAColor::Green; | 
					
						
							|  |  |  |     case Console::Color::Cyan: | 
					
						
							|  |  |  |         return VGAColor::Cyan; | 
					
						
							|  |  |  |     case Console::Color::LightGray: | 
					
						
							|  |  |  |         return VGAColor::LightGray; | 
					
						
							|  |  |  |     case Console::Color::DarkGray: | 
					
						
							|  |  |  |         return VGAColor::DarkGray; | 
					
						
							|  |  |  |     case Console::Color::BrightRed: | 
					
						
							|  |  |  |         return VGAColor::BrightRed; | 
					
						
							|  |  |  |     case Console::Color::BrightGreen: | 
					
						
							|  |  |  |         return VGAColor::BrightGreen; | 
					
						
							|  |  |  |     case Console::Color::Yellow: | 
					
						
							|  |  |  |         return VGAColor::Yellow; | 
					
						
							|  |  |  |     case Console::Color::BrightBlue: | 
					
						
							|  |  |  |         return VGAColor::BrightBlue; | 
					
						
							|  |  |  |     case Console::Color::BrightMagenta: | 
					
						
							|  |  |  |         return VGAColor::BrightMagenta; | 
					
						
							|  |  |  |     case Console::Color::BrightCyan: | 
					
						
							|  |  |  |         return VGAColor::BrightCyan; | 
					
						
							|  |  |  |     case Console::Color::White: | 
					
						
							|  |  |  |         return VGAColor::White; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TextModeConsole::set_cursor(size_t x, size_t y) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ScopedSpinLock main_lock(GraphicsManagement::the().main_vga_lock()); | 
					
						
							|  |  |  |     ScopedSpinLock lock(m_vga_lock); | 
					
						
							|  |  |  |     m_cursor_x = x; | 
					
						
							|  |  |  |     m_cursor_y = y; | 
					
						
							|  |  |  |     u16 value = m_current_vga_start_address + (y * width() + x); | 
					
						
							|  |  |  |     IO::out8(0x3d4, 0x0e); | 
					
						
							|  |  |  |     IO::out8(0x3d5, MSB(value)); | 
					
						
							|  |  |  |     IO::out8(0x3d4, 0x0f); | 
					
						
							|  |  |  |     IO::out8(0x3d5, LSB(value)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void TextModeConsole::hide_cursor() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ScopedSpinLock main_lock(GraphicsManagement::the().main_vga_lock()); | 
					
						
							|  |  |  |     ScopedSpinLock lock(m_vga_lock); | 
					
						
							|  |  |  |     IO::out8(0x3D4, 0xA); | 
					
						
							|  |  |  |     IO::out8(0x3D5, 0x20); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void TextModeConsole::show_cursor() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ScopedSpinLock main_lock(GraphicsManagement::the().main_vga_lock()); | 
					
						
							|  |  |  |     ScopedSpinLock lock(m_vga_lock); | 
					
						
							|  |  |  |     IO::out8(0x3D4, 0xA); | 
					
						
							|  |  |  |     IO::out8(0x3D5, 0x20); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-12 22:30:05 +10:00
										 |  |  | void TextModeConsole::clear(size_t x, size_t y, size_t length) | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  | { | 
					
						
							|  |  |  |     ScopedSpinLock lock(m_vga_lock); | 
					
						
							|  |  |  |     auto* buf = (u16*)(m_current_vga_window + (x * 2) + (y * width() * 2)); | 
					
						
							|  |  |  |     for (size_t index = 0; index < length; index++) { | 
					
						
							|  |  |  |         buf[index] = 0x0720; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-06-12 22:30:05 +10:00
										 |  |  | void TextModeConsole::write(size_t x, size_t y, char ch, bool critical) | 
					
						
							| 
									
										
										
										
											2021-06-03 17:41:27 +03:00
										 |  |  | { | 
					
						
							|  |  |  |     write(x, y, ch, m_default_background_color, m_default_foreground_color, critical); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-12 22:30:05 +10:00
										 |  |  | void TextModeConsole::write(size_t x, size_t y, char ch, Color background, Color foreground, bool critical) | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  | { | 
					
						
							|  |  |  |     ScopedSpinLock lock(m_vga_lock); | 
					
						
							| 
									
										
										
										
											2021-06-03 17:41:27 +03:00
										 |  |  |     // If we are in critical printing mode, we need to handle new lines here
 | 
					
						
							|  |  |  |     // because there's no other responsible object to do that in the print call path
 | 
					
						
							|  |  |  |     if (critical && (ch == '\r' || ch == '\n')) { | 
					
						
							|  |  |  |         // Disable hardware VGA cursor
 | 
					
						
							|  |  |  |         ScopedSpinLock main_lock(GraphicsManagement::the().main_vga_lock()); | 
					
						
							|  |  |  |         IO::out8(0x3D4, 0xA); | 
					
						
							|  |  |  |         IO::out8(0x3D5, 0x20); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  |         m_x = 0; | 
					
						
							| 
									
										
										
										
											2021-06-03 17:41:27 +03:00
										 |  |  |         m_y += 1; | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  |         if (m_y >= max_row()) | 
					
						
							|  |  |  |             m_y = 0; | 
					
						
							| 
									
										
										
										
											2021-06-03 17:41:27 +03:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-28 13:11:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  |     auto* buf = (u16*)(m_current_vga_window + (x * 2) + (y * width() * 2)); | 
					
						
							|  |  |  |     *buf = foreground << 8 | background << 12 | ch; | 
					
						
							|  |  |  |     m_x = x + 1; | 
					
						
							| 
									
										
										
										
											2021-06-03 17:41:27 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  |     if (m_x >= max_column()) { | 
					
						
							|  |  |  |         m_x = 0; | 
					
						
							|  |  |  |         m_y = y + 1; | 
					
						
							|  |  |  |         if (m_y >= max_row()) | 
					
						
							|  |  |  |             m_y = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TextModeConsole::clear_vga_row(u16 row) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     clear(row * width(), width(), width()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TextModeConsole::set_vga_start_row(u16 row) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ScopedSpinLock lock(m_vga_lock); | 
					
						
							|  |  |  |     m_vga_start_row = row; | 
					
						
							|  |  |  |     m_current_vga_start_address = row * width(); | 
					
						
							|  |  |  |     m_current_vga_window = m_current_vga_window + row * width() * bytes_per_base_glyph(); | 
					
						
							|  |  |  |     IO::out8(0x3d4, 0x0c); | 
					
						
							|  |  |  |     IO::out8(0x3d5, MSB(m_current_vga_start_address)); | 
					
						
							|  |  |  |     IO::out8(0x3d4, 0x0d); | 
					
						
							|  |  |  |     IO::out8(0x3d5, LSB(m_current_vga_start_address)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-12 22:30:05 +10:00
										 |  |  | void TextModeConsole::write(char ch, bool critical) | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-06-03 17:41:27 +03:00
										 |  |  |     write(m_x, m_y, ch, critical); | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |