1

implement exercise 04 interrupts

This commit is contained in:
churl
2022-05-14 21:12:32 +02:00
parent deb0ebd8eb
commit 13df44fb6f
8 changed files with 208 additions and 120 deletions

View File

@ -9,6 +9,7 @@
*****************************************************************************/ *****************************************************************************/
#include "devices/Keyboard.h" #include "devices/Keyboard.h"
#include "kernel/Globals.h"
/* Tabellen fuer ASCII-Codes (Klassenvariablen) intiialisieren */ /* Tabellen fuer ASCII-Codes (Klassenvariablen) intiialisieren */
@ -321,3 +322,44 @@ void Keyboard::set_led(char led, bool on) {
/* Hier muss Code eingefuegt werden. */ /* Hier muss Code eingefuegt werden. */
} }
// Registriert die Tastatur ISR im IntDispatcher
// und erlaubt den keyboard interrupt
void Keyboard::plugin(IntDispatcher& intdis, PIC& pic) {
intdis.assign(IntDispatcher::keyboard, *this);
pic.allow(PIC::keyboard);
}
void scroll_mode(Key key);
void Keyboard::trigger() {
// TODO: Get data from PS/2 Mouse if necessary
Key key = this->key_hit();
// NOTE: My keyboard has no delete key...
if (key.ctrl_left() && key.alt_left() && (char)key == 'r') {
this->reboot();
}
scroll_mode(key);
// kout.show(0, 0, (char)key);
}
// TODO: Where to place this?
// Waits for keys to control the scrollback buffer display
void scroll_mode(Key key) {
kout.show(kout.COLUMNS - 1, 0, (char)(48 + kout.current_page));
switch ((char)key) {
case 'k':
kout.scroll_page_backward();
kout.show(kout.COLUMNS - 1, 0, (char)(48 + kout.current_page));
break;
case 'j':
kout.scroll_page_forward();
kout.show(kout.COLUMNS - 1, 0, (char)(48 + kout.current_page));
break;
}
}

View File

@ -12,44 +12,53 @@
#define __Keyboard_include__ #define __Keyboard_include__
#include "devices/Key.h" #include "devices/Key.h"
#include "kernel/IOport.h" #include "kernel/interrupts/IntDispatcher.h"
#include "kernel/interrupts/ISR.h" #include "kernel/interrupts/ISR.h"
#include "kernel/interrupts/PIC.h"
#include "kernel/IOport.h"
class Keyboard : public ISR { class Keyboard : public ISR {
private:
Keyboard(const Keyboard &copy); // Verhindere Kopieren
unsigned char code; // Byte von Tastatur private:
unsigned char prefix; // Prefix von Tastatur Keyboard(const Keyboard& copy); // Verhindere Kopieren
Key gather; // letzter dekodierter Key
char leds; // Zustand LEDs unsigned char code; // Byte von Tastatur
unsigned char prefix; // Prefix von Tastatur
Key gather; // letzter dekodierter Key
char leds; // Zustand LEDs
// Benutzte Ports des Tastaturcontrollers // Benutzte Ports des Tastaturcontrollers
const IOport ctrl_port; // Status- (R) u. Steuerregister (W) const IOport ctrl_port; // Status- (R) u. Steuerregister (W)
const IOport data_port; // Ausgabe- (R) u. Eingabepuffer (W) const IOport data_port; // Ausgabe- (R) u. Eingabepuffer (W)
// Bits im Statusregister // Bits im Statusregister
enum { outb = 0x01, inpb = 0x02, auxb = 0x20 }; enum { outb = 0x01,
inpb = 0x02,
auxb = 0x20 };
// Kommandos an die Tastatur // Kommandos an die Tastatur
struct kbd_cmd { struct kbd_cmd {
enum { set_led = 0xed, set_speed = 0xf3 }; enum { set_led = 0xed,
set_speed = 0xf3 };
}; };
enum { cpu_reset = 0xfe }; enum { cpu_reset = 0xfe };
// Namen der LEDs // Namen der LEDs
struct led { struct led {
enum { caps_lock = 4, num_lock = 2, scroll_lock = 1 }; enum { caps_lock = 4,
}; num_lock = 2,
scroll_lock = 1 };
};
// Antworten der Tastatur // Antworten der Tastatur
struct kbd_reply { struct kbd_reply {
enum { ack = 0xfa }; enum { ack = 0xfa };
}; };
// Konstanten fuer die Tastaturdekodierung // Konstanten fuer die Tastaturdekodierung
enum { break_bit = 0x80, prefix1 = 0xe0, prefix2 = 0xe1 }; enum { break_bit = 0x80,
prefix1 = 0xe0,
prefix2 = 0xe1 };
// Klassenvariablen // Klassenvariablen
static unsigned char normal_tab[]; static unsigned char normal_tab[];
@ -57,36 +66,35 @@ private:
static unsigned char alt_tab[]; static unsigned char alt_tab[];
static unsigned char asc_num_tab[]; static unsigned char asc_num_tab[];
static unsigned char scan_num_tab[]; static unsigned char scan_num_tab[];
// Interpretiert die Make und Break-Codes der Tastatur. // Interpretiert die Make und Break-Codes der Tastatur.
bool key_decoded (); bool key_decoded();
// Ermittelt anhand von Tabellen den ASCII-Code. // Ermittelt anhand von Tabellen den ASCII-Code.
void get_ascii_code (); void get_ascii_code();
public: public:
// Initialisierung der Tastatur.
Keyboard();
// Initialisierung der Tastatur. // Tastaturabfrage (vorerst Polling)
Keyboard (); Key key_hit();
// Tastaturabfrage (vorerst Polling) // Fuehrt einen Neustart des Rechners durch.
Key key_hit (); void reboot();
// Fuehrt einen Neustart des Rechners durch. // Einstellen der Wiederholungsrate der Tastatur.
void reboot (); void set_repeat_rate(int speed, int delay);
// Einstellen der Wiederholungsrate der Tastatur. // Setzt oder loescht die angegebene Leuchtdiode.
void set_repeat_rate (int speed, int delay); void set_led(char led, bool on);
// Setzt oder loescht die angegebene Leuchtdiode. // Aktivierung der Unterbrechungen fuer die Tastatur
void set_led (char led, bool on); // TODO: NOTE: I added this (parameters), but is it supposed to be this way?
void plugin(IntDispatcher& intdis, PIC& pic);
// Aktivierung der Unterbrechungen fuer die Tastatur // Unterbrechnungsroutine der Tastatur.
void plugin (); void trigger() override;
// Unterbrechnungsroutine der Tastatur.
void trigger ();
}; };
#endif #endif

View File

@ -12,43 +12,41 @@
#ifndef __CPU_include__ #ifndef __CPU_include__
#define __CPU_include__ #define __CPU_include__
class CPU { class CPU {
private: private:
CPU(const CPU &copy); // Verhindere Kopieren CPU(const CPU& copy); // Verhindere Kopieren
public: public:
CPU() {} CPU() {}
// Erlauben von (Hardware-)Interrupts // Erlauben von (Hardware-)Interrupts
inline void enable_int () { inline void enable_int() {
asm volatile ( "sti" ); asm volatile("sti");
} }
// Interrupts werden ignoriert/verboten // Interrupts werden ignoriert/verboten
inline void disable_int () { inline void disable_int() {
asm volatile ( "cli" ); asm volatile("cli");
} }
// Prozessor bis zum naechsten Interrupt anhalten // Prozessor bis zum naechsten Interrupt anhalten
inline void idle () { inline void idle() {
asm volatile ( "sti;" asm volatile("sti;"
"hlt" "hlt");
);
} }
// Prozessor anhalten // Prozessor anhalten
inline void halt () { inline void halt() {
asm volatile ( "cli;" asm volatile("cli;"
"hlt" "hlt");
);
} }
// Time-Stamp-Counter auslesen // Time-Stamp-Counter auslesen
inline unsigned long long int rdtsc() { inline unsigned long long int rdtsc() {
unsigned long long int ret; unsigned long long int ret;
asm volatile ( "rdtsc" : "=A"(ret) ); asm volatile("rdtsc"
: "=A"(ret));
return ret; return ret;
} }
}; };

View File

@ -10,13 +10,11 @@
* * * *
* Autor: Michael Schoettner, 31.8.2016 * * Autor: Michael Schoettner, 31.8.2016 *
*****************************************************************************/ *****************************************************************************/
#include "kernel/interrupts/IntDispatcher.h"
#include "kernel/CPU.h" #include "kernel/CPU.h"
#include "kernel/Globals.h" #include "kernel/Globals.h"
#include "kernel/interrupts/IntDispatcher.h"
extern "C" void int_disp (unsigned int slot);
extern "C" void int_disp(unsigned int slot);
/***************************************************************************** /*****************************************************************************
* Prozedur: int_disp * * Prozedur: int_disp *
@ -30,26 +28,25 @@ extern "C" void int_disp (unsigned int slot);
* Parameter: * * Parameter: *
* vector: Vektor-Nummer der Unterbrechung * * vector: Vektor-Nummer der Unterbrechung *
*****************************************************************************/ *****************************************************************************/
void int_disp (unsigned int vector) { void int_disp(unsigned int vector) {
/* hier muss Code eingefuegt werden */ /* hier muss Code eingefuegt werden */
kout << "Ein Interrupt ist aufgetreten" << slot << endl;
// kout << "Ein Interrupt ist aufgetreten (vector: " << vector << ")" << endl;
intdis.report(vector);
} }
/***************************************************************************** /*****************************************************************************
* Konstruktor: IntDispatcher::IntDispatcher * * Konstruktor: IntDispatcher::IntDispatcher *
*---------------------------------------------------------------------------* *---------------------------------------------------------------------------*
* Beschreibung: Initialisierung der ISR map mit einer Default-ISR. * * Beschreibung: Initialisierung der ISR map mit einer Default-ISR. *
*****************************************************************************/ *****************************************************************************/
IntDispatcher::IntDispatcher () { IntDispatcher::IntDispatcher() {
for (unsigned int slot=0; slot<size; slot++) for (unsigned int slot = 0; slot < size; slot++) {
map[slot] = 0; map[slot] = 0;
}
} }
/***************************************************************************** /*****************************************************************************
* Methode: IntDispatcher::assign * * Methode: IntDispatcher::assign *
*---------------------------------------------------------------------------* *---------------------------------------------------------------------------*
@ -61,12 +58,20 @@ IntDispatcher::IntDispatcher () {
* * * *
* Rueckgabewert: 0 = Erfolg, -1 = Fehler * * Rueckgabewert: 0 = Erfolg, -1 = Fehler *
*****************************************************************************/ *****************************************************************************/
int IntDispatcher::assign (unsigned int vector, ISR& isr) { int IntDispatcher::assign(unsigned int vector, ISR& isr) {
/* hier muss Code eingefuegt werden */ /* hier muss Code eingefuegt werden */
} if (vector >= this->size) {
kout << "Invalid vector number when assigning" << endl;
return -1;
}
this->map[vector] = &isr;
kout << "Registered ISR for vector " << dec << vector << endl;
return 0;
}
/***************************************************************************** /*****************************************************************************
* Methode: IntDispatcher::report * * Methode: IntDispatcher::report *
@ -78,8 +83,22 @@ int IntDispatcher::assign (unsigned int vector, ISR& isr) {
* * * *
* Rueckgabewert: 0 = ISR wurde aufgerufen, -1 = unbekannte Vektor-Nummer * * Rueckgabewert: 0 = ISR wurde aufgerufen, -1 = unbekannte Vektor-Nummer *
*****************************************************************************/ *****************************************************************************/
int IntDispatcher::report (unsigned int vector) { int IntDispatcher::report(unsigned int vector) {
/* hier muss Code eingefuegt werden */ /* hier muss Code eingefuegt werden */
if (vector >= this->size) {
return -1;
}
ISR* isr = this->map[vector];
if (isr == 0) {
kout << "No ISR registered for vector " << vector << endl;
return -1;
}
isr->trigger();
return 0;
} }

View File

@ -15,13 +15,11 @@
* Autor: Olaf Spinczyk, TU Dortmund * * Autor: Olaf Spinczyk, TU Dortmund *
*****************************************************************************/ *****************************************************************************/
#include "kernel/PIC.h" #include "kernel/interrupts/PIC.h"
#include "kernel/IOport.h" #include "kernel/IOport.h"
static IOport IMR1(0x21); // interrupt mask register von PIC 1
static IOport IMR1 (0x21); // interrupt mask register von PIC 1 static IOport IMR2(0xa1); // interrupt mask register von PIC 2
static IOport IMR2 (0xa1); // interrupt mask register von PIC 2
/***************************************************************************** /*****************************************************************************
* Methode: PIC::allow * * Methode: PIC::allow *
@ -34,12 +32,24 @@ static IOport IMR2 (0xa1); // interrupt mask register von PIC 2
* Parameter: * * Parameter: *
* irq: IRQ der erlaubt werden soll * * irq: IRQ der erlaubt werden soll *
*****************************************************************************/ *****************************************************************************/
void PIC::allow (int irq) { void PIC::allow(int irq) {
/* hier muss Code eingefuegt werden */ /* 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 * * Methode: PIC::forbid *
@ -49,12 +59,24 @@ void PIC::allow (int irq) {
* Parameter: * * Parameter: *
* interrupt: IRQ der maskiert werden soll * * interrupt: IRQ der maskiert werden soll *
*****************************************************************************/ *****************************************************************************/
void PIC::forbid (int irq) { void PIC::forbid(int irq) {
/* hier muss Code eingefuegt werden */ /* 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 * * Methode: PIC::status *
@ -65,9 +87,23 @@ void PIC::forbid (int irq) {
* Parameter: * * Parameter: *
* irq: IRQ dessen Status erfragt werden soll * * irq: IRQ dessen Status erfragt werden soll *
*****************************************************************************/ *****************************************************************************/
bool PIC::status (int irq) { bool PIC::status(int irq) {
/* hier muss Code eingefuegt werden */ /* hier muss Code eingefuegt werden */
// TODO: How is IRQ2 handled (Slave PIC)?
// Does masking IRQ2 disable the whole slave?
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;
} }

View File

@ -18,27 +18,28 @@
#define __PIC_include__ #define __PIC_include__
class PIC { class PIC {
private: private:
PIC(const PIC &copy); // Verhindere Kopieren PIC(const PIC& copy); // Verhindere Kopieren
public: public:
PIC() {} PIC() {}
public: public:
// IRQ-Nummern von Geraeten // IRQ-Nummern von Geraeten
enum { enum {
timer = 0, // Programmable Interrupt Timer (PIT) timer = 0, // Programmable Interrupt Timer (PIT)
keyboard = 1 // Tastatur keyboard = 1 // Tastatur
}; };
// Freischalten der Weiterleitung eines IRQs durch den PIC an die CPU // Freischalten der Weiterleitung eines IRQs durch den PIC an die CPU
void allow (int irq); void allow(int irq);
// Unterdruecken der Weiterleitung eines IRQs durch den PIC an die CPU // Unterdruecken der Weiterleitung eines IRQs durch den PIC an die CPU
void forbid (int irq); void forbid(int irq);
// Abfragen, ob die Weiterleitung fuer einen bestimmten IRQ unterdrueckt ist // Abfragen, ob die Weiterleitung fuer einen bestimmten IRQ unterdrueckt ist
bool status (int interrupt_device); bool status(int interrupt_device);
}; };
#endif #endif

View File

@ -15,27 +15,6 @@
#include "user/HeapDemo.h" #include "user/HeapDemo.h"
#include "user/KeyIRQDemo.h" #include "user/KeyIRQDemo.h"
// Waits for keys to control the scrollback buffer display
void scroll_mode() {
kout.show(kout.COLUMNS - 1, 0, (char)(48 + kout.current_page));
Key key;
while (true) {
key = kb.key_hit();
switch ((char)key) {
case 'k':
kout.scroll_page_backward();
kout.show(kout.COLUMNS - 1, 0, (char)(48 + kout.current_page));
break;
case 'j':
kout.scroll_page_forward();
kout.show(kout.COLUMNS - 1, 0, (char)(48 + kout.current_page));
break;
}
}
}
int main() { int main() {
kout.clear(); kout.clear();
@ -43,7 +22,7 @@ int main() {
allocator.init(); allocator.init();
// Initialize scrollback buffer after allocator.init() // Initialize scrollback buffer after allocator.init()
kout.init(); kout.init(5);
// text_demo(); // text_demo();
// sound_demo(); // sound_demo();
@ -52,14 +31,13 @@ int main() {
// Tastatur-Unterbrechungsroutine 'einstoepseln' // Tastatur-Unterbrechungsroutine 'einstoepseln'
/* hier muss Code eingefuegt werden */ /* hier muss Code eingefuegt werden */
kb.plugin(intdis, pic);
// Interrupts erlauben (Tastatur) // Interrupts erlauben (Tastatur)
/* hier muss Code eingefuegt werden */ /* hier muss Code eingefuegt werden */
cpu.enable_int();
key_irq_demo(); // key_irq_demo();
// TODO: Use interrupts
// scroll_mode();
while (1) {}; while (1) {};
return 0; return 0;

View File

@ -10,9 +10,15 @@
#include "kernel/Globals.h" #include "kernel/Globals.h"
void key_irq_demo() { void key_irq_demo() {
/* Hier muss Code eingefuegt werden */ /* Hier muss Code eingefuegt werden */
// TODO: I don't understand the task
while (true) {
for (unsigned char i = 0; i < 10; ++i) {
kout.show(kout.COLUMNS - 1, i, (char)(48 + i));
}
}
} }