Skip to content

Commit

Permalink
Merge pull request #20 from pbrucla/pic
Browse files Browse the repository at this point in the history
Pic
  • Loading branch information
RoryHemmings authored Nov 16, 2023
2 parents edb1e2f + 0a9510f commit 470c3d6
Show file tree
Hide file tree
Showing 15 changed files with 902 additions and 62 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ OBJ_FILES=$(patsubst $(LIBC_DIR)/%.c,$(BUILD_DIR)/%.o,$(LIBC_SRC)) \
$(BUILD_DIR)/%.o: $(KERNEL_DIR)/%.c
$(GCC) $(GCC_FLAGS) -c $< -o $@
$(BUILD_DIR)/%.o: $(KERNEL_DIR)/%.asm
$(ASM) $< -f elf32 -o $@
$(ASM) -i $(INCLUDES) $< -f elf32 -o $@
$(BUILD_DIR)/%.o: $(LIBC_DIR)/%.c
$(GCC) $(GCC_FLAGS) -c $< -o $@

Expand Down
2 changes: 1 addition & 1 deletion source/boot/disk_load.asm
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ disk_load:
jnz .stop
inc esi
loop .loop
.stop
.stop:
ret

Expand Down
127 changes: 105 additions & 22 deletions source/kernel/idt.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "idt.h"
#include "io.h"
#include "isr.h"
#include "terminal_driver.h"
#include <stdint.h>

#define NUM_IDTS 256
Expand All @@ -17,31 +19,38 @@ __attribute__((aligned(0x10))) static idt_entry_t idt[NUM_IDTS];
// define the idtr
static idtr_t idtr;

static uint64_t has_triggered = 0;
static uint32_t has_triggered = 0;
static uint32_t hits = 0;
static uint32_t oopsie_woopsie = 0;

uint32_t get_hits(void) { return oopsie_woopsie; }

// we no-inline because I don't want it inlined :lemonthink:
// also i want the actual isr to only have save register, call, then iret
// __attribute__((noinline)) static void actual_exception_handler(void)
// {
// if (terminal_driver_loaded() && !has_triggered) {
// printf("Hello");
// has_triggered = 1;
// }
// }

// we put the actual handler in a different function because
// we want to clean up the stack before we iret
// idt_handler_t interrupt_handler(registers_t* frame)
// {
// terminal_putchar(frame->int_no + '0');
// terminal_putchar('\n');
// }
// interrupts {8, 10-14} push error codes on stack
// Note: tested it. Doesn't fucking work. Ima strangle Richard Stallman.
// idt_handler_t exception_handler(registers_t* frame, uint32_t error_code) {
// printf("error code pushed");
// terminal_putchar('\n');
// }
__attribute__((noinline)) static void actual_exception_handler(void)
{
oopsie_woopsie++;
}

// this currently will triple-fault on pressing a keyboard
__attribute__((noinline)) static void actualirq1Handler(void)
{
// seems to triple fault before reaching here, idk pls can we get serial
// driver
hits++;
if (terminal_driver_loaded() && !has_triggered) {
terminal_putchar('U');
terminal_update_cursor();
// inb(0x60) is the port containing the key pressed
terminal_put64(inb(0x60));
terminal_update_cursor();

// send eoi to the master PIC
// this is needed in the PIC remapping, don't question it
outbb(0x20, 0x20);
__asm__ volatile("cli");
}
}

void idt_set_entry(int idx, uint32_t handler_ptr, uint16_t code_selector,
uint8_t attributes)
Expand All @@ -55,6 +64,59 @@ void idt_set_entry(int idx, uint32_t handler_ptr, uint16_t code_selector,
.isr_high = upper};
}

void setup_pic(void)
{
// for some context:
// PIC1 is the "master" PIC which can cascade signals to PIC2 via interrupt
// 2 port 0x20 -> PIC1 command port 0x21 -> PIC1 data port 0xa0 -> PIC2
// command port 0xa1 -> PIC2 data

// data ports will have the irq masks when read
// note that the 8-bit mask has bit set to 1 for disabled interrupts
// and 0 for enabled interrupts
unsigned char mask1 = inb(0x21);
unsigned char mask2 = inb(0xa1);

// send initialization command (0x11) to both PICs
// PIC will now wait for 4 outbb to their data port
outbb(0x20, 0x11);
io_wait();
outbb(0xa0, 0x11);
io_wait();

// remap PIC1 to 0x20-0x27 and PIC2 to 0x28-0x30
outbb(0x21, 0x20);
io_wait();
outbb(0xa1, 0x28);
io_wait();

// tell PIC1 and PIC2 about each other
outbb(0x21, 1 << 2); // PIC2 is at IRQ2
io_wait();
outbb(0xa1, 2); // PIC1 cascade identify (idk what that means)
io_wait();

// tell PICs they are in 32-bit mode
outbb(0x21, 1);
io_wait();
outbb(0xa1, 1);
io_wait();

// restore previous irq masks (0xb8 for PIC1 and 0x8e for PIC2)
// for now, i only want 1 interrupt (the keyboard interrupt) so i will mask
// off everything else keyboard interrupt is the 1 << 1, cascade to PIC2
// signal is the 1 << 2
//
// remember that ^ toggles bits, so bits 1 and 2 will be toggled to 0
// (which will enable them in hw)
mask1 = 0xff ^ (1 << 1 | 1 << 2);
mask2 = 0xff;
outbb(0x21, mask1);
io_wait();
outbb(0xa1, mask2);
io_wait();
}

void init_idt(void)
{
idt_set_reg(idtr, &idt[0], NUM_IDTS);
Expand Down Expand Up @@ -90,5 +152,26 @@ void init_idt(void)
idt_set_entry(29, (uint32_t)isr29, IDT_CODE_SEL, IDT_ATTR);
idt_set_entry(30, (uint32_t)isr30, IDT_CODE_SEL, IDT_ATTR);
idt_set_entry(31, (uint32_t)isr31, IDT_CODE_SEL, IDT_ATTR);

setup_pic();
idt_set_entry(32, (uint32_t)irq0, IDT_CODE_SEL, IDT_ATTR);
idt_set_entry(33, (uint32_t)irq1, IDT_CODE_SEL, IDT_ATTR);
idt_set_entry(34, (uint32_t)irq2, IDT_CODE_SEL, IDT_ATTR);
idt_set_entry(35, (uint32_t)irq3, IDT_CODE_SEL, IDT_ATTR);
idt_set_entry(36, (uint32_t)irq4, IDT_CODE_SEL, IDT_ATTR);
idt_set_entry(37, (uint32_t)irq5, IDT_CODE_SEL, IDT_ATTR);
idt_set_entry(38, (uint32_t)irq6, IDT_CODE_SEL, IDT_ATTR);
idt_set_entry(39, (uint32_t)irq7, IDT_CODE_SEL, IDT_ATTR);
idt_set_entry(40, (uint32_t)irq8, IDT_CODE_SEL, IDT_ATTR);
idt_set_entry(41, (uint32_t)irq9, IDT_CODE_SEL, IDT_ATTR);
idt_set_entry(42, (uint32_t)irq10, IDT_CODE_SEL, IDT_ATTR);
idt_set_entry(43, (uint32_t)irq11, IDT_CODE_SEL, IDT_ATTR);
idt_set_entry(44, (uint32_t)irq12, IDT_CODE_SEL, IDT_ATTR);
idt_set_entry(45, (uint32_t)irq13, IDT_CODE_SEL, IDT_ATTR);
idt_set_entry(46, (uint32_t)irq14, IDT_CODE_SEL, IDT_ATTR);
idt_set_entry(47, (uint32_t)irq15, IDT_CODE_SEL, IDT_ATTR);

init_isr();

idt_flush(idtr);
}
1 change: 1 addition & 0 deletions source/kernel/include/idt.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ typedef struct {
} registers_t;

void init_idt(void);
uint32_t get_hits(void);
32 changes: 32 additions & 0 deletions source/kernel/include/int_stack_frame.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
%ifndef STUB_FRAME_PUSH
%macro STUB_FRAME_PUSH 0
pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax

mov ax, ds ; Lower 16-bits of eax = ds.
push eax ; save the data segment descriptor

mov ax, 0x10 ; load the kernel data segment descriptor
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
push esp
%endmacro
%endif

%ifndef STUB_FRAME_POP
%macro STUB_FRAME_POP 0
pop eax

pop eax ; reload the original data segment descriptor
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

popa ; Pops edi,esi,ebp...
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
sti
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
%endmacro
%endif
26 changes: 25 additions & 1 deletion source/kernel/include/isr.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once
#include "idt.h"
#define IRQ_OFFSET 32

extern void isr0();
extern void isr1();
Expand Down Expand Up @@ -34,4 +35,27 @@ extern void isr29();
extern void isr30();
extern void isr31();

void isr_handler(registers_t *frame);
extern void irq0();
extern void irq1();
extern void irq2();
extern void irq3();
extern void irq4();
extern void irq5();
extern void irq6();
extern void irq7();
extern void irq8();
extern void irq9();
extern void irq10();
extern void irq11();
extern void irq12();
extern void irq13();
extern void irq14();
extern void irq15();

void isr_handler(registers_t *frame);
void irq_handler(registers_t *frame);

typedef void (*isr_t)(registers_t *);
void register_interrupt_handler(uint8_t int_no, isr_t handler);

void init_isr();
Loading

0 comments on commit 470c3d6

Please sign in to comment.