| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-01 09:58:50 +03:00
										 |  |  | #include <Kernel/Arch/x86/IO.h>
 | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  | #include <Kernel/Graphics/Console/TextModeConsole.h>
 | 
					
						
							|  |  |  | #include <Kernel/Graphics/GraphicsManagement.h>
 | 
					
						
							| 
									
										
										
										
											2021-06-22 17:40:16 +02:00
										 |  |  | #include <Kernel/Sections.h>
 | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace Kernel::Graphics { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-09 20:53:17 +02:00
										 |  |  | UNMAP_AFTER_INIT NonnullRefPtr<TextModeConsole> TextModeConsole::initialize() | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-02-09 20:53:17 +02:00
										 |  |  |     return adopt_ref(*new TextModeConsole()); | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-09 20:53:17 +02:00
										 |  |  | UNMAP_AFTER_INIT TextModeConsole::TextModeConsole() | 
					
						
							|  |  |  |     : VGAConsole(VGAConsole::Mode::TextMode, 80, 25) | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  |     , 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, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-05 18:08:48 +02:00
										 |  |  | [[maybe_unused]] static inline VGAColor convert_standard_color_to_vga_color(Console::Color color) | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  | { | 
					
						
							|  |  |  |     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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-08-22 01:49:22 +02:00
										 |  |  |     SpinlockLocker lock(m_vga_lock); | 
					
						
							| 
									
										
										
										
											2022-03-15 21:41:22 +02:00
										 |  |  |     GraphicsManagement::the().set_vga_text_mode_cursor(width(), x, y); | 
					
						
							| 
									
										
										
										
											2022-03-19 14:31:56 +02:00
										 |  |  |     m_x = x; | 
					
						
							|  |  |  |     m_y = y; | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  | } | 
					
						
							|  |  |  | void TextModeConsole::hide_cursor() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-08-22 01:49:22 +02:00
										 |  |  |     SpinlockLocker lock(m_vga_lock); | 
					
						
							| 
									
										
										
										
											2022-03-15 21:41:22 +02:00
										 |  |  |     GraphicsManagement::the().disable_vga_text_mode_console_cursor(); | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  | } | 
					
						
							|  |  |  | void TextModeConsole::show_cursor() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-03-19 14:31:56 +02:00
										 |  |  |     set_cursor(m_x, m_y); | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-08-22 01:49:22 +02:00
										 |  |  |     SpinlockLocker lock(m_vga_lock); | 
					
						
							| 
									
										
										
										
											2021-09-08 18:41:07 +02:00
										 |  |  |     auto* buf = (u16*)m_current_vga_window.offset((x * 2) + (y * width() * 2)).as_ptr(); | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  |     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
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-08-22 01:49:22 +02:00
										 |  |  |     SpinlockLocker 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
 | 
					
						
							| 
									
										
										
										
											2022-03-15 21:41:22 +02:00
										 |  |  |         GraphicsManagement::the().disable_vga_text_mode_console_cursor(); | 
					
						
							| 
									
										
										
										
											2021-06-03 17:41:27 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-09-08 18:41:07 +02:00
										 |  |  |     auto* buf = (u16*)m_current_vga_window.offset((x * 2) + (y * width() * 2)).as_ptr(); | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  |     *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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-01-21 21:00:48 +02:00
										 |  |  |     clear(0, row, width()); | 
					
						
							| 
									
										
										
										
											2021-04-16 22:58:51 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |