mirror of
https://github.com/limine-bootloader/limine
synced 2025-01-05 20:34:33 +03:00
Add IDT and PIT driver
This commit is contained in:
parent
9b5c159d1f
commit
cddacc280a
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
);
|
||||
}
|
||||
|
@ -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
66
src/sys/interrupt.c
Normal 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
30
src/sys/interrupt.h
Normal 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
|
Loading…
Reference in New Issue
Block a user