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;
|
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))
|
((index) << 3))
|
||||||
|
|
||||||
int idtSetup();
|
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 "irq.h"
|
||||||
|
#include "idt.h"
|
||||||
#include "pic.h"
|
#include "pic.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
int irqSetup()
|
int irqSetup()
|
||||||
{
|
{
|
||||||
initPic();
|
initPic();
|
||||||
return 0;
|
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
|
#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_TIMER 0 // MASTER IRQ
|
||||||
#define IRQ_KEYBOARD 1
|
#define IRQ_KEYBOARD 1
|
||||||
#define IRQ_SLAVE_PIC 2
|
#define IRQ_SLAVE_PIC 2
|
||||||
@ -17,5 +28,12 @@
|
|||||||
#define IRQ_HARDDISK 14
|
#define IRQ_HARDDISK 14
|
||||||
#define IRQ_RESERVED_5 15
|
#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 irqSetup();
|
||||||
|
int irqSetRoutine(int irq, irq_handler handler);
|
||||||
|
51
main.c
51
main.c
@ -6,32 +6,45 @@
|
|||||||
|
|
||||||
char getScancode()
|
char getScancode()
|
||||||
{
|
{
|
||||||
char c = 0;
|
char c = 0;
|
||||||
do {
|
do {
|
||||||
if (inb(0x60) != c) {
|
if (inb(0x60) != c) {
|
||||||
c = inb(0x60);
|
c = inb(0x60);
|
||||||
if (c > 0)
|
if (c > 0)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
} while (1);
|
} while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpuid(int code, uint32_t *a, uint32_t *d)
|
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()
|
void kmain()
|
||||||
{
|
{
|
||||||
const short color = GREEN;
|
const short color = GREEN;
|
||||||
clearScreen(BLACK);
|
clearScreen(BLACK);
|
||||||
printString("Setting up IDT", color, BLACK, 0, 0);
|
printString("Setting up IDT", color, BLACK, 0, 0);
|
||||||
idtSetup();
|
idtSetup();
|
||||||
printString("Setting up IRQ", color, BLACK, 0, 1);
|
printString("Setting up IRQ", color, BLACK, 0, 1);
|
||||||
irqSetup();
|
irqSetup();
|
||||||
|
|
||||||
while (1) {
|
irqSetRoutine(IRQ_KEYBOARD, keyboard_handler);
|
||||||
char c = getScancode();
|
// Enabling the HW interrupts
|
||||||
printChar(c, color, BLACK, 0, 5);
|
//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
|
mov ax, 0x3
|
||||||
int 0x10
|
int 0x10
|
||||||
|
|
||||||
|
; http://www.ctyme.com/intr/rb-0607.htm
|
||||||
; Bios read first 512 bytes, read next disk sector
|
; Bios read first 512 bytes, read next disk sector
|
||||||
mov ah, 0x2 ;read sectors
|
mov ah, 0x2 ;read sectors
|
||||||
mov al, 6 ;sectors to read
|
mov al, 6 ;sectors to read
|
||||||
|
27
pic.c
27
pic.c
@ -1,29 +1,30 @@
|
|||||||
#include "pic.h"
|
#include "pic.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
#include "irq.h"
|
||||||
|
|
||||||
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
|
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
|
||||||
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
|
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
|
||||||
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
|
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
|
||||||
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
|
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
|
||||||
#define ICW1_INIT 0x10 /* Initialization - required! */
|
#define ICW1_INIT 0x10 /* Initialization - required! */
|
||||||
|
|
||||||
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
|
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
|
||||||
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
|
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
|
||||||
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
|
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
|
||||||
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
|
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
|
||||||
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
|
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
|
||||||
|
|
||||||
void initPic(void)
|
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_MASTER_CMD);
|
||||||
outb(ICW1_INIT + ICW1_ICW4, PIC_SLAVE_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
|
/* Send ICW2: ctrl base address. Remap IRQ from interupt range 0x0-0xF to 0x20-0x2F as
|
||||||
* intel
|
* intel
|
||||||
* reserve interupt 0x0-0x1F in protected mode (e.g. 0-7 are CPU exception) */
|
* reserve interupt 0x0-0x1F in protected mode (e.g. 0-7 are CPU exception) */
|
||||||
outb(0x20, PIC_MASTER_DATA);
|
outb(IRQ_BASE_ADDRESS, PIC_MASTER_DATA);
|
||||||
outb(0x28, PIC_SLAVE_DATA);
|
outb(IRQ_BASE_ADDRESS + 8, PIC_SLAVE_DATA);
|
||||||
|
|
||||||
/* Send ICW3 master: mask where slaves are connected */
|
/* Send ICW3 master: mask where slaves are connected */
|
||||||
outb(0x4, PIC_MASTER_DATA);
|
outb(0x4, PIC_MASTER_DATA);
|
||||||
|
Loading…
Reference in New Issue
Block a user