Add IRQ handler
This commit is contained in:
parent
a82a055ea1
commit
35c0fb8f86
20
idt.c
20
idt.c
@ -42,3 +42,23 @@ int idtSetup()
|
||||
return 0;
|
||||
}
|
||||
|
||||
int idt_set_handler(int index, unsigned int addr, int priviledge)
|
||||
{
|
||||
struct idtEntry *idte;
|
||||
|
||||
if (index < 0 || index >= IDT_NUM)
|
||||
return -1;
|
||||
if ((priviledge < 0) || priviledge > 3)
|
||||
return -1;
|
||||
|
||||
idte = &idt[index];
|
||||
|
||||
if (addr != (unsigned int)NULL) {
|
||||
idte->offset_low = addr && 0xffff;
|
||||
idte->offset_high = (addr >> 16) && 0xffff;
|
||||
idte->dpl = priviledge;
|
||||
idte->present = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
1
idt.h
1
idt.h
@ -42,3 +42,4 @@ struct idtRegister {
|
||||
((index) << 3))
|
||||
|
||||
int idtSetup();
|
||||
int idt_set_handler(int index, unsigned int addr, int priviledge);
|
||||
|
24
irq.c
24
irq.c
@ -1,8 +1,32 @@
|
||||
#include "irq.h"
|
||||
#include "idt.h"
|
||||
#include "pic.h"
|
||||
#include "types.h"
|
||||
|
||||
int irqSetup()
|
||||
{
|
||||
initPic();
|
||||
return 0;
|
||||
}
|
||||
|
||||
irq_handler irq_handler_array[IRQ_NUM] = {NULL, };
|
||||
|
||||
int irqSetRoutine(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_BASE_ADDRESS + irq, (unsigned int)irq_handler_array[irq], 0);
|
||||
if (!ret)
|
||||
enableIrq(irq);
|
||||
}
|
||||
restore_IRQs(flags);
|
||||
return 0;
|
||||
}
|
||||
|
20
irq.h
20
irq.h
@ -1,5 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#define save_flags(flags) asm volatile("pushfl ; popl %0" : "=g"(flags)::"memory")
|
||||
#define restore_flags(flags) asm volatile("push %0; popfl" ::"g"(flags) : "memory")
|
||||
|
||||
#define disable_IRQs(flags) \
|
||||
({ \
|
||||
save_flags(flags); \
|
||||
asm("cli\n"); \
|
||||
})
|
||||
#define restore_IRQs(flags) restore_flags(flags)
|
||||
|
||||
|
||||
#define IRQ_TIMER 0 // MASTER IRQ
|
||||
#define IRQ_KEYBOARD 1
|
||||
#define IRQ_SLAVE_PIC 2
|
||||
@ -17,5 +28,12 @@
|
||||
#define IRQ_HARDDISK 14
|
||||
#define IRQ_RESERVED_5 15
|
||||
|
||||
typedef void (*irq_handler)(int irq);
|
||||
#define IRQ_BASE_ADDRESS 0x20
|
||||
#define IRQ_NUM 16
|
||||
|
||||
// An handler should finish by the iret opcode -> 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)(int *irq);
|
||||
int irqSetup();
|
||||
int irqSetRoutine(int irq, irq_handler handler);
|
||||
|
13
main.c
13
main.c
@ -21,6 +21,16 @@ void cpuid(int code, uint32_t *a, uint32_t *d)
|
||||
asm volatile("cpuid" : "=a"(*a), "=d"(*d) : "0"(code) : "ebx", "ecx");
|
||||
}
|
||||
|
||||
void keyboard_handler(int *id)
|
||||
{
|
||||
__asm__("pushal");
|
||||
(void)id;
|
||||
const char *tictac = "tic tac";
|
||||
const short color = RED;
|
||||
printString(tictac, color, BLACK, 0, 3);
|
||||
__asm__("popal; leave; iret");
|
||||
}
|
||||
|
||||
void kmain()
|
||||
{
|
||||
const short color = GREEN;
|
||||
@ -30,6 +40,9 @@ void kmain()
|
||||
printString("Setting up IRQ", color, BLACK, 0, 1);
|
||||
irqSetup();
|
||||
|
||||
irqSetRoutine(IRQ_KEYBOARD, keyboard_handler);
|
||||
// Enabling the HW interrupts
|
||||
//asm volatile("sti\n");
|
||||
while (1) {
|
||||
char c = getScancode();
|
||||
printChar(c, color, BLACK, 0, 5);
|
||||
|
1
mbr.asm
1
mbr.asm
@ -83,6 +83,7 @@ main:
|
||||
mov ax, 0x3
|
||||
int 0x10
|
||||
|
||||
; http://www.ctyme.com/intr/rb-0607.htm
|
||||
; Bios read first 512 bytes, read next disk sector
|
||||
mov ah, 0x2 ;read sectors
|
||||
mov al, 6 ;sectors to read
|
||||
|
7
pic.c
7
pic.c
@ -1,5 +1,6 @@
|
||||
#include "pic.h"
|
||||
#include "io.h"
|
||||
#include "irq.h"
|
||||
|
||||
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
|
||||
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
|
||||
@ -15,15 +16,15 @@
|
||||
|
||||
void initPic(void)
|
||||
{
|
||||
/* Send CMD: Init + senquence in 4 DATA */
|
||||
/* Send CMD: Init + sequence in 4 DATA */
|
||||
outb(ICW1_INIT + ICW1_ICW4, PIC_MASTER_CMD);
|
||||
outb(ICW1_INIT + ICW1_ICW4, PIC_SLAVE_CMD);
|
||||
|
||||
/* Send ICW2: ctrl base address. Remap IRQ from interupt range 0x0-0xF to 0x20-0x2F as
|
||||
* intel
|
||||
* reserve interupt 0x0-0x1F in protected mode (e.g. 0-7 are CPU exception) */
|
||||
outb(0x20, PIC_MASTER_DATA);
|
||||
outb(0x28, PIC_SLAVE_DATA);
|
||||
outb(IRQ_BASE_ADDRESS, PIC_MASTER_DATA);
|
||||
outb(IRQ_BASE_ADDRESS + 8, PIC_SLAVE_DATA);
|
||||
|
||||
/* Send ICW3 master: mask where slaves are connected */
|
||||
outb(0x4, PIC_MASTER_DATA);
|
||||
|
Loading…
Reference in New Issue
Block a user