Added a keyboard driver and somehow broke the kernel.
Further researches are being done
This commit is contained in:
parent
054e1bc230
commit
ff8ba97d2a
18 changed files with 230 additions and 46 deletions
BIN
core
BIN
core
Binary file not shown.
|
@ -1,7 +1,9 @@
|
|||
LD = ld
|
||||
LDFLAGS = -melf_i386 -Tkernel.ld
|
||||
SRCS = $(shell find -name '*.cpp' -o -name '*.[cS]')
|
||||
OBJS = $(addsuffix .o,$(basename $(SRCS)))
|
||||
LD = g++
|
||||
LDFLAGS = -T kernel.ld -nostdlib -nodefaultlibs
|
||||
all: hal
|
||||
$(LD) $(LDFLAGS) -o mtgos hal/hal.o
|
||||
$(LD) $(LDFLAGS) -o mtgos $(OBJS)
|
||||
hal:
|
||||
make -C hal
|
||||
clean:
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
all: x86
|
||||
#Currently only do X86
|
||||
mv x86/hal.o hal.o
|
||||
|
||||
x86:
|
||||
make -C x86
|
||||
|
|
|
@ -3,16 +3,14 @@ OBJS = $(addsuffix .o,$(basename $(SRCS)))
|
|||
|
||||
CPP = g++
|
||||
CC = gcc
|
||||
LD = ld
|
||||
ASFLAGS = -m32
|
||||
CFLAGS = -m32 -Wall -fno-stack-protector -nostdinc -Ic_include/ -ffreestanding -fbuiltin -march=native -std=c11 -fno-builtin
|
||||
CPPFLAGS = -m32 -Wall -fno-stack-protector -nostdinc -std=c++14 -Iinclude/ -Ic_include/ -fno-rtti -fno-exceptions -ffreestanding -fbuiltin -march=native -fno-builtin
|
||||
CFLAGS = -m32 -Wall -fno-stack-protector -nostdinc -Ic_include/ -ffreestanding -march=native -std=c11 -fno-builtin -Werror -nostdlib
|
||||
CPPFLAGS = -m32 -Wall -fno-stack-protector -nostdinc -std=c++14 -Iinclude/ -Ic_include/ -fno-rtti -fno-exceptions -ffreestanding -march=native -fno-builtin -Werror -nostdlib
|
||||
LDFLAGS = -r -melf_i386
|
||||
|
||||
include ../../../kernel.settings
|
||||
|
||||
hal.o: $(OBJS)
|
||||
$(LD) $(LDFLAGS) -o $@ $^
|
||||
all: $(OBJS)
|
||||
|
||||
%.o: %.cpp
|
||||
$(CPP) $(CPPFLAGS) -c -o $@ $^
|
||||
|
@ -26,4 +24,4 @@ hal.o: $(OBJS)
|
|||
clean:
|
||||
rm -rf $(OBJS)
|
||||
|
||||
.PHONY: clean
|
||||
.PHONY: clean all
|
||||
|
|
|
@ -1,38 +1,53 @@
|
|||
#ifndef _IO_H
|
||||
#define _IO_H
|
||||
#include <stdint.h>
|
||||
static inline void outb(uint16_t port, uint8_t val) __attribute__((always_inline));
|
||||
static inline void outb(uint16_t port, uint8_t val) {
|
||||
asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
|
||||
}
|
||||
static inline void outw(uint16_t port, uint16_t val) __attribute__((always_inline));
|
||||
static inline void outw(uint16_t port, uint16_t val) {
|
||||
asm volatile("outw %0, %1" : : "a"(val), "Nd"(port));
|
||||
}
|
||||
static inline void outl(uint16_t port, uint32_t val) __attribute__((always_inline));
|
||||
static inline void outl(uint16_t port, uint32_t val) {
|
||||
asm volatile("outl %0, %1" : : "a"(val), "Nd"(port));
|
||||
}
|
||||
static inline uint8_t inb(uint16_t port) __attribute__((always_inline));
|
||||
static inline uint8_t inb(uint16_t port) {
|
||||
uint8_t ret;
|
||||
asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
|
||||
return ret;
|
||||
}
|
||||
static inline uint16_t inw(uint16_t port) __attribute__((always_inline));
|
||||
static inline uint16_t inw(uint16_t port) {
|
||||
uint16_t ret;
|
||||
asm volatile("inw %1, %0" : "=a"(ret) : "Nd"(port));
|
||||
return ret;
|
||||
}
|
||||
static inline uint32_t inl(uint16_t port) __attribute__((always_inline));
|
||||
static inline uint32_t inl(uint16_t port) {
|
||||
uint32_t ret;
|
||||
asm volatile("inl %1, %0" : "=a"(ret) : "Nd"(port));
|
||||
return ret;
|
||||
}
|
||||
static inline void io_wait() __attribute__((always_inline));
|
||||
static inline void io_wait() {
|
||||
asm volatile("outb %%al, $0x80" : : "a"(0));
|
||||
}
|
||||
static inline void cli() __attribute__((always_inline));
|
||||
static inline void cli() {
|
||||
asm volatile("cli");
|
||||
}
|
||||
static inline void sti() __attribute__((always_inline));
|
||||
static inline void sti() {
|
||||
asm volatile("sti");
|
||||
}
|
||||
|
||||
static inline uint64_t rdtsc() __attribute__((always_inline));
|
||||
static inline uint64_t rdtsc()
|
||||
{
|
||||
uint64_t ret;
|
||||
asm volatile ( "rdtsc" : "=A"(ret) );
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
#include <stdint.h>
|
||||
namespace MTGosHAL {
|
||||
class Output;
|
||||
class Input;
|
||||
class Serial;
|
||||
class Screen;
|
||||
class Keyboard;
|
||||
class GDT;
|
||||
class IDT;
|
||||
enum class BG_color: uint16_t;
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace MTGosHAL {
|
|||
class IDT {
|
||||
private:
|
||||
uint64_t idt[256];
|
||||
void (*ivt[256][16])(struct cpu_state *);
|
||||
struct idtp {
|
||||
uint16_t limit;
|
||||
uint64_t* pointer;
|
||||
|
@ -46,6 +47,7 @@ namespace MTGosHAL {
|
|||
auto setEntry(int i, void* offset, uint16_t seg, uint8_t flags) -> void;
|
||||
auto apply() -> void;
|
||||
auto handle(struct cpu_state* cpu) -> void;
|
||||
auto request(uint8_t intr, void (*handler)(struct cpu_state*)) -> bool;
|
||||
};
|
||||
}
|
||||
extern "C" void handleINT(struct cpu_state* cpu);
|
||||
|
|
29
kernel/hal/x86/include/input.hpp
Normal file
29
kernel/hal/x86/include/input.hpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef _INPUT_HPP
|
||||
#define _INPUT_HPP
|
||||
namespace MTGosHAL {
|
||||
class Input {
|
||||
private:
|
||||
virtual auto getChar() -> char = 0;
|
||||
public:
|
||||
auto operator>>(char &input) -> Input & {
|
||||
input=getChar();
|
||||
return *this;
|
||||
}
|
||||
//Note that it receives up to 256 bytes.
|
||||
auto operator>>(char* input) -> Input & {
|
||||
int ptr=0;
|
||||
char tmp='\0';
|
||||
while(ptr<256 && tmp!='\r') {
|
||||
while(!(tmp=getChar()));
|
||||
if(tmp=='\r')
|
||||
input[ptr++]='\0';
|
||||
else
|
||||
input[ptr++]=tmp;
|
||||
}
|
||||
input[255]='\0';
|
||||
return *this;
|
||||
}
|
||||
//TODO: Add more possibilities.
|
||||
};
|
||||
}
|
||||
#endif
|
21
kernel/hal/x86/include/keyboard.hpp
Normal file
21
kernel/hal/x86/include/keyboard.hpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef _KEYBOARD_HPP
|
||||
#define _KEYBOARD_HPP
|
||||
#include <stdint.h>
|
||||
#include <input.hpp>
|
||||
#include <io.h>
|
||||
#include <idt.hpp>
|
||||
namespace MTGosHAL {
|
||||
class Keyboard: public Input {
|
||||
private:
|
||||
//This kernel has a buffer of 16 chars
|
||||
char buf[16];
|
||||
int len;
|
||||
auto getChar() -> char;
|
||||
auto sendCommand(uint8_t command) -> void;
|
||||
static auto handleIRQ1(struct cpu_state* cpu) -> void;
|
||||
bool shift, numlock, caps, scrollock;
|
||||
public:
|
||||
Keyboard();
|
||||
};
|
||||
}
|
||||
#endif // -Wno-pmf-conversions
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef _SERIAL_HPP
|
||||
#define _SERIAL_HPP
|
||||
#include <output.hpp>
|
||||
#include <input.hpp>
|
||||
#include <textDISP.hpp>
|
||||
#include <io.h>
|
||||
#define SERIAL_IER 1
|
||||
#define SERIAL_IIR 2
|
||||
|
@ -10,42 +12,18 @@
|
|||
#define SERIAL_LSR 5
|
||||
#define SERIAL_MSR 6
|
||||
namespace MTGosHAL {
|
||||
class Serial: public Output {
|
||||
class Serial: public Output, public Input {
|
||||
private:
|
||||
uint16_t port;
|
||||
auto isTransmitEmpty() -> int {
|
||||
return inb(port+SERIAL_LSR)&0x20;
|
||||
}
|
||||
auto putChar(char chr) -> void {
|
||||
while(!isTransmitEmpty());
|
||||
outb(port, chr);
|
||||
}
|
||||
auto puts(const char* s) -> void {
|
||||
int i=0;
|
||||
while(s[i]!='\0')
|
||||
putChar(s[i++]);
|
||||
}
|
||||
uint64_t waittimes;
|
||||
uint64_t transmits;
|
||||
auto isTransmitEmpty() -> int;
|
||||
auto putChar(char chr) -> void;
|
||||
auto serial_received() -> int;
|
||||
auto getChar() -> char;
|
||||
public:
|
||||
Serial(uint32_t baud) {
|
||||
port=*((uint16_t*)0x0400);
|
||||
union {
|
||||
uint8_t b[2];
|
||||
uint16_t w;
|
||||
} divisor;
|
||||
divisor.w = 115200/baud;
|
||||
//Turn off interrupts
|
||||
outb(port+SERIAL_IER, 0x00);
|
||||
//Set DLAB-bit
|
||||
outb(port+SERIAL_LCR, 0x80);
|
||||
//Set baud divisor
|
||||
outb(port, divisor.b[0]);
|
||||
outb(port+1, divisor.b[1]);
|
||||
//Set bit count, parity and reset DLAB
|
||||
outb(port+SERIAL_LCR, 3);
|
||||
//Finish init
|
||||
outb(port+SERIAL_FCR, 0xC7);
|
||||
outb(port+SERIAL_MCR, 0x0B);
|
||||
}
|
||||
Serial(uint32_t baud);
|
||||
auto debug() -> void;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -37,13 +37,29 @@ namespace MTGosHAL {
|
|||
while(1) {
|
||||
asm volatile("cli; hlt");
|
||||
}
|
||||
} else if(cpu->intr >= 0x20 && cpu->intr <= 0x20) {
|
||||
} else if(cpu->intr >= 0x20 && cpu->intr <= 0x2F) {
|
||||
if(cpu->intr >= 0x28) {
|
||||
outb(0xA0, 0x20);
|
||||
}
|
||||
outb(0x20, 0x20);
|
||||
*debug << "The IRQ " << Base::DECIMAL << (int) cpu->intr-0x20 << " was handled.\n";
|
||||
if(cpu->intr==0x20) {
|
||||
debug->debug();
|
||||
}
|
||||
}
|
||||
for(int i=0;i<16;i++) {
|
||||
if(ivt[cpu->intr][i])
|
||||
ivt[cpu->intr][i](cpu);
|
||||
}
|
||||
}
|
||||
auto IDT::request(uint8_t intr, void (*handler)(struct cpu_state*)) -> bool {
|
||||
for(int i=0;i<16;i++) {
|
||||
if(ivt[intr][i])
|
||||
continue;
|
||||
ivt[intr][i]=handler;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
extern "C" void handleINT(struct cpu_state* cpu) {
|
||||
|
|
|
@ -4,11 +4,13 @@
|
|||
#include <textDISP.hpp>
|
||||
#include <gdt.hpp>
|
||||
#include <idt.hpp>
|
||||
#include <keyboard.hpp>
|
||||
extern "C" void intr_stub_0(void);
|
||||
namespace MTGosHAL {
|
||||
Serial* debug;
|
||||
Screen* out;
|
||||
Screen* err;
|
||||
Keyboard* in;
|
||||
IDT* idt;
|
||||
void main() {
|
||||
Serial serialOUT(115200);
|
||||
|
@ -36,6 +38,10 @@ namespace MTGosHAL {
|
|||
idt->setEntry(48, (void *)((uint32_t)&intr_stub_0+768), SEG_KERNEL, IDT_TRAP_GATE | IDT_SEG_32_BIT | IDT_RING_0 | IDT_USED);
|
||||
idt->setEntry(8, (void *)((uint32_t)&intr_stub_0+128), SEG_DBL_FAULT, IDT_TASK_GATE | IDT_SEG_32_BIT | IDT_RING_0 | IDT_USED);
|
||||
idt->apply();
|
||||
|
||||
//Init the Keyboard
|
||||
Keyboard kb;
|
||||
in = &kb;
|
||||
sti();
|
||||
for(;;);
|
||||
}
|
||||
|
|
45
kernel/hal/x86/io/keyboard.cpp
Normal file
45
kernel/hal/x86/io/keyboard.cpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
#include <base.hpp>
|
||||
#include <output.hpp>
|
||||
#include <serial.hpp>
|
||||
#include <keyboard.hpp>
|
||||
namespace MTGosHAL {
|
||||
auto Keyboard::getChar() -> char {
|
||||
char chr=buf[0];
|
||||
for(int i=0;i<15;i++) {
|
||||
buf[i]=buf[i+1];
|
||||
}
|
||||
buf[15]='\0';
|
||||
if(len)
|
||||
len--;
|
||||
return chr;
|
||||
}
|
||||
auto Keyboard::sendCommand(uint8_t command) -> void {
|
||||
while((inb(0x64) & 0x2));
|
||||
outb(0x60, command);
|
||||
}
|
||||
auto Keyboard::handleIRQ1(struct cpu_state* cpu) -> void {
|
||||
*debug << "Keyboard interrupt received.\nGot: 0x" << Base::HEXADECIMAL << (int) inb(0x60) << ".\n";
|
||||
}
|
||||
Keyboard::Keyboard(): shift(false), numlock(true), caps(false), scrollock(false) {
|
||||
if(!idt->request(0x21, (void(*)(struct cpu_state*))&MTGosHAL::Keyboard::handleIRQ1)) {
|
||||
*debug << "Could not get an handler for IRQ1 (Keyboard)\n";
|
||||
return;
|
||||
}
|
||||
//Clear keyboard buffer
|
||||
while(inb(0x64) & 0x1) {
|
||||
inb(0x60);
|
||||
}
|
||||
sendCommand(0xF4); //Activate keyboard
|
||||
//Check for self-test being passed
|
||||
sendCommand(0x20);
|
||||
uint8_t ccb=inb(0x60);
|
||||
if(!(ccb&4)) {
|
||||
*debug << "Keyboard didn't pass self-test!\nDeactivating IRQ1.\n";
|
||||
ccb &= ~1;
|
||||
} else {
|
||||
ccb |= 1;
|
||||
}
|
||||
sendCommand(0x60);
|
||||
outb(0x64, ccb);
|
||||
}
|
||||
}
|
67
kernel/hal/x86/io/serial.cpp
Normal file
67
kernel/hal/x86/io/serial.cpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
#include <base.hpp>
|
||||
#include <serial.hpp>
|
||||
namespace MTGosHAL {
|
||||
auto Serial::isTransmitEmpty() -> int {
|
||||
return inb(port+SERIAL_LSR)&0x20;
|
||||
}
|
||||
auto Serial::putChar(char chr) -> void {
|
||||
while(!isTransmitEmpty())
|
||||
waittimes++;
|
||||
outb(port, chr);
|
||||
transmits++;
|
||||
}
|
||||
auto Serial::serial_received() -> int {
|
||||
return inb(port+SERIAL_LSR)&1;
|
||||
}
|
||||
auto Serial::getChar() -> char {
|
||||
//We try 500 times to get a character
|
||||
int tries=500;
|
||||
while(!serial_received()) {
|
||||
tries--;
|
||||
waittimes++;
|
||||
if(!tries) {
|
||||
return '\0';
|
||||
}
|
||||
}
|
||||
transmits++;
|
||||
char chr = inb(port);
|
||||
if(chr!='\r')
|
||||
*this << chr;
|
||||
else
|
||||
*this << '\n';
|
||||
return chr;
|
||||
}
|
||||
Serial::Serial(uint32_t baud) {
|
||||
port=*((uint16_t*)0x0400);
|
||||
union {
|
||||
uint8_t b[2];
|
||||
uint16_t w;
|
||||
} divisor;
|
||||
divisor.w = 115200/baud;
|
||||
//Turn off interrupts
|
||||
outb(port+SERIAL_IER, 0x00);
|
||||
//Set DLAB-bit
|
||||
outb(port+SERIAL_LCR, 0x80);
|
||||
//Set baud divisor
|
||||
outb(port, divisor.b[0]);
|
||||
outb(port+1, divisor.b[1]);
|
||||
//Set bit count, parity and reset DLAB
|
||||
outb(port+SERIAL_LCR, 3);
|
||||
//Finish init
|
||||
outb(port+SERIAL_FCR, 0xC7);
|
||||
outb(port+SERIAL_MCR, 0x0B);
|
||||
}
|
||||
auto Serial::debug() -> void {
|
||||
if(getChar()) {
|
||||
*this << "The interactive debug shell was started.\n> ";
|
||||
*out << "The debug shell was started.\n";
|
||||
char buf[256];
|
||||
*out << buf << "\nDebug shell closed.\n";
|
||||
*this << "Unknown command. TODO\n";
|
||||
}
|
||||
uint64_t wt = waittimes;
|
||||
uint64_t tm = transmits;
|
||||
*this << "Transmit stats: " << (int32_t)wt << " times waited; " << (int32_t)tm << " bytes transferred.\n";
|
||||
waittimes=transmits=0;
|
||||
}
|
||||
}
|
|
@ -9,6 +9,9 @@ namespace MTGosHAL {
|
|||
case '\r':
|
||||
x=0;
|
||||
break;
|
||||
case 0x7F:
|
||||
x--;
|
||||
if(x<0) x=0;
|
||||
case '\0':
|
||||
break;
|
||||
default:
|
|
@ -1,4 +1,6 @@
|
|||
ENTRY(_start)
|
||||
OUTPUT_FORMAT(elf32-i386)
|
||||
OUTPUT_ARCH(i386:i386)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x100000;
|
||||
|
|
0
qemu-system-i386
Normal file
0
qemu-system-i386
Normal file
Loading…
Reference in a new issue