cleans up the arch folder some
This commit is contained in:
131
kernel/arch/io/tty.c
Normal file
131
kernel/arch/io/tty.c
Normal file
@ -0,0 +1,131 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <kernel/tty.h>
|
||||
|
||||
#include "vga.h"
|
||||
#include "io.h"
|
||||
|
||||
/* I/O ports */
|
||||
#define VGA_COMMAND_PORT 0x3D4
|
||||
#define VGA_DATA_PORT 0x3D5
|
||||
|
||||
/* I/O port commands */
|
||||
#define VGA_HIGH_BYTE_COMMAND 14
|
||||
#define VGA_LOW_BYTE_COMMAND 15
|
||||
|
||||
static const size_t VGA_WIDTH = 80;
|
||||
static const size_t VGA_HEIGHT = 25;
|
||||
static uint16_t* const VGA_MEMORY = (uint16_t*) 0xB8000;
|
||||
|
||||
static size_t terminal_row;
|
||||
static size_t terminal_column;
|
||||
static uint8_t terminal_colour;
|
||||
static struct vga_entry* terminal_buffer;
|
||||
|
||||
struct vga_entry {
|
||||
char c;
|
||||
unsigned char colour;
|
||||
} __attribute__((packed));
|
||||
|
||||
void terminal_set_colour(uint8_t colour)
|
||||
{
|
||||
terminal_colour = colour;
|
||||
}
|
||||
|
||||
void terminal_clear(void)
|
||||
{
|
||||
for (size_t y = 0; y < VGA_HEIGHT; y++)
|
||||
for (size_t x = 0; x < VGA_WIDTH; x++)
|
||||
terminal_write_cell((y * VGA_WIDTH) + x, ' ');
|
||||
terminal_move_cursor(0);
|
||||
}
|
||||
|
||||
void terminal_initialize(void)
|
||||
{
|
||||
terminal_row = 0;
|
||||
terminal_column = 0;
|
||||
|
||||
terminal_buffer = (struct vga_entry*) VGA_MEMORY;
|
||||
terminal_set_colour(vga_entry_colour(VGA_COLOUR_LIGHT_GREY, VGA_COLOUR_BLACK));
|
||||
|
||||
terminal_clear();
|
||||
}
|
||||
|
||||
void terminal_move_cursor(unsigned short pos)
|
||||
{
|
||||
if (terminal_row >= VGA_HEIGHT)
|
||||
terminal_scroll_screen();
|
||||
|
||||
outb(VGA_COMMAND_PORT, VGA_HIGH_BYTE_COMMAND);
|
||||
outb(VGA_DATA_PORT, ((pos >> 8) & 0x00FF));
|
||||
outb(VGA_COMMAND_PORT, VGA_LOW_BYTE_COMMAND);
|
||||
outb(VGA_DATA_PORT, pos & 0x00FF);
|
||||
}
|
||||
|
||||
inline size_t terminal_get_pos(void)
|
||||
{return (terminal_row * VGA_WIDTH) + terminal_column;}
|
||||
|
||||
void terminal_write_cell(unsigned int i, char c)
|
||||
{
|
||||
struct vga_entry entry;
|
||||
|
||||
entry.c = c;
|
||||
entry.colour = terminal_colour;
|
||||
|
||||
terminal_buffer[i] = entry;
|
||||
}
|
||||
|
||||
void terminal_write_character(unsigned int i, char c)
|
||||
{
|
||||
switch(c) {
|
||||
case '\n':
|
||||
terminal_row += 1;
|
||||
__attribute__((fallthrough));
|
||||
case '\r':
|
||||
terminal_column = 0;
|
||||
terminal_move_cursor(terminal_get_pos());
|
||||
break;
|
||||
default:
|
||||
terminal_write_cell(i, c);
|
||||
|
||||
terminal_column += 1;
|
||||
if (terminal_column >= VGA_WIDTH) {
|
||||
terminal_column = 0;
|
||||
terminal_row += 1;
|
||||
}
|
||||
|
||||
terminal_move_cursor(terminal_get_pos());
|
||||
}
|
||||
}
|
||||
|
||||
void terminal_write(const char* buf, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++)
|
||||
terminal_write_character(terminal_get_pos(), buf[i]);
|
||||
}
|
||||
|
||||
void terminal_writestring(const char* buf)
|
||||
{
|
||||
terminal_write(buf, strlen(buf));
|
||||
}
|
||||
|
||||
void terminal_scroll_screen(void)
|
||||
{
|
||||
size_t y, x;
|
||||
for (y = 0; y < VGA_HEIGHT -1; y++) {
|
||||
for (x = 0; x < VGA_WIDTH; x++) {
|
||||
terminal_buffer[(y * VGA_WIDTH) + x] =
|
||||
terminal_buffer[((y + 1) * VGA_WIDTH) + x];
|
||||
}
|
||||
}
|
||||
for (x = 0; x < VGA_WIDTH; x++)
|
||||
terminal_write_cell(((VGA_HEIGHT - 1) * VGA_WIDTH) + x, ' ');
|
||||
|
||||
terminal_row -= 1;
|
||||
terminal_column = 0;
|
||||
terminal_move_cursor(terminal_get_pos());
|
||||
}
|
||||
|
Reference in New Issue
Block a user