From: Nathan Wagner Date: Tue, 25 Oct 2016 01:33:02 +0000 (-0500) Subject: terminal and vga screen X-Git-Url: https://pd.if.org/git/?p=zos;a=commitdiff_plain;h=3afdcc11364fbed161b57409f90fe572fc789047 terminal and vga screen --- diff --git a/tty.c b/tty.c new file mode 100644 index 0000000..d619a65 --- /dev/null +++ b/tty.c @@ -0,0 +1,132 @@ +#include +#include + +#include "tty.h" + +#include "kernel.h" +#include "interrupt.h" +#include "ioport.h" + +#include "string.h" + +#include + +#define make_color(fg, bg) (fg | bg << 4) +#define make_vga(ch, color) ((uint16_t)(ch & 0xff | color << 8)) + +#define VGA_WIDTH 80 +#define VGA_HEIGHT 25 + +static struct virtual_console { + int row, column; + uint8_t color; + +} con; + +struct terminal terminal = { 0 }; + +static void clear() { + int i; + uint16_t blank = make_vga(' ', terminal.color); + for (i=0; i < VGA_WIDTH * VGA_HEIGHT; i++) { + terminal.vmem[i] = blank; + } +} + +static void scroll(int lines) { + uint16_t *base, *offset; + uint16_t blank; + int i; + + base = terminal.vmem; + offset = base + VGA_WIDTH * lines; + memmove(base, offset, (VGA_WIDTH * VGA_HEIGHT - lines) * 2); + + offset = base + (VGA_WIDTH * VGA_HEIGHT - lines); + blank = make_vga(' ', terminal.color); + for (i=0; i < VGA_WIDTH * lines; i++) { + offset[i] = blank; + } +} + +static void putentryat(int c, uint8_t color, size_t x, size_t y) { + size_t index = y * VGA_WIDTH + x; + terminal.vmem[index] = make_vga(c, color); +} + +static void putchar(int c) { + if (terminal.escape) { + switch(c) { + + } + + return; + } + + switch (c) { + case '\n': + terminal.column = 0; + if (++terminal.row == VGA_HEIGHT) { + terminal.row = VGA_HEIGHT-1; + scroll(1); + } + break; + case '\r': + terminal.column = 0; + break; + default: + putentryat(c, terminal.color, terminal.column, terminal.row); + terminal.column++; + break; + } + + if (terminal.column == VGA_WIDTH) { + terminal.column = 0; + if (++terminal.row == VGA_HEIGHT) { + terminal.row = VGA_HEIGHT-1; + scroll(1); + } + } +} + +static void setcursor(int row, int col) { + uint16_t position = (row*VGA_WIDTH) + col; + + /* cursor low port to vga index register */ + outport8(0x3D4, 0x0F); + outport8(0x3D5, (unsigned char)(position&0xFF)); + /* cursor high port to vga index register */ + outport8(0x3D4, 0x0E); + outport8(0x3D5, (unsigned char )((position>>8)&0xFF)); +} + +static void updcursor() { + setcursor(terminal.row, terminal.column); +} + +static void writestring(const char *data) { + size_t i = 0; + + while (data[i]) { + putchar(data[i++]); + } + updcursor(); +} + +void terminal_initialize() { + terminal.putchar = putchar; + terminal.clear = clear; + terminal.scroll = scroll; + terminal.writestring = writestring; + terminal.vc = &con; + terminal.vmem = (uint16_t *) (0xb8000 + _asm_physmap); + terminal.update_cursor = updcursor; + + terminal.row = 0; + terminal.column = 0; + updcursor(); + + terminal.color = make_color(VGA_LIGHT_GREY, VGA_BLACK); + + clear(); +} diff --git a/tty.h b/tty.h new file mode 100644 index 0000000..17a5c29 --- /dev/null +++ b/tty.h @@ -0,0 +1,42 @@ +#ifndef _TTY_H_ +#define _TTY_H_ 1 + +#include +#include + +enum vga_color { + VGA_BLACK = 0, + VGA_BLUE = 1, + VGA_GREEN = 2, + VGA_CYAN = 3, + VGA_RED = 4, + VGA_MAGENTA = 5, + VGA_BROWN = 6, + VGA_LIGHT_GREY = 7, + VGA_DARK_GREY = 8, + VGA_LIGHT_BLUE = 9, + VGA_LIGHT_GREEN = 10, + VGA_LIGHT_CYAN = 11, + VGA_LIGHT_RED = 12, + VGA_LIGHT_MAGENTA = 13, + VGA_LIGHT_BROWN = 14, + VGA_WHITE = 15 +}; + +struct terminal { + void (*putchar)(int); + void (*clear)(void); + void (*scroll)(int); + void (*writestring)(const char *); + void (*update_cursor)(void); + uint16_t *vmem; + struct virtual_console *vc; + int row, column; + int color; + int escape; +}; + +extern struct terminal terminal; + +void terminal_initialize(); +#endif