107 lines
4.8 KiB
C++
Executable File
107 lines
4.8 KiB
C++
Executable File
/*****************************************************************************
|
|
* *
|
|
* P I C *
|
|
* *
|
|
*---------------------------------------------------------------------------*
|
|
* Beschreibung: Mit Hilfe des PICs koennen Hardware-Interrupts (IRQs) *
|
|
* einzeln zugelassen oder unterdrueckt werden. Auf diese *
|
|
* Weise wird also bestimmt, ob die Unterbrechung eines *
|
|
* Geraetes ueberhaupt an den Prozessor weitergegeben wird. *
|
|
* Selbst dann erfolgt eine Aktivierung der Unterbrechungs- *
|
|
* routine nur, wenn der Prozessor bereit ist, auf Unter- *
|
|
* brechungen zu reagieren. Dies kann mit Hilfe der Klasse *
|
|
* CPU festgelegt werden. *
|
|
* *
|
|
* Autor: Olaf Spinczyk, TU Dortmund *
|
|
*****************************************************************************/
|
|
|
|
#include "kernel/interrupts/PIC.h"
|
|
#include "kernel/IOport.h"
|
|
|
|
IOport const PIC::IMR1(0x21); // interrupt mask register von PIC 1
|
|
IOport const PIC::IMR2(0xa1); // interrupt mask register von PIC 2
|
|
|
|
/*****************************************************************************
|
|
* Methode: PIC::allow *
|
|
*---------------------------------------------------------------------------*
|
|
* Beschreibung: Sorgt dafuer, dass der uebergebene IRQ ab sofort durch *
|
|
* den PIC an den Prozessor weitergereicht wird. Um eine *
|
|
* Unterbrechungsbehandlung zu ermoeglichen, muss *
|
|
* zusaetzlich CPU::enable_int() aufgerufen werden. *
|
|
* *
|
|
* Parameter: *
|
|
* irq: IRQ der erlaubt werden soll *
|
|
*****************************************************************************/
|
|
void PIC::allow(int irq) {
|
|
|
|
/* hier muss Code eingefuegt werden */
|
|
|
|
// NOTE: allow sets the bit to 0
|
|
|
|
unsigned char IMR;
|
|
unsigned char mask = ~(0x1 << (irq % 8));
|
|
if (irq < 8) {
|
|
// PIC 1
|
|
IMR = IMR1.inb(); // We don't want to change the other interrupt masks so use this as start value
|
|
IMR1.outb(IMR & mask);
|
|
} else {
|
|
// PIC 2
|
|
IMR = IMR2.inb();
|
|
IMR2.outb(IMR & mask);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Methode: PIC::forbid *
|
|
*---------------------------------------------------------------------------*
|
|
* Beschreibung: Unterdrueckt mit Hilfe des PICs einen bestimmten IRQ. *
|
|
* *
|
|
* Parameter: *
|
|
* interrupt: IRQ der maskiert werden soll *
|
|
*****************************************************************************/
|
|
void PIC::forbid(int irq) {
|
|
|
|
/* hier muss Code eingefuegt werden */
|
|
|
|
// NOTE: forbid sets the bit to 1
|
|
|
|
unsigned char IMR;
|
|
unsigned char mask = 0x1 << (irq % 8);
|
|
if (irq < 8) {
|
|
// PIC 1
|
|
IMR = IMR1.inb(); // We don't want to change the other interrupt masks so use this as start value
|
|
IMR1.outb(IMR | mask);
|
|
} else {
|
|
// PIC 2
|
|
IMR = IMR2.inb();
|
|
IMR2.outb(IMR | mask);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Methode: PIC::status *
|
|
*---------------------------------------------------------------------------*
|
|
* Beschreibung: Liefert den aktuellen Zustand des Maskierbits eines *
|
|
* bestimmten IRQs. *
|
|
* *
|
|
* Parameter: *
|
|
* irq: IRQ dessen Status erfragt werden soll *
|
|
*****************************************************************************/
|
|
bool PIC::status(int irq) {
|
|
|
|
/* hier muss Code eingefuegt werden */
|
|
|
|
unsigned char IMR;
|
|
if (irq < 8) {
|
|
// PIC 1
|
|
IMR = IMR1.inb();
|
|
} else {
|
|
// PIC 2
|
|
IMR = IMR2.inb();
|
|
}
|
|
|
|
// Use % 8 to account for two PICs
|
|
unsigned char mask = 0x1 << (irq % 8);
|
|
return IMR & mask;
|
|
}
|