1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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);
}
|