1 #include <klibc/string.h>
2 #include <lunaix/device.h>
3 #include <lunaix/lxconsole.h>
4 #include <lunaix/mm/pmm.h>
5 #include <lunaix/mm/vmm.h>
6 #include <lunaix/tty/console.h>
7 #include <lunaix/tty/tty.h>
9 static struct console lx_console;
12 __tty_write(struct device* dev,
20 memset(&lx_console, 0, sizeof(lx_console));
21 lx_console.buffer.data = VGA_BUFFER_VADDR + 0x1000;
22 lx_console.buffer.size = 8192;
23 mutex_init(&lx_console.buffer.lock);
26 for (size_t i = 0; i < PG_ALIGN(lx_console.buffer.size); i += PG_SIZE) {
27 uintptr_t pa = pmm_alloc_page(KERNEL_PID, 0);
28 vmm_set_mapping(PD_REFERENCED,
29 (uintptr_t)lx_console.buffer.data + i,
35 memset(lx_console.buffer.data, 0, lx_console.buffer.size);
37 lx_console.flush_timer = NULL;
39 struct device* tty_dev = device_add(NULL, &lx_console, "tty");
40 tty_dev->write = __tty_write;
44 __tty_write(struct device* dev,
49 struct console* console = (struct console*)dev->underlay;
50 console_write(console, buf, len);
54 console_schedule_flush()
56 // TODO make the flush on-demand rather than periodic
62 struct fifo_buffer* buffer = &lx_console.buffer;
63 mutex_lock(&buffer->lock);
64 size_t p = lx_console.erd_pos - 2;
65 while (p < lx_console.erd_pos && p != buffer->wr_pos &&
66 ((char*)buffer->data)[p] != '\n') {
71 if (p > lx_console.erd_pos) {
75 buffer->flags |= FIFO_DIRTY;
76 lx_console.erd_pos = p;
77 mutex_unlock(&buffer->lock);
81 __find_next_line(size_t start)
84 while (p != lx_console.buffer.wr_pos &&
85 ((char*)lx_console.buffer.data)[p] != '\n') {
86 p = (p + 1) % lx_console.buffer.size;
94 struct fifo_buffer* buffer = &lx_console.buffer;
95 mutex_lock(&buffer->lock);
97 lx_console.erd_pos = __find_next_line(lx_console.erd_pos);
98 buffer->flags |= FIFO_DIRTY;
99 mutex_unlock(&buffer->lock);
105 if (mutex_on_hold(&lx_console.buffer.lock)) {
108 if (!(lx_console.buffer.flags & FIFO_DIRTY)) {
112 tty_flush_buffer(lx_console.buffer.data,
114 lx_console.buffer.wr_pos,
115 lx_console.buffer.size);
116 lx_console.buffer.flags &= ~FIFO_DIRTY;
120 console_write(struct console* console, uint8_t* data, size_t size)
122 mutex_lock(&console->buffer.lock);
123 uint8_t* buffer = console->buffer.data;
124 uintptr_t ptr = console->buffer.wr_pos;
125 uintptr_t rd_ptr = console->buffer.rd_pos;
129 for (size_t i = 0; i < size; i++) {
131 buffer[(ptr + i) % console->buffer.size] = c;
132 lines += (c == '\n');
135 uintptr_t new_ptr = (ptr + size) % console->buffer.size;
136 console->buffer.wr_pos = new_ptr;
138 if (console->lines > TTY_HEIGHT && lines > 0) {
139 console->buffer.rd_pos =
140 __find_next_line((size + rd_ptr) % console->buffer.size);
143 if (new_ptr < ptr + size && new_ptr > rd_ptr) {
144 console->buffer.rd_pos = new_ptr;
147 console->lines += lines;
148 console->erd_pos = console->buffer.rd_pos;
149 console->buffer.flags |= FIFO_DIRTY;
150 mutex_unlock(&console->buffer.lock);
154 console_write_str(char* str)
156 console_write(&lx_console, str, strlen(str));
160 console_write_char(char str)
162 console_write(&lx_console, &str, 1);
166 console_start_flushing()
168 struct lx_timer* timer =
169 timer_run_ms(20, console_flush, NULL, TIMER_MODE_PERIODIC);
170 lx_console.flush_timer = timer;