Initial commit
This commit is contained in:
70
kernel/drivers/keyboard.c
Normal file
70
kernel/drivers/keyboard.c
Normal 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
10
kernel/drivers/keyboard.h
Normal 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
33
kernel/drivers/ports.c
Normal 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
51
kernel/drivers/ports.h
Normal 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
56
kernel/drivers/serial.c
Normal 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
12
kernel/drivers/serial.h
Normal 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
122
kernel/drivers/vgascreen.c
Normal 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;
|
||||
}
|
||||
34
kernel/drivers/vgascreen.h
Normal file
34
kernel/drivers/vgascreen.h
Normal 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
|
||||
Reference in New Issue
Block a user