moin,
Ich habe in dem Tut "Brans kernel development tuturial" die Kapittel über die Interrupts durgearbeitet, weil ich es wesentlich eleganter finde sie in C zu definieren(z.T wegen mangelnder asm Erfahrung).
Mit den isrs ist auch alles in ordnung, die funktionieren, aber mit dem PIC klappts nich sonderlich...
Hier der Code:

Wie gesagt ist noch alles Orginalzustand aus dem tut.
Ich wär sehr dankbar, wenn mir jemand Verbesserungsvorschläge machen würde.
Ich habe in dem Tut "Brans kernel development tuturial" die Kapittel über die Interrupts durgearbeitet, weil ich es wesentlich eleganter finde sie in C zu definieren(z.T wegen mangelnder asm Erfahrung).
Mit den isrs ist auch alles in ordnung, die funktionieren, aber mit dem PIC klappts nich sonderlich...

Hier der Code:
Code: [Auswählen]
#include "System.h"
/* These are function prototypes for all of the exception
* handlers: The first 32 entries in the IDT are reserved
* by Intel, and are designed to service exceptions! */
extern void isr0();
extern void isr1();
extern void isr2();
extern void isr3();
extern void isr4();
extern void isr5();
extern void isr6();
extern void isr7();
extern void isr8();
extern void isr9();
extern void isr10();
extern void isr11();
extern void isr12();
extern void isr13();
extern void isr14();
extern void isr15();
extern void isr16();
extern void isr17();
extern void isr18();
extern void isr19();
extern void isr20();
extern void isr21();
extern void isr22();
extern void isr23();
extern void isr24();
extern void isr25();
extern void isr26();
extern void isr27();
extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();
extern void irq0();
extern void irq1();
extern void irq2();
extern void irq3();
extern void irq4();
extern void irq5();
extern void irq6();
extern void irq7();
extern void irq8();
extern void irq9();
extern void irq10();
extern void irq11();
extern void irq12();
extern void irq13();
extern void irq14();
extern void irq15();
/* This is a very repetitive function... it's not hard, it's
* just annoying. As you can see, we set the first 32 entries
* in the IDT to the first 32 ISRs. We can't use a for loop
* for this, because there is no way to get the function names
* that correspond to that given entry. We set the access
* flags to 0x8E. This means that the entry is present, is
* running in ring 0 (kernel level), and has the lower 5 bits
* set to the required '14', which is represented by 'E' in
* hex. */
void isrs_install()
{
set_idt_entry(0, (unsigned)isr0, 0x08, 0x8E);
set_idt_entry(1, (unsigned)isr1, 0x08, 0x8E);
set_idt_entry(2, (unsigned)isr2, 0x08, 0x8E);
set_idt_entry(3, (unsigned)isr3, 0x08, 0x8E);
set_idt_entry(4, (unsigned)isr4, 0x08, 0x8E);
set_idt_entry(5, (unsigned)isr5, 0x08, 0x8E);
set_idt_entry(6, (unsigned)isr6, 0x08, 0x8E);
set_idt_entry(7, (unsigned)isr7, 0x08, 0x8E);
set_idt_entry(8, (unsigned)isr8, 0x08, 0x8E);
set_idt_entry(9, (unsigned)isr9, 0x08, 0x8E);
set_idt_entry(10, (unsigned)isr10, 0x08, 0x8E);
set_idt_entry(11, (unsigned)isr11, 0x08, 0x8E);
set_idt_entry(12, (unsigned)isr12, 0x08, 0x8E);
set_idt_entry(13, (unsigned)isr13, 0x08, 0x8E);
set_idt_entry(14, (unsigned)isr14, 0x08, 0x8E);
set_idt_entry(15, (unsigned)isr15, 0x08, 0x8E);
set_idt_entry(16, (unsigned)isr16, 0x08, 0x8E);
set_idt_entry(17, (unsigned)isr17, 0x08, 0x8E);
set_idt_entry(18, (unsigned)isr18, 0x08, 0x8E);
set_idt_entry(19, (unsigned)isr19, 0x08, 0x8E);
set_idt_entry(20, (unsigned)isr20, 0x08, 0x8E);
set_idt_entry(21, (unsigned)isr21, 0x08, 0x8E);
set_idt_entry(22, (unsigned)isr22, 0x08, 0x8E);
set_idt_entry(23, (unsigned)isr23, 0x08, 0x8E);
set_idt_entry(24, (unsigned)isr24, 0x08, 0x8E);
set_idt_entry(25, (unsigned)isr25, 0x08, 0x8E);
set_idt_entry(26, (unsigned)isr26, 0x08, 0x8E);
set_idt_entry(27, (unsigned)isr27, 0x08, 0x8E);
set_idt_entry(28, (unsigned)isr28, 0x08, 0x8E);
set_idt_entry(29, (unsigned)isr29, 0x08, 0x8E);
set_idt_entry(30, (unsigned)isr30, 0x08, 0x8E);
set_idt_entry(31, (unsigned)isr31, 0x08, 0x8E);
}
/* This is a simple string array. It contains the message that
* corresponds to each and every exception. We get the correct
* message by accessing like:
* exception_message[interrupt_number] */
char *exception_messages[] =
{
"Division By Zero",
"Debug",
"Non Maskable Interrupt",
"Non Maskable Interrupt",
"Breakpoint",
"Into Detected Overflow",
"Out of Bounds",
"Invalid Opcode",
"No Coprocessor",
"Double Fault",
"Coprocessor Segment Overrun",
"Bad TSS"
"Segment Not Present"
"Stack Fault",
"General Protection Fault",
"Page Fault",
"Unknown Interrupt",
"Coprocessor Fault",
"Alignment Check",
"Machine Check",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved"
};
/* This array is actually an array of function pointers. We use
* this to handle custom IRQ handlers for a given IRQ */
void *irq_routines[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 irq_install_handler(int irq, void (*handler)(struct regs *r))
{
irq_routines[irq] = handler;
}
/* This clears the handler for a given IRQ */
void irq_uninstall_handler(int irq)
{
irq_routines[irq] = 0;
}
/* Normally, IRQs 0 to 7 are mapped to entries 8 to 15. This
* is a problem in protected mode, because IDT entry 8 is a
* Double Fault! Without remapping, every time IRQ0 fires,
* you get a Double Fault Exception, which is NOT actually
* what's happening. We send commands to the Programmable
* Interrupt Controller (PICs - also called the 8259's) in
* order to make IRQ0 to 15 be remapped to IDT entries 32 to
* 47 */
void irq_remap(void)
{
outb(0x20, 0x11);
outb(0xA0, 0x11);
outb(0x21, 0x20);
outb(0xA1, 0x28);
outb(0x21, 0x04);
outb(0xA1, 0x02);
outb(0x21, 0x01);
outb(0xA1, 0x01);
outb(0x21, 0x0);
outb(0xA1, 0x0);
}
/* 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 irq_install()
{
irq_remap();
set_idt_entry(32, (unsigned)irq0, 0x08, 0x8E);
set_idt_entry(33, (unsigned)irq1, 0x08, 0x8E);
set_idt_entry(34, (unsigned)irq2, 0x08, 0x8E);
set_idt_entry(35, (unsigned)irq3, 0x08, 0x8E);
set_idt_entry(36, (unsigned)irq4, 0x08, 0x8E);
set_idt_entry(37, (unsigned)irq5, 0x08, 0x8E);
set_idt_entry(38, (unsigned)irq6, 0x08, 0x8E);
set_idt_entry(39, (unsigned)irq7, 0x08, 0x8E);
set_idt_entry(40, (unsigned)irq8, 0x08, 0x8E);
set_idt_entry(41, (unsigned)irq9, 0x08, 0x8E);
set_idt_entry(42, (unsigned)irq10, 0x08, 0x8E);
set_idt_entry(43, (unsigned)irq12, 0x08, 0x8E);
set_idt_entry(44, (unsigned)irq13, 0x08, 0x8E);
set_idt_entry(45, (unsigned)irq14, 0x08, 0x8E);
set_idt_entry(46, (unsigned)irq15, 0x08, 0x8E);
}
/* 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 fault_handler(struct regs *r)
{
/* Is this a fault whose number is from 0 to 31? */
if (r->int_no < 32)
{
/* Display the description for the Exception that occurred.
* In this tutorial, we will simply halt the system using an
* infinite loop */
newline();newline(); //2 Zeilen frilassen
printkcolor(exception_messages[r->int_no],0x04);
printkcolor(" Exception. System Halted!\n",0x04);
for (;;);
}
}
/* 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 irq_handler(struct regs *r)
{
/* This is a blank function pointer */
void (*handler)(struct regs *r);
/* Find out if we have a custom handler to run for this
* IRQ, and then finally, run it */
handler = irq_routines[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)
{
outb(0xA0, 0x20);
}
/* In either case, we need to send an EOI to the master
* interrupt controller too */
outb(0x20, 0x20);
}

Wie gesagt ist noch alles Orginalzustand aus dem tut.
Ich wär sehr dankbar, wenn mir jemand Verbesserungsvorschläge machen würde.

Übersicht
Wiki
Hilfe
Suche
Einloggen
Registrieren
Drucken
Gespeichert




.