1 #include <klibc/string.h>
2 #include <lunaix/device.h>
3 #include <lunaix/keyboard.h>
4 #include <lunaix/lxconsole.h>
5 #include <lunaix/mm/pmm.h>
6 #include <lunaix/mm/valloc.h>
7 #include <lunaix/mm/vmm.h>
8 #include <lunaix/tty/console.h>
9 #include <lunaix/tty/tty.h>
11 static struct console lx_console;
14 __tty_write(struct device* dev, void* buf, size_t offset, size_t len);
17 __tty_read(struct device* dev, void* buf, size_t offset, size_t len);
22 memset(&lx_console, 0, sizeof(lx_console));
23 fifo_init(&lx_console.output, VGA_BUFFER_VADDR + 0x1000, 8192, 0);
24 fifo_init(&lx_console.input, valloc(4096), 4096, 0);
26 // FIXME use valloc to allocate console buffer.
27 // In doing this, the console buffer can only be accessed from kernel mode
28 // any direct write to this buffer from user land should be purged!
31 for (size_t i = 0; i < PG_ALIGN(lx_console.output.size); i += PG_SIZE) {
32 uintptr_t pa = pmm_alloc_page(KERNEL_PID, 0);
33 vmm_set_mapping(PD_REFERENCED,
34 (uintptr_t)lx_console.output.data + i,
40 lx_console.flush_timer = NULL;
42 struct device* tty_dev = device_addseq(NULL, &lx_console, "tty");
43 tty_dev->write = __tty_write;
44 tty_dev->read = __tty_read;
48 __tty_write(struct device* dev, void* buf, size_t offset, size_t len)
50 struct console* console = (struct console*)dev->underlay;
51 console_write(console, buf, len);
55 __tty_read(struct device* dev, void* buf, size_t offset, size_t len)
57 struct kdb_keyinfo_pkt keyevent;
58 struct console* console = (struct console*)dev->underlay;
60 // FIXME keyboard is duplicating the key that user typed
61 if (!kbd_recv_key(&keyevent)) {
64 if ((keyevent.keycode & 0xff00) <= KEYPAD) {
65 char c = (char)(keyevent.keycode & 0x00ff);
66 if (c == 0x08 && !fifo_backone(&console->input)) {
69 // console_write_char(c);
70 if (!fifo_putone(&console->input, c) || c == '\n') {
75 return fifo_read(&console->input, buf, len);
79 console_schedule_flush()
81 // TODO make the flush on-demand rather than periodic
87 struct fifo_buf* buffer = &lx_console.output;
88 mutex_lock(&buffer->lock);
89 size_t p = lx_console.erd_pos - 2;
90 while (p < lx_console.erd_pos && p != buffer->wr_pos &&
91 ((char*)buffer->data)[p] != '\n') {
96 if (p > lx_console.erd_pos) {
100 buffer->flags |= FIFO_DIRTY;
101 lx_console.erd_pos = p;
102 mutex_unlock(&buffer->lock);
106 __find_next_line(size_t start)
109 while (p != lx_console.output.wr_pos &&
110 ((char*)lx_console.output.data)[p] != '\n') {
111 p = (p + 1) % lx_console.output.size;
119 struct fifo_buf* buffer = &lx_console.output;
120 mutex_lock(&buffer->lock);
122 lx_console.erd_pos = __find_next_line(lx_console.erd_pos);
123 buffer->flags |= FIFO_DIRTY;
124 mutex_unlock(&buffer->lock);
130 if (mutex_on_hold(&lx_console.output.lock)) {
133 if (!(lx_console.output.flags & FIFO_DIRTY)) {
137 tty_flush_buffer(lx_console.output.data,
139 lx_console.output.wr_pos,
140 lx_console.output.size);
141 lx_console.output.flags &= ~FIFO_DIRTY;
145 console_write(struct console* console, uint8_t* data, size_t size)
147 mutex_lock(&console->output.lock);
148 uint8_t* buffer = console->output.data;
149 uintptr_t ptr = console->output.wr_pos;
150 uintptr_t rd_ptr = console->output.rd_pos;
155 for (size_t i = 0; i < size; i++) {
160 buffer[(ptr + j) % console->output.size] = c;
161 lines += (c == '\n');
167 uintptr_t new_ptr = (ptr + size) % console->output.size;
168 console->output.wr_pos = new_ptr;
170 if (console->lines > TTY_HEIGHT && lines > 0) {
171 console->output.rd_pos =
172 __find_next_line((size + rd_ptr) % console->output.size);
175 if (new_ptr < ptr + size && new_ptr > rd_ptr) {
176 console->output.rd_pos = new_ptr;
179 console->lines += lines;
180 console->erd_pos = console->output.rd_pos;
181 console->output.flags |= FIFO_DIRTY;
182 mutex_unlock(&console->output.lock);
186 console_write_str(char* str)
188 console_write(&lx_console, str, strlen(str));
192 console_write_char(char str)
194 console_write(&lx_console, &str, 1);
198 console_start_flushing()
200 struct lx_timer* timer =
201 timer_run_ms(20, console_flush, NULL, TIMER_MODE_PERIODIC);
202 lx_console.flush_timer = timer;