Wrap IRQ with ASM
This commit is contained in:
parent
590311f3f1
commit
ddc0c4c84a
4
Makefile
4
Makefile
@ -17,7 +17,7 @@ CPPFLAGS += $(foreach dir, $(SUBDIRS), -I$(dir))
|
|||||||
asmsrc=$(wildcard arch/$(ARCH)/boot/*.asm)
|
asmsrc=$(wildcard arch/$(ARCH)/boot/*.asm)
|
||||||
asmobj=$(asmsrc:%.asm=%.o)
|
asmobj=$(asmsrc:%.asm=%.o)
|
||||||
csrc=$(shell find $(SUBDIRS) -type f -name "*.c")# $(wildcard *.c)
|
csrc=$(shell find $(SUBDIRS) -type f -name "*.c")# $(wildcard *.c)
|
||||||
cobj=$(csrc:%.c=%.o) arch/$(ARCH)/cpu_context_switch.o arch/$(ARCH)/irq_pit.o
|
cobj=$(csrc:%.c=%.o) arch/$(ARCH)/cpu_context_switch.o arch/$(ARCH)/irq_pit.o arch/$(ARCH)/irq_wrappers.o
|
||||||
deps = $(csrc:%.c=%.d)
|
deps = $(csrc:%.c=%.d)
|
||||||
|
|
||||||
kernel kernel.sym &: $(asmobj) $(cobj) linker.ld
|
kernel kernel.sym &: $(asmobj) $(cobj) linker.ld
|
||||||
@ -37,8 +37,6 @@ disk.img:
|
|||||||
#https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html#x86-Function-Attributes
|
#https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html#x86-Function-Attributes
|
||||||
arch/$(ARCH)/exception_handler.o:arch/$(ARCH)/exception_handler.c
|
arch/$(ARCH)/exception_handler.o:arch/$(ARCH)/exception_handler.c
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) -mgeneral-regs-only -c $< -o $@
|
$(CC) $(CFLAGS) $(CPPFLAGS) -mgeneral-regs-only -c $< -o $@
|
||||||
arch/$(ARCH)/irq_handler.o:arch/$(ARCH)/irq_handler.c
|
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) -mgeneral-regs-only -c $< -o $@
|
|
||||||
|
|
||||||
%.o:%.asm
|
%.o:%.asm
|
||||||
$(AS) $(ASFLAGS) -o $@ $<
|
$(AS) $(ASFLAGS) -o $@ $<
|
||||||
|
@ -21,7 +21,7 @@ To generate iso image
|
|||||||
|
|
||||||
you can also test it
|
you can also test it
|
||||||
|
|
||||||
`make self_test`
|
`make test`
|
||||||
|
|
||||||
# Debug
|
# Debug
|
||||||
|
|
||||||
|
@ -52,6 +52,3 @@ DECLARE_INTERRUPT(EXCEPTION_RESERVED_11)
|
|||||||
|
|
||||||
// IRQ
|
// IRQ
|
||||||
void pit_handler(struct interrupt_frame *frame);
|
void pit_handler(struct interrupt_frame *frame);
|
||||||
void keyboard_handler(struct interrupt_frame *frame);
|
|
||||||
void timer_handler(struct interrupt_frame *frame);
|
|
||||||
void serial_handler(struct interrupt_frame *frame);
|
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
#include "irq.h"
|
#include "irq.h"
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "klibc.h"
|
||||||
#include "pic.h"
|
#include "pic.h"
|
||||||
#include "stdarg.h"
|
#include "stdarg.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
int irqSetup()
|
int irqSetup()
|
||||||
{
|
{
|
||||||
@ -9,10 +12,28 @@ int irqSetup()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assembly defined array. This is used to wrap C function than cannot:
|
||||||
|
// * get some cpu state
|
||||||
|
// * return using "iret" instead of "ret" without some compiler __attribute__
|
||||||
|
extern vaddr_t irq_handler_wrapper_array[IRQ_NUM];
|
||||||
|
|
||||||
irq_handler irq_handler_array[IRQ_NUM] = {
|
irq_handler irq_handler_array[IRQ_NUM] = {
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void interrupt_handler_pic(int interrupt, struct interrupt_frame *frame)
|
||||||
|
{
|
||||||
|
if (0 > interrupt || IRQ_NUM <= interrupt) {
|
||||||
|
pr_err("Trying to handle unknow interrupt %d\n", interrupt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EOIIrq(interrupt);
|
||||||
|
|
||||||
|
if (irq_handler_array[interrupt] != NULL)
|
||||||
|
irq_handler_array[interrupt](frame);
|
||||||
|
}
|
||||||
|
|
||||||
int irqSetRoutine(int irq, irq_handler handler)
|
int irqSetRoutine(int irq, irq_handler handler)
|
||||||
{
|
{
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
@ -32,3 +53,23 @@ int irqSetRoutine(int irq, irq_handler handler)
|
|||||||
restore_IRQs(flags);
|
restore_IRQs(flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int irqSetRoutineWrapped(int irq, irq_handler handler)
|
||||||
|
{
|
||||||
|
uint32_t flags;
|
||||||
|
if ((irq < 0) || irq >= IRQ_NUM)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
disable_IRQs(flags);
|
||||||
|
|
||||||
|
irq_handler_array[irq] = handler;
|
||||||
|
|
||||||
|
if (handler != NULL) {
|
||||||
|
int ret = idt_set_handler(IRQ_INTERRUPT_BASE_ADDRESS + irq,
|
||||||
|
(unsigned int)irq_handler_wrapper_array[irq], 0);
|
||||||
|
if (!ret)
|
||||||
|
enableIrq(irq);
|
||||||
|
}
|
||||||
|
restore_IRQs(flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -37,4 +37,7 @@
|
|||||||
// __attribute__((interrupt)) void (*irq_handler)(int irq);
|
// __attribute__((interrupt)) void (*irq_handler)(int irq);
|
||||||
typedef void (*irq_handler)(struct interrupt_frame *frame);
|
typedef void (*irq_handler)(struct interrupt_frame *frame);
|
||||||
int irqSetup();
|
int irqSetup();
|
||||||
|
// For C coded handler (The interrupt specific part is managed by a wrapper)
|
||||||
|
int irqSetRoutineWrapped(int irq, irq_handler handler);
|
||||||
|
// For ASM handler taking care of the special instruction needed by an IRQ handler
|
||||||
int irqSetRoutine(int irq, irq_handler handler);
|
int irqSetRoutine(int irq, irq_handler handler);
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
#include "interrupt.h"
|
|
||||||
#include "io.h"
|
|
||||||
#include "irq.h"
|
|
||||||
#include "keyboard.h"
|
|
||||||
#include "pic.h"
|
|
||||||
#include "serial.h"
|
|
||||||
#include "vga.h"
|
|
||||||
|
|
||||||
// Need GCC > 6
|
|
||||||
__attribute__((interrupt)) void keyboard_handler(struct interrupt_frame *frame)
|
|
||||||
{
|
|
||||||
EOIIrq(IRQ_KEYBOARD);
|
|
||||||
keyboard_do_irq();
|
|
||||||
(void)frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((interrupt)) void timer_handler(struct interrupt_frame *frame)
|
|
||||||
{
|
|
||||||
static int timeCnt = 0;
|
|
||||||
EOIIrq(IRQ_TIMER);
|
|
||||||
VGAPrintf(RED, BLACK, 20, VGA_HEIGHT - 1, "IRQ %d", timeCnt++);
|
|
||||||
(void)frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((interrupt)) void serial_handler(struct interrupt_frame *frame)
|
|
||||||
{
|
|
||||||
EOIIrq(IRQ_COM1);
|
|
||||||
serialDoIrq(frame);
|
|
||||||
}
|
|
@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "assert.h"
|
||||||
#include "stdarg.h"
|
#include "stdarg.h"
|
||||||
#include "minmax.h"
|
#include "minmax.h"
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "interrupt.h"
|
#include "interrupt.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "irq.h"
|
#include "irq.h"
|
||||||
|
#include "keyboard.h"
|
||||||
#include "klibc.h"
|
#include "klibc.h"
|
||||||
#include "kthread.h"
|
#include "kthread.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
@ -134,7 +135,7 @@ void kmain(unsigned long magic, unsigned long addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf("Setting up IRQ handlers\n");
|
printf("Setting up IRQ handlers\n");
|
||||||
irqSetRoutine(IRQ_KEYBOARD, keyboard_handler);
|
irqSetRoutineWrapped(IRQ_KEYBOARD, keyboard_do_irq);
|
||||||
|
|
||||||
printf("Enabling HW interrupts\n");
|
printf("Enabling HW interrupts\n");
|
||||||
// Enabling the HW interrupts
|
// Enabling the HW interrupts
|
||||||
|
@ -32,7 +32,7 @@ void serialSetup(int speed)
|
|||||||
UART_1_STOP_BIT); // 8 bits, no parity, one stop bit
|
UART_1_STOP_BIT); // 8 bits, no parity, one stop bit
|
||||||
outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
||||||
outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
|
outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
|
||||||
irqSetRoutine(IRQ_COM1, serial_handler);
|
irqSetRoutineWrapped(IRQ_COM1, serialDoIrq);
|
||||||
}
|
}
|
||||||
|
|
||||||
int isTransmitEmpty()
|
int isTransmitEmpty()
|
||||||
|
Loading…
Reference in New Issue
Block a user