summaryrefslogtreecommitdiff
path: root/drivers/console.cc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/console.cc')
-rw-r--r--drivers/console.cc119
1 files changed, 119 insertions, 0 deletions
diff --git a/drivers/console.cc b/drivers/console.cc
new file mode 100644
index 0000000..f741dd2
--- /dev/null
+++ b/drivers/console.cc
@@ -0,0 +1,119 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright (C) 2026 Richard Qin */
+
+/*
+ * console.cc — Console character device (/dev/console)
+ *
+ * Wraps the existing early_putc() UART driver as a file_operations
+ * chardev. read() is a stub for now (returns 0 = EOF).
+ * write() sends each byte through early_putc().
+ */
+
+#include <lume/file.h>
+#include <lume/chardev.h>
+#include <lume/types.h>
+
+extern "C" void early_putc(char c);
+
+/* ================================================================== */
+/* console_write */
+/* ================================================================== */
+
+static int64 console_write(file* fp, const char* buf, uint64 count, int64* pos)
+{
+ (void)fp;
+ (void)pos;
+
+ for (uint64 i = 0; i < count; i++) {
+ early_putc(buf[i]);
+ }
+
+ return static_cast<int64>(count);
+}
+
+/* ================================================================== */
+/* console_read — stub (returns 0 = EOF for now) */
+/* ================================================================== */
+
+static int64 console_read(file* fp, char* buf, uint64 count, int64* pos)
+{
+ (void)fp;
+ (void)buf;
+ (void)count;
+ (void)pos;
+ /* TODO: implement UART RX polling/IRQ-based blocking read */
+ return 0;
+}
+
+/* ================================================================== */
+/* null device — /dev/null */
+/* ================================================================== */
+
+static int64 null_read(file* /*fp*/, char* /*buf*/, uint64 /*count*/, int64* /*pos*/)
+{
+ return 0; /* EOF */
+}
+
+static int64 null_write(file* /*fp*/, const char* /*buf*/, uint64 count, int64* /*pos*/)
+{
+ return static_cast<int64>(count); /* discard */
+}
+
+/* ================================================================== */
+/* zero device — /dev/zero */
+/* ================================================================== */
+
+static int64 zero_read(file* /*fp*/, char* buf, uint64 count, int64* /*pos*/)
+{
+ for (uint64 i = 0; i < count; i++) {
+ buf[i] = 0;
+ }
+ return static_cast<int64>(count);
+}
+
+static int64 zero_write(file* /*fp*/, const char* /*buf*/, uint64 count, int64* /*pos*/)
+{
+ return static_cast<int64>(count); /* discard */
+}
+
+/* ================================================================== */
+/* Registration — runtime init (no static initializers!) */
+/* ================================================================== */
+
+static file_operations console_fops;
+static file_operations null_fops;
+static file_operations zero_fops;
+
+static cdev console_cdev;
+static cdev null_cdev;
+static cdev zero_cdev;
+
+void console_cdev_init()
+{
+ /* Console: major=5, minor=1 */
+ console_fops.read = console_read;
+ console_fops.write = console_write;
+
+ console_cdev.name = "console";
+ console_cdev.dev = MKDEV(5, 1);
+ console_cdev.fops = &console_fops;
+ cdev_register(&console_cdev);
+
+ /* /dev/null: major=1, minor=3 */
+ null_fops.read = null_read;
+ null_fops.write = null_write;
+
+ null_cdev.name = "null";
+ null_cdev.dev = MKDEV(1, 3);
+ null_cdev.fops = &null_fops;
+ cdev_register(&null_cdev);
+
+ /* /dev/zero: major=1, minor=5 */
+ zero_fops.read = zero_read;
+ zero_fops.write = zero_write;
+
+ zero_cdev.name = "zero";
+ zero_cdev.dev = MKDEV(1, 5);
+ zero_cdev.fops = &zero_fops;
+ cdev_register(&zero_cdev);
+}