Remove old console code

This commit is contained in:
Mark
2020-06-18 10:54:55 +03:00
parent 4b23568d2f
commit bc36220152
12 changed files with 92 additions and 634 deletions
-436
View File
@@ -1,436 +0,0 @@
#include "arch/amd64/hw/con.h"
#include "user/termios.h"
#include "arch/amd64/hw/io.h"
#include "sys/string.h"
#include "sys/types.h"
#include "sys/debug.h"
#include "sys/panic.h"
#include "sys/spin.h"
#include "sys/heap.h"
#include "sys/mm.h"
#if defined(VESA_ENABLE)
#include "arch/amd64/hw/vesa.h"
#include "sys/font/psf.h"
#include "sys/font/logo.h"
#else
#define vesa_available 0
#endif
static spin_t display_lock = 0;
#define ESC_ESC 1
#define ESC_CSI 2
#define CGA_BUFFER_ADDR 0xB8000
#define ATTR_DEFAULT 0x1700ULL
#define ATTR_BOLD 1
static uint16_t *con_buffer;
static uint16_t x = 0, y = 0;
static uint16_t con_width, con_height;
static uint16_t saved_x = 0, saved_y = 0;
static int con_avail = 0;
static uint16_t char_width, char_height;
static int con_blink_state = 0;
// Map CSI colors to CGA
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,
};
static uint32_t esc_argv[8];
static size_t esc_argc;
static char esc_letter = 0;
static int esc_mode = 0;
static uint16_t attr = ATTR_DEFAULT;
static uint16_t xattr = 0;
static void setc(uint16_t row, uint16_t col, uint16_t v);
#if defined(VESA_ENABLE)
static uint16_t old_blink_x, old_blink_y;
void con_blink(void) {
if (vesa_available && !vesa_hold) {
uint32_t fg = rgb_map[(attr >> 8) & 0xF];
uint32_t bg = rgb_map[(attr >> 12) & 0xF];
con_blink_state = !con_blink_state;
if (old_blink_x != x || old_blink_y != y) {
uint16_t v = con_buffer[old_blink_y * con_width + old_blink_x];
psf_draw(old_blink_y, old_blink_x, v & 0xFF, rgb_map[(v >> 8) & 0xF], rgb_map[(v >> 12) & 0xF]);
}
uint16_t v = con_buffer[y * con_width + x];
if (con_blink_state) {
psf_draw(y, x, v & 0xFF, bg, fg);
} else {
psf_draw(y, x, v & 0xFF, fg, bg);
}
old_blink_x = x;
old_blink_y = y;
}
}
#endif
void amd64_con_sync_cursor(void) {
static uint16_t old_pos = 0;
uint16_t pos = y * 80 + x;
if (old_pos != pos) {
// This is slow as hell
outb(0x3D4, 0x0F);
outb(0x3D5, (uint8_t) (pos & 0xFF));
outb(0x3D4, 0x0E);
outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF));
}
old_pos = pos;
}
static void amd64_con_flush(void) {
#if defined(VESA_ENABLE)
if (vesa_available) {
for (uint16_t row = 0; row < con_height; ++row) {
for (uint16_t col = 0; col < con_width; ++col) {
uint16_t v = con_buffer[row * con_width + col];
psf_draw(row, col, v & 0xFF, rgb_map[(v >> 8) & 0xF], rgb_map[(v >> 12) & 0xF]);
}
}
} else {
#else
{
#endif
memcpyq((uint64_t *) MM_VIRTUALIZE(CGA_BUFFER_ADDR), (uint64_t *) con_buffer, 25 * 20);
}
}
static void amd64_scroll_down(void) {
#if defined(VESA_ENABLE)
if (vesa_available && !vesa_hold) {
memcpy(con_buffer, &con_buffer[con_width], (con_height - 1) * con_width * 2);
memsetw(&con_buffer[(con_height - 1) * con_width], ATTR_DEFAULT, con_width);
} else {
#else
{
#endif
memcpyq((uint64_t *) con_buffer, (uint64_t *) &con_buffer[con_width], 20 * 24);
memsetq((uint64_t *) &con_buffer[(con_height - 1) * con_width],
ATTR_DEFAULT | (ATTR_DEFAULT << 16) | (ATTR_DEFAULT << 32) | (ATTR_DEFAULT << 48), 20);
}
// Flush whole backbuffer
amd64_con_flush();
y = con_height - 1;
}
static void clear(void) {
memsetw(con_buffer, attr, con_width * con_height);
#if defined(VESA_ENABLE)
if (vesa_available) {
for (size_t i = 0; i < vesa_height; ++i) {
memsetl((uint32_t *) (vesa_addr + vesa_pitch * i), rgb_map[(attr >> 12) & 0xF], vesa_width);
}
}
#else
amd64_con_flush();
#endif
}
// I guess I could've implemented VT100 escape handling better, but
// this is all I invented so far
static void process_csi(void) {
switch (esc_letter) {
case 'm':
for (size_t i = 0; i < esc_argc; ++i) {
uint32_t v = esc_argv[i];
switch (v / 10) {
case 0:
switch (v % 10) {
case 0:
// Reset
attr = ATTR_DEFAULT;
xattr = 0;
break;
case 1:
// Bright
xattr |= ATTR_BOLD;
break;
case 2:
// Dim
xattr &= ~ATTR_BOLD;
break;
case 7:
// Reverse
attr >>= 4;
attr |= (attr & 0xF0) << 8;
attr &= 0xFF00;
break;
}
break;
case 3:
// Foreground
attr &= ~0x0F00;
attr |= (uint16_t) color_map[v % 10] << 8;
break;
case 4:
// Background
attr &= ~0xF000;
attr |= (uint16_t) color_map[v % 10] << 12;
break;
}
}
break;
case 'A':
// Cursor up
if (!esc_argv[0]) {
esc_argv[0] = 1;
}
if (esc_argv[0] >= y) {
y = 0;
} else {
y -= esc_argv[0];
}
break;
case 'B':
// Cursor down
if (!esc_argv[0]) {
esc_argv[0] = 1;
}
if (esc_argv[0] + y >= (uint32_t) (con_height - 1)) {
y = 22;
} else {
y += esc_argv[0];
}
break;
case 'C':
// Forward
if (!esc_argv[0]) {
esc_argv[0] = 1;
}
if (esc_argv[0] + x >= con_width) {
x = 79;
} else {
x += esc_argv[0];
}
break;
case 'D':
// Backward
if (!esc_argv[0]) {
esc_argv[0] = 1;
}
if (esc_argv[0] >= x) {
x = 0;
} else {
x -= esc_argv[0];
}
break;
case 'K':
// Erase end of line
memsetw(&con_buffer[y * con_width + x], attr, con_width - x);
break;
case 'J':
switch (esc_argv[0]) {
case 0:
// Erase lines down
memsetw(con_buffer, attr, con_width * y);
break;
case 1:
// Erase lines up
memsetw(&con_buffer[y * con_width], attr, con_width * (con_height - y));
break;
case 2:
// Erase all
clear();
break;
}
break;
case 'f':
// Set cursor position
y = (esc_argv[0] - 1) % con_height;
x = (esc_argv[1] - 1) % (con_width - 1);
break;
case 's':
// Save cursor
saved_y = y;
saved_x = x;
break;
case 'u':
// Unsave cursor
y = saved_y;
x = saved_x;
break;
}
}
static void setc(uint16_t row, uint16_t col, uint16_t v) {
if (xattr & ATTR_BOLD) {
v += 0x800;
}
con_buffer[row * con_width + col] = v;
#if defined(VESA_ENABLE)
if (vesa_available && !vesa_hold) {
psf_draw(row, col, v & 0xFF, rgb_map[(v >> 8) & 0xF], rgb_map[(v >> 12) & 0xF]);
} else {
#else
{
#endif
((uint16_t *) MM_VIRTUALIZE(CGA_BUFFER_ADDR))[row * 80 + col] = v;
}
}
void amd64_con_putc(int c) {
if (!con_avail || !c) {
// Ignore NULs
return;
}
c = (uint8_t) (c & 0xFF);
switch (esc_mode) {
case ESC_CSI:
if (c >= '0' && c <= '9') {
esc_argv[esc_argc] *= 10;
esc_argv[esc_argc] += c - '0';
} else if (c == ';') {
esc_argv[++esc_argc] = 0;
} else {
++esc_argc;
esc_letter = c;
process_csi();
esc_mode = 0;
}
break;
case ESC_ESC:
if (c == '[') {
esc_mode = ESC_CSI;
break;
} else {
esc_mode = 0;
}
__attribute__((fallthrough));
case 0:
if (c == '\033') {
esc_mode = ESC_ESC;
esc_argv[0] = 0;
esc_argc = 0;
return;
}
if (c >= ' ') {
setc(y, x, c | attr);
++x;
if (x >= con_width) {
++y;
x = 0;
if (y == con_height) {
amd64_scroll_down();
}
}
} else {
switch (c) {
case '\n':
++y;
x = 0;
if (y >= con_height) {
amd64_scroll_down();
}
break;
default:
amd64_con_putc('?');
return;
}
}
break;
}
}
int pc_con_putc(void *dev, char c) {
uintptr_t irq;
spin_lock_irqsave(&display_lock, &irq);
amd64_con_putc(c);
spin_release_irqrestore(&display_lock, &irq);
return 0;
}
void amd64_con_get_size(struct winsize *ws) {
ws->ws_row = con_height;
ws->ws_col = con_width;
#if defined(VESA_ENABLE)
if (vesa_available) {
ws->ws_xpixel = vesa_width;
ws->ws_ypixel = vesa_height;
} else {
#else
{
#endif
ws->ws_xpixel = con_width;
ws->ws_ypixel = con_height;
}
}
void amd64_con_init(void) {
// XXX XXX XXX: Had to do this because of memory allocation problem:
// setc overwrites data in heap headers
static uint16_t second_buffer[80 * 25];
#if defined(VESA_ENABLE)
if (vesa_available) {
psf_init(vesa_addr, vesa_pitch, &char_width, &char_height);
con_width = vesa_width / char_width;
con_height = vesa_height / char_height;
con_buffer = (uint16_t *) kmalloc(con_width * con_height * 2);
} else {
#else
{
#endif
con_buffer = second_buffer;
con_width = 80;
con_height = 25;
}
con_avail = 1;
clear();
#if defined(VESA_ENABLE)
if (vesa_available) {
y = FONT_LOGO_HEIGHT / char_height;
char pixel[4];
char *data = font_logo_header_data;
uint32_t v;
for (uint32_t j = 0; j < FONT_LOGO_HEIGHT; ++j) {
for (uint32_t i = 0; i < FONT_LOGO_WIDTH; ++i) {
FONT_LOGO_HEADER_PIXEL(data, pixel);
v = pixel[2] | ((uint32_t) pixel[1] << 8) | ((uint32_t) pixel[0] << 16);
if (v) {
vesa_put(i, j, v);
}
}
}
}
#endif
}
+16 -16
View File
@@ -28,8 +28,8 @@ static spin_t g_sleep_lock = 0;
static LIST_HEAD(g_sleep_head);
void timer_add_sleep(struct thread *thr) {
if (thr->pid > 0)
kdebug("Adding %d to sleepers\n", thr->pid);
//if (thr->pid > 0)
//kdebug("Adding %d to sleepers\n", thr->pid);
uintptr_t irq;
struct io_notify *n = &thr->sleep_notify;
spin_lock_irqsave(&g_sleep_lock, &irq);
@@ -38,8 +38,8 @@ void timer_add_sleep(struct thread *thr) {
}
void timer_remove_sleep(struct thread *thr) {
if (thr->pid > 0)
kdebug("Removing sleep %d\n", thr->pid);
//if (thr->pid > 0)
//kdebug("Removing sleep %d\n", thr->pid);
uintptr_t irq;
struct io_notify *n = &thr->sleep_notify;
struct io_notify *it;
@@ -58,18 +58,18 @@ void timer_remove_sleep(struct thread *thr) {
static uint32_t timer_tick(void *arg) {
switch ((uint64_t) arg) {
case TIMER_PIT:
#if defined(VESA_ENABLE)
++int_timer_ticks;
if (int_timer_ticks >= 300) {
con_blink();
int_timer_ticks = 0;
}
if (!vesa_available) {
#else
{
#endif
amd64_con_sync_cursor();
}
// #if defined(VESA_ENABLE)
// ++int_timer_ticks;
// if (int_timer_ticks >= 300) {
// con_blink();
// int_timer_ticks = 0;
// }
// if (!vesa_available) {
//#else
// {
//#endif
// amd64_con_sync_cursor();
// }
// Each tick is approx. 1ms, so add 1ms to system time
system_time += 1000000;
break;
-106
View File
@@ -1,106 +0,0 @@
#include "arch/amd64/multiboot2.h"
#include "arch/amd64/hw/vesa.h"
#include "sys/mem/vmalloc.h"
#include "arch/amd64/cpu.h"
#include "sys/block/blk.h"
#include "sys/thread.h"
#include "user/video.h"
#include "user/errno.h"
#include "sys/assert.h"
#include "sys/string.h"
#include "sys/panic.h"
#include "sys/debug.h"
#include "sys/dev.h"
#include "sys/mm.h"
static int vesa_blk_ioctl(struct blkdev *blk, unsigned long cmd, void *arg);
static void *vesa_blk_mmap(struct blkdev *blk, struct ofile *fd, void *hint, size_t length, int flags);
int vesa_hold = 0;
int vesa_available = 0;
uint64_t vesa_addr;
uint32_t vesa_bpp, vesa_pitch, vesa_width, vesa_height;
static struct blkdev _vesa_fb0 = {
.flags = 0,
.dev_data = NULL,
.read = NULL,
.write = NULL,
.ioctl = vesa_blk_ioctl,
.mmap = vesa_blk_mmap
};
static int vesa_blk_ioctl(struct blkdev *blk, unsigned long cmd, void *arg) {
switch (cmd) {
case IOC_GETVMODE:
_assert(arg);
((struct ioc_vmode *) arg)->width = vesa_width;
((struct ioc_vmode *) arg)->height = vesa_height;
return 0;
case IOC_FBCON:
_assert(arg);
vesa_hold = !*(uint32_t *) arg;
return 0;
default:
return -EINVAL;
}
}
static void *vesa_blk_mmap(struct blkdev *blk, struct ofile *fd, void *hint, size_t length, int flags) {
struct thread *thr = thread_self;
_assert(thr);
uintptr_t vaddr = vmfind(thr->space, 0x80000000, 0x100000000, length / MM_PAGE_SIZE);
_assert(vaddr != MM_NADDR);
uintptr_t phys = MM_PHYS(vesa_addr);
for (size_t i = 0; i < length / MM_PAGE_SIZE; ++i) {
mm_map_single(thr->space, vaddr + i * MM_PAGE_SIZE, phys + i * MM_PAGE_SIZE, MM_PAGE_WRITE | MM_PAGE_USER, 0);
}
return (void *) vaddr;
}
void vesa_clear(uint32_t color) {
if (vesa_hold) {
return;
}
switch (vesa_bpp) {
case 32:
for (size_t i = 0; i < vesa_height; ++i) {
memsetl((uint32_t *) (i * vesa_pitch + vesa_addr), color, vesa_width);
}
break;
default:
panic("NYI\n");
}
}
void vesa_put(uint32_t x, uint32_t y, uint32_t v) {
if (vesa_hold) {
return;
}
switch (vesa_bpp) {
case 32:
((uint32_t *) (vesa_addr + vesa_pitch * y))[x] = v;
break;
default:
panic("NYI\n");
}
}
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("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");
}
}
+6 -6
View File
@@ -107,12 +107,12 @@ 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);
// }
// amd64_con_init();
//#endif
ps2_register_device();
+1 -1
View File
@@ -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
+1 -2
View File
@@ -45,8 +45,7 @@ OBJS+=$(ACPICA_OBJS) \
$(O)/arch/amd64/sched_s.o \
$(O)/arch/amd64/syscall_s.o \
$(O)/arch/amd64/syscall.o \
$(O)/arch/amd64/binfmt_elf.o \
$(O)/arch/amd64/hw/con.o
$(O)/arch/amd64/binfmt_elf.o
kernel_LINKER=arch/amd64/link.ld
kernel_LDFLAGS=-nostdlib \
+10
View File
@@ -1,6 +1,16 @@
#pragma once
#include "sys/types.h"
struct chrdev;
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);
};
// From keyboard handlers and stuff
void tty_control_write(struct chrdev *n, char c);
void tty_data_write(struct chrdev *n, char c);
+1
View File
@@ -21,6 +21,7 @@ struct page {
PU_UNKNOWN = 0,
PU_PRIVATE, // Program data: image + mmap()ed anonymous regions
PU_SHARED, // Shared memory mapping
PU_DEVICE, // Possibly shared device mapping
PU_KERNEL, // Not a userspace page
} usage;
size_t refcount;
+5 -63
View File
@@ -23,19 +23,11 @@
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);
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);
};
// Keyboard + display
static struct tty_data _dev_tty0_data = {
.fg_pgid = 1,
.out_dev = 0,
.out_putc = pc_con_putc
.out_dev = NULL,
.out_putc = NULL, //pc_con_putc
};
static struct chrdev _dev_tty0 = {
@@ -48,23 +40,6 @@ static struct chrdev _dev_tty0 = {
.ioctl = tty_ioctl
};
// Serial console
//static struct tty_data _dev_ttyS0_data = {
// .fg_pgid = 1,
// .out_dev = (void *) RS232_COM1,
// .out_putc = rs232_putc
//};
//static struct chrdev _dev_ttyS0 = {
// .type = CHRDEV_TTY,
// .dev_data = &_dev_ttyS0_data,
// .tc = TERMIOS_DEFAULT,
// .write = tty_write,
// // Line discipline
// .read = line_read,
// .ioctl = tty_ioctl
//};
void tty_control_write(struct chrdev *tty, char c) {
struct tty_data *data = tty->dev_data;
_assert(data);
@@ -126,8 +101,8 @@ void tty_puts(struct chrdev *tty, const char *s) {
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->out_putc);
//data->out_putc(data->out_dev, c);
}
void tty_init(void) {
@@ -143,42 +118,9 @@ 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);
_assert(data->out_putc);
for (size_t i = 0; i < lim; ++i) {
// This is printed as-is without tty_putc wrapper
data->out_putc(data->out_dev, ((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 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 TIOCGWINSZ:
// TODO: See comment on tty data struct
amd64_con_get_size(arg);
return 0;
case TIOCSPGRP:
// Clear interrupts and stuff
tty->buffer.flags = 0;
data->fg_pgid = *(pid_t *) arg;
return 0;
default:
return -EINVAL;
}
return -EINVAL;
}
+3 -3
View File
@@ -197,9 +197,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]) {
// amd64_con_putc(c);
//}
#endif
}
+43 -1
View File
@@ -61,8 +61,40 @@ void *sys_mmap(void *hint, size_t length, int prot, int flags, int fd, off_t off
// Anonymous mapping
return sys_mmap_anon(page_count, prot, flags);
} else {
struct thread *thr = thread_self;
// File/device-backed mapping
panic("TODO\n");
if (fd < 0 || fd >= THREAD_MAX_FDS) {
return (void *) -EBADF;
}
struct ofile *of = thr->fds[fd];
if (!of) {
return (void *) -EBADF;
}
if (of->flags & OF_SOCKET) {
return (void *) -EINVAL;
}
struct vnode *vn = of->file.vnode;
_assert(vn);
switch (vn->type) {
case VN_BLK:
{
struct blkdev *blk = vn->dev;
_assert(blk);
if (!blk->mmap) {
return (void *) -EINVAL;
}
return blk->mmap(blk, of, hint, length, flags);
}
default:
return (void *) -EINVAL;
}
}
}
@@ -90,6 +122,8 @@ int sys_munmap(void *ptr, size_t len) {
len /= MM_PAGE_SIZE;
// TODO: If it's a device mapping, notify device a page was unmapped
for (size_t i = 0; i < len; ++i) {
uint64_t flags;
uintptr_t phys = mm_map_get(thr->space, addr + i * MM_PAGE_SIZE, &flags);
@@ -101,6 +135,14 @@ int sys_munmap(void *ptr, size_t len) {
struct page *page = PHYS2PAGE(phys);
_assert(page);
// TODO: FIX THIS
if (page->usage == PU_DEVICE) {
_assert(page->refcount);
_assert(mm_umap_single(thr->space, addr + i * MM_PAGE_SIZE, 1) == phys);
continue;
}
if (!(page->flags & PG_MMAPED)) {
panic("Tried to unmap non-mmapped page\n");
}
+6
View File
@@ -53,6 +53,12 @@ void thread_notify_io(struct io_notify *n) {
spin_release_irqrestore(&n->lock, &irq);
if (t) {
// Prevent double task wakeup when
// two event sources simultaneously try
// to do it
if (t->sched_next) {
return;
}
sched_queue(t);
}
}