diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2025-07-24 20:51:55 +0000 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2025-07-24 20:51:55 +0000 |
| commit | dd04850c27e8bc273506f4a64bb28b7ddf111dc5 (patch) | |
| tree | a00212f5c903e80e4e729c87ce34ece2c40e4ee6 | |
| parent | feac668578a35aac280b59d478a57b6937bb68da (diff) | |
| download | teachos-dd04850c27e8bc273506f4a64bb28b7ddf111dc5.tar.xz teachos-dd04850c27e8bc273506f4a64bb28b7ddf111dc5.zip | |
kapi: rework text device interface
| -rw-r--r-- | arch/x86_64/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | arch/x86_64/include/x86_64/vga/text.hpp | 122 | ||||
| -rw-r--r-- | arch/x86_64/kapi/cio.cpp | 16 | ||||
| -rw-r--r-- | arch/x86_64/kapi/io.cpp | 36 | ||||
| -rw-r--r-- | arch/x86_64/src/vga/text.cpp | 23 | ||||
| -rw-r--r-- | kapi/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | kapi/include/kapi/cio.hpp | 29 | ||||
| -rw-r--r-- | kapi/include/kapi/io.hpp | 17 | ||||
| -rw-r--r-- | kapi/src/cio.cpp | 29 | ||||
| -rw-r--r-- | kapi/src/system.cpp | 10 | ||||
| -rw-r--r-- | src/main.cpp | 6 |
11 files changed, 148 insertions, 145 deletions
diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt index c585cbf..e8b5162 100644 --- a/arch/x86_64/CMakeLists.txt +++ b/arch/x86_64/CMakeLists.txt @@ -12,7 +12,7 @@ target_link_libraries("x86_64" PUBLIC target_sources("x86_64" PRIVATE # api::kapi implementation - "kapi/io.cpp" + "kapi/cio.cpp" "kapi/memory.cpp" "kapi/system.cpp" diff --git a/arch/x86_64/include/x86_64/vga/text.hpp b/arch/x86_64/include/x86_64/vga/text.hpp index 267eae9..f8e6f1b 100644 --- a/arch/x86_64/include/x86_64/vga/text.hpp +++ b/arch/x86_64/include/x86_64/vga/text.hpp @@ -1,9 +1,10 @@ #ifndef TEACHOS_X86_64_VIDEO_VGA_TEXT_HPP #define TEACHOS_X86_64_VIDEO_VGA_TEXT_HPP +#include "kapi/cio.hpp" + #include <cstdint> #include <string_view> -#include <type_traits> namespace teachos::x86_64::vga::text { @@ -89,84 +90,57 @@ namespace teachos::x86_64::vga::text attribute{color::gray, foreground_flag::intense, color::red, background_flag::none}; } // namespace common_attributes - /** - * @brief Clear the VGA text mode buffer. - * - * @note This function also resets the text mode buffer pointer. - * - * @param attribute The attribute to "clear" the screen with. - */ - auto clear(attribute attribute = common_attributes::gray_on_black) -> void; - - /** - * @brief Enable or disable the VGA text mode cursor. - * - * @param enabled Whether or not to enable the cursors. - */ - auto cursor(bool enabled) -> void; + struct device final : teachos::cio::output_device + { + /** + * @brief Clear the VGA text mode buffer. + * + * @note This function also resets the text mode buffer pointer. + * + * @param attribute The attribute to "clear" the screen with. + */ + auto clear(attribute attribute = common_attributes::gray_on_black) -> void; - /** - * @brief Move the cursor to a new line, scrolling the buffer if necessary. - */ - auto newline() -> void; + /** + * @brief Enable or disable the VGA text mode cursor. + * + * @param enabled Whether or not to enable the cursors. + */ + auto cursor(bool enabled) -> void; - /** - * @brief Write a string of code points to the VGA text buffer. - * - * @note This function also updates the text mode buffer pointer. - * - * @param code_points A string of (8-bit) code points to write to the VGA text mode buffer. - * @param attribute The attribute to apply to the written sequence of code points. - * @see vga::text::attribute - */ - auto write(std::string_view code_points, attribute attribute) -> void; + auto write(std::string_view text) -> void override { write(text, common_attributes::green_on_black); } + auto writeln(std::string_view text) -> void override { writeln(text, common_attributes::green_on_black); } + auto write_error(std::string_view text) -> void override { write(text, common_attributes::red_on_black); } + auto writeln_error(std::string_view text) -> void override { writeln(text, common_attributes::red_on_black); } - /** - * @brief Write a single character to the VGA text buffer. - * - * @note This function also updates the text mode buffer pointer. - * - * @param code_point A code point to write to the VGA text mode buffer. - * @param attribute The attribute to apply to the written sequence of code points. - * @see vga::text::attribute - */ - auto write_char(char code_point, attribute attribute) -> void; + private: + /** + * @brief Move the cursor to a new line, scrolling the buffer if necessary. + */ + auto newline() -> void; - template<typename T> - concept Integral = std::is_integral_v<T>; + /** + * @brief Write a string of code points to the VGA text buffer. + * + * @note This function also updates the text mode buffer pointer. + * + * @param code_points A string of (8-bit) code points to write to the VGA text mode buffer. + * @param attribute The attribute to apply to the written sequence of code points. + * @see vga::text::attribute + */ + auto write(std::string_view code_points, attribute attribute) -> void; - /** - * @brief Write a integral value to the VGA text buffer. - * - * @note This function also updates the text mode buffer pointer. - * - * @param value A integral value to write to the VGA text mode buffer. - * @param attribute The attribute to apply to the written sequence of code points. - * @see vga::text::attribute - */ - template<Integral T> - auto write_number(T value, attribute attribute) -> void - { - T current_value = value; - T divisor = 1; - - while (current_value > 9) - { - divisor *= 10; - current_value = current_value / 10; - } - - current_value = value; - while (divisor > 0) - { - uint8_t quotient = current_value / divisor; - char ascii_digit = quotient + '0'; - - write_char(ascii_digit, attribute); - current_value %= divisor; - divisor /= 10; - } - } + /** + * @brief Write a string of code points followed by a newline to the VGA text buffer. + * + * @note This function also updates the text mode buffer pointer. + * + * @param code_points A string of (8-bit) code points to write to the VGA text mode buffer. + * @param attribute The attribute to apply to the written sequence of code points. + * @see vga::text::attribute + */ + auto writeln(std::string_view code_points, attribute attribute) -> void; + }; } // namespace teachos::x86_64::vga::text diff --git a/arch/x86_64/kapi/cio.cpp b/arch/x86_64/kapi/cio.cpp new file mode 100644 index 0000000..ac3ae39 --- /dev/null +++ b/arch/x86_64/kapi/cio.cpp @@ -0,0 +1,16 @@ +#include "kapi/cio.hpp" + +#include "x86_64/vga/text.hpp" + +namespace teachos::cio +{ + + auto static constinit vga_device = std::optional<x86_64::vga::text::device>{}; + + auto init() -> void + { + vga_device.emplace(); + set_output_device(*vga_device); + } + +} // namespace teachos::cio diff --git a/arch/x86_64/kapi/io.cpp b/arch/x86_64/kapi/io.cpp deleted file mode 100644 index eab6473..0000000 --- a/arch/x86_64/kapi/io.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "kapi/io.hpp" - -#include "x86_64/vga/text.hpp" - -namespace teachos::io -{ - - auto init() -> void - { - x86_64::vga::text::clear(); - x86_64::vga::text::cursor(false); - } - - auto print(std::string_view text) -> void - { - x86_64::vga::text::write(text, x86_64::vga::text::common_attributes::green_on_black); - } - - auto println(std::string_view text) -> void - { - x86_64::vga::text::write(text, x86_64::vga::text::common_attributes::green_on_black); - x86_64::vga::text::newline(); - } - - auto print_error(std::string_view text) -> void - { - x86_64::vga::text::write(text, x86_64::vga::text::common_attributes::red_on_black); - } - - auto println_error(std::string_view text) -> void - { - x86_64::vga::text::write(text, x86_64::vga::text::common_attributes::red_on_black); - x86_64::vga::text::newline(); - } - -} // namespace teachos::io diff --git a/arch/x86_64/src/vga/text.cpp b/arch/x86_64/src/vga/text.cpp index 5c94b84..af089fd 100644 --- a/arch/x86_64/src/vga/text.cpp +++ b/arch/x86_64/src/vga/text.cpp @@ -13,19 +13,24 @@ namespace teachos::x86_64::vga::text { namespace { - auto buffer_offset = std::ptrdiff_t{}; + auto constinit buffer_offset = std::ptrdiff_t{}; auto constexpr DEFAULT_TEXT_BUFFER_WIDTH = 80U; auto constexpr DEFAULT_TEXT_BUFFER_HEIGHT = 25U; + + auto write_char(char code_point, attribute attribute) -> void + { + vga_buffer_pointer[buffer_offset++] = std::pair{code_point, std::bit_cast<std::byte>(attribute)}; + }; } // namespace - auto clear(attribute attribute) -> void + auto device::clear(attribute attribute) -> void { buffer_offset = 0; std::ranges::fill_n(vga_buffer_pointer.get(), 2000, std::pair{' ', std::bit_cast<std::byte>(attribute)}); } - auto cursor(bool enabled) -> void + auto device::cursor(bool enabled) -> void { auto cursor_disable_byte = std::byte{!enabled} << 5; @@ -33,7 +38,7 @@ namespace teachos::x86_64::vga::text crtc::data::write(crtc::data::read() | cursor_disable_byte); } - auto newline() -> void + auto device::newline() -> void { auto current_line = buffer_offset / DEFAULT_TEXT_BUFFER_WIDTH; auto next_line = current_line + 1; @@ -51,13 +56,15 @@ namespace teachos::x86_64::vga::text } } - auto write_char(char code_point, attribute attribute) -> void + auto device::write(std::string_view code_points, attribute attribute) -> void { - vga_buffer_pointer[buffer_offset++] = std::pair{code_point, std::bit_cast<std::byte>(attribute)}; - }; + std::ranges::for_each(code_points, [&](auto code_point) { write_char(code_point, attribute); }); + } - auto write(std::string_view code_points, attribute attribute) -> void + auto device::writeln(std::string_view code_points, attribute attribute) -> void { std::ranges::for_each(code_points, [&](auto code_point) { write_char(code_point, attribute); }); + newline(); } + } // namespace teachos::x86_64::vga::text diff --git a/kapi/CMakeLists.txt b/kapi/CMakeLists.txt index 3a15fee..14244bc 100644 --- a/kapi/CMakeLists.txt +++ b/kapi/CMakeLists.txt @@ -5,12 +5,13 @@ target_sources("kapi" PUBLIC FILE_SET HEADERS BASE_DIRS "include" FILES - "include/kapi/io.hpp" + "include/kapi/cio.hpp" "include/kapi/memory.hpp" "include/kapi/system.hpp" ) target_sources("kapi" PRIVATE + "src/cio.cpp" "src/system.cpp" ) diff --git a/kapi/include/kapi/cio.hpp b/kapi/include/kapi/cio.hpp new file mode 100644 index 0000000..6b93638 --- /dev/null +++ b/kapi/include/kapi/cio.hpp @@ -0,0 +1,29 @@ +#ifndef TEACHOS_KAPI_IO_HPP +#define TEACHOS_KAPI_IO_HPP + +#include <optional> +#include <string_view> + +namespace teachos::cio +{ + struct output_device + { + auto virtual write(std::string_view text [[maybe_unused]]) -> void {} + auto virtual writeln(std::string_view text [[maybe_unused]]) -> void {} + + auto virtual write_error(std::string_view text [[maybe_unused]]) -> void {} + auto virtual writeln_error(std::string_view text [[maybe_unused]]) -> void {} + }; + + auto init() -> void; + + auto set_output_device(output_device & device) -> std::optional<output_device *>; + + auto print(std::string_view text) -> void; + auto println(std::string_view text) -> void; + + auto print_error(std::string_view text) -> void; + auto println_error(std::string_view text) -> void; +} // namespace teachos::cio + +#endif diff --git a/kapi/include/kapi/io.hpp b/kapi/include/kapi/io.hpp deleted file mode 100644 index 764738f..0000000 --- a/kapi/include/kapi/io.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef TEACHOS_KAPI_IO_HPP -#define TEACHOS_KAPI_IO_HPP - -#include <string_view> - -namespace teachos::io -{ - auto init() -> void; - - auto print(std::string_view text) -> void; - auto println(std::string_view text) -> void; - - auto print_error(std::string_view text) -> void; - auto println_error(std::string_view text) -> void; -} // namespace teachos::io - -#endif diff --git a/kapi/src/cio.cpp b/kapi/src/cio.cpp new file mode 100644 index 0000000..aa26d49 --- /dev/null +++ b/kapi/src/cio.cpp @@ -0,0 +1,29 @@ +#include "kapi/cio.hpp" + +#include <optional> +#include <utility> + +namespace teachos::cio +{ + auto constinit null_device = output_device{}; + + auto constinit active_device = &null_device; + + auto set_output_device(output_device & device) -> std::optional<output_device *> + { + if (&device == active_device) + { + return {}; + } + return std::exchange(active_device, &device); + } + + auto print(std::string_view text) -> void { active_device->write(text); } + + auto println(std::string_view text) -> void { active_device->writeln(text); } + + auto print_error(std::string_view text) -> void { active_device->write_error(text); } + + auto println_error(std::string_view text) -> void { active_device->writeln_error(text); } + +} // namespace teachos::cio
\ No newline at end of file diff --git a/kapi/src/system.cpp b/kapi/src/system.cpp index c3b1c5e..041404e 100644 --- a/kapi/src/system.cpp +++ b/kapi/src/system.cpp @@ -1,16 +1,16 @@ #include "kapi/system.hpp" -#include "kapi/io.hpp" +#include "kapi/cio.hpp" namespace teachos::system { auto panic(std::string_view message, std::source_location location) -> void { - io::println_error("!!!Kernel Panic!!! "); - io::println_error(message); - io::println_error(location.file_name()); - io::println_error(location.function_name()); + cio::println_error("!!!Kernel Panic!!! "); + cio::println_error(message); + cio::println_error(location.file_name()); + cio::println_error(location.function_name()); halt(); } diff --git a/src/main.cpp b/src/main.cpp index d6199d0..120e7e0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,11 +1,11 @@ -#include "kapi/io.hpp" +#include "kapi/cio.hpp" #include "kapi/memory.hpp" #include "kapi/system.hpp" auto main() -> int { - teachos::io::init(); - teachos::io::println("[OS] IO subsystem initialized."); + teachos::cio::init(); + teachos::cio::println("[OS] IO subsystem initialized."); teachos::memory::init(); |
