This repository has been archived on 2025-04-11. You can view files and clone it, but cannot push or open issues or pull requests.
csce410pine64backup/MP3/MP3_Sources/interrupts.C

172 lines
5.4 KiB
C
Executable file

/*
File: interrupts.C
Author: R. Bettati
Department of Computer Science
Texas A&M University
Date : 12/09/05
*/
/*--------------------------------------------------------------------------*/
/* DEFINES */
/*--------------------------------------------------------------------------*/
/* (none) */
/*--------------------------------------------------------------------------*/
/* INCLUDES */
/*--------------------------------------------------------------------------*/
#include "assert.H"
#include "utils.H"
#include "console.H"
#include "idt.H"
#include "irq.H"
#include "exceptions.H"
#include "interrupts.H"
/*--------------------------------------------------------------------------*/
/* EXTERNS */
/*--------------------------------------------------------------------------*/
/* The low-level functions (defined in file 'irq_low.s') that handle the
16 PIC-generated interrupts.
These functions are actually merely stubs that put the error code and
the exception code on the stack and then call a low-level function, which
in turn calls the interrupt dispatcher.
Yes, there are more efficient ways to handle exceptions, but they require more
code replication.
*/
extern "C" void irq0();
extern "C" void irq1();
extern "C" void irq2();
extern "C" void irq3();
extern "C" void irq4();
extern "C" void irq5();
extern "C" void irq6();
extern "C" void irq7();
extern "C" void irq8();
extern "C" void irq9();
extern "C" void irq10();
extern "C" void irq11();
extern "C" void irq12();
extern "C" void irq13();
extern "C" void irq14();
extern "C" void irq15();
extern "C" void lowlevel_dispatch_interrupt(REGS * _r) {
InterruptHandler::dispatch_interrupt(_r);
}
/*--------------------------------------------------------------------------*/
/* LOCAL VARIABLES */
/*--------------------------------------------------------------------------*/
InterruptHandler * InterruptHandler::handler_table[InterruptHandler::IRQ_TABLE_SIZE];
/*--------------------------------------------------------------------------*/
/* EXPORTED INTERRUPT DISPATCHER FUNCTIONS */
/*--------------------------------------------------------------------------*/
void InterruptHandler::init_dispatcher() {
/* -- INITIALIZE LOW-LEVEL INTERRUPT HANDLERS */
/* Add any new ISRs to the IDT here using IDT::set_gate */
IDT::set_gate( 0+ IRQ_BASE, (unsigned) irq0, 0x08, 0x8E);
IDT::set_gate( 1+ IRQ_BASE, (unsigned) irq1, 0x08, 0x8E);
IDT::set_gate( 2+ IRQ_BASE, (unsigned) irq2, 0x08, 0x8E);
IDT::set_gate( 3+ IRQ_BASE, (unsigned) irq3, 0x08, 0x8E);
IDT::set_gate( 4+ IRQ_BASE, (unsigned) irq4, 0x08, 0x8E);
IDT::set_gate( 5+ IRQ_BASE, (unsigned) irq5, 0x08, 0x8E);
IDT::set_gate( 6+ IRQ_BASE, (unsigned) irq6, 0x08, 0x8E);
IDT::set_gate( 7+ IRQ_BASE, (unsigned) irq7, 0x08, 0x8E);
IDT::set_gate( 8+ IRQ_BASE, (unsigned) irq8, 0x08, 0x8E);
IDT::set_gate( 9+ IRQ_BASE, (unsigned) irq9, 0x08, 0x8E);
IDT::set_gate(10+ IRQ_BASE, (unsigned)irq10, 0x08, 0x8E);
IDT::set_gate(11+ IRQ_BASE, (unsigned)irq11, 0x08, 0x8E);
IDT::set_gate(12+ IRQ_BASE, (unsigned)irq12, 0x08, 0x8E);
IDT::set_gate(13+ IRQ_BASE, (unsigned)irq13, 0x08, 0x8E);
IDT::set_gate(14+ IRQ_BASE, (unsigned)irq14, 0x08, 0x8E);
IDT::set_gate(15+ IRQ_BASE, (unsigned)irq15, 0x08, 0x8E);
/* -- INITIALIZE THE HIGH-LEVEL INTERRUPT HANDLER */
int i;
for(i = 0; i < IRQ_TABLE_SIZE; i++) {
handler_table[i] = NULL;
}
}
bool InterruptHandler::generated_by_slave_PIC(unsigned int int_no) {
return int_no > 7;
}
void InterruptHandler::dispatch_interrupt(REGS * _r) {
/* -- INTERRUPT NUMBER */
unsigned int int_no = _r->int_no - IRQ_BASE;
//Console::puts("INTERRUPT DISPATCHER: int_no = ");
//Console::putui(int_no);
//Console::puts("\n");
assert((int_no >= 0) && (int_no < IRQ_TABLE_SIZE));
/* -- HAS A HANDLER BEEN REGISTERED FOR THIS INTERRUPT NO? */
InterruptHandler * handler = handler_table[int_no];
if (!handler) {
/* --- NO DEFAULT HANDLER HAS BEEN REGISTERED. SIMPLY RETURN AN ERROR. */
Console::puts("INTERRUPT NO: ");
Console::puti(int_no);
Console::puts("\n");
Console::puts("NO DEFAULT INTERRUPT HANDLER REGISTERED\n");
// abort();
}
else {
/* -- HANDLE THE INTERRUPT */
handler->handle_interrupt(_r);
}
/* This is an interrupt that was raised by the interrupt controller. We need
to send and end-of-interrupt (EOI) signal to the controller after the
interrupt has been handled. */
/* Check if the interrupt was generated by the slave interrupt controller.
If so, send an End-of-Interrupt (EOI) message to the slave controller. */
if (generated_by_slave_PIC(int_no)) {
Machine::outportb(0xA0, 0x20);
}
/* Send an EOI message to the master interrupt controller. */
Machine::outportb(0x20, 0x20);
}
void InterruptHandler::register_handler(unsigned int _irq_code,
InterruptHandler * _handler) {
assert(_irq_code >= 0 && _irq_code < IRQ_TABLE_SIZE);
handler_table[_irq_code] = _handler;
Console::puts("Installed interrupt handler at IRQ ");
Console::putui(_irq_code);
Console::puts("\n");
}
void InterruptHandler::deregister_handler(unsigned int _irq_code) {
assert(_irq_code >= 0 && _irq_code < IRQ_TABLE_SIZE);
handler_table[_irq_code] = NULL;
Console::puts("UNINSTALLED interrupt handler at IRQ ");
Console::putui(_irq_code);
Console::puts("\n");
}