]> pd.if.org Git - zos/blobdiff - tty.c
terminal and vga screen
[zos] / tty.c
diff --git a/tty.c b/tty.c
new file mode 100644 (file)
index 0000000..d619a65
--- /dev/null
+++ b/tty.c
@@ -0,0 +1,132 @@
+#include <stddef.h>
+#include <stdint.h>
+#include "tty.h"
+
+#include "kernel.h"
+#include "interrupt.h"
+#include "ioport.h"
+
+#include "string.h"
+
+#include <mem.h>
+
+#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();
+}