aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraqua <aqua@iserlohn-fortress.net>2022-11-01 17:43:33 +0200
committeraqua <aqua@iserlohn-fortress.net>2022-11-01 17:43:33 +0200
commit247fb5a8476aa66fdc6d4f042b0a743fe7c3ab2b (patch)
treec719f192e3352363652a33544f4ab7167509d3c8
parentmakefile: add Makefile.config (diff)
downloadkernel-247fb5a8476aa66fdc6d4f042b0a743fe7c3ab2b.tar.xz
Add uppercase scancodes
Make text mode screen scroll
-rw-r--r--devices/ps2_keyboard.c28
-rw-r--r--devices/vga.c112
-rw-r--r--devices/vga.h7
-rw-r--r--lib/stdio/printf.c50
-rw-r--r--src/kernel.c34
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");