Added a keyboard driver and somehow broke the kernel.

Further researches are being done
This commit is contained in:
Morten Delenk 2015-10-13 16:11:06 +02:00
parent 054e1bc230
commit ff8ba97d2a
18 changed files with 230 additions and 46 deletions

BIN
core

Binary file not shown.

View file

@ -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:

View file

@ -1,6 +1,4 @@
all: x86
#Currently only do X86
mv x86/hal.o hal.o
x86:
make -C x86

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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);

View 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

View 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

View file

@ -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;
};
}

View file

@ -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) {

View file

@ -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(;;);
}

View 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);
}
}

View 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;
}
}

View file

@ -9,6 +9,9 @@ namespace MTGosHAL {
case '\r':
x=0;
break;
case 0x7F:
x--;
if(x<0) x=0;
case '\0':
break;
default:

View file

@ -1,4 +1,6 @@
ENTRY(_start)
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386:i386)
SECTIONS
{
. = 0x100000;

0
qemu-system-i386 Normal file
View file