IDT is now really ready

This commit is contained in:
Adrien Bourmault 2019-04-27 00:04:27 +02:00
parent 74593f7f71
commit e7d56a8550
11 changed files with 196 additions and 269 deletions

View File

@ -148,24 +148,6 @@ $(KOBJDIR)/kernel/cpu/idt.o: $(KALEIDDIR)/kernel/cpu/idt.c \
@rm -f $@.1 $@.2 @rm -f $@.1 $@.2
@echo ${CL2}[$@] ${CL}Compiled.${CL3} @echo ${CL2}[$@] ${CL}Compiled.${CL3}
$(KOBJDIR)/kernel/io/keyb.o: $(KALEIDDIR)/kernel/io/keyb.c \
$(KALEIDDIR)/kernel/io/keyb.asm $(INCLUDEDIR)/*/*.h | $(KOBJDIR)
@mkdir -p $(shell dirname $@)
@$(ASM) $(ASMFLAGS) $(KALEIDDIR)/kernel/io/keyb.asm -o $@.1
@$(KCC) $< -o $@.2
@$(LD) $(LDFLAGS) -r $@.1 $@.2 -o $@
@rm -f $@.1 $@.2
@echo ${CL2}[$@] ${CL}Compiled.${CL3}
$(KOBJDIR)/kernel/io/rtc.o: $(KALEIDDIR)/kernel/io/rtc.c \
$(KALEIDDIR)/kernel/io/rtc.asm $(INCLUDEDIR)/*/*.h | $(KOBJDIR)
@mkdir -p $(shell dirname $@)
@$(ASM) $(ASMFLAGS) $(KALEIDDIR)/kernel/io/rtc.asm -o $@.1
@$(KCC) $< -o $@.2
@$(LD) $(LDFLAGS) -r $@.1 $@.2 -o $@
@rm -f $@.1 $@.2
@echo ${CL2}[$@] ${CL}Compiled.${CL3}
## MAIN MAKEFILE ------------------------------------------------------------- # ## MAIN MAKEFILE ------------------------------------------------------------- #
$(KOBJDIR)/%.o: %.c $(INCLUDEDIR)/*/*.h | $(KOBJDIR) $(KOBJDIR)/%.o: %.c $(INCLUDEDIR)/*/*.h | $(KOBJDIR)

View File

@ -43,8 +43,7 @@ typedef struct BootInfo_t BootInfo_t;
typedef struct ListHead_t ListHead_t; typedef struct ListHead_t ListHead_t;
typedef struct ListNode_t ListNode_t; typedef struct ListNode_t ListNode_t;
typedef struct Processor_t Processor_t; typedef struct Processor_t Processor_t;
typedef struct IRQList_t IRQList_t; typedef struct ISRFrame_t ISRFrame_t;
typedef enum ProcState_t ProcState_t; typedef enum ProcState_t ProcState_t;
//------------------------------------------// //------------------------------------------//
@ -89,6 +88,23 @@ struct Processor_t
ListHead_t *timeCritProcs; ListHead_t *timeCritProcs;
}; };
struct ISRFrame_t {
/* the register file */
ulong regs[15];
/* the error code and interrupt id */
ulong intNo;
ulong ErrorCode;
/* these are pushed automatically by the CPU */
ulong rip;
ulong cs;
ulong rflags;
ulong rsp;
ulong ss;
} __attribute__((__packed__));
//------------------------------------------// //------------------------------------------//
#ifndef NCPUS #ifndef NCPUS

View File

@ -13,7 +13,7 @@ typedef struct ISRFrame_t ISRFrame_t;
// -------------------------------------------------------------------------- // // -------------------------------------------------------------------------- //
#define interrupt(n) asm volatile ("int %0" : : "N" (n) : "cc", "memory") \ #define interrupt(n) asm volatile ("int %0" : : "N" (n) : "cc", "memory")
// -------------------------------------------------------------------------- // // -------------------------------------------------------------------------- //
@ -44,28 +44,12 @@ struct IRQList_t
uchar n; //number of entries in the list uchar n; //number of entries in the list
struct entry { struct entry {
void (*isr)(void); void (*isr)(ISRFrame_t *regs);
uchar irq; uchar irq;
uchar flags; uchar flags;
} entry[224]; } entry[224];
}; };
struct ISRFrame_t {
/* the register file */
uint64_t regs[15];
/* the error code and interrupt id */
uint64_t id;
uint64_t error;
/* these are pushed automatically by the CPU */
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
} __attribute__((__packed__));
typedef struct typedef struct
{ {
@ -108,10 +92,10 @@ static char *IsrExceptions[32] = {
// -------------------------------------------------------------------------- // // -------------------------------------------------------------------------- //
void IdtRegisterIrq(void (*isr)(void), uchar irq, uchar flags); void IdtRegisterIrq(void (*isr)(ISRFrame_t *regs), uchar irq, uchar flags);
void IdtSetup(void); void IdtSetup(void);
void IdtSetGate(uchar rank, ulong base, ushort selector, uchar flags); void IdtSetGate(uchar rank, ulong base, ushort selector, uchar flags);
//void IdtHandler(ulong intNo); void IdtExceptionHandler(ISRFrame_t *regs);
static void EnablePIC(void); static void EnablePIC(void);
void SendEOItoPIC(uchar isr); void SendEOItoPIC(uchar isr);
@ -148,5 +132,34 @@ extern void isr28();
extern void isr29(); extern void isr29();
extern void isr30(); extern void isr30();
extern void isr31(); extern void isr31();
extern void isr32();
extern void isr33();
extern void isr34();
extern void isr35();
extern void isr36();
extern void isr37();
extern void isr38();
extern void isr39();
extern void isr40();
extern void isr41();
extern void isr42();
extern void isr43();
extern void isr44();
extern void isr45();
extern void isr46();
extern void isr47();
extern void isr48();
extern void isr49();
extern void isr50();
extern void isr51();
extern void isr52();
extern void isr53();
extern void isr54();
extern void isr55();
extern void isr56();
extern void isr57();
extern void isr58();
extern void isr59();
extern void isr60();
#endif #endif

View File

@ -64,7 +64,7 @@ static inline ulong KePauseIRQs(void) {
extern void IoSendEOItoPIC(uchar isr); extern void IoSendEOItoPIC(uchar isr);
extern void IoEnableNMI(void); extern void IoEnableNMI(void);
extern void IoDisableNMI(void); extern void IoDisableNMI(void);
extern void IdtRegisterIrq(void (*isr)(void), uchar irq, uchar flags); extern void IdtRegisterIrq(void (*isr)(ISRFrame_t *regs), uchar irq, uchar flags);
// //
// Restore IRQ flag to its state before KePauseIRQs // Restore IRQ flag to its state before KePauseIRQs

View File

@ -37,11 +37,11 @@ IRQList_t irqList = { 0 };
// //
// Registers an isr with his IRQ to handle driver interrupts // Registers an isr with his IRQ to handle driver interrupts
// //
void IdtRegisterIrq(void (*isr)(void), uchar irq, uchar flags) void IdtRegisterIrq(void (*isr)(ISRFrame_t *regs), uchar irq, uchar flags)
{ {
uchar n = irqList.n; uchar n = irqList.n;
KalAssert(idt[0].flags==0); // IDT uninitialized KalAssert(idt[0].flags!=0); // IDT initialized
if ((n == 224)) // IRQs not filled if ((n == 224)) // IRQs not filled
KeStartPanic("[IdtRegisterIrq] Cannot register IRQ %c function %p !", KeStartPanic("[IdtRegisterIrq] Cannot register IRQ %c function %p !",
@ -103,15 +103,36 @@ void IdtSetup(void)
IdtSetGate(30, (ulong)isr30, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(30, (ulong)isr30, codeSeg, 0x8E); // INTEL RESERVED
IdtSetGate(31, (ulong)isr31, codeSeg, 0x8E); // INTEL RESERVED IdtSetGate(31, (ulong)isr31, codeSeg, 0x8E); // INTEL RESERVED
// Set the IRQ Driver Gates // Set IDT IRQs Gates
for (int i = 0 ; i < irqList.n ; i++) { IdtSetGate(32, (ulong)isr32, codeSeg, 0x8E);
IdtSetGate( IdtSetGate(33, (ulong)isr33, codeSeg, 0x8E);
irqList.entry[i].irq, IdtSetGate(34, (ulong)isr34, codeSeg, 0x8E);
(ulong)irqList.entry[i].isr, IdtSetGate(35, (ulong)isr35, codeSeg, 0x8E);
codeSeg, IdtSetGate(36, (ulong)isr36, codeSeg, 0x8E);
irqList.entry[i].flags IdtSetGate(37, (ulong)isr37, codeSeg, 0x8E);
); IdtSetGate(38, (ulong)isr38, codeSeg, 0x8E);
} IdtSetGate(39, (ulong)isr39, codeSeg, 0x8E);
IdtSetGate(40, (ulong)isr40, codeSeg, 0x8E);
IdtSetGate(41, (ulong)isr41, codeSeg, 0x8E);
IdtSetGate(42, (ulong)isr42, codeSeg, 0x8E);
IdtSetGate(43, (ulong)isr43, codeSeg, 0x8E);
IdtSetGate(44, (ulong)isr44, codeSeg, 0x8E);
IdtSetGate(45, (ulong)isr45, codeSeg, 0x8E);
IdtSetGate(46, (ulong)isr46, codeSeg, 0x8E);
IdtSetGate(47, (ulong)isr47, codeSeg, 0x8E);
IdtSetGate(48, (ulong)isr48, codeSeg, 0x8E);
IdtSetGate(49, (ulong)isr49, codeSeg, 0x8E);
IdtSetGate(50, (ulong)isr50, codeSeg, 0x8E);
IdtSetGate(51, (ulong)isr51, codeSeg, 0x8E);
IdtSetGate(52, (ulong)isr52, codeSeg, 0x8E);
IdtSetGate(53, (ulong)isr53, codeSeg, 0x8E);
IdtSetGate(54, (ulong)isr54, codeSeg, 0x8E);
IdtSetGate(55, (ulong)isr55, codeSeg, 0x8E);
IdtSetGate(56, (ulong)isr56, codeSeg, 0x8E);
IdtSetGate(57, (ulong)isr57, codeSeg, 0x8E);
IdtSetGate(58, (ulong)isr58, codeSeg, 0x8E);
IdtSetGate(59, (ulong)isr59, codeSeg, 0x8E);
IdtSetGate(60, (ulong)isr60, codeSeg, 0x8E);
// Load IDT // Load IDT
IdtInit(); IdtInit();
@ -185,21 +206,57 @@ void IoDisableNMI(void)
} }
// //
// The main exception handler // The main ISR handler
// //
void IdtHandler(ulong intNo) void IsrHandler(ISRFrame_t *regs)
{
if ((!regs) || (!regs->rip))
KeStartPanic("[ISR ?] Unknown ISR Exception Abort\n");
if (regs->intNo < 32) {
IdtExceptionHandler(regs);
return;
}
for (int i = 0; i < irqList.n; i++) {
if (regs->intNo == irqList.entry[i].irq) {
irqList.entry[i].isr(regs);
return;
}
}
KeStartPanic("[ISR 0x%x] Unknown ISR Exception Abort\n", regs->intNo);
}
//
// CPU Exception handler
//
void IdtExceptionHandler(ISRFrame_t *regs)
{ {
int recoverable = 0; int recoverable = 0;
char *exceptionMsg = "Unhandled ISR exception"; char *exceptionMsg = "Unhandled ISR exception";
if (intNo >= 32) recoverable++; exceptionMsg = IsrExceptions[regs->intNo];
if (intNo < 32) exceptionMsg = IsrExceptions[intNo];
if (!recoverable) { if (!recoverable) {
KeStartPanic("[ISR 0x%x] Irrecoverable %s\n", intNo, exceptionMsg); KeStartPanic("[ISR 0x%x] Irrecoverable Kernel %s\n"
" Error code : 0x%x\n"
" RIP:\t\t%p\n"
" CS:\t\t%p\n"
" RFLAGS:\t%022b\n"
" RSP:\t\t%p\n"
" SS:\t\t%p\n",
regs->intNo,
exceptionMsg,
regs->ErrorCode,
regs->rip,
regs->cs,
regs->rflags,
regs->rsp,
regs->ss
);
} else { } else {
bprintf(BStdOut, "[ISR 0x%x] %s\n", intNo, exceptionMsg); bprintf(BStdOut, "[ISR 0x%x] %s\n", regs->intNo, exceptionMsg);
//IoSendEOItoPIC(intNo);
} }
} }

View File

@ -27,7 +27,7 @@
global IdtInit global IdtInit
global divideByZero global divideByZero
extern idtPtr extern idtPtr
extern IdtHandler extern IsrHandler
extern label0 extern label0
;; ;;
@ -41,16 +41,14 @@ IdtInit:
;; Bug test ;; Bug test
;; ;;
divideByZero: divideByZero:
pushAll
mov eax, 17 mov eax, 17
mov ebx, 0 mov ebx, 0
xor edx, edx xor edx, edx
div ebx div ebx
popAll
ret ret
;; ;;
;; ISR handler ;; ISR Exception pre-handler
;; ;;
isrPreHandler: isrPreHandler:
pushAll pushAll
@ -71,7 +69,7 @@ isrPreHandler:
mov rdi, rsp ; First argument points to the processor state mov rdi, rsp ; First argument points to the processor state
mov rbp, 0 ; Terminate stack traces here mov rbp, 0 ; Terminate stack traces here
call IdtHandler call IsrHandler
; decrement mask count ; decrement mask count
dec qword [gs:8] dec qword [gs:8]
@ -81,7 +79,7 @@ isrPreHandler:
and rax, 0x3000 and rax, 0x3000
jz .SExit jz .SExit
swapgs swapgs ; XXX need TSS
.SExit: .SExit:
popAll popAll
@ -164,3 +162,11 @@ IsrWithoutErrCode 29
IsrWithoutErrCode 30 IsrWithoutErrCode 30
IsrWithoutErrCode 31 IsrWithoutErrCode 31
;; IRQs
%assign i 32
%rep 225
IsrWithoutErrCode i
%assign i i+1
%endrep

View File

@ -38,7 +38,6 @@ extern void BtInitBootInfo(multiboot_info_t *mbi, void *codeSeg);
extern error_t IoInitVGABuffer(void); extern error_t IoInitVGABuffer(void);
//io/keyb.c //io/keyb.c
extern void IoSetupKeyb(void);
extern void IoEnableKeyb(void); extern void IoEnableKeyb(void);
// cpu/idt.c // cpu/idt.c
@ -82,9 +81,6 @@ noreturn void BtStartKern(multiboot_info_t *mbInfo, uint mbMagic, void *codeSeg)
MmInitHeap(); MmInitHeap();
PsInitSched(); PsInitSched();
// Drivers ISR inits
IoSetupRtc();
IoSetupKeyb();
// Interrupts launching // Interrupts launching
IdtSetup(); IdtSetup();
KeEnableIRQs(); KeEnableIRQs();
@ -95,12 +91,14 @@ noreturn void BtStartKern(multiboot_info_t *mbInfo, uint mbMagic, void *codeSeg)
IoPrintRtcTime(); IoPrintRtcTime();
KernLog("There was %d ticks\n", IoGetRtcTicks()); KernLog("There was %d ticks\n", IoGetRtcTicks());
for (uint i = 1; i < 20000 ; i++) { for (uint i = 1; i < 2 ; i++) {
while (IoGetRtcTicks() < i * 10000) { while (IoGetRtcTicks() < i * 10000) {
} }
IoPrintRtcTime(); IoPrintRtcTime();
} }
divideByZero();
KernLog("Goodbye after %d ticks\n", IoGetRtcTicks()); KernLog("Goodbye after %d ticks\n", IoGetRtcTicks());
// End this machine's suffering // End this machine's suffering
BFlushBuf(BStdOut); BFlushBuf(BStdOut);

View File

@ -1,68 +0,0 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Desc: Basic Read Only Keyboard Driver ;
; (x86_64 architecture only) ;
; ;
; ;
; Copyright © 2018-2019 The OS/K Team ;
; ;
; This file is part of OS/K. ;
; ;
; OS/K is free software: you can redistribute it and/or modify ;
; it under the terms of the GNU General Public License as published by ;
; the Free Software Foundation, either version 3 of the License, or ;
; (at your option) any later version. ;
; ;
; OS/K is distributed in the hope that it will be useful, ;
; but WITHOUT ANY WARRANTY; without even the implied warranty of ;
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;
; GNU General Public License for more details. ;
; ;
; You should have received a copy of the GNU General Public License ;
; along with OS/K. If not, see <https://www.gnu.org/licenses/>. ;
;=----------------------------------------------------------------------------=;
[BITS 64]
global KeybIsr
extern KeybHandler
%macro pushAll 0
push rax
push rcx
push rdx
push rbx
push rbp
push rsi
push rdi
%endmacro
%macro popAll 0
pop rdi
pop rsi
pop rbp
pop rbx
pop rdx
pop rcx
pop rax
%endmacro
;;
;; Keyboard handler
;;
KeybIsr:
cli
pushAll
xor rax, rax
mov ax, ds
push rax
call KeybHandler
pop rax
mov ds, ax
popAll
iretq

View File

@ -26,14 +26,8 @@
#include <kernel/iomisc.h> #include <kernel/iomisc.h>
#include <extras/buf.h> #include <extras/buf.h>
extern void KeybIsr(void);
char ScanCodes[100] = { 0 }; char ScanCodes[100] = { 0 };
void IoSetupKeyb(void)
{
IdtRegisterIrq(KeybIsr, 0x21, 0x8E);
}
void KeybPrint(char code) void KeybPrint(char code)
{ {
if (code) { if (code) {
@ -88,17 +82,7 @@ void ScanCodesInit(void)
ScanCodes[0x39] = ' '; ScanCodes[0x39] = ' ';
} }
void IoEnableKeyb(void) void KeybHandler(ISRFrame_t *regs)
{
ulong flags = KePauseIRQs();
char readedInterruptConfig = IoReadByteFromPort(0x21);
IoWriteByteOnPort(0x21, 0xFD & readedInterruptConfig);
KeRestoreIRQs(flags);
IoEnableNMI();
ScanCodesInit();
}
void KeybHandler(void)
{ {
char status; char status;
char code = 0; char code = 0;
@ -116,3 +100,14 @@ void KeybHandler(void)
KeybPrint((int)code); KeybPrint((int)code);
IoSendEOItoPIC(0x21); IoSendEOItoPIC(0x21);
} }
void IoEnableKeyb(void)
{
ulong flags = KePauseIRQs();
IdtRegisterIrq(KeybHandler, 0x21, 0x8E);
char readedInterruptConfig = IoReadByteFromPort(0x21);
IoWriteByteOnPort(0x21, 0xFD & readedInterruptConfig);
KeRestoreIRQs(flags);
IoEnableNMI();
ScanCodesInit();
}

View File

@ -1,68 +0,0 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Desc: Basic Read Only Keyboard Driver ;
; (x86_64 architecture only) ;
; ;
; ;
; Copyright © 2018-2019 The OS/K Team ;
; ;
; This file is part of OS/K. ;
; ;
; OS/K is free software: you can redistribute it and/or modify ;
; it under the terms of the GNU General Public License as published by ;
; the Free Software Foundation, either version 3 of the License, or ;
; (at your option) any later version. ;
; ;
; OS/K is distributed in the hope that it will be useful, ;
; but WITHOUT ANY WARRANTY; without even the implied warranty of ;
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;
; GNU General Public License for more details. ;
; ;
; You should have received a copy of the GNU General Public License ;
; along with OS/K. If not, see <https://www.gnu.org/licenses/>. ;
;=----------------------------------------------------------------------------=;
[BITS 64]
global RtcIsr
extern RtcHandler
%macro pushAll 0
push rax
push rcx
push rdx
push rbx
push rbp
push rsi
push rdi
%endmacro
%macro popAll 0
pop rdi
pop rsi
pop rbp
pop rbx
pop rdx
pop rcx
pop rax
%endmacro
;;
;; Keyboard handler
;;
RtcIsr:
cli
pushAll
xor rax, rax
mov ax, ds
push rax
call RtcHandler
pop rax
mov ds, ax
popAll
iretq

View File

@ -27,17 +27,11 @@
#include <extras/buf.h> #include <extras/buf.h>
#include <kernel/time.h> #include <kernel/time.h>
extern void RtcIsr(void);
static ulong IoRtcTicks = 0; static ulong IoRtcTicks = 0;
static uchar RtcRate = 0x05; //2048Hz static uchar RtcRate = 0x05; //2048Hz
static Time_t IoRtcOriginTime; static Time_t IoRtcOriginTime;
static Time_t IoRtcTime; static Time_t IoRtcTime;
static char time24or12Mode; static char time24or12Mode;
void IoSetupRtc(void)
{
IdtRegisterIrq(RtcIsr, 0x28, 0x8E);
}
static void GetTimeFromRtc(void) static void GetTimeFromRtc(void)
{ {
@ -143,45 +137,7 @@ static void GetTimeFromRtc(void)
IoRtcTime.century = IoRtcOriginTime.century; IoRtcTime.century = IoRtcOriginTime.century;
} }
void IoEnableRtc(void) void RtcHandler(ISRFrame_t *regs)
{
ulong flags = KePauseIRQs();
char readedInterruptConfig;
char readedRegister;
char readedIrqs;
// Setting up the register control and interrupt rates
DebugLog("[RTC Time] Interrupt frequency set to %d Hz\n",
32768 >> (RtcRate-1));
IoWriteByteOnPort(0x70, 0x8B);
readedRegister = IoReadByteFromPort(0x71);
IoWriteByteOnPort(0x70, 0x8B); // Because reading flushes
IoWriteByteOnPort(0x71, readedRegister | 0x40);
IoWriteByteOnPort(0x70, 0x8A);
readedInterruptConfig = IoReadByteFromPort(0x71);
IoWriteByteOnPort(0x70, 0x8A); // Because reading flushes
IoWriteByteOnPort(0x71, (readedInterruptConfig & 0xF0) | RtcRate);
IoWriteByteOnPort(0x70, 0x0C);
IoReadByteFromPort(0x71); // Flush
// Setting up the IRQs
readedIrqs = IoReadByteFromPort(0xA1);
IoWriteByteOnPort(0xA1, 0xFE & readedIrqs); // Enables IRQ on PIC 2
readedIrqs = IoReadByteFromPort(0x21);
IoWriteByteOnPort(0x21, 0xFB & readedIrqs); // Enables IRQ on PIC 1
// Clean-up
IoWriteByteOnPort(0x70, 0x0C); // Select status reg C
IoReadByteFromPort(0x71); // Flush
GetTimeFromRtc();
KeRestoreIRQs(flags);
IoEnableNMI();
}
void RtcHandler(void)
{ {
//bprintf(BStdOut, " *RTC - "); //bprintf(BStdOut, " *RTC - ");
IoWriteByteOnPort(0x70, 0x0C); // Selects status reg C IoWriteByteOnPort(0x70, 0x0C); // Selects status reg C
@ -258,4 +214,44 @@ ulong IoGetRtcTicks(void)
return IoRtcTicks; return IoRtcTicks;
} }
void IoEnableRtc(void)
{
ulong flags = KePauseIRQs();
char readedInterruptConfig;
char readedRegister;
char readedIrqs;
IdtRegisterIrq(RtcHandler, 0x28, 0x8E);
// Setting up the register control and interrupt rates
DebugLog("[RTC Time] Interrupt frequency set to %d Hz\n",
32768 >> (RtcRate-1));
IoWriteByteOnPort(0x70, 0x8B);
readedRegister = IoReadByteFromPort(0x71);
IoWriteByteOnPort(0x70, 0x8B); // Because reading flushes
IoWriteByteOnPort(0x71, readedRegister | 0x40);
IoWriteByteOnPort(0x70, 0x8A);
readedInterruptConfig = IoReadByteFromPort(0x71);
IoWriteByteOnPort(0x70, 0x8A); // Because reading flushes
IoWriteByteOnPort(0x71, (readedInterruptConfig & 0xF0) | RtcRate);
IoWriteByteOnPort(0x70, 0x0C);
IoReadByteFromPort(0x71); // Flush
// Setting up the IRQs
readedIrqs = IoReadByteFromPort(0xA1);
IoWriteByteOnPort(0xA1, 0xFE & readedIrqs); // Enables IRQ on PIC 2
readedIrqs = IoReadByteFromPort(0x21);
IoWriteByteOnPort(0x21, 0xFB & readedIrqs); // Enables IRQ on PIC 1
// Clean-up
IoWriteByteOnPort(0x70, 0x0C); // Select status reg C
IoReadByteFromPort(0x71); // Flush
GetTimeFromRtc();
KeRestoreIRQs(flags);
IoEnableNMI();
}