forked from Bananymous/banan-os
Kernel: IRQs are now working :)
This commit is contained in:
parent
343dda629c
commit
4202c999fa
|
@ -14,7 +14,7 @@ BOOTDIR?=$(EXEC_PREFIX)/boot
|
||||||
INCLUDEDIR?=$(PREFIX)/include
|
INCLUDEDIR?=$(PREFIX)/include
|
||||||
|
|
||||||
CFLAGS:=$(CFLAGS) -D__is_kernel -Iinclude -fstack-protector -ffreestanding -Wall -Wextra -Wno-unused-function
|
CFLAGS:=$(CFLAGS) -D__is_kernel -Iinclude -fstack-protector -ffreestanding -Wall -Wextra -Wno-unused-function
|
||||||
CPPFLAGS:=$(CPPFLAGS)
|
CPPFLAGS:=$(CPPFLAGS) -fno-rtti -fno-exceptions
|
||||||
LDFLAGS:=$(LDFLAGS)
|
LDFLAGS:=$(LDFLAGS)
|
||||||
LIBS:=$(LIBS) -nostdlib -lk -lgcc
|
LIBS:=$(LIBS) -nostdlib -lk -lgcc
|
||||||
|
|
||||||
|
@ -32,9 +32,14 @@ BUILDDIR=$(abspath build)
|
||||||
KERNEL_OBJS=\
|
KERNEL_OBJS=\
|
||||||
$(KERNEL_ARCH_OBJS) \
|
$(KERNEL_ARCH_OBJS) \
|
||||||
kernel/GDT.o \
|
kernel/GDT.o \
|
||||||
|
kernel/GDT_asm.o \
|
||||||
kernel/IDT.o \
|
kernel/IDT.o \
|
||||||
|
kernel/IDT_asm.o \
|
||||||
kernel/kernel.o \
|
kernel/kernel.o \
|
||||||
kernel/kmalloc.o \
|
kernel/kmalloc.o \
|
||||||
|
kernel/PIC.o \
|
||||||
|
kernel/PIT.o \
|
||||||
|
kernel/PS2.o \
|
||||||
kernel/SSP.o \
|
kernel/SSP.o \
|
||||||
|
|
||||||
OBJS=\
|
OBJS=\
|
||||||
|
@ -59,7 +64,7 @@ $(ARCHDIR)/crtn.o \
|
||||||
all: banan-os.kernel
|
all: banan-os.kernel
|
||||||
|
|
||||||
banan-os.kernel: always $(OBJS) $(ARCHDIR)/linker.ld
|
banan-os.kernel: always $(OBJS) $(ARCHDIR)/linker.ld
|
||||||
cd $(BUILDDIR) && $(CC) -T ../$(ARCHDIR)/linker.ld -o banan-os.kernel $(CFLAGS) $(LINK_LIST)
|
cd $(BUILDDIR) && $(CXX) -T ../$(ARCHDIR)/linker.ld -o banan-os.kernel $(CFLAGS) $(CPPFLAGS) $(LINK_LIST)
|
||||||
cd $(BUILDDIR) && grub-file --is-x86-multiboot banan-os.kernel
|
cd $(BUILDDIR) && grub-file --is-x86-multiboot banan-os.kernel
|
||||||
|
|
||||||
$(ARCHDIR)/crtbegin.o $(ARCHDIR)/crtend.o:
|
$(ARCHDIR)/crtbegin.o $(ARCHDIR)/crtend.o:
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <kernel/IO.h>
|
||||||
#include <kernel/multiboot.h>
|
#include <kernel/multiboot.h>
|
||||||
#include <kernel/panic.h>
|
#include <kernel/panic.h>
|
||||||
#include <kernel/tty.h>
|
#include <kernel/tty.h>
|
||||||
|
@ -77,19 +78,13 @@ void terminal_clear_line(size_t line)
|
||||||
terminal_putentryat(' ', terminal_color, x, line);
|
terminal_putentryat(' ', terminal_color, x, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void outb(uint16_t port, uint8_t value)
|
|
||||||
{
|
|
||||||
asm volatile ("outb %0, %1" : : "a" (value), "Nd" (port));
|
|
||||||
}
|
|
||||||
static void terminal_update_cursor()
|
static void terminal_update_cursor()
|
||||||
{
|
{
|
||||||
uint16_t pos = terminal_row * VGA_WIDTH + terminal_col;
|
uint16_t pos = terminal_row * VGA_WIDTH + terminal_col;
|
||||||
|
IO::outb(0x3D4, 0x0F);
|
||||||
outb(0x3D4, 0x0F);
|
IO::outb(0x3D5, (uint8_t) (pos & 0xFF));
|
||||||
outb(0x3D5, (uint8_t) (pos & 0xFF));
|
IO::outb(0x3D4, 0x0E);
|
||||||
outb(0x3D4, 0x0E);
|
IO::outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF));
|
||||||
outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void terminal_set_cursor_pos(int x, int y)
|
void terminal_set_cursor_pos(int x, int y)
|
||||||
|
|
|
@ -2,26 +2,12 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
union GateDescriptor
|
constexpr uint8_t IRQ_VECTOR_BASE = 0x50;
|
||||||
|
|
||||||
|
namespace IDT
|
||||||
{
|
{
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint16_t offset_lo;
|
|
||||||
uint16_t selector;
|
|
||||||
uint8_t reserved;
|
|
||||||
uint8_t type : 4;
|
|
||||||
uint8_t zero : 1;
|
|
||||||
uint8_t dpl : 2;
|
|
||||||
uint8_t present : 1;
|
|
||||||
uint16_t offset_hi;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct
|
void initialize();
|
||||||
{
|
void register_irq_handler(uint8_t irq, void (*f)());
|
||||||
uint32_t low;
|
|
||||||
uint32_t high;
|
|
||||||
};
|
|
||||||
|
|
||||||
} __attribute__((packed));
|
}
|
||||||
|
|
||||||
void idt_initialize();
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace IO
|
||||||
|
{
|
||||||
|
|
||||||
|
static inline void outb(uint16_t port, uint8_t val)
|
||||||
|
{
|
||||||
|
asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t inb(uint16_t port)
|
||||||
|
{
|
||||||
|
uint8_t ret;
|
||||||
|
asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void io_wait()
|
||||||
|
{
|
||||||
|
outb(0x80, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace PIC
|
||||||
|
{
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
void eoi(uint8_t);
|
||||||
|
void unmask(uint8_t);
|
||||||
|
void mask(uint8_t);
|
||||||
|
|
||||||
|
uint16_t get_isr();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace PIT
|
||||||
|
{
|
||||||
|
|
||||||
|
uint64_t ms_since_boot();
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace PS2
|
||||||
|
{
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
|
||||||
|
}
|
|
@ -10,37 +10,34 @@ struct GDTR
|
||||||
static GDTR s_gdtr;
|
static GDTR s_gdtr;
|
||||||
static SegmentDesriptor* s_gdt;
|
static SegmentDesriptor* s_gdt;
|
||||||
|
|
||||||
void write_gdt_entry_raw(uint8_t index, uint32_t low, uint32_t high)
|
extern "C" void load_gdt(void* gdt_ptr);
|
||||||
|
|
||||||
|
void write_gdt_entry_raw(uint8_t segment, uint32_t low, uint32_t high)
|
||||||
{
|
{
|
||||||
|
uint8_t index = segment >> 3;
|
||||||
s_gdt[index].low = low;
|
s_gdt[index].low = low;
|
||||||
s_gdt[index].high = high;
|
s_gdt[index].high = high;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_gdt_entry(uint8_t index, SegmentDesriptor descriptor)
|
void write_gdt_entry(uint8_t segment, SegmentDesriptor descriptor)
|
||||||
{
|
{
|
||||||
write_gdt_entry_raw(index, descriptor.low, descriptor.high);
|
write_gdt_entry_raw(segment, descriptor.low, descriptor.high);
|
||||||
}
|
|
||||||
|
|
||||||
static void flush_gdt()
|
|
||||||
{
|
|
||||||
asm volatile("lgdt %0"::"m"(s_gdtr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gdt_initialize()
|
void gdt_initialize()
|
||||||
{
|
{
|
||||||
constexpr size_t gdt_size = 256;
|
constexpr uint8_t GDT_SIZE = 5;
|
||||||
|
|
||||||
s_gdt = new SegmentDesriptor[gdt_size];
|
s_gdt = new SegmentDesriptor[GDT_SIZE];
|
||||||
|
|
||||||
s_gdtr.address = s_gdt;
|
s_gdtr.address = s_gdt;
|
||||||
s_gdtr.size = gdt_size * 8 - 1;
|
s_gdtr.size = GDT_SIZE * 8 - 1;
|
||||||
|
|
||||||
uint8_t index = 0;
|
write_gdt_entry(0x00, { 0, 0x00000, 0x00, 0x0 }); // null
|
||||||
write_gdt_entry(index++, { 0, 0x0000, 0x00, 0x0 }); // null
|
write_gdt_entry(0x08, { 0, 0xFFFFF, 0x9A, 0xC }); // kernel code
|
||||||
write_gdt_entry(index++, { 0, 0xFFFF, 0x9A, 0xC }); // kernel code
|
write_gdt_entry(0x10, { 0, 0xFFFFF, 0x92, 0xC }); // kernel data
|
||||||
write_gdt_entry(index++, { 0, 0xFFFF, 0x92, 0xC }); // kernel data
|
write_gdt_entry(0x18, { 0, 0xFFFFF, 0xFA, 0xC }); // user code
|
||||||
write_gdt_entry(index++, { 0, 0xFFFF, 0xFA, 0xC }); // user code
|
write_gdt_entry(0x20, { 0, 0xFFFFF, 0xF2, 0xC }); // user data
|
||||||
write_gdt_entry(index++, { 0, 0xFFFF, 0xF2, 0xC }); // user data
|
|
||||||
|
|
||||||
flush_gdt();
|
load_gdt(&s_gdtr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
.global load_gdt
|
||||||
|
|
||||||
|
load_gdt:
|
||||||
|
movl 4(%esp),%eax
|
||||||
|
lgdt (%eax)
|
||||||
|
|
||||||
|
movw $0x10, %ax
|
||||||
|
movw %ax, %ds
|
||||||
|
movw %ax, %es
|
||||||
|
movw %ax, %fs
|
||||||
|
movw %ax, %gs
|
||||||
|
movw %ax, %ss
|
||||||
|
jmp $0x08,$flush
|
||||||
|
|
||||||
|
flush:
|
||||||
|
ret
|
|
@ -1,8 +1,31 @@
|
||||||
#include <kernel/IDT.h>
|
#include <kernel/IDT.h>
|
||||||
#include <kernel/kmalloc.h>
|
#include <kernel/kmalloc.h>
|
||||||
#include <kernel/panic.h>
|
#include <kernel/panic.h>
|
||||||
|
#include <kernel/PIC.h>
|
||||||
#include <kernel/kprint.h>
|
#include <kernel/kprint.h>
|
||||||
|
|
||||||
|
union GateDescriptor
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint16_t offset_lo;
|
||||||
|
uint16_t selector;
|
||||||
|
uint8_t reserved;
|
||||||
|
uint8_t type : 4;
|
||||||
|
uint8_t zero : 1;
|
||||||
|
uint8_t dpl : 2;
|
||||||
|
uint8_t present : 1;
|
||||||
|
uint16_t offset_hi;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t low;
|
||||||
|
uint32_t high;
|
||||||
|
};
|
||||||
|
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct IDTR
|
struct IDTR
|
||||||
{
|
{
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
|
@ -12,6 +35,10 @@ struct IDTR
|
||||||
static IDTR s_idtr;
|
static IDTR s_idtr;
|
||||||
static GateDescriptor* s_idt;
|
static GateDescriptor* s_idt;
|
||||||
|
|
||||||
|
static void (*s_irq_handlers[16])();
|
||||||
|
|
||||||
|
extern "C" void handle_irq();
|
||||||
|
extern "C" void handle_irq_common();
|
||||||
|
|
||||||
#define INTERRUPT_HANDLER(i, msg) \
|
#define INTERRUPT_HANDLER(i, msg) \
|
||||||
static void interrupt ## i () \
|
static void interrupt ## i () \
|
||||||
|
@ -42,27 +69,62 @@ INTERRUPT_HANDLER(0x0e, "Page fault")
|
||||||
INTERRUPT_HANDLER(0x0f, "Unknown error")
|
INTERRUPT_HANDLER(0x0f, "Unknown error")
|
||||||
INTERRUPT_HANDLER(0x10, "Coprocessor error")
|
INTERRUPT_HANDLER(0x10, "Coprocessor error")
|
||||||
|
|
||||||
#define REGISTER_HANDLER(i) register_interrupt_handeler(i, interrupt ## i)
|
#define REGISTER_HANDLER(i) register_interrupt_handler(i, interrupt ## i)
|
||||||
|
|
||||||
static void flush_idt()
|
void handle_irq()
|
||||||
{
|
{
|
||||||
|
uint16_t isr = PIC::get_isr();
|
||||||
|
if (!isr) {
|
||||||
|
kprint("Spurious IRQ\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t irq = 0;
|
||||||
|
for (uint8_t i = 0; i < 16; ++i) {
|
||||||
|
if (i == 2)
|
||||||
|
continue;
|
||||||
|
if (isr & (1 << i)) {
|
||||||
|
irq = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_irq_handlers[irq])
|
||||||
|
s_irq_handlers[irq]();
|
||||||
|
else
|
||||||
|
kprint("no handler for irq {}\n", irq);
|
||||||
|
|
||||||
|
PIC::eoi(irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace IDT
|
||||||
|
{
|
||||||
|
|
||||||
|
static void flush_idt()
|
||||||
|
{
|
||||||
asm volatile("lidt %0"::"m"(s_idtr));
|
asm volatile("lidt %0"::"m"(s_idtr));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unimplemented_trap()
|
static void unimplemented_trap()
|
||||||
{
|
{
|
||||||
Kernel::panic("Unhandeled IRQ");
|
Kernel::panic("Unhandeled IRQ");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void register_interrupt_handeler(uint8_t index, void (*f)())
|
static void register_interrupt_handler(uint8_t index, void (*f)())
|
||||||
{
|
{
|
||||||
s_idt[index].low = 0x00080000 | ((uint32_t)(f) & 0x0000ffff);
|
s_idt[index].low = 0x00080000 | ((uint32_t)(f) & 0x0000ffff);
|
||||||
s_idt[index].high = ((uint32_t)(f) & 0xffff0000) | 0x8e00;
|
s_idt[index].high = ((uint32_t)(f) & 0xffff0000) | 0x8e00;
|
||||||
flush_idt();
|
flush_idt();
|
||||||
}
|
}
|
||||||
|
|
||||||
void idt_initialize()
|
void register_irq_handler(uint8_t irq, void (*f)())
|
||||||
{
|
{
|
||||||
|
s_irq_handlers[irq] = f;
|
||||||
|
register_interrupt_handler(IRQ_VECTOR_BASE + irq, handle_irq_common);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize()
|
||||||
|
{
|
||||||
constexpr size_t idt_size = 256;
|
constexpr size_t idt_size = 256;
|
||||||
|
|
||||||
s_idt = new GateDescriptor[idt_size];
|
s_idt = new GateDescriptor[idt_size];
|
||||||
|
@ -70,6 +132,9 @@ void idt_initialize()
|
||||||
s_idtr.offset = s_idt;
|
s_idtr.offset = s_idt;
|
||||||
s_idtr.size = idt_size * 8;
|
s_idtr.size = idt_size * 8;
|
||||||
|
|
||||||
|
for (uint8_t i = 0xff; i > 0x10; i--)
|
||||||
|
register_interrupt_handler(i, unimplemented_trap);
|
||||||
|
|
||||||
REGISTER_HANDLER(0x00);
|
REGISTER_HANDLER(0x00);
|
||||||
REGISTER_HANDLER(0x01);
|
REGISTER_HANDLER(0x01);
|
||||||
REGISTER_HANDLER(0x02);
|
REGISTER_HANDLER(0x02);
|
||||||
|
@ -88,8 +153,10 @@ void idt_initialize()
|
||||||
REGISTER_HANDLER(0x0f);
|
REGISTER_HANDLER(0x0f);
|
||||||
REGISTER_HANDLER(0x10);
|
REGISTER_HANDLER(0x10);
|
||||||
|
|
||||||
for (uint16_t i = 0x11; i < idt_size; i++)
|
for (uint8_t i = 0; i < sizeof(s_irq_handlers) / sizeof(*s_irq_handlers); i++)
|
||||||
register_interrupt_handeler(i, unimplemented_trap);
|
s_irq_handlers[i] = nullptr;
|
||||||
|
|
||||||
flush_idt();
|
flush_idt();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
.globl handle_irq_common
|
||||||
|
|
||||||
|
handle_irq_common:
|
||||||
|
pusha
|
||||||
|
pushw %ds
|
||||||
|
pushw %es
|
||||||
|
pushw %ss
|
||||||
|
pushw %ss
|
||||||
|
popw %ds
|
||||||
|
popw %es
|
||||||
|
call handle_irq
|
||||||
|
popw %es
|
||||||
|
popw %ds
|
||||||
|
popa
|
||||||
|
iret
|
|
@ -0,0 +1,105 @@
|
||||||
|
#include <kernel/PIC.h>
|
||||||
|
#include <kernel/IDT.h>
|
||||||
|
#include <kernel/IO.h>
|
||||||
|
|
||||||
|
#define PIC1 0x20 /* IO base address for master PIC */
|
||||||
|
#define PIC2 0xA0 /* IO base address for slave PIC */
|
||||||
|
#define PIC1_COMMAND PIC1
|
||||||
|
#define PIC1_DATA (PIC1+1)
|
||||||
|
#define PIC2_COMMAND PIC2
|
||||||
|
#define PIC2_DATA (PIC2+1)
|
||||||
|
|
||||||
|
#define PIC_EOI 0x20 /* End-of-interrupt command code */
|
||||||
|
|
||||||
|
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
|
||||||
|
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
|
||||||
|
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
|
||||||
|
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
|
||||||
|
#define ICW1_INIT 0x10 /* Initialization - required! */
|
||||||
|
|
||||||
|
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
|
||||||
|
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
|
||||||
|
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
|
||||||
|
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
|
||||||
|
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
|
||||||
|
|
||||||
|
|
||||||
|
namespace PIC
|
||||||
|
{
|
||||||
|
|
||||||
|
void initialize()
|
||||||
|
{
|
||||||
|
// Start the initialization sequence (in cascade mode)
|
||||||
|
IO::outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);
|
||||||
|
IO::io_wait();
|
||||||
|
IO::outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
|
||||||
|
IO::io_wait();
|
||||||
|
|
||||||
|
// ICW2
|
||||||
|
IO::outb(PIC1_DATA, IRQ_VECTOR_BASE);
|
||||||
|
IO::io_wait();
|
||||||
|
IO::outb(PIC2_DATA, IRQ_VECTOR_BASE + 0x08);
|
||||||
|
IO::io_wait();
|
||||||
|
|
||||||
|
// ICW3
|
||||||
|
IO::outb(PIC1_DATA, 4);
|
||||||
|
IO::io_wait();
|
||||||
|
IO::outb(PIC2_DATA, 2);
|
||||||
|
IO::io_wait();
|
||||||
|
|
||||||
|
// ICW4
|
||||||
|
IO::outb(PIC1_DATA, ICW4_8086);
|
||||||
|
IO::io_wait();
|
||||||
|
IO::outb(PIC2_DATA, ICW4_8086);
|
||||||
|
IO::io_wait();
|
||||||
|
|
||||||
|
// Mask everything
|
||||||
|
IO::outb(PIC1_DATA, 0xff);
|
||||||
|
IO::outb(PIC2_DATA, 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void eoi(uint8_t irq)
|
||||||
|
{
|
||||||
|
if (irq >= 8)
|
||||||
|
IO::outb(PIC2_COMMAND, PIC_EOI);
|
||||||
|
IO::outb(PIC1_COMMAND, PIC_EOI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mask(uint8_t irq) {
|
||||||
|
uint16_t port;
|
||||||
|
uint8_t value;
|
||||||
|
|
||||||
|
if(irq < 8) {
|
||||||
|
port = PIC1_DATA;
|
||||||
|
} else {
|
||||||
|
port = PIC2_DATA;
|
||||||
|
irq -= 8;
|
||||||
|
}
|
||||||
|
value = IO::inb(port) | (1 << irq);
|
||||||
|
IO::outb(port, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unmask(uint8_t irq) {
|
||||||
|
uint16_t port;
|
||||||
|
uint8_t value;
|
||||||
|
|
||||||
|
if(irq < 8) {
|
||||||
|
port = PIC1_DATA;
|
||||||
|
} else {
|
||||||
|
port = PIC2_DATA;
|
||||||
|
irq -= 8;
|
||||||
|
}
|
||||||
|
value = IO::inb(port) & ~(1 << irq);
|
||||||
|
IO::outb(port, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t get_isr()
|
||||||
|
{
|
||||||
|
IO::outb(PIC1_COMMAND, 0x0b);
|
||||||
|
IO::outb(PIC2_COMMAND, 0x0b);
|
||||||
|
uint8_t isr0 = IO::inb(PIC1_COMMAND);
|
||||||
|
uint8_t isr1 = IO::inb(PIC2_COMMAND);
|
||||||
|
return (isr1 << 8) | isr0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
#include <kernel/IDT.h>
|
||||||
|
#include <kernel/IO.h>
|
||||||
|
#include <kernel/kprint.h>
|
||||||
|
#include <kernel/PIC.h>
|
||||||
|
|
||||||
|
#define IRQ_TIMER 0
|
||||||
|
|
||||||
|
#define TIMER0_CTL 0x40
|
||||||
|
#define TIMER1_CTL 0x41
|
||||||
|
#define TIMER2_CTL 0x42
|
||||||
|
#define PIT_CTL 0x43
|
||||||
|
|
||||||
|
#define SELECT_CHANNEL0 0x00
|
||||||
|
#define SELECT_CHANNEL1 0x40
|
||||||
|
#define SELECT_CHANNEL2 0x80
|
||||||
|
|
||||||
|
#define ACCESS_HI 0x10
|
||||||
|
#define ACCESS_LO 0x20
|
||||||
|
|
||||||
|
#define MODE_SQUARE_WAVE 0x06
|
||||||
|
|
||||||
|
#define BASE_FREQUENCY 1193182
|
||||||
|
#define TICKS_PER_SECOND 1000
|
||||||
|
|
||||||
|
namespace PIT
|
||||||
|
{
|
||||||
|
static uint64_t s_system_time = 0;
|
||||||
|
|
||||||
|
void clock_handle()
|
||||||
|
{
|
||||||
|
PIT::s_system_time++;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t ms_since_boot()
|
||||||
|
{
|
||||||
|
return s_system_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize()
|
||||||
|
{
|
||||||
|
constexpr uint16_t timer_reload = BASE_FREQUENCY / TICKS_PER_SECOND;
|
||||||
|
|
||||||
|
IO::outb(PIT_CTL, SELECT_CHANNEL0 | ACCESS_LO | ACCESS_HI | MODE_SQUARE_WAVE);
|
||||||
|
|
||||||
|
IO::outb(TIMER0_CTL, (timer_reload >> 0) & 0xff);
|
||||||
|
IO::outb(TIMER0_CTL, (timer_reload >> 8) & 0xff);
|
||||||
|
|
||||||
|
IDT::register_irq_handler(IRQ_TIMER, clock_handle);
|
||||||
|
|
||||||
|
PIC::unmask(IRQ_TIMER);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include <kernel/IDT.h>
|
||||||
|
#include <kernel/PIC.h>
|
||||||
|
#include <kernel/PS2.h>
|
||||||
|
#include <kernel/kprint.h>
|
||||||
|
|
||||||
|
#define PS2_IRQ 0x01
|
||||||
|
|
||||||
|
|
||||||
|
namespace PS2
|
||||||
|
{
|
||||||
|
|
||||||
|
void irq_handler()
|
||||||
|
{
|
||||||
|
kprint("keyboard\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize()
|
||||||
|
{
|
||||||
|
IDT::register_irq_handler(PS2_IRQ, irq_handler);
|
||||||
|
PIC::unmask(PS2_IRQ);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,8 +3,12 @@
|
||||||
#include <kernel/kmalloc.h>
|
#include <kernel/kmalloc.h>
|
||||||
#include <kernel/multiboot.h>
|
#include <kernel/multiboot.h>
|
||||||
#include <kernel/panic.h>
|
#include <kernel/panic.h>
|
||||||
|
#include <kernel/PIC.h>
|
||||||
|
#include <kernel/PIT.h>
|
||||||
|
#include <kernel/PS2.h>
|
||||||
#include <kernel/tty.h>
|
#include <kernel/tty.h>
|
||||||
#include <kernel/kprint.h>
|
#include <kernel/kprint.h>
|
||||||
|
#include <kernel/IO.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -19,20 +23,29 @@ void kernel_main(multiboot_info_t* mbi, uint32_t magic)
|
||||||
{
|
{
|
||||||
DISABLE_INTERRUPTS();
|
DISABLE_INTERRUPTS();
|
||||||
|
|
||||||
if (magic != 0x2BADB002)
|
|
||||||
asm volatile("hlt");
|
|
||||||
|
|
||||||
s_multiboot_info = mbi;
|
s_multiboot_info = mbi;
|
||||||
|
|
||||||
|
if (magic != 0x2BADB002)
|
||||||
|
goto halt;
|
||||||
|
|
||||||
terminal_initialize();
|
terminal_initialize();
|
||||||
|
|
||||||
kmalloc_initialize();
|
kmalloc_initialize();
|
||||||
|
|
||||||
|
PIC::initialize();
|
||||||
gdt_initialize();
|
gdt_initialize();
|
||||||
idt_initialize();
|
IDT::initialize();
|
||||||
|
|
||||||
|
PIT::initialize();
|
||||||
|
PS2::initialize();
|
||||||
|
|
||||||
kprint("Hello from the kernel!\n");
|
kprint("Hello from the kernel!\n");
|
||||||
|
|
||||||
asm volatile("int $14");
|
ENABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
halt:
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
asm("hlt");
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue