Initial commit

This commit is contained in:
2021-01-28 22:59:39 +01:00
commit d7f0e8dd36
30 changed files with 2092 additions and 0 deletions

70
kernel/drivers/keyboard.c Normal file
View File

@@ -0,0 +1,70 @@
//
// Created by rick on 23-03-20.
//
#include "keyboard.h"
#include <kprint.h>
#include <drivers/ports.h>
#include <cpu/isr.h>
#include <libc/libc.h>
char scancodes_ascii[] = {
0, 0,
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0,
0, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 0,
0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0,
'*',
0, ' ',
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F1-F10
0, 0,
'7', '8', '9', '-',
'4', '5', '6', '+',
'1', '2', '3',
'0', 0,
0, // sysrq
0, 0, // weird
0, 0, // F11 F12
// weid
};
char *MSG_KEY = "Clicked on key 'x'\n";
void print_scancode(unsigned char scancode);
static void keyboard_callback(registers_t regs) {
unsigned char status = port_byte_in(PORT_PS2_STATUS);
// check if data available
if ((status & 0b00000001) == 0) {
return;
}
unsigned char scancode = port_byte_in(0x60);
print_scancode(scancode);
}
void init_keyboard() {
register_interrupt_handler(IRQ1, keyboard_callback);
}
void print_scancode(unsigned char scancode) {
char msg[256];
char release = 0;
if (scancode > 0x80) {
// release
release = 1;
scancode -= 0x80;
}
char code = scancodes_ascii[scancode];
if (code == 0) {
// special
} else {
if (release && code > 0x60 && code < 0x7B) {
code -= 0x20; // to lowercase
}
memcpy(msg, MSG_KEY, strlen(MSG_KEY));
msg[strlen(msg) - 3] = code;
kprint(msg);
}
}

10
kernel/drivers/keyboard.h Normal file
View File

@@ -0,0 +1,10 @@
//
// Created by rick on 23-03-20.
//
#ifndef MY_KERNEL_KEYBOARD_H
#define MY_KERNEL_KEYBOARD_H
void init_keyboard();
#endif //MY_KERNEL_KEYBOARD_H

33
kernel/drivers/ports.c Normal file
View File

@@ -0,0 +1,33 @@
/*
* ports.c
*
* Created on: Aug 18, 2019
* Author: rick
*/
#include "ports.h"
/**
* Read a byte from the specified port
*/
unsigned char port_byte_in(unsigned short port) {
unsigned char result;
__asm__("in %%dx, %%al" : "=a" (result) : "d" (port));
return result;
}
void port_byte_out(unsigned short port, unsigned char data) {
__asm__("out %%al, %%dx" : : "a" (data), "d" (port));
}
unsigned short port_word_in(unsigned short port) {
unsigned short result;
__asm__("in %%dx, %%ax" : "=a" (result) : "d" (port));
return result;
}
void port_wordt_out(unsigned short port, unsigned short data) {
__asm__("out %%ax, %%dx" : : "a" (data), "d" (port));
}

51
kernel/drivers/ports.h Normal file
View File

@@ -0,0 +1,51 @@
#ifndef MY_KERNEL_DRIVERS_PORT_H
#define MY_KERNEL_DRIVERS_PORT_H
//http://www.osdever.net/FreeVGA/vga/crtcreg.htm#0A
#define PORT_REG_SCREEN_CTRL 0x3d4
#define PORT_REG_SCREEN_CTRL_CURSOR_H 0x0E
#define PORT_REG_SCREEN_CTRL_CURSOR_L 0x0F
#define PORT_REG_SCREEN_DATA 0x3d5
// https://wiki.osdev.org/Serial_Ports
#define PORT_SERIAL_0 0x3f8
#define PORT_SERIAL_1 0x2f8
#define PORT_SERIAL_2 0x3e8
#define PORT_SERIAL_3 0x2e8
#define PORT_SERIAL_DATA 0
#define PORT_SERIAL_INTERRUPT 1
#define PORT_SERIAL_DLAB_LSB 0
#define PORT_SERIAL_DLAB_MSB 1
#define PORT_SERIAL_INTERRUPT_ID_FIFO 2
#define PORT_SERIAL_LINE_CONTROL 3
#define PORT_SERIAL_MODEM_CONTROL 4
#define PORT_SERIAL_LINE_STATUS 5
#define PORT_SERIAL_MODEM_STATUS 6
#define PORT_SERIAL_SCRATCH 6
// https://wiki.osdev.org/PIT
#define PORT_PIT_COMMAND 0x43
#define PIT_MODE_BIN 0x0
#define PIT_MODE_HW_STROBE 0b0101
#define PIT_MODE_SQUARE_WAVE 0b0110
#define PIT_ACCESS_MODE_HL 0b000011
#define PIT_CHANNEL_0 0b00000000
#define PORT_PIT_DATA_0 0x40
#define PORT_PIT_DATA_1 0x41
#define PORT_PIT_DATA_3 0x42
// https://wiki.osdev.org/%228042%22_PS/2_Controller
#define PORT_PS2_DATA 0x60
#define PORT_PS2_STATUS 0x64
#define PORT_PS2_COMMAND 0x64
unsigned char port_byte_in(unsigned short port);
void port_byte_out(unsigned short port, unsigned char data);
unsigned short port_word_in(unsigned short port);
void port_word_out(unsigned short port, unsigned short data);
#endif

56
kernel/drivers/serial.c Normal file
View File

@@ -0,0 +1,56 @@
//
// Created by rick on 28-01-21.
//
#include "serial.h"
#include <types.h>
#include <drivers/ports.h>
int serial_init() {
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_INTERRUPT, 0x00); // Disable all interrupts
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_LINE_CONTROL, 0x80); // Enable DLAB (set baud rate divisor)
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_DLAB_LSB, 0x03); // Set divisor to 3 (lo byte) 38400 baud
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_DLAB_MSB, 0x00); // (hi byte)
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_LINE_CONTROL, 0x03); // 8 bits, no parity, one stop bit
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_INTERRUPT_ID_FIFO,
0xC7); // Enable FIFO, clear them, with 14-byte threshold
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_MODEM_CONTROL, 0x0B); // IRQs enabled, RTS/DSR set
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_MODEM_CONTROL, 0x1E); // Set in loopback mode, test the serial chip
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_DATA,
0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
// Check if serial is faulty (i.e: not same byte as sent)
if (port_byte_in(PORT_SERIAL_0 + PORT_SERIAL_DATA) != 0xAE) {
return 1;
}
// If serial is not faulty set it in normal operation mode
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_MODEM_CONTROL, 0x0F);
return 0;
}
int is_transmit_empty() {
return port_byte_in(PORT_SERIAL_0 + PORT_SERIAL_LINE_STATUS) & 0x20;
}
void write_serial(char a) {
while (is_transmit_empty() == 0);
port_byte_out(PORT_SERIAL_0 + PORT_SERIAL_DATA, a);
}
void serial_kprint(char *msg) {
u32 i = 0;
while (1) {
char c = msg[i];
if (c == 0) {
break;
}
if (c == '\n') {
write_serial('\r');
}
write_serial(c);
i++;
}
}

12
kernel/drivers/serial.h Normal file
View File

@@ -0,0 +1,12 @@
//
// Created by rick on 28-01-21.
//
#ifndef NEW_KERNEL_SERIAL_H
#define NEW_KERNEL_SERIAL_H
int serial_init();
void serial_kprint(char *msg);
#endif //NEW_KERNEL_SERIAL_H

122
kernel/drivers/vgascreen.c Normal file
View File

@@ -0,0 +1,122 @@
//
// Created by rick on 8/18/19.
//
#include "vgascreen.h"
#include <libc/libc.h>
#include <drivers/ports.h>
char *_vga_character_memory = (char *) VGA_CHARACTER_MEMORY_LOCATION;
int get_offset(int col, int row);
int get_cursor_offset();
void set_cursor_offset(int offset);
int get_offset_row(int offset);
int get_offset_col(int offset);
int print_char(char character, int col, int row, char attributes);
void vga_clear_screen() {
int size = VGA_COL_MAX * VGA_ROW_MAX;
for (int i = 0; i < size; ++i) {
_vga_character_memory[i * 2] = ' ';
_vga_character_memory[i * 2 + 1] = VGA_WHITE | (VGA_BLACK << VGA_SHIFT_BG);
}
set_cursor_offset(0);
}
void kprint_at(char *message, int col, int row) {
int offset;
if (col > 0 && row > 0) {
offset = get_offset(col, row);
} else {
offset = get_cursor_offset();
row = get_offset_row(offset);
col = get_offset_col(offset);
}
int i = 0;
while (message[i] != 0) {
offset = print_char(message[i++], col, row, VGA_WHITE | (VGA_BLACK << VGA_SHIFT_BG));
row = get_offset_row(offset);
col = get_offset_col(offset);
}
}
void vga_kprint(char *message) {
kprint_at(message, -1, -1);
}
int print_char(char character, int col, int row, char attributes) {
if (!attributes) attributes = VGA_WHITE | (VGA_BLACK < VGA_SHIFT_BG);
if (col >= VGA_COL_MAX || row > +VGA_ROW_MAX) {
_vga_character_memory[2 * (VGA_COL_MAX) * (VGA_ROW_MAX) - 2] = 'E';
_vga_character_memory[2 * (VGA_COL_MAX) * (VGA_ROW_MAX) - 1] = VGA_RED | (VGA_WHITE < VGA_SHIFT_BG);
return get_offset(col, row);
}
int offset;
if (col >= 0 && row >= 0) {
offset = get_offset(col, row);
} else {
offset = get_cursor_offset();
}
if (character == '\n') {
row = get_offset_row(offset);
offset = get_offset(0, row + 1);
} else {
_vga_character_memory[offset] = character;
_vga_character_memory[offset + 1] = attributes;
offset += 2;
}
if (offset >= (VGA_COL_MAX * 2 * VGA_ROW_MAX)) {
memcpy(_vga_character_memory,
_vga_character_memory + (VGA_COL_MAX * 2),
(2 * VGA_COL_MAX * VGA_ROW_MAX) - (2 * VGA_COL_MAX));
for (int i = 0; i < VGA_COL_MAX; ++i) {
_vga_character_memory[get_offset(i, VGA_ROW_MAX - 1)] = ' ';
}
offset = get_offset(0, VGA_ROW_MAX - 1);
}
set_cursor_offset(offset);
return offset;
}
int get_cursor_offset() {
port_byte_out(PORT_REG_SCREEN_CTRL, PORT_REG_SCREEN_CTRL_CURSOR_H);
int offset = ((int) port_byte_in(PORT_REG_SCREEN_DATA)) << 8;
port_byte_out(PORT_REG_SCREEN_CTRL, PORT_REG_SCREEN_CTRL_CURSOR_L);
offset += port_byte_in(PORT_REG_SCREEN_DATA);
return offset * 2;
}
void set_cursor_offset(int offset) {
offset /= 2;
port_byte_out(PORT_REG_SCREEN_CTRL, PORT_REG_SCREEN_CTRL_CURSOR_L);
port_byte_out(PORT_REG_SCREEN_DATA, (unsigned char) (offset & 0xFF));
port_byte_out(PORT_REG_SCREEN_CTRL, PORT_REG_SCREEN_CTRL_CURSOR_H);
port_byte_out(PORT_REG_SCREEN_DATA, (unsigned char) (offset >> 8) & 0xFF);
}
int get_offset(int col, int row) {
return (row * VGA_COL_MAX + col) * 2;
}
int get_offset_row(int offset) {
return offset / (VGA_COL_MAX * 2);
}
int get_offset_col(int offset) {
return (offset - (get_offset_row(offset) * 2 * VGA_COL_MAX)) / 2;
}

View File

@@ -0,0 +1,34 @@
//
// Created by rick on 8/18/19.
//
#ifndef MY_KERNEL_DRIVERS_VGASCREEN_H
#define MY_KERNEL_DRIVERS_VGASCREEN_H
#define VGA_CHARACTER_MEMORY_LOCATION 0xb8000
#define VGA_BLACK 0x0
#define VGA_BLUE 0x1
#define VGA_GREEN 0x2
#define VGA_CIAN 0x3
#define VGA_RED 0x4
#define VGA_PURPLE 0x5
#define VGA_ORANGE 0x6
#define VGA_GRAY 0x7
#define VGA_DARK_GRAY 0x8
#define VGA_LIGHT_BLUE 0x9
#define VGA_LIGHT_GREEN 0xA
#define VGA_LIGHT_RED 0xB
#define VGA_PINK 0xD
#define VGA_YELLOW 0xE
#define VGA_WHITE 0xF
#define VGA_SHIFT_BG 4
#define VGA_BLINK 0x80
#define VGA_COL_MAX 80
#define VGA_ROW_MAX 25
void vga_clear_screen();
void vga_kprint(char *msg);
#endif //MY_KERNEL_VGASCREEN_H