diff options
author | aqua <aqua@iserlohn-fortress.net> | 2022-11-01 17:43:33 +0200 |
---|---|---|
committer | aqua <aqua@iserlohn-fortress.net> | 2022-11-01 17:43:33 +0200 |
commit | 247fb5a8476aa66fdc6d4f042b0a743fe7c3ab2b (patch) | |
tree | c719f192e3352363652a33544f4ab7167509d3c8 | |
parent | makefile: add Makefile.config (diff) | |
download | kernel-247fb5a8476aa66fdc6d4f042b0a743fe7c3ab2b.tar.xz |
Add uppercase scancodes
Make text mode screen scroll
-rw-r--r-- | devices/ps2_keyboard.c | 28 | ||||
-rw-r--r-- | devices/vga.c | 112 | ||||
-rw-r--r-- | devices/vga.h | 7 | ||||
-rw-r--r-- | lib/stdio/printf.c | 50 | ||||
-rw-r--r-- | src/kernel.c | 34 |
5 files changed, 183 insertions, 48 deletions
diff --git a/devices/ps2_keyboard.c b/devices/ps2_keyboard.c index 6171d18..e5af423 100644 --- a/devices/ps2_keyboard.c +++ b/devices/ps2_keyboard.c @@ -11,9 +11,16 @@ const uint8_t comm_write_ctrl_config = 0x60; const uint8_t data_port = 0x60; // rw const uint8_t data_enable_scanning = 0xf4; -const char scancodes[] = {'E', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', 'T', 'q', 'w', 'e', - 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 'C', 'a', 's', 'd', 'f', 'g', 'h', 'j', - 'k', 'l', ';', '\'', '`', 'L', '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 'R'}; +const char scancodes[2][68] = {{'E', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', + 'T', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', + 'C', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 'L', + '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 'R', 'P', 'A', + ' ', 'C', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}, + {'E', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', 'T', 'Q', 'W', + 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', 'C', 'A', 'S', 'D', 'F', 'G', + 'H', 'J', 'K', 'L', ':', '"', '~', 'L', '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', + '>', '?', 'R', 'P', 'A', ' ', 'C', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}}; +int shift_case = 0; void ps2_keyboard_init() @@ -32,9 +39,22 @@ void ps2_keyboard_irq_handler() { const uint8_t key = inb(data_port); + + switch (key) { + case 0x2a: // left shift down + case 0x36: // right shift down + shift_case = 1; + return; + + case 0xaa: // left shift up + case 0xb6: // right shift up + shift_case = 0; + return; + } + if (key >= 0x80) return; - if (key < 0x37) printf("%c", scancodes[key - 1]); + if (key < (sizeof(scancodes[0]) / sizeof(const char))) printf("%c", scancodes[shift_case][key - 1]); else printf("key pressed: %x\n", key); } diff --git a/devices/vga.c b/devices/vga.c index 983e630..908bd5e 100644 --- a/devices/vga.c +++ b/devices/vga.c @@ -1,35 +1,131 @@ #include "vga.h" -#include <stddef.h> #include <stdint.h> +#include <sys/io.h> struct __attribute__((packed)) VGAEntry { unsigned char text; uint8_t foreground : 4; uint8_t background : 4; }; +_Static_assert(sizeof(struct VGAEntry) == 2, "sizeof VGAEntry"); -_Static_assert(sizeof(struct VGAEntry) == 2); - -const size_t width = 80; -const size_t height = 25; +const int width = 80; +const int height = 25; struct VGAEntry *buffer; +int col = 0; +int row = 0; void vga_init() { buffer = (struct VGAEntry *)0xc03ff000; + // vga_enable_cursor(0, 15); vga_clear(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_LIGHT_GREY); } void vga_clear(enum vga_color foreground, enum vga_color background) { - for (size_t y = 0; y < height; ++y) - for (size_t x = 0; x < width; ++x) { - const size_t index = y * width + x; + for (int y = 0; y < height; ++y) + for (int x = 0; x < width; ++x) { + const int index = y * width + x; buffer[index].text = ' '; buffer[index].foreground = foreground; buffer[index].background = background; } + col = row = 0; + // vga_update_cursor(); +} + +void +vga_putc(char a) +{ + switch (a) { + case '\n': + col = 0; + ++row; + break; + case '\r': + col = 0; + break; + case '\b': + --col; + if (col < 0) col = 0; + break; + default: + buffer[row * width + col].text = a; + ++col; + } + + if (col == width) { + col = 0; + ++row; + } + + if (row == height) { + // scroll up + for (int y = 1; y < height; ++y) + for (int x = 0; x < width; ++x) { + const int prev = (y - 1) * width + x; + const int curr = y * width + x; + buffer[prev] = buffer[curr]; + } + // blank out last row + for (int i = (height - 1) * width; i < height * width; ++i) buffer[i].text = ' '; + --row; + } +} + +void +vga_puts(const char *string, int len) +{ + + if (len == -1) + while (*string != '\0') { + vga_putc(*string); + ++string; + } + + else + for (int i = 0; i < len; ++i) { vga_putc(string[i]); } +} + +// Cursor +const uint16_t cga_idx_port = 0x3d4; +const uint16_t cga_dat_port = 0x3d5; + +const uint8_t cursor_start = 0xa; +const uint8_t cursor_end = 0xb; +const uint8_t cursor_addr_h = 0xe; +const uint8_t cursor_addr_l = 0xf; +const uint8_t cursor_hide = 0x20; + +void +vga_enable_cursor(unsigned char start, unsigned char end) +{ + outb(cga_idx_port, cursor_start); + outb(cga_dat_port, (inb(cga_dat_port) & 0xc0) | start); + + outb(cga_idx_port, cursor_end); + outb(cga_dat_port, (inb(cga_dat_port) & 0xe0) | end); +} + +void +vga_disable_cursor() +{ + outb(cga_idx_port, cursor_start); + outb(cga_dat_port, cursor_hide); +} + +void +vga_update_cursor() +{ + const uint16_t pos = row * width + col; + + outb(cga_idx_port, cursor_addr_l); + outb(cga_dat_port, pos & 0xff); + + outb(cga_idx_port, cursor_addr_h); + outb(cga_dat_port, (pos >> 8) & 0xff); } diff --git a/devices/vga.h b/devices/vga.h index c2ef2ef..63de309 100644 --- a/devices/vga.h +++ b/devices/vga.h @@ -22,3 +22,10 @@ enum vga_color { void vga_init(); void vga_clear(enum vga_color foreground, enum vga_color background); + +void vga_putc(char a); +void vga_puts(const char *string, int len); + +void vga_enable_cursor(unsigned char start, unsigned char end); +void vga_disable_cursor(); +void vga_update_cursor(); diff --git a/lib/stdio/printf.c b/lib/stdio/printf.c index 7adf76e..25cce40 100644 --- a/lib/stdio/printf.c +++ b/lib/stdio/printf.c @@ -3,6 +3,7 @@ #include <string.h> #include <devices/uart_16550.h> +#include <devices/vga.h> static char buffer[3 * sizeof(int) + 2]; @@ -18,26 +19,37 @@ printf(const char *restrict format, ...) for (int i = 0; format[i] != '\0'; ++i) { if (format[i] == '%') { written += uart_puts(COM1, &format[s], l); + vga_puts(&format[s], l); s = i + 2; ++i; switch (format[i]) { - case 's': - written += uart_puts(COM1, va_arg(params, const char *), -1); - break; - case 'c': - written++; - uart_write(COM1, va_arg(params, int)); - break; - case 'd': - written += uart_puts(COM1, itoa(buffer, va_arg(params, int), 10), -1); - break; - case 'u': - written += uart_puts(COM1, utoa(buffer, va_arg(params, unsigned int), 10), -1); - break; - case 'x': - written += uart_puts(COM1, utoa(buffer, va_arg(params, unsigned int), 16), -1); - break; + case 's': { + const char *arg = va_arg(params, const char *); + written += uart_puts(COM1, arg, -1); + vga_puts(arg, -1); + } break; + case 'c': { + const int arg = va_arg(params, int); + uart_write(COM1, arg); + vga_putc(arg); + ++written; + } break; + case 'd': { + const char *arg = itoa(buffer, va_arg(params, int), 10); + written += uart_puts(COM1, arg, -1); + vga_puts(arg, -1); + } break; + case 'u': { + const char *arg = utoa(buffer, va_arg(params, unsigned int), 10); + written += uart_puts(COM1, arg, -1); + vga_puts(arg, -1); + } break; + case 'x': { + const char *arg = utoa(buffer, va_arg(params, unsigned int), 16); + written += uart_puts(COM1, arg, -1); + vga_puts(arg, -1); + } break; } l = 0; @@ -47,8 +59,12 @@ printf(const char *restrict format, ...) ++l; } - if (l > 0) written += uart_puts(COM1, &format[s], l); + if (l > 0) { + written += uart_puts(COM1, &format[s], l); + vga_puts(&format[s], l); + } va_end(params); + // vga_update_cursor(); return written; } diff --git a/src/kernel.c b/src/kernel.c index 41025d7..6b3df3f 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -6,35 +6,31 @@ #include "mem.h" #include <stdio.h> -#include "devices/pic.h" #include "devices/uart_16550.h" #include "devices/vga.h" #include <conf.h> #include <sys/cpuid.h> void kmain() { + vga_init(vmm_map(0xb8000, 0xc03ff000)); if (uart_init(COM1) != 0) printf("UART self-test failed.\r\n"); printf("glitch [version " VERSION "] [" CC "]\n"); - char vendor[13] = {'\0'}; - unsigned int eax; - __get_cpuid(0, &eax, (unsigned int *)vendor, (unsigned int *)(vendor + 8), (unsigned int *)(vendor + 4)); - struct CPUVersion v; - __get_cpuid(1, (unsigned int *)&v, &eax, &eax, &eax); - printf("CPU: %s family %u model %u stepping %u\n", vendor, family(v), model(v), v.stepping); - - printf("hello %s world\n", "kernel"); - printf("Hello %c\n", 'C'); - printf("we are number %d\n", 1); - printf("a negative %d as hex %x\n", -1, -1); - printf("hex 255=0x%x\n", 255); - - vga_init(vmm_map(0xb8000, 0xc03ff000)); - - alloc4M(); - char *c = (char *)0xc0700000; - if (*c == 0) printf("c is 0\r\n"); + { + char vendor[13] = {'\0'}; + unsigned int eax; + __get_cpuid(0, &eax, (unsigned int *)vendor, (unsigned int *)(vendor + 8), (unsigned int *)(vendor + 4)); + struct CPUVersion v; + __get_cpuid(1, (unsigned int *)&v, &eax, &eax, &eax); + printf("CPU: %s family %u model %u stepping %u\n", vendor, family(v), model(v), v.stepping); + } + + /* + alloc4M(); + char *c = (char *)0xc0700000; + if (*c == 0) printf("c is 0\r\n"); + */ // asm volatile("int $0x80"); |