This commit is contained in:
2021-09-14 18:46:50 +03:00
parent d605c6a016
commit b6ddeca1c3
180 changed files with 5909 additions and 2039 deletions

View File

@@ -0,0 +1,18 @@
@echo off
rem The name of the loader assembly file (without extension, must be .asm):
set loader_name=loader
rem NASM and DJGPP executable paths:
set nasm_path=C:\nasm
set djgpp_path=C:\mingw\bin
set objpath=../../objects
set incpath=../../include
@echo on
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/cpu.o cpu.c
@echo off
@echo .
@echo Done!
@pause

40
SysCore/drivers/cpu/cpu.c Normal file
View File

@@ -0,0 +1,40 @@
#include <system.h>
#include "cpu.h"
#include "gdt/gdt.h"
#include "idt/idt.h"
#include "irq/irq.h"
#include "isrs/isrs.h"
#define cpuid(in, a, b, c, d) __asm__("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in));
// initializes cpu resources
void i86_CpuInitialize()
{
i86_GdtInstall();
i86_IdtInstall();
i86_IsrsInstall();
i86_IrqInstall();
}
void i86_CpuShutdown()
{
}
char* i86_CpuGetVendor()
{
unsigned unused;
unsigned static arr[3];
cpuid(0, unused, arr[0], arr[2], arr[1]);
return (char*) arr;
}
_R32BIT i86_CpuID(unsigned function)
{
_R32BIT ret = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
cpuid(function, ret.eax, ret.ebx, ret.ecx, ret.edx);
return ret;
}

17
SysCore/drivers/cpu/cpu.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef _CPU_H_INCLUDED
#define _CPU_H_INCLUDED
#include <stdint.h>
#include <regs.h>
#include "gdt/gdt.h"
#include "idt/idt.h"
#include "irq/irq.h"
#include "irq/pic.h"
#include "isrs/isrs.h"
extern void i86_CpuInitialize ();
extern void i86_CpuShutdown ();
extern char* i86_CpuGetVendor ();
#endif

View File

@@ -0,0 +1,20 @@
bits 32
; !!! GDT !!!
; This will set up our new segment registers. We need to do
; something special in order to set CS. We do what is called a
; far jump. A jump that includes a segment as well as an offset.
; This is declared in C as 'extern void gdt_flush();'
global _i86_GdtFlush ; Allows the C code to link to this
extern _gp ; Says that '_gp' is in another file
_i86_GdtFlush:
lgdt [_gp] ; Load the GDT with our '_gp' which is a special pointer
mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:flush2 ; 0x08 is the offset to our code segment: Far jump!
flush2:
ret ; Returns back to the C code!

View File

@@ -0,0 +1,76 @@
/******************************************************************
* gdt.c - GLOBAL DESCRIPTOR TABLE *
* Contains function prototypes for setting up the GDT *
******************************************************************/
#define MAX_DESCRIPTORS 5
#include "gdt.h"
extern void i86_GdtInstall();
/* Our GDT, with 3 entries, and finally our special GDT pointer */
struct GdtEntry gdt[MAX_DESCRIPTORS];
struct GdtPointer gp;
/* Setup a descriptor in the Global Descriptor Table */
void i86_GdtSetGate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran)
{
/* Sanity check */
if (num >= MAX_DESCRIPTORS) return;
/* Setup the descriptor base address */
gdt[num].base_low = (base & 0xFFFF);
gdt[num].base_middle = (base >> 16) & 0xFF;
gdt[num].base_high = (base >> 24) & 0xFF;
/* Setup the descriptor limits */
gdt[num].limit_low = (limit & 0xFFFF);
gdt[num].granularity = ((limit >> 16) & 0x0F);
/* Finally, set up the granularity and access flags */
gdt[num].granularity |= (gran & 0xF0);
gdt[num].access = access;
}
/*struct gdt_entry* i86_GdtGetGate(int num)
{
if (num>MAX_DESCRIPTORS) return 0;
return &gdt[num];
}*/
/* Should be called by main. This will setup the special GDT
* pointer, set up the first 3 entries in our GDT, and then
* finally call gdt_flush() in our assembler file in order
* to tell the processor where the new GDT is and update the
* new segment registers */
void i86_GdtInstall()
{
/* Setup the GDT pointer and limit */
gp.limit = (sizeof(struct GdtEntry) * 3) - 1;
gp.base = (unsigned int)&gdt;
/* Our NULL descriptor */
i86_GdtSetGate(0, 0, 0, 0, 0);
/* The second entry is our Code Segment. The base address
* is 0, the limit is 4GBytes, it uses 4KByte granularity,
* uses 32-bit opcodes, and is a Code Segment descriptor.
* Please check the table above in the tutorial in order
* to see exactly what each value means */
i86_GdtSetGate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
/* The third entry is our Data Segment. It's EXACTLY the
* same as our code segment, but the descriptor type in
* this entry's access byte says it's a Data Segment */
i86_GdtSetGate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
/* User mode Code segment*/
i86_GdtSetGate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF);
/* User mode data segment*/
i86_GdtSetGate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF);
/* Flush out the old GDT and install the new changes! */
i86_GdtFlush();
}

View File

@@ -0,0 +1,38 @@
/******************************************************************
* gdt.h - GLOBAL DESCRIPTOR TABLE *
* Contains structures and function declarations for GDT *
******************************************************************/
#ifndef __GDT_H
#define __GDT_H
/* Defines a GDT entry. We say packed, because it prevents the
* compiler from doing things that it thinks is best: Prevent
* compiler "optimization" by packing */
struct GdtEntry
{
unsigned short limit_low;
unsigned short base_low;
unsigned char base_middle;
unsigned char access;
unsigned char granularity;
unsigned char base_high;
} __attribute__((packed));
/* Special pointer which includes the limit: The max bytes
* taken up by the GDT, minus 1. Again, this NEEDS to be packed */
struct GdtPointer
{
unsigned short limit;
unsigned int base;
} __attribute__((packed));
/* This will be a function in start.asm. We use this to properly
* reload the new segment registers */
extern void i86_GdtInstall();
extern void i86_GdtFlush();
extern void i86_GdtSetGate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran);
//extern struct GdtEntry* i86_GdtGetGate(int num);
#endif

View File

@@ -0,0 +1,9 @@
bits 32
; !!! IDT !!!
; Loads the IDT defined in '_idtp'
global _i86_IdtLoad
extern _idtp
_i86_IdtLoad:
lidt [_idtp]
ret

View File

@@ -0,0 +1,45 @@
/******************************************************************
* idt.h - INTERRUPT DESCRIPTOR TABLE *
* Contains structures and function declarations for IDT *
******************************************************************/
#include <system.h>
#include "idt.h"
extern void i86_IdtLoad();
/* Declare an IDT of 256 entries. */
struct IdtEntry idt[256];
struct IdtPointer idtp;
/* Use this function to set an entry in the IDT. Alot simpler
* than twiddling with the GDT ;) */
void i86_IdtSetGate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags)
{
/* The interrupt routine's base address */
idt[num].base_lo = (base & 0xFFFF);
idt[num].base_hi = (base >> 16) & 0xFFFF;
/* The segment or 'selector' that this IDT entry will use
* is set here, along with any access flags */
idt[num].sel = sel;
idt[num].always0 = 0;
idt[num].flags = flags;
}
struct IdtEntry* i86_IdtGetGate(unsigned char num)
{
return &idt[num];
}
/* Installs the IDT */
void i86_IdtInstall()
{
/* Sets the special IDT pointer up, just like in 'gdt.c' */
idtp.limit = (sizeof (struct IdtEntry) * 256) - 1;
idtp.base = (unsigned int)&idt;
/* Clear out the entire IDT, initializing it to zeros */
memset (&idt, 0, sizeof(struct IdtEntry) * 256);
/* Points the processor's internal register to the new IDT */
i86_IdtLoad();
}

View File

@@ -0,0 +1,31 @@
/******************************************************************
* idt.h - INTERRUPT DESCRIPTOR TABLE *
* Contains structures and function declarations for IDT *
******************************************************************/
#ifndef __IDT_H
#define __IDT_H
/* Defines an IDT entry */
struct IdtEntry
{
unsigned short base_lo;
unsigned short sel;
unsigned char always0;
unsigned char flags;
unsigned short base_hi;
} __attribute__((packed));
struct IdtPointer
{
unsigned short limit;
unsigned int base;
} __attribute__((packed));
/* This exists in 'start.asm', and is used to load our IDT */
extern void i86_IdtSetGate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags);
extern struct IdtEntry* i86_IdtGetGate(unsigned char num);
extern void i86_IdtInstall();
#endif

View File

@@ -0,0 +1,159 @@
bits 32
; !!! IRQ !!!
global _i86_irq0
global _i86_irq1
global _i86_irq2
global _i86_irq3
global _i86_irq4
global _i86_irq5
global _i86_irq6
global _i86_irq7
global _i86_irq8
global _i86_irq9
global _i86_irq10
global _i86_irq11
global _i86_irq12
global _i86_irq13
global _i86_irq14
global _i86_irq15
; 32: IRQ0
_i86_irq0:
cli
push byte 0
push byte 32; Note that these don't push an error code on the stack:
; We need to push a dummy error code
jmp irq_common_stub
; 33: IRQ1
_i86_irq1:
cli
push byte 0
push byte 33
jmp irq_common_stub
; 34: IRQ2
_i86_irq2:
cli
push byte 0
push byte 34
jmp irq_common_stub
; 35: IRQ3
_i86_irq3:
cli
push byte 0
push byte 35
jmp irq_common_stub
; 36: IRQ4
_i86_irq4:
cli
push byte 0
push byte 36
jmp irq_common_stub
; 37: IRQ5
_i86_irq5:
cli
push byte 0
push byte 37
jmp irq_common_stub
; 38: IRQ6
_i86_irq6:
cli
push byte 0
push byte 38
jmp irq_common_stub
; 39: IRQ7
_i86_irq7:
cli
push byte 0
push byte 39
jmp irq_common_stub
; 40: IRQ8
_i86_irq8:
cli
push byte 0
push byte 40
jmp irq_common_stub
; 41: IRQ9
_i86_irq9:
cli
push byte 0
push byte 41
jmp irq_common_stub
; 42: IRQ10
_i86_irq10:
cli
push byte 0
push byte 42
jmp irq_common_stub
; 43: IRQ11
_i86_irq11:
cli
push byte 0
push byte 43
jmp irq_common_stub
; 44: IRQ12
_i86_irq12:
cli
push byte 0
push byte 44
jmp irq_common_stub
; 45: IRQ13
_i86_irq13:
cli
push byte 0
push byte 45
jmp irq_common_stub
; 46: IRQ14
_i86_irq14:
cli
push byte 0
push byte 46
jmp irq_common_stub
; 47: IRQ15
_i86_irq15:
cli
push byte 0
push byte 47
jmp irq_common_stub
extern _i86_IrqHandler
; This is a stub that we have created for IRQ based ISRs. This calls
; '_i86_irq_handler' in our C code. We need to create this in an 'irq.c'
irq_common_stub:
pusha
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp
push eax
mov eax, _i86_IrqHandler
call eax
pop eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8
iret

View File

@@ -0,0 +1,99 @@
#include <system.h>
#include "pic.h"
#include "irq.h"
#include "../idt/idt.h"
/* These are own ISRs that point to our special IRQ handler
* instead of the regular 'fault_handler' function */
extern void i86_irq0();
extern void i86_irq1();
extern void i86_irq2();
extern void i86_irq3();
extern void i86_irq4();
extern void i86_irq5();
extern void i86_irq6();
extern void i86_irq7();
extern void i86_irq8();
extern void i86_irq9();
extern void i86_irq10();
extern void i86_irq11();
extern void i86_irq12();
extern void i86_irq13();
extern void i86_irq14();
extern void i86_irq15();
/* This array is actually an array of function pointers. We use
* this to handle custom IRQ handlers for a given IRQ */
void *IrqRoutines[16] =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
/* This installs a custom IRQ handler for the given IRQ */
void i86_IrqInstallHandler (int irq, void (*handler)(ISR_stack_regs *r))
{
IrqRoutines[irq] = handler;
}
void i86_IrqUninstallHandler (int irq)
{
IrqRoutines[irq] = 0;
}
/* We first remap the interrupt controllers, and then we install
* the appropriate ISRs to the correct entries in the IDT. This
* is just like installing the exception handlers */
void i86_IrqInstall()
{
i86_PicRemap(32,40);
i86_IdtSetGate(32, (unsigned)i86_irq0, 0x08, 0x8E);
i86_IdtSetGate(33, (unsigned)i86_irq1, 0x08, 0x8E);
i86_IdtSetGate(34, (unsigned)i86_irq2, 0x08, 0x8E);
i86_IdtSetGate(35, (unsigned)i86_irq3, 0x08, 0x8E);
i86_IdtSetGate(36, (unsigned)i86_irq4, 0x08, 0x8E);
i86_IdtSetGate(37, (unsigned)i86_irq5, 0x08, 0x8E);
i86_IdtSetGate(38, (unsigned)i86_irq6, 0x08, 0x8E);
i86_IdtSetGate(39, (unsigned)i86_irq7, 0x08, 0x8E);
i86_IdtSetGate(40, (unsigned)i86_irq8, 0x08, 0x8E);
i86_IdtSetGate(41, (unsigned)i86_irq9, 0x08, 0x8E);
i86_IdtSetGate(42, (unsigned)i86_irq10, 0x08, 0x8E);
i86_IdtSetGate(43, (unsigned)i86_irq11, 0x08, 0x8E);
i86_IdtSetGate(44, (unsigned)i86_irq12, 0x08, 0x8E);
i86_IdtSetGate(45, (unsigned)i86_irq13, 0x08, 0x8E);
i86_IdtSetGate(46, (unsigned)i86_irq14, 0x08, 0x8E);
i86_IdtSetGate(47, (unsigned)i86_irq15, 0x08, 0x8E);
}
/* Each of the IRQ ISRs point to this function, rather than
* the 'fault_handler' in 'isrs.c'. The IRQ Controllers need
* to be told when you are done servicing them, so you need
* to send them an "End of Interrupt" command (0x20). There
* are two 8259 chips: The first exists at 0x20, the second
* exists at 0xA0. If the second controller (an IRQ from 8 to
* 15) gets an interrupt, you need to acknowledge the
* interrupt at BOTH controllers, otherwise, you only send
* an EOI command to the first controller. If you don't send
* an EOI, you won't raise any more IRQs */
void i86_IrqHandler (ISR_stack_regs *r)
{
/* This is a blank function pointer */
void (*handler)(ISR_stack_regs *r);
/* Find out if we have a custom handler to run for this
* IRQ, and then finally, run it */
handler = IrqRoutines[r->int_no - 32];
if (handler) handler(r);
/* If the IDT entry that was invoked was greater than 40
* (meaning IRQ8 - 15), then we need to send an EOI to
* the slave controller */
if (r->int_no >=40) outportb(0x0A, 0x20);
/* In either case, we need to send an EOI to the master
* interrupt controller too */
outportb(0x20, 0x20);
}

View File

@@ -0,0 +1,10 @@
#ifndef __IRQ_H
#define __IRQ_H
#include <regs.h>
extern void i86_IrqInstallHandler (int irq, void (*handler)(ISR_stack_regs *r));
extern void i86_IrqUninstallHandler (int irq);
extern void i86_IrqInstall();
#endif

View File

@@ -0,0 +1,23 @@
#include <system.h>
#include "pic.h"
void i86_PicRemap(int pic1, int pic2)
{
// Send ICW1
outportb(0x20, 0x11);
outportb(0xA0, 0x11);
// send ICW2
outportb(0x21, pic1); // remap pics
outportb(0xA1, pic2);
// send ICW3
outportb(0x21, 4);
outportb(0xA1, 2);
// Send ICW4
outportb(0x21, 0x01);
outportb(0xA1, 0x01);
outportb(0x21, 0x00);
}

View File

@@ -0,0 +1,6 @@
#ifndef _PIC_H
#define _PIC_H
extern void i86_PicRemap(int pic1, int pic2);
#endif

View File

@@ -0,0 +1,217 @@
bits 32
; !!! ISRs !!!
global _i86_isr0
global _i86_isr1
global _i86_isr2
global _i86_isr3
global _i86_isr4
global _i86_isr5
global _i86_isr6
global _i86_isr7
global _i86_isr8
global _i86_isr9
global _i86_isr10
global _i86_isr11
global _i86_isr12
global _i86_isr13
global _i86_isr14
global _i86_isr15
global _i86_isr16
global _i86_isr17
global _i86_isr18
global _i86_isr19
global _i86_isr20
global _i86_isr21
global _i86_isr22
global _i86_isr23
global _i86_isr24
global _i86_isr25
global _i86_isr26
global _i86_isr27
global _i86_isr28
global _i86_isr29
global _i86_isr30
global _i86_isr31
_i86_isr0:
cli
push byte 0; A normal ISR stub that pops a dummy error code to keep a
; uniform stack frame
push byte 0
jmp isr_common_stub
_i86_isr1:
cli
push byte 0
push byte 1
jmp isr_common_stub
_i86_isr2:
cli
push byte 0
push byte 2
jmp isr_common_stub
_i86_isr3:
cli
push byte 0
push byte 3
jmp isr_common_stub
_i86_isr4:
cli
push byte 0
push byte 4
jmp isr_common_stub
_i86_isr5:
cli
push byte 0
push byte 5
jmp isr_common_stub
_i86_isr6:
cli
push byte 0
push byte 6
jmp isr_common_stub
_i86_isr7:
cli
push byte 0
push byte 7
jmp isr_common_stub
_i86_isr8:
cli
push byte 8
jmp isr_common_stub
_i86_isr9:
cli
push byte 0
push byte 9
jmp isr_common_stub
_i86_isr10:
cli
push byte 10
jmp isr_common_stub
_i86_isr11:
cli
push byte 11
jmp isr_common_stub
_i86_isr12:
cli
push byte 12
jmp isr_common_stub
_i86_isr13:
cli
push byte 13
jmp isr_common_stub
_i86_isr14:
cli
push byte 14
jmp isr_common_stub
_i86_isr15:
cli
push byte 0
push byte 15
jmp isr_common_stub
_i86_isr16:
cli
push byte 0
push byte 16
jmp isr_common_stub
_i86_isr17:
cli
push byte 0
push byte 17
jmp isr_common_stub
_i86_isr18:
cli
push byte 0
push byte 18
jmp isr_common_stub
_i86_isr19:
cli
push byte 0
push byte 19
jmp isr_common_stub
_i86_isr20:
cli
push byte 0
push byte 20
jmp isr_common_stub
_i86_isr21:
cli
push byte 0
push byte 21
jmp isr_common_stub
_i86_isr22:
cli
push byte 0
push byte 22
jmp isr_common_stub
_i86_isr23:
cli
push byte 0
push byte 23
jmp isr_common_stub
_i86_isr24:
cli
push byte 0
push byte 24
jmp isr_common_stub
_i86_isr25:
cli
push byte 0
push byte 25
jmp isr_common_stub
_i86_isr26:
cli
push byte 0
push byte 26
jmp isr_common_stub
_i86_isr27:
cli
push byte 0
push byte 27
jmp isr_common_stub
_i86_isr28:
cli
push byte 0
push byte 28
jmp isr_common_stub
_i86_isr29:
cli
push byte 0
push byte 29
jmp isr_common_stub
_i86_isr30:
cli
push byte 0
push byte 30
jmp isr_common_stub
_i86_isr31:
cli
push byte 0
push byte 31
jmp isr_common_stub
extern _i86_FaultHandler
isr_common_stub:
pusha
push ds
push es
push fs
push gs
mov ax, 0x10 ; Load the Kernel Data Segment descriptor!
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp ; Push us the stack
push eax
mov eax, _i86_FaultHandler
call eax ; A special call, preserves the 'eip' register
pop eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP!

View File

@@ -0,0 +1,115 @@
#include <system.h>
#include <conio.h>
#include "isrs.h"
#include "../idt/idt.h"
// Assembly coded
extern void i86_isr0();
extern void i86_isr1();
extern void i86_isr2();
extern void i86_isr3();
extern void i86_isr4();
extern void i86_isr5();
extern void i86_isr6();
extern void i86_isr7();
extern void i86_isr8();
extern void i86_isr9();
extern void i86_isr10();
extern void i86_isr11();
extern void i86_isr12();
extern void i86_isr13();
extern void i86_isr14();
extern void i86_isr15();
extern void i86_isr16();
extern void i86_isr17();
extern void i86_isr18();
extern void i86_isr19();
extern void i86_isr20();
extern void i86_isr21();
extern void i86_isr22();
extern void i86_isr23();
extern void i86_isr24();
extern void i86_isr25();
extern void i86_isr26();
extern void i86_isr27();
extern void i86_isr28();
extern void i86_isr29();
extern void i86_isr30();
extern void i86_isr31();
void* IdtFaultHandlers[32] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
void i86_IsrsInstall()
{
i86_IdtSetGate(0, (unsigned)i86_isr0, 0x08, 0x8E);
i86_IdtSetGate(1, (unsigned)i86_isr1, 0x08, 0x8E);
i86_IdtSetGate(2, (unsigned)i86_isr2, 0x08, 0x8E);
i86_IdtSetGate(3, (unsigned)i86_isr3, 0x08, 0x8E);
i86_IdtSetGate(4, (unsigned)i86_isr4, 0x08, 0x8E);
i86_IdtSetGate(5, (unsigned)i86_isr5, 0x08, 0x8E);
i86_IdtSetGate(6, (unsigned)i86_isr6, 0x08, 0x8E);
i86_IdtSetGate(7, (unsigned)i86_isr7, 0x08, 0x8E);
i86_IdtSetGate(8, (unsigned)i86_isr8, 0x08, 0x8E);
i86_IdtSetGate(9, (unsigned)i86_isr9, 0x08, 0x8E);
i86_IdtSetGate(10, (unsigned)i86_isr10, 0x08, 0x8E);
i86_IdtSetGate(11, (unsigned)i86_isr11, 0x08, 0x8E);
i86_IdtSetGate(12, (unsigned)i86_isr12, 0x08, 0x8E);
i86_IdtSetGate(13, (unsigned)i86_isr13, 0x08, 0x8E);
i86_IdtSetGate(14, (unsigned)i86_isr14, 0x08, 0x8E);
i86_IdtSetGate(15, (unsigned)i86_isr15, 0x08, 0x8E);
i86_IdtSetGate(16, (unsigned)i86_isr16, 0x08, 0x8E);
i86_IdtSetGate(17, (unsigned)i86_isr17, 0x08, 0x8E);
i86_IdtSetGate(18, (unsigned)i86_isr18, 0x08, 0x8E);
i86_IdtSetGate(19, (unsigned)i86_isr19, 0x08, 0x8E);
i86_IdtSetGate(20, (unsigned)i86_isr20, 0x08, 0x8E);
i86_IdtSetGate(21, (unsigned)i86_isr21, 0x08, 0x8E);
i86_IdtSetGate(22, (unsigned)i86_isr22, 0x08, 0x8E);
i86_IdtSetGate(23, (unsigned)i86_isr23, 0x08, 0x8E);
i86_IdtSetGate(24, (unsigned)i86_isr24, 0x08, 0x8E);
i86_IdtSetGate(25, (unsigned)i86_isr25, 0x08, 0x8E);
i86_IdtSetGate(26, (unsigned)i86_isr26, 0x08, 0x8E);
i86_IdtSetGate(27, (unsigned)i86_isr27, 0x08, 0x8E);
i86_IdtSetGate(28, (unsigned)i86_isr28, 0x08, 0x8E);
i86_IdtSetGate(29, (unsigned)i86_isr29, 0x08, 0x8E);
i86_IdtSetGate(30, (unsigned)i86_isr30, 0x08, 0x8E);
i86_IdtSetGate(31, (unsigned)i86_isr31, 0x08, 0x8E);
}
void i86_IsrsInstallHandler(int interr, void (*function)(ISR_stack_regs *r))
{
if (interr < 32) IdtFaultHandlers[interr] = function;
}
void i86_IsrsUninstallHandler(int interr)
{
if (interr < 32) IdtFaultHandlers[interr] = 0;
}
/* All of our Exception handling Interrupt Service Routines will
* point to this function. This will tell us what exception has
* happened! Right now, we simply halt the system by hitting an
* endless loop. All ISRs disable interrupts while they are being
* serviced as a 'locking' mechanism to prevent an IRQ from
* happening and messing up kernel data structures */
void i86_FaultHandler(ISR_stack_regs *r)
{
/* Is this a fault whose number is from 0 to 31? */
if (r->int_no < 32)
{
void (*func)(ISR_stack_regs *r);
func = IdtFaultHandlers[r->int_no];
// Halt system if unhandled
if (!func) {
cprintf("%#0C*** %#0EFatal error: Unhandled interrupt (INT%u)", r->int_no);
for(;;);
}
else (*func)(r);
}
}

View File

@@ -0,0 +1,8 @@
#ifndef __ISRS_H_
#define __ISRS_H_
extern void i86_IsrsInstall();
extern void i86_IsrsInstallHandler(int interr, void (*function)(ISR_stack_regs *r));
extern void i86_IsrsUninstallHandler(int interr);
#endif