ASM_WRAPPER #3
@ -1,8 +1,10 @@
|
||||
#pragma once
|
||||
#include "stdarg.h"
|
||||
#include "cpu_context.h"
|
||||
|
||||
// c.f. intel software-developer-vol-1 6.4.1
|
||||
struct interrupt_frame {
|
||||
/* Stacked by the CPU */
|
||||
uint32_t eip;
|
||||
uint32_t cs;
|
||||
uint32_t eflags;
|
||||
|
@ -15,13 +15,13 @@ int irqSetup()
|
||||
// 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];
|
||||
extern native_irq_handler irq_handler_wrapper_array[IRQ_NUM];
|
||||
|
||||
irq_handler irq_handler_array[IRQ_NUM] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
void interrupt_handler_pic(int interrupt, struct interrupt_frame *frame)
|
||||
void interrupt_handler_pic(int interrupt, struct cpu_state *frame)
|
||||
{
|
||||
if (0 > interrupt || IRQ_NUM <= interrupt) {
|
||||
pr_err("Trying to handle unknow interrupt %d\n", interrupt);
|
||||
@ -34,7 +34,7 @@ void interrupt_handler_pic(int interrupt, struct interrupt_frame *frame)
|
||||
irq_handler_array[interrupt](frame);
|
||||
}
|
||||
|
||||
int irqSetRoutine(int irq, irq_handler handler)
|
||||
int irqSetRoutine(int irq, native_irq_handler handler)
|
||||
{
|
||||
uint32_t flags;
|
||||
if ((irq < 0) || irq >= IRQ_NUM)
|
||||
@ -42,11 +42,9 @@ int irqSetRoutine(int irq, irq_handler handler)
|
||||
|
||||
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_array[irq], 0);
|
||||
(unsigned int)handler, 0);
|
||||
if (!ret)
|
||||
enableIrq(irq);
|
||||
}
|
||||
|
@ -35,9 +35,10 @@
|
||||
// https://wiki.osdev.org/Interrupt_Service_Routines That's why we use wrapper around them or
|
||||
// the gcc interrupt attribut
|
||||
// __attribute__((interrupt)) void (*irq_handler)(int irq);
|
||||
typedef void (*irq_handler)(struct interrupt_frame *frame);
|
||||
typedef void (*irq_handler)(struct cpu_state *frame);
|
||||
typedef void (*native_irq_handler)(struct interrupt_frame *frame);
|
||||
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, native_irq_handler handler);
|
||||
|
@ -16,19 +16,54 @@
|
||||
/* uint32_t ip */
|
||||
/* uint32_t cs; */
|
||||
/* uint32_t flags */
|
||||
/* uint32_t sp; */
|
||||
/* uint32_t ss; */
|
||||
/* Pushes the general purpose registers to the stack */
|
||||
pushal
|
||||
/* Interrupt frame end */
|
||||
pushl %esp
|
||||
/* Pushes the other reg to save same and look like a struct cpu_state*/
|
||||
/* Fake error code */
|
||||
pushl $0
|
||||
|
||||
/* Backup the actual context */
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %edx
|
||||
pushl %ecx
|
||||
pushl %ebx
|
||||
pushl %eax
|
||||
subl $2,%esp
|
||||
pushw %ss
|
||||
pushw %ds
|
||||
pushw %es
|
||||
pushw %fs
|
||||
pushw %gs
|
||||
|
||||
push %esp
|
||||
pushl $\irq
|
||||
call interrupt_handler_pic
|
||||
addl $8, %esp
|
||||
popal
|
||||
|
||||
/* Restore the context */
|
||||
popw %gs
|
||||
popw %fs
|
||||
popw %es
|
||||
popw %ds
|
||||
popw %ss
|
||||
addl $2,%esp
|
||||
popl %eax
|
||||
popl %ebx
|
||||
popl %ecx
|
||||
popl %edx
|
||||
popl %esi
|
||||
popl %edi
|
||||
popl %ebp
|
||||
|
||||
/* Remove fake error code */
|
||||
addl $4, %esp
|
||||
|
||||
iret
|
||||
.endm
|
||||
|
||||
|
||||
.set i, 0
|
||||
.rept 0x10
|
||||
interrupt_pic %i
|
||||
|
@ -48,9 +48,9 @@ void serialPutc(char a)
|
||||
outb(PORT, a);
|
||||
}
|
||||
|
||||
void serialDoIrq(struct interrupt_frame *level)
|
||||
void serialDoIrq(struct cpu_state *state)
|
||||
{
|
||||
(void)level;
|
||||
(void)state;
|
||||
char c = inb(PORT);
|
||||
serialPutc(c);
|
||||
}
|
||||
|
@ -3,4 +3,4 @@
|
||||
|
||||
void serialSetup(int speed);
|
||||
void serialPutc(char a);
|
||||
void serialDoIrq(struct interrupt_frame *frame);
|
||||
void serialDoIrq(struct cpu_state *state);
|
||||
|
Loading…
Reference in New Issue
Block a user