(Maybe) better console subsystem
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
#include "arch/amd64/multiboot2.h"
|
||||
#include "arch/amd64/hw/vesa.h"
|
||||
#include "sys/display.h"
|
||||
#include "sys/debug.h"
|
||||
#include "sys/mm.h"
|
||||
|
||||
static struct display display_vesa_fb;
|
||||
|
||||
void amd64_vesa_init(struct multiboot_tag_framebuffer *tag) {
|
||||
if (tag->common.framebuffer_type == 1) {
|
||||
//vesa_available = 1;
|
||||
//vesa_addr = MM_VIRTUALIZE(tag->common.framebuffer_addr);
|
||||
//vesa_pitch = tag->common.framebuffer_pitch;
|
||||
//vesa_width = tag->common.framebuffer_width;
|
||||
//vesa_height = tag->common.framebuffer_height;
|
||||
//vesa_bpp = tag->common.framebuffer_bpp;
|
||||
kdebug("Initializing VESA framebuffer\n");
|
||||
display_vesa_fb.flags = DISP_GRAPHIC | DISP_LFB;
|
||||
display_vesa_fb.width_pixels = tag->common.framebuffer_width;
|
||||
display_vesa_fb.height_pixels = tag->common.framebuffer_height;
|
||||
display_vesa_fb.bpp = tag->common.framebuffer_bpp;
|
||||
display_vesa_fb.pitch = tag->common.framebuffer_pitch;
|
||||
display_vesa_fb.framebuffer = MM_VIRTUALIZE(tag->common.framebuffer_addr);
|
||||
list_head_init(&display_vesa_fb.list);
|
||||
|
||||
display_add(&display_vesa_fb);
|
||||
|
||||
//kdebug("Set up VESA video:\n");
|
||||
//kdebug("BPP: %d, Width: %d, Height: %d\n", vesa_bpp, vesa_width, vesa_height);
|
||||
//kdebug("Addr: %p\n", vesa_addr);
|
||||
|
||||
//dev_add(DEV_CLASS_BLOCK, DEV_BLOCK_OTHER, &_vesa_fb0, "fb0");
|
||||
}
|
||||
}
|
||||
+5
-6
@@ -107,12 +107,11 @@ void kernel_early_init(void) {
|
||||
amd64_mm_init();
|
||||
|
||||
// Console can only be initialized after memory buffers can be allocated
|
||||
//#if defined(VESA_ENABLE)
|
||||
// if (multiboot_tag_framebuffer) {
|
||||
// amd64_vesa_init(multiboot_tag_framebuffer);
|
||||
// }
|
||||
// amd64_con_init();
|
||||
//#endif
|
||||
#if defined(VESA_ENABLE)
|
||||
if (multiboot_tag_framebuffer) {
|
||||
amd64_vesa_init(multiboot_tag_framebuffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
ps2_register_device();
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ DEFINES+=-DVESA_ENABLE=1 \
|
||||
-DVESA_HEIGHT=$(VESA_HEIGHT) \
|
||||
-DVESA_DEPTH=$(VESA_DEPTH) \
|
||||
-DVESA_MODE=0
|
||||
#OBJS+=$(O)/arch/amd64/hw/vesa.o
|
||||
OBJS+=$(O)/arch/amd64/hw/vesa.o
|
||||
endif
|
||||
|
||||
### From config
|
||||
|
||||
@@ -64,6 +64,8 @@ OBJS+=$(O)/sys/ubsan.o \
|
||||
$(O)/sys/mem/shmem.o \
|
||||
$(O)/sys/mem/slab.o \
|
||||
$(O)/sys/wait.o \
|
||||
$(O)/sys/console.o \
|
||||
$(O)/sys/display.o \
|
||||
$(O)/sys/mod.o
|
||||
DIRS+=$(O)/sys \
|
||||
$(O)/sys/char \
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
|
||||
struct multiboot_tag_framebuffer;
|
||||
|
||||
extern int vesa_available, vesa_hold;
|
||||
extern uint32_t vesa_width, vesa_height, vesa_pitch, vesa_bpp;
|
||||
extern uint64_t vesa_addr;
|
||||
//extern int vesa_available, vesa_hold;
|
||||
//extern uint32_t vesa_width, vesa_height, vesa_pitch, vesa_bpp;
|
||||
//extern uint64_t vesa_addr;
|
||||
|
||||
void amd64_vesa_init(struct multiboot_tag_framebuffer *info);
|
||||
void vesa_put(uint32_t x, uint32_t y, uint32_t v);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
#include "sys/types.h"
|
||||
|
||||
struct chrdev;
|
||||
extern struct chrdev *g_keyboard_tty;
|
||||
struct console;
|
||||
extern struct console *g_keyboard_console;
|
||||
|
||||
#define INPUT_MOD_CONTROL (1 << 0)
|
||||
#define INPUT_MOD_SHIFT (1 << 1)
|
||||
|
||||
+10
-3
@@ -1,14 +1,19 @@
|
||||
#pragma once
|
||||
#include "sys/types.h"
|
||||
#include "sys/list.h"
|
||||
|
||||
struct chrdev;
|
||||
struct console;
|
||||
struct console_buffer;
|
||||
|
||||
struct tty_data {
|
||||
// Process group ID of the foreground group (session leader)
|
||||
pid_t fg_pgid;
|
||||
// Output device info
|
||||
void *out_dev;
|
||||
int (*out_putc) (void *dev, char c);
|
||||
// Console to which the TTY is attached
|
||||
struct console *master;
|
||||
struct console_buffer *buffer;
|
||||
// List link of TTYs which share the same console
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
// From keyboard handlers and stuff
|
||||
@@ -19,4 +24,6 @@ void tty_data_write(struct chrdev *n, char c);
|
||||
void tty_puts(struct chrdev *n, const char *s);
|
||||
void tty_putc(struct chrdev *n, char c);
|
||||
|
||||
int tty_create(struct console *con);
|
||||
|
||||
void tty_init(void);
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
#include "sys/types.h"
|
||||
#include "sys/list.h"
|
||||
|
||||
struct chrdev;
|
||||
struct display;
|
||||
struct console_buffer;
|
||||
|
||||
struct console {
|
||||
struct display *display;
|
||||
|
||||
// Current display
|
||||
struct chrdev *tty_active;
|
||||
struct console_buffer *buf_active;
|
||||
|
||||
// This console's slaves
|
||||
struct list_head slaves;
|
||||
// All consoles
|
||||
struct list_head list;
|
||||
|
||||
uint16_t width_chars, height_chars;
|
||||
};
|
||||
|
||||
// Enslave a TTY to a physical console
|
||||
void console_attach(struct console *con, struct chrdev *tty);
|
||||
|
||||
void console_resize(struct console *con, uint16_t new_width, uint16_t new_height);
|
||||
|
||||
void console_putc(struct console *con, struct chrdev *tty, int c);
|
||||
void console_type(struct console *con, int c);
|
||||
|
||||
void console_default_putc(int c);
|
||||
|
||||
struct console *console_get_default(void);
|
||||
|
||||
void console_init_default(void);
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
#include "sys/types.h"
|
||||
#include "sys/list.h"
|
||||
|
||||
// Not a text mode
|
||||
#define DISP_GRAPHIC (1 << 0)
|
||||
// Has a linear framebuffer
|
||||
#define DISP_LFB (1 << 1)
|
||||
|
||||
struct display {
|
||||
// Text modes: set character at y, x
|
||||
void (*setc) (uint16_t y, uint16_t x, uint16_t c);
|
||||
// If DISP_GRAPHIC and not DISP_LFB
|
||||
void (*setpixel) (uint32_t x, uint32_t y, uint32_t c);
|
||||
|
||||
uint32_t flags;
|
||||
// If DISP_GRAPHIC
|
||||
uint32_t width_pixels, height_pixels;
|
||||
uint32_t bpp, pitch;
|
||||
// If DISP_LFB
|
||||
uintptr_t framebuffer;
|
||||
|
||||
uint16_t width_chars, height_chars;
|
||||
|
||||
// Private data
|
||||
void *data;
|
||||
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
void display_add(struct display *d);
|
||||
struct display *display_create(void);
|
||||
|
||||
void display_setc(struct display *disp, uint16_t y, uint16_t x, uint16_t ch);
|
||||
|
||||
struct display *display_get_default(void);
|
||||
@@ -14,5 +14,7 @@ struct psf_font {
|
||||
uint32_t width;
|
||||
};
|
||||
|
||||
void psf_init(uintptr_t addr, uintptr_t pitch, uint16_t *charw, uint16_t *charh);
|
||||
void psf_draw(uint16_t row, uint16_t col, uint8_t c, uint32_t fg, uint32_t bg);
|
||||
extern struct psf_font *font;
|
||||
|
||||
struct display;
|
||||
void psf_draw(struct display *disp, uint16_t row, uint16_t col, uint8_t c, uint32_t fg, uint32_t bg);
|
||||
|
||||
+52
-47
@@ -1,51 +1,56 @@
|
||||
#include "sys/char/input.h"
|
||||
#include "sys/char/tty.h"
|
||||
#include "sys/console.h"
|
||||
#include "sys/debug.h"
|
||||
#include "sys/ctype.h"
|
||||
|
||||
struct chrdev *g_keyboard_tty = 0;
|
||||
struct console *g_keyboard_console = NULL;
|
||||
|
||||
void input_scan(uint8_t c) {
|
||||
switch (c) {
|
||||
case INPUT_KEY_UP:
|
||||
tty_data_write(g_keyboard_tty, '\033');
|
||||
tty_data_write(g_keyboard_tty, '[');
|
||||
tty_data_write(g_keyboard_tty, 'A');
|
||||
break;
|
||||
case INPUT_KEY_DOWN:
|
||||
tty_data_write(g_keyboard_tty, '\033');
|
||||
tty_data_write(g_keyboard_tty, '[');
|
||||
tty_data_write(g_keyboard_tty, 'B');
|
||||
break;
|
||||
case INPUT_KEY_RIGHT:
|
||||
tty_data_write(g_keyboard_tty, '\033');
|
||||
tty_data_write(g_keyboard_tty, '[');
|
||||
tty_data_write(g_keyboard_tty, 'C');
|
||||
break;
|
||||
case INPUT_KEY_LEFT:
|
||||
tty_data_write(g_keyboard_tty, '\033');
|
||||
tty_data_write(g_keyboard_tty, '[');
|
||||
tty_data_write(g_keyboard_tty, 'D');
|
||||
break;
|
||||
case INPUT_KEY_HOME:
|
||||
tty_data_write(g_keyboard_tty, '\033');
|
||||
tty_data_write(g_keyboard_tty, '[');
|
||||
tty_data_write(g_keyboard_tty, '[');
|
||||
tty_data_write(g_keyboard_tty, 'H');
|
||||
break;
|
||||
case INPUT_KEY_END:
|
||||
tty_data_write(g_keyboard_tty, '\033');
|
||||
tty_data_write(g_keyboard_tty, '[');
|
||||
tty_data_write(g_keyboard_tty, '[');
|
||||
tty_data_write(g_keyboard_tty, 'F');
|
||||
break;
|
||||
default:
|
||||
kdebug("Ignoring unhandled key: %02x\n", c);
|
||||
break;
|
||||
}
|
||||
//switch (c) {
|
||||
//case INPUT_KEY_UP:
|
||||
// tty_data_write(g_keyboard_tty, '\033');
|
||||
// tty_data_write(g_keyboard_tty, '[');
|
||||
// tty_data_write(g_keyboard_tty, 'A');
|
||||
// break;
|
||||
//case INPUT_KEY_DOWN:
|
||||
// tty_data_write(g_keyboard_tty, '\033');
|
||||
// tty_data_write(g_keyboard_tty, '[');
|
||||
// tty_data_write(g_keyboard_tty, 'B');
|
||||
// break;
|
||||
//case INPUT_KEY_RIGHT:
|
||||
// tty_data_write(g_keyboard_tty, '\033');
|
||||
// tty_data_write(g_keyboard_tty, '[');
|
||||
// tty_data_write(g_keyboard_tty, 'C');
|
||||
// break;
|
||||
//case INPUT_KEY_LEFT:
|
||||
// tty_data_write(g_keyboard_tty, '\033');
|
||||
// tty_data_write(g_keyboard_tty, '[');
|
||||
// tty_data_write(g_keyboard_tty, 'D');
|
||||
// break;
|
||||
//case INPUT_KEY_HOME:
|
||||
// tty_data_write(g_keyboard_tty, '\033');
|
||||
// tty_data_write(g_keyboard_tty, '[');
|
||||
// tty_data_write(g_keyboard_tty, '[');
|
||||
// tty_data_write(g_keyboard_tty, 'H');
|
||||
// break;
|
||||
//case INPUT_KEY_END:
|
||||
// tty_data_write(g_keyboard_tty, '\033');
|
||||
// tty_data_write(g_keyboard_tty, '[');
|
||||
// tty_data_write(g_keyboard_tty, '[');
|
||||
// tty_data_write(g_keyboard_tty, 'F');
|
||||
// break;
|
||||
//default:
|
||||
// kdebug("Ignoring unhandled key: %02x\n", c);
|
||||
// break;
|
||||
//}
|
||||
}
|
||||
|
||||
void input_key(uint8_t key, uint8_t mods, const char *map0, const char *map1) {
|
||||
if (!g_keyboard_console) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(mods & INPUT_MOD_CONTROL)) {
|
||||
const char *map = (mods & INPUT_MOD_SHIFT) ? map1 : map0;
|
||||
uint8_t c = map[key];
|
||||
@@ -60,20 +65,20 @@ void input_key(uint8_t key, uint8_t mods, const char *map0, const char *map1) {
|
||||
}
|
||||
|
||||
// Normal key
|
||||
tty_data_write(g_keyboard_tty, c);
|
||||
console_type(g_keyboard_console, c);
|
||||
} else {
|
||||
// Special keys
|
||||
input_scan(c);
|
||||
}
|
||||
} else {
|
||||
char c = map0[key];
|
||||
//char c = map0[key];
|
||||
|
||||
switch (c) {
|
||||
case 'c':
|
||||
case '.':
|
||||
case 'd':
|
||||
tty_control_write(g_keyboard_tty, c);
|
||||
break;
|
||||
}
|
||||
//switch (c) {
|
||||
//case 'c':
|
||||
//case '.':
|
||||
//case 'd':
|
||||
// tty_control_write(g_keyboard_tty, c);
|
||||
// break;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
+75
-21
@@ -10,6 +10,7 @@
|
||||
#include "arch/amd64/cpu.h"
|
||||
#include "sys/char/tty.h"
|
||||
#include "sys/char/chr.h"
|
||||
#include "sys/console.h"
|
||||
#include "sys/string.h"
|
||||
#include "sys/thread.h"
|
||||
#include "sys/assert.h"
|
||||
@@ -17,28 +18,14 @@
|
||||
#include "sys/debug.h"
|
||||
#include "sys/sched.h"
|
||||
#include "sys/panic.h"
|
||||
#include "sys/heap.h"
|
||||
#include "sys/dev.h"
|
||||
#include "sys/mm.h"
|
||||
|
||||
static ssize_t tty_write(struct chrdev *tty, const void *buf, size_t pos, size_t lim);
|
||||
static int tty_ioctl(struct chrdev *tty, unsigned int cmd, void *arg);
|
||||
|
||||
// Keyboard + display
|
||||
static struct tty_data _dev_tty0_data = {
|
||||
.fg_pgid = 1,
|
||||
.out_dev = NULL,
|
||||
.out_putc = NULL, //pc_con_putc
|
||||
};
|
||||
|
||||
static struct chrdev _dev_tty0 = {
|
||||
.type = CHRDEV_TTY,
|
||||
.dev_data = &_dev_tty0_data,
|
||||
.tc = TERMIOS_DEFAULT,
|
||||
.write = tty_write,
|
||||
// Line discipline
|
||||
.read = line_read,
|
||||
.ioctl = tty_ioctl
|
||||
};
|
||||
static const struct termios default_termios = TERMIOS_DEFAULT;
|
||||
|
||||
void tty_control_write(struct chrdev *tty, char c) {
|
||||
struct tty_data *data = tty->dev_data;
|
||||
@@ -98,18 +85,47 @@ void tty_puts(struct chrdev *tty, const char *s) {
|
||||
}
|
||||
}
|
||||
|
||||
int tty_create(struct console *master) {
|
||||
struct chrdev *tty = kmalloc(sizeof(struct chrdev));
|
||||
_assert(tty);
|
||||
|
||||
struct tty_data *data = kmalloc(sizeof(struct tty_data));
|
||||
_assert(data);
|
||||
|
||||
data->fg_pgid = 1;
|
||||
data->master = NULL;
|
||||
data->buffer = NULL;
|
||||
list_head_init(&data->list);
|
||||
|
||||
tty->type = CHRDEV_TTY;
|
||||
memcpy(&tty->tc, &default_termios, sizeof(struct termios));
|
||||
tty->write = tty_write;
|
||||
tty->ioctl = tty_ioctl;
|
||||
tty->read = line_read;
|
||||
tty->dev_data = data;
|
||||
|
||||
ring_init(&tty->buffer, 16);
|
||||
|
||||
console_attach(master, tty);
|
||||
|
||||
dev_add(DEV_CLASS_CHAR, DEV_CHAR_TTY, tty, "tty0");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tty_putc(struct chrdev *tty, char c) {
|
||||
struct tty_data *data = tty->dev_data;
|
||||
_assert(data);
|
||||
//_assert(data->out_putc);
|
||||
//data->out_putc(data->out_dev, c);
|
||||
_assert(data->master);
|
||||
|
||||
console_putc(data->master, tty, c);
|
||||
}
|
||||
|
||||
void tty_init(void) {
|
||||
// tty0
|
||||
ring_init(&_dev_tty0.buffer, 16);
|
||||
g_keyboard_tty = &_dev_tty0;
|
||||
dev_add(DEV_CLASS_CHAR, DEV_CHAR_TTY, &_dev_tty0, "tty0");
|
||||
// ring_init(&_dev_tty0.buffer, 16);
|
||||
// g_keyboard_tty = &_dev_tty0;
|
||||
// dev_add(DEV_CLASS_CHAR, DEV_CHAR_TTY, &_dev_tty0, "tty0");
|
||||
|
||||
// ttyS0
|
||||
//ring_init(&_dev_ttyS0.buffer, 16);
|
||||
@@ -118,9 +134,47 @@ void tty_init(void) {
|
||||
}
|
||||
|
||||
static ssize_t tty_write(struct chrdev *tty, const void *buf, size_t pos, size_t lim) {
|
||||
struct tty_data *data = tty->dev_data;
|
||||
_assert(data);
|
||||
|
||||
for (size_t i = 0; i < lim; ++i) {
|
||||
console_putc(data->master, tty, ((const char *) buf)[i]);
|
||||
}
|
||||
|
||||
return lim;
|
||||
}
|
||||
|
||||
static int tty_ioctl(struct chrdev *tty, unsigned int cmd, void *arg) {
|
||||
struct tty_data *data = tty->dev_data;
|
||||
_assert(data);
|
||||
|
||||
switch (cmd) {
|
||||
case TIOCGWINSZ:
|
||||
{
|
||||
_assert(arg);
|
||||
struct winsize *winsz = arg;
|
||||
_assert(data->master);
|
||||
|
||||
winsz->ws_col = data->master->width_chars;
|
||||
winsz->ws_row = data->master->height_chars;
|
||||
}
|
||||
return 0;
|
||||
case TCGETS:
|
||||
memcpy(arg, &tty->tc, sizeof(struct termios));
|
||||
return 0;
|
||||
case TCSETS:
|
||||
memcpy(&tty->tc, arg, sizeof(struct termios));
|
||||
if (tty->tc.c_iflag & ICANON) {
|
||||
tty->buffer.flags &= ~RING_RAW;
|
||||
} else {
|
||||
tty->buffer.flags |= RING_RAW;
|
||||
}
|
||||
return 0;
|
||||
case TIOCSPGRP:
|
||||
// Clear interrupts and stuff
|
||||
tty->buffer.flags = 0;
|
||||
data->fg_pgid = *(pid_t *) arg;
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
#include "sys/char/input.h"
|
||||
#include "sys/char/tty.h"
|
||||
#include "sys/char/chr.h"
|
||||
#include "sys/display.h"
|
||||
#include "sys/console.h"
|
||||
#include "sys/assert.h"
|
||||
#include "sys/string.h"
|
||||
#include "sys/debug.h"
|
||||
#include "sys/heap.h"
|
||||
|
||||
#define ATTR_DEFAULT 0x1700
|
||||
|
||||
static void console_flush(struct console *con, struct console_buffer *buf);
|
||||
|
||||
static LIST_HEAD(g_consoles);
|
||||
|
||||
struct console_buffer {
|
||||
uint16_t attr;
|
||||
uint16_t y, x;
|
||||
uint16_t data[0];
|
||||
};
|
||||
|
||||
static struct console_buffer *console_buffer_create(uint16_t rows, uint16_t cols) {
|
||||
struct console_buffer *buf = kmalloc(sizeof(struct console_buffer) + rows * cols * sizeof(uint16_t));
|
||||
_assert(buf);
|
||||
memsetw(buf->data, ATTR_DEFAULT, rows * cols);
|
||||
buf->y = 0;
|
||||
buf->x = 0;
|
||||
buf->attr = ATTR_DEFAULT;
|
||||
return buf;
|
||||
}
|
||||
|
||||
void console_attach(struct console *con, struct chrdev *tty) {
|
||||
struct console_buffer *tty_buffer = console_buffer_create(con->width_chars, con->height_chars);
|
||||
_assert(tty_buffer);
|
||||
|
||||
struct tty_data *data = tty->dev_data;
|
||||
_assert(data);
|
||||
|
||||
// Make sure the TTY hasn't already been enslaved to a console
|
||||
_assert(!data->buffer);
|
||||
_assert(!data->master);
|
||||
data->master = con;
|
||||
data->buffer = tty_buffer;
|
||||
|
||||
list_add(&data->list, &con->slaves);
|
||||
|
||||
// Make current active TTY if none yet selected
|
||||
if (!con->tty_active) {
|
||||
con->tty_active = tty;
|
||||
con->buf_active = tty_buffer;
|
||||
|
||||
// Clear new default console
|
||||
console_flush(con, tty_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static void console_flush(struct console *con, struct console_buffer *buf) {
|
||||
for (uint16_t row = 0; row < con->height_chars; ++row) {
|
||||
for (uint16_t col = 0; col < con->width_chars; ++col) {
|
||||
uint16_t ch = buf->data[row * con->width_chars + col];
|
||||
display_setc(con->display, row, col, ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void console_scroll_check(struct console *con, struct console_buffer *buf) {
|
||||
if (buf->y >= con->height_chars) {
|
||||
buf->y = con->height_chars - 1;
|
||||
|
||||
memcpy(buf->data, &buf->data[con->width_chars], (con->height_chars - 1) * con->width_chars * 2);
|
||||
memsetw(&buf->data[(con->height_chars - 1) * con->width_chars], ATTR_DEFAULT, con->width_chars);
|
||||
|
||||
console_flush(con, buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void _console_putc(struct console *con, struct console_buffer *buf, int c) {
|
||||
int act = buf == con->buf_active;
|
||||
|
||||
if (c == '\n') {
|
||||
++buf->y;
|
||||
buf->x = 0;
|
||||
console_scroll_check(con, buf);
|
||||
} else if (c >= ' ') {
|
||||
buf->data[buf->y * con->width_chars + buf->x] = c | buf->attr;
|
||||
if (act) {
|
||||
display_setc(con->display, buf->y, buf->x, c | buf->attr);
|
||||
}
|
||||
|
||||
++buf->x;
|
||||
if (buf->x >= con->width_chars) {
|
||||
++buf->y;
|
||||
buf->x = 0;
|
||||
console_scroll_check(con, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void console_putc(struct console *con, struct chrdev *tty, int c) {
|
||||
struct tty_data *data = tty->dev_data;
|
||||
_assert(data);
|
||||
|
||||
struct console_buffer *buf = data->buffer;
|
||||
_assert(buf);
|
||||
|
||||
_console_putc(con, buf, c);
|
||||
}
|
||||
|
||||
void console_type(struct console *con, int c) {
|
||||
if (con->tty_active) {
|
||||
tty_data_write(con->tty_active, c);
|
||||
}
|
||||
}
|
||||
|
||||
void console_default_putc(int c) {
|
||||
if (list_empty(&g_consoles)) {
|
||||
return;
|
||||
}
|
||||
struct console *con = list_entry(g_consoles.next, struct console, list);
|
||||
if (con->buf_active) {
|
||||
_console_putc(con, con->buf_active, c);
|
||||
}
|
||||
}
|
||||
|
||||
void console_init_default(void) {
|
||||
// Initialize default display+keyboard pair
|
||||
struct console *con = kmalloc(sizeof(struct console));
|
||||
_assert(con);
|
||||
con->tty_active = NULL;
|
||||
con->buf_active = NULL;
|
||||
list_head_init(&con->slaves);
|
||||
list_head_init(&con->list);
|
||||
|
||||
struct display *display = display_get_default();
|
||||
_assert(display);
|
||||
con->display = display;
|
||||
|
||||
// Extract initial display mode
|
||||
con->width_chars = display->width_chars;
|
||||
con->height_chars = display->height_chars;
|
||||
kdebug("Initializing default console: %ux%u\n", con->width_chars, con->height_chars);
|
||||
|
||||
if (!g_keyboard_console) {
|
||||
g_keyboard_console = con;
|
||||
}
|
||||
|
||||
// Create a single TTY device
|
||||
_assert(tty_create(con) == 0);
|
||||
list_add(&con->list, &g_consoles);
|
||||
}
|
||||
+4
-3
@@ -1,4 +1,5 @@
|
||||
#include "arch/amd64/multiboot2.h"
|
||||
#include "sys/console.h"
|
||||
#include "sys/string.h"
|
||||
#include "sys/debug.h"
|
||||
#include "sys/ctype.h"
|
||||
@@ -197,9 +198,9 @@ void debugc(int level, char c) {
|
||||
if (DEBUG_SERIAL(level) & kernel_config[CFG_DEBUG]) {
|
||||
rs232_send(RS232_COM1, c);
|
||||
}
|
||||
//if (DEBUG_DISP(level) & kernel_config[CFG_DEBUG]) {
|
||||
// amd64_con_putc(c);
|
||||
//}
|
||||
if (DEBUG_DISP(level) & kernel_config[CFG_DEBUG]) {
|
||||
console_default_putc(c);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "sys/font/psf.h"
|
||||
#include "sys/display.h"
|
||||
#include "sys/debug.h"
|
||||
#include <stddef.h>
|
||||
|
||||
static LIST_HEAD(displays);
|
||||
|
||||
static uint8_t color_map[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
|
||||
static uint32_t rgb_map[16] = {
|
||||
0x000000,
|
||||
0x0000AA,
|
||||
0x00AA00,
|
||||
0x00AAAA,
|
||||
0xAA0000,
|
||||
0xAA00AA,
|
||||
0xAA5500,
|
||||
0xAAAAAA,
|
||||
0x555555,
|
||||
0x5555FF,
|
||||
0x55FF55,
|
||||
0x55FFFF,
|
||||
0xFF5555,
|
||||
0xFF55FF,
|
||||
0xFFFF55,
|
||||
0xFFFFFF,
|
||||
};
|
||||
|
||||
struct display *display_get_default(void) {
|
||||
if (list_empty(&displays)) {
|
||||
return NULL;
|
||||
}
|
||||
return list_entry(displays.next, struct display, list);
|
||||
}
|
||||
|
||||
void display_add(struct display *disp) {
|
||||
// Initialize text mode for framebuffers
|
||||
if (disp->flags & DISP_GRAPHIC) {
|
||||
disp->width_chars = disp->width_pixels / font->width;
|
||||
disp->height_chars = disp->height_pixels / font->height;
|
||||
}
|
||||
|
||||
list_add(&disp->list, &displays);
|
||||
}
|
||||
|
||||
void display_setc(struct display *disp, uint16_t y, uint16_t x, uint16_t ch) {
|
||||
if (disp->flags & DISP_GRAPHIC) {
|
||||
// TODO: attr conversion
|
||||
psf_draw(disp, y, x, ch & 0xFF, rgb_map[(ch >> 8) & 0xF], rgb_map[(ch >> 12) & 0xF]);
|
||||
}
|
||||
}
|
||||
+8
-14
@@ -1,26 +1,20 @@
|
||||
#include "sys/font/psf.h"
|
||||
#include "sys/display.h"
|
||||
#include "sys/panic.h"
|
||||
// XXX: Only supports non-indexed linear buffers
|
||||
#include "sys/attr.h"
|
||||
|
||||
extern char _psf_start;
|
||||
extern char _psf_end;
|
||||
static struct psf_font *font;
|
||||
static uintptr_t psf_fb_addr, psf_fb_pitch;
|
||||
struct psf_font *font;
|
||||
|
||||
void psf_init(uintptr_t addr, uintptr_t pitch, uint16_t *charw, uint16_t *charh) {
|
||||
static __init void psf_init(void) {
|
||||
font = (struct psf_font *) &_psf_start;
|
||||
if (font->magic != PSF_FONT_MAGIC) {
|
||||
panic("Invalid PSF magic\n");
|
||||
}
|
||||
|
||||
psf_fb_addr = addr;
|
||||
psf_fb_pitch = pitch;
|
||||
|
||||
*charw = font->width;
|
||||
*charh = font->height;
|
||||
}
|
||||
|
||||
void psf_draw(uint16_t row, uint16_t col, uint8_t c, uint32_t fg, uint32_t bg) {
|
||||
void psf_draw(struct display *disp, uint16_t row, uint16_t col, uint8_t c, uint32_t fg, uint32_t bg) {
|
||||
if (c >= font->numglyph) {
|
||||
c = 0;
|
||||
}
|
||||
@@ -31,7 +25,7 @@ void psf_draw(uint16_t row, uint16_t col, uint8_t c, uint32_t fg, uint32_t bg) {
|
||||
// XXX: Assuming BPP is 32
|
||||
/* calculate the upper left corner on screen where we want to display.
|
||||
we only do this once, and adjust the offset later. This is faster. */
|
||||
uintptr_t offs = (row * font->height * psf_fb_pitch) + (col * font->width * 4);
|
||||
uintptr_t offs = (row * font->height * disp->pitch) + (col * font->width * 4);
|
||||
/* finally display pixels according to the bitmap */
|
||||
uint32_t x, y, line, mask;
|
||||
for (y = 0; y < font->height; ++y) {
|
||||
@@ -40,13 +34,13 @@ void psf_draw(uint16_t row, uint16_t col, uint8_t c, uint32_t fg, uint32_t bg) {
|
||||
mask = 1 << (font->width - 1);
|
||||
/* display a row */
|
||||
for (x = 0; x < font->width; ++x) {
|
||||
*((uint32_t *)(psf_fb_addr + line)) = ((int) *glyph) & (mask) ? fg : bg;
|
||||
*((uint32_t *)(disp->framebuffer + line)) = ((int) *glyph) & (mask) ? fg : bg;
|
||||
/* adjust to the next pixel */
|
||||
mask >>= 1;
|
||||
line += 4;
|
||||
}
|
||||
/* adjust to the next line */
|
||||
glyph += bytesperline;
|
||||
offs += psf_fb_pitch;
|
||||
offs += disp->pitch;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "drivers/pci/pci.h"
|
||||
#include "drivers/usb/usb.h"
|
||||
#include "sys/char/tty.h"
|
||||
#include "sys/console.h"
|
||||
#include "sys/sched.h"
|
||||
#include "sys/panic.h"
|
||||
#include "fs/sysfs.h"
|
||||
@@ -13,6 +14,7 @@ void main(void) {
|
||||
pci_init();
|
||||
|
||||
vfs_init();
|
||||
console_init_default();
|
||||
tty_init();
|
||||
|
||||
sysfs_populate();
|
||||
|
||||
Reference in New Issue
Block a user