Add IRQ handler

This commit is contained in:
Mathieu Maret 2018-06-26 16:41:06 +02:00
parent a82a055ea1
commit 35c0fb8f86
8 changed files with 113 additions and 33 deletions

20
idt.c
View File

@ -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
View File

@ -42,3 +42,4 @@ struct idtRegister {
((index) << 3))
int idtSetup();
int idt_set_handler(int index, unsigned int addr, int priviledge);

24
irq.c
View File

@ -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
View File

@ -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);

51
main.c
View File

@ -6,32 +6,45 @@
char getScancode()
{
char c = 0;
do {
if (inb(0x60) != c) {
c = inb(0x60);
if (c > 0)
return c;
}
} while (1);
char c = 0;
do {
if (inb(0x60) != c) {
c = inb(0x60);
if (c > 0)
return c;
}
} while (1);
}
void cpuid(int code, uint32_t *a, uint32_t *d)
{
asm volatile("cpuid" : "=a"(*a), "=d"(*d) : "0"(code) : "ebx", "ecx");
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;
clearScreen(BLACK);
printString("Setting up IDT", color, BLACK, 0, 0);
idtSetup();
printString("Setting up IRQ", color, BLACK, 0, 1);
irqSetup();
const short color = GREEN;
clearScreen(BLACK);
printString("Setting up IDT", color, BLACK, 0, 0);
idtSetup();
printString("Setting up IRQ", color, BLACK, 0, 1);
irqSetup();
while (1) {
char c = getScancode();
printChar(c, color, BLACK, 0, 5);
}
irqSetRoutine(IRQ_KEYBOARD, keyboard_handler);
// Enabling the HW interrupts
//asm volatile("sti\n");
while (1) {
char c = getScancode();
printChar(c, color, BLACK, 0, 5);
}
}

View File

@ -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

27
pic.c
View File

@ -1,29 +1,30 @@
#include "pic.h"
#include "io.h"
#include "irq.h"
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
#define ICW1_INIT 0x10 /* Initialization - required! */
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
#define ICW1_INIT 0x10 /* Initialization - required! */
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
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);

View File

@ -34,3 +34,5 @@ typedef __u32 uint32_t;
typedef __u64 uint64_t;
typedef __u64 u_int64_t;
typedef __s64 int64_t;
#define NULL ((void*)0)