diff options
Diffstat (limited to 'Kernel/Devices')
-rw-r--r-- | Kernel/Devices/ConsoleDevice.cpp | 76 | ||||
-rw-r--r-- | Kernel/Devices/ConsoleDevice.h | 40 |
2 files changed, 116 insertions, 0 deletions
diff --git a/Kernel/Devices/ConsoleDevice.cpp b/Kernel/Devices/ConsoleDevice.cpp new file mode 100644 index 0000000000..d782848f0e --- /dev/null +++ b/Kernel/Devices/ConsoleDevice.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <AK/Singleton.h> +#include <Kernel/Devices/ConsoleDevice.h> +#include <Kernel/IO.h> +#include <Kernel/Locking/Spinlock.h> +#include <Kernel/Sections.h> +#include <Kernel/kstdio.h> + +// Output bytes to kernel debug port 0xE9 (Bochs console). It's very handy. +#define CONSOLE_OUT_TO_BOCHS_DEBUG_PORT + +static Singleton<ConsoleDevice> s_the; +static Kernel::Spinlock g_console_lock; + +UNMAP_AFTER_INIT void ConsoleDevice::initialize() +{ + s_the.ensure_instance(); + s_the->after_inserting(); +} + +ConsoleDevice& ConsoleDevice::the() +{ + return *s_the; +} + +bool ConsoleDevice::is_initialized() +{ + return s_the.is_initialized(); +} + +UNMAP_AFTER_INIT ConsoleDevice::ConsoleDevice() + : CharacterDevice(5, 1) +{ +} + +UNMAP_AFTER_INIT ConsoleDevice::~ConsoleDevice() +{ +} + +bool ConsoleDevice::can_read(const Kernel::OpenFileDescription&, size_t) const +{ + return false; +} + +Kernel::KResultOr<size_t> ConsoleDevice::read(OpenFileDescription&, u64, Kernel::UserOrKernelBuffer&, size_t) +{ + // FIXME: Implement reading from the console. + // Maybe we could use a ring buffer for this device? + return 0; +} + +Kernel::KResultOr<size_t> ConsoleDevice::write(OpenFileDescription&, u64, const Kernel::UserOrKernelBuffer& data, size_t size) +{ + if (!size) + return 0; + + return data.read_buffered<256>(size, [&](ReadonlyBytes readonly_bytes) { + for (const auto& byte : readonly_bytes) + put_char(byte); + return readonly_bytes.size(); + }); +} + +void ConsoleDevice::put_char(char ch) +{ + Kernel::SpinlockLocker lock(g_console_lock); +#ifdef CONSOLE_OUT_TO_BOCHS_DEBUG_PORT + IO::out8(IO::BOCHS_DEBUG_PORT, ch); +#endif + m_logbuffer.enqueue(ch); +} diff --git a/Kernel/Devices/ConsoleDevice.h b/Kernel/Devices/ConsoleDevice.h new file mode 100644 index 0000000000..9bcd5f1160 --- /dev/null +++ b/Kernel/Devices/ConsoleDevice.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/CircularQueue.h> +#include <AK/Vector.h> +#include <Kernel/Devices/CharacterDevice.h> + +namespace Kernel { + +class ConsoleDevice final : public CharacterDevice { + AK_MAKE_ETERNAL +public: + static ConsoleDevice& the(); + static void initialize(); + static bool is_initialized(); + + ConsoleDevice(); + virtual ~ConsoleDevice() override; + + // ^CharacterDevice + virtual bool can_read(const Kernel::OpenFileDescription&, size_t) const override; + virtual bool can_write(const Kernel::OpenFileDescription&, size_t) const override { return true; } + virtual Kernel::KResultOr<size_t> read(OpenFileDescription&, u64, Kernel::UserOrKernelBuffer&, size_t) override; + virtual Kernel::KResultOr<size_t> write(OpenFileDescription&, u64, const Kernel::UserOrKernelBuffer&, size_t) override; + virtual StringView class_name() const override { return "Console"; } + + void put_char(char); + + const CircularQueue<char, 16384>& logbuffer() const { return m_logbuffer; } + +private: + CircularQueue<char, 16384> m_logbuffer; +}; + +} |