Add IDT and PIT driver

This commit is contained in:
mintsuki 2020-01-25 02:05:19 +01:00
parent 9b5c159d1f
commit cddacc280a
6 changed files with 142 additions and 0 deletions

View File

@ -4,6 +4,14 @@
#include <lib/blib.h>
#include <drivers/vga_textmode.h>
#include <lib/real.h>
#include <sys/interrupt.h>
void pit_sleep(uint64_t pit_ticks) {
uint64_t target = global_pit_tick + pit_ticks;
while (global_pit_tick < target) {
asm volatile ("hlt");
}
}
uint64_t strtoui(const char *s) {
uint64_t n = 0;

View File

@ -2,6 +2,9 @@
#define __LIB__BLIB_H__
#include <stddef.h>
#include <stdint.h>
void pit_sleep(uint64_t pit_ticks);
void print(const char *fmt, ...);
char getchar(void);

View File

@ -25,6 +25,18 @@ void rm_int(
"push ebp\n\t"
"pushf\n\t"
"cli\n\t"
"mov dx, 0x21\n\t"
"mov al, byte ptr ds:[rm_pic0_mask]\n\t"
"out dx, al\n\t"
"mov dx, 0xa1\n\t"
"mov al, byte ptr ds:[rm_pic1_mask]\n\t"
"out dx, al\n\t"
"sidt [8f]\n\t"
"lidt [9f]\n\t"
// Jump to real mode
"jmp 0x08:1f\n\t"
"1: .code16\n\t"
@ -59,10 +71,14 @@ void rm_int(
"pop eax\n\t"
"mov esp, dword ptr ds:[5f]\n\t"
"sti\n\t"
// Indirect interrupt call
".byte 0xcd\n\t"
"3: .byte 0\n\t"
"cli\n\t"
// Load out_regs
"mov dword ptr ds:[5f], esp\n\t"
"mov esp, dword ptr ds:[6f]\n\t"
@ -90,6 +106,15 @@ void rm_int(
"mov gs, ax\n\t"
"mov ss, ax\n\t"
"mov dx, 0x21\n\t"
"mov al, byte ptr ds:[pm_pic0_mask]\n\t"
"out dx, al\n\t"
"mov dx, 0xa1\n\t"
"mov al, byte ptr ds:[pm_pic1_mask]\n\t"
"out dx, al\n\t"
"lidt [8f]\n\t"
// Restore non-scratch GPRs
"popf\n\t"
"pop ebp\n\t"
@ -106,5 +131,11 @@ void rm_int(
"6: .long 0\n\t"
// in_regs
"7: .long 0\n\t"
// pmode IDT
"8: .short 0\n\t"
" .long 0\n\t"
// rmode IDT
"9: .short 0x3ff\n\t"
" .long 0\n\t"
);
}

View File

@ -11,6 +11,7 @@ asm (
#include <lib/mbr.h>
#include <lib/config.h>
#include <fs/echfs.h>
#include <sys/interrupt.h>
#define CONFIG_NAME "qloader2.cfg"
@ -26,6 +27,9 @@ void main(int boot_drive) {
// Initial prompt.
init_vga_textmode();
init_idt();
print("qLoader 2\n\n");
print("=> Boot drive: %x\n", boot_drive);

66
src/sys/interrupt.c Normal file
View File

@ -0,0 +1,66 @@
#include <stddef.h>
#include <stdint.h>
#include <sys/interrupt.h>
#include <lib/cio.h>
#include <lib/blib.h>
volatile uint64_t global_pit_tick = 0;
__attribute__((interrupt)) static void unhandled_int(void *r) {
(void)r;
print("Warning: unhandled interrupt");
}
__attribute__((interrupt)) static void pit_irq(void *r) {
(void)r;
global_pit_tick++;
port_out_b(0x20, 0x20);
}
uint8_t rm_pic0_mask = 0xff;
uint8_t rm_pic1_mask = 0xff;
uint8_t pm_pic0_mask = 0xff;
uint8_t pm_pic1_mask = 0xff;
#define IDT_MAX_ENTRIES 16
static struct idt_entry_t idt[IDT_MAX_ENTRIES];
void init_idt(void) {
rm_pic0_mask = port_in_b(0x21);
rm_pic1_mask = port_in_b(0xa1);
for (int i = 0; i < IDT_MAX_ENTRIES; i++) {
register_interrupt_handler(i, unhandled_int, 0x8e);
}
register_interrupt_handler(0x08, pit_irq, 0x8e);
struct idt_ptr_t idt_ptr = {
sizeof(idt) - 1,
(uint32_t)idt
};
asm volatile (
"lidt %0"
:
: "m" (idt_ptr)
);
pm_pic0_mask = 0xfe;
pm_pic1_mask = 0xff;
port_out_b(0x21, pm_pic0_mask);
port_out_b(0xa1, pm_pic1_mask);
asm volatile ("sti");
}
void register_interrupt_handler(size_t vec, void *handler, uint8_t type) {
uint32_t p = (uint32_t)handler;
idt[vec].offset_lo = (uint16_t)p;
idt[vec].selector = 0x18;
idt[vec].unused = 0;
idt[vec].type_attr = type;
idt[vec].offset_hi = (uint16_t)(p >> 16);
}

30
src/sys/interrupt.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef __SYS__INTERRUPT_H__
#define __SYS__INTERRUPT_H__
#include <stdint.h>
#include <stddef.h>
extern volatile uint64_t global_pit_tick;
extern uint8_t rm_pic0_mask;
extern uint8_t rm_pic1_mask;
extern uint8_t pm_pic0_mask;
extern uint8_t pm_pic1_mask;
struct idt_entry_t {
uint16_t offset_lo;
uint16_t selector;
uint8_t unused;
uint8_t type_attr;
uint16_t offset_hi;
} __attribute__((packed));
struct idt_ptr_t {
uint16_t size;
uint32_t address;
} __attribute__((packed));
void init_idt(void);
void register_interrupt_handler(size_t, void *, uint8_t);
#endif