summaryrefslogtreecommitdiff
path: root/Kernel/Devices
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel/Devices')
-rw-r--r--Kernel/Devices/ConsoleDevice.cpp76
-rw-r--r--Kernel/Devices/ConsoleDevice.h40
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;
+};
+
+}