Browse Source

Implemented rudimentary keyboard driver

master
Leonie 10 months ago
parent
commit
570398d608
2 changed files with 86 additions and 21 deletions
  1. +39
    -13
      kernel/arch/i386/tty.c
  2. +47
    -8
      kernel/kernel/kernel.c

+ 39
- 13
kernel/arch/i386/tty.c View File

@@ -52,20 +52,46 @@ void update_cursor(int x, int y)
outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF));
}


//TODO: implement working terminal scrolling
void terminal_putchar(char c) {
unsigned char uc = c;
if (c == '\n') {
terminal_column = -1;
terminal_row++;
} else {
terminal_putentryat(uc, terminal_color, terminal_column, terminal_row);
}
if (++terminal_column == VGA_WIDTH) {
terminal_column = 0;
if (++terminal_row == VGA_HEIGHT)
terminal_row = 0;
}
update_cursor(terminal_column, terminal_row);
unsigned char uc = c;

// Handle character output and terminal_row/column modification
switch(c) {
case '\n':
terminal_row++;
terminal_column = 0;
break;
default:
terminal_putentryat(uc, terminal_color, terminal_column, terminal_row);
terminal_column++;
}

// Handle validation on terminal_column before terminal_row, since the logic in terminal_column can update terminal_row
if(terminal_column >= VGA_WIDTH) {
terminal_column = 0;
terminal_row++;
}

// Handle validating terminal_row, and scrolling the screen upwards if necessary.
if(terminal_row >= VGA_HEIGHT) {
size_t i, j;
for(i = 0; i < VGA_WIDTH-1; i++) {
for(j = VGA_HEIGHT-2; j > 0; j--) {
terminal_buffer[(j * VGA_WIDTH) + i] = terminal_buffer[((j+1) * VGA_WIDTH) + i];
}
}

// Also clear out the bottom row
for(i = 0; i < VGA_WIDTH-1; i++) {
terminal_putentryat(' ', terminal_color, i, VGA_HEIGHT-1);
}

terminal_row = VGA_HEIGHT-1;
}

update_cursor(terminal_column, terminal_row);
}

void terminal_write(const char* data, size_t size) {

+ 47
- 8
kernel/kernel/kernel.c View File

@@ -9,18 +9,57 @@ void kernel_panic(char str[]) {
__builtin_unreachable();
}

//IO
static inline void outb(uint16_t port, uint8_t val)
{
asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) );
/* There's an outb %al, $imm8 encoding, for compile-time constant port numbers that fit in 8b. (N constraint).
* Wider immediate constants would be truncated at assemble-time (e.g. "i" constraint).
* The outb %al, %dx encoding is the only option for all other cases.
* %1 expands to %dx because port is a uint16_t. %w1 could be used if we had the port number a wider C type */
}

static inline uint8_t inb(uint16_t port)
{
uint8_t ret;
asm volatile ( "inb %1, %0"
: "=a"(ret)
: "Nd"(port) );
return ret;
}

//Kernel main, keyboard driver and shell

void kernel_main(void) {
terminal_initialize();
printf("FreezeOS 1.0\n");
printf("Starting...\n");
printf("Testing colors...\n");
for (int i=0; i<15; i++) {
terminal_setcolor(i);
printf(i + "\n");
}
terminal_setcolor(VGA_COLOR_LIGHT_GREY);
printf("System initialized. Starting shell...");
printf("\n");
printf("fos> ");
kernel_panic("shell not implemented");
}
while (42) {
/* Wait until the status register says us that a key was pressed. That should
* be very short so the code must be executed at the same time the computer
* can process a key press. I know this implementation is shitty, but our
* computers are fast enough nowadays to process that in no time. */
uint8_t status_register = inb(0x64);
if (status_register & (1 << 0))
{
unsigned char scancode;

//Read from the keyboard's data buffer.
scancode = inb(0x60);
//...aand translate that scancode
switch (scancode) {
case 0x1c:
printf("\n");
printf("fos> ");
break;
default:
break;
}
}
}
}

Loading…
Cancel
Save