feature (kernel): implemented PIC functionalities and PIT functionalities
This commit is contained in:
parent
12cc5ca0e1
commit
68d2ef7de4
|
@ -0,0 +1,26 @@
|
|||
/* Copyright (C) Antifallobst <antifallobst@systemausfall.org>
|
||||
*
|
||||
* NoxOS 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.
|
||||
*
|
||||
* NoxOS 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 this program.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NOX_PIT_H
|
||||
#define NOX_PIT_H
|
||||
|
||||
#include "utils/stdtypes.h"
|
||||
|
||||
#define PIT_CHANNEL_0_PORT 0x40
|
||||
#define PIT_DIVISOR 32768 // This gives an interrupt every ~27.46ms
|
||||
|
||||
void pit_set_divisor(uint16_t divisor);
|
||||
|
||||
#endif //NOX_PIT_H
|
|
@ -22,6 +22,43 @@
|
|||
#define IDT_ENTRY_CALL_GATE 0b10001100
|
||||
#define IDT_ENTRY_TRAP_GATE 0b10001111
|
||||
|
||||
#define PIC_MASTER_PORT 0x20
|
||||
#define PIC_MASTER_COMMAND 0x20
|
||||
#define PIC_MASTER_DATA 0x21
|
||||
#define PIC_SLAVE_PORT 0xA0
|
||||
#define PIC_SLAVE_COMMAND 0xA0
|
||||
#define PIC_SLAVE_DATA 0xA1
|
||||
#define PIC_END_OF_INTERRUPT 0x20
|
||||
|
||||
#define ICW1_ICW4 0x01
|
||||
#define ICW1_INIT 0x10
|
||||
#define ICW4_8086 0x01
|
||||
|
||||
#define IRQ_MASTER_OFFSET 0x20
|
||||
#define IRQ_SLAVE_OFFSET 0x28
|
||||
|
||||
typedef enum {
|
||||
// Master PIC
|
||||
IRQ_PIT,
|
||||
IRQ_KEYBOARD,
|
||||
IRQ_CASCADE,
|
||||
IRQ_COM2,
|
||||
IRQ_COM1,
|
||||
IRQ_LPT2,
|
||||
IRQ_FLOPPY,
|
||||
IRQ_SPURIOUS,
|
||||
|
||||
// Slave PIC
|
||||
IRQ_CMOS_RTC,
|
||||
IRQ_FREE_0,
|
||||
IRQ_FREE_1,
|
||||
IRQ_FREE_2,
|
||||
IRQ_PS2_MOUSE,
|
||||
IRQ_FPU,
|
||||
IRQ_ATA_PRIMARY,
|
||||
IRQ_ATA_SECONDARY
|
||||
} pic_irq_E;
|
||||
|
||||
typedef struct {
|
||||
uint16_t limit;
|
||||
uint64_t offset;
|
||||
|
@ -39,6 +76,11 @@ typedef struct {
|
|||
|
||||
extern idt_register_T g_idt_register;
|
||||
|
||||
void idt_init();
|
||||
void idt_init ();
|
||||
void pic_init ();
|
||||
void pic_remap ();
|
||||
void pic_send_end_of_interrupt (pic_irq_E irq);
|
||||
void pic_mask_irq (pic_irq_E irq);
|
||||
void pic_unmask_irq (pic_irq_E irq);
|
||||
|
||||
#endif //NOX_INTERRUPTS_H
|
||||
|
|
|
@ -18,8 +18,11 @@
|
|||
|
||||
#include "utils/logger.h"
|
||||
|
||||
#define CORE_HALT_WHILE(a) while(a) { asm("hlt"); }
|
||||
#define CORE_HALT_FOREVER log(LOG_WARNING, "!=====[ HALTING SYSTEM ]=====!");\
|
||||
while(1) { asm("hlt"); }
|
||||
#define CORE_HALT_WHILE(a) while(a) { asm("hlt"); }
|
||||
#define CORE_HALT_FOREVER log(LOG_WARNING, "!=====[ HALTING SYSTEM ]=====!");\
|
||||
while(1) { asm("hlt"); }
|
||||
|
||||
#define CORE_INTERRUPTS_ENABLE asm("sti");
|
||||
#define CORE_INTERRUPTS_DISABLE asm("cli");
|
||||
|
||||
#endif //NOX_CORE_H
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/* Copyright (C) Antifallobst <antifallobst@systemausfall.org>
|
||||
*
|
||||
* NoxOS 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.
|
||||
*
|
||||
* NoxOS 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 this program.
|
||||
* If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "drivers/time/pit.h"
|
||||
#include "utils/io.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
uint16_t g_divisor;
|
||||
|
||||
void pit_set_divisor(uint16_t divisor) {
|
||||
if (divisor < 100) { divisor = 100; }
|
||||
|
||||
g_divisor = divisor;
|
||||
|
||||
io_out_byte(PIT_CHANNEL_0_PORT, divisor & 0x00FF); io_wait();
|
||||
io_out_byte(PIT_CHANNEL_0_PORT, (divisor & 0xFF00) >> 8);
|
||||
|
||||
log(LOG_INFO, "pit -> divisor set to %d", divisor);
|
||||
}
|
|
@ -17,21 +17,27 @@
|
|||
#include "utils/core.h"
|
||||
#include "utils/memory.h"
|
||||
#include "boot/boot_info.h"
|
||||
#include "platform/gdt.h"
|
||||
#include "platform/interrupts.h"
|
||||
#include "mm/page_frame.h"
|
||||
#include "mm/page_map.h"
|
||||
#include "drivers/time/pit.h"
|
||||
|
||||
void limine_terminal_print(boot_info_T* boot_info, string_t string) {
|
||||
boot_info->terminal->write(boot_info->terminal->terminals[0], string, string_length(string));
|
||||
}
|
||||
|
||||
void kernel_init(boot_info_T* boot_info) {
|
||||
gdt_init();
|
||||
pframe_manager_init(boot_info);
|
||||
|
||||
CORE_INTERRUPTS_DISABLE
|
||||
idt_init();
|
||||
pic_init();
|
||||
pit_set_divisor(PIT_DIVISOR);
|
||||
CORE_INTERRUPTS_ENABLE
|
||||
|
||||
paging_init();
|
||||
memory_allocator_init((void*)0x100000000000);
|
||||
// scheduler_init();
|
||||
}
|
||||
|
||||
void kmain(boot_info_T boot_info) {
|
||||
|
@ -41,7 +47,11 @@ void kmain(boot_info_T boot_info) {
|
|||
|
||||
kernel_init(&boot_info);
|
||||
|
||||
void* debug = memory_allocate(1312);
|
||||
log(LOG_INFO, "!=====[ Kernel Initialized ]=====!\n");
|
||||
|
||||
asm("int $0x80");
|
||||
|
||||
// void* debug = memory_allocate(1312);
|
||||
|
||||
CORE_HALT_FOREVER
|
||||
}
|
||||
|
|
|
@ -19,10 +19,13 @@
|
|||
#include "platform/exceptions.h"
|
||||
#include "mm/page_frame.h"
|
||||
#include "utils/logger.h"
|
||||
#include "utils/io.h"
|
||||
|
||||
idt_register_T g_idt_register;
|
||||
|
||||
extern void idt_load(idt_register_T* idt_register);
|
||||
|
||||
// Exceptions
|
||||
extern void interrupt_stub_0x00();
|
||||
extern void interrupt_stub_0x01();
|
||||
extern void interrupt_stub_0x02();
|
||||
|
@ -56,6 +59,29 @@ extern void interrupt_stub_0x1D();
|
|||
extern void interrupt_stub_0x1E();
|
||||
extern void interrupt_stub_0x1F();
|
||||
|
||||
// IRQs on Master PIC
|
||||
extern void interrupt_stub_0x20();
|
||||
extern void interrupt_stub_0x21();
|
||||
extern void interrupt_stub_0x22();
|
||||
extern void interrupt_stub_0x23();
|
||||
extern void interrupt_stub_0x24();
|
||||
extern void interrupt_stub_0x25();
|
||||
extern void interrupt_stub_0x26();
|
||||
extern void interrupt_stub_0x27();
|
||||
|
||||
// IRQs on Slave PIC
|
||||
extern void interrupt_stub_0x28();
|
||||
extern void interrupt_stub_0x29();
|
||||
extern void interrupt_stub_0x2A();
|
||||
extern void interrupt_stub_0x2B();
|
||||
extern void interrupt_stub_0x2C();
|
||||
extern void interrupt_stub_0x2D();
|
||||
extern void interrupt_stub_0x2E();
|
||||
extern void interrupt_stub_0x2F();
|
||||
|
||||
// Custom
|
||||
extern void interrupt_stub_0x80();
|
||||
|
||||
void idt_set_descriptor_entry_offset(idt_descriptor_entry_T* entry, uint64_t offset) {
|
||||
entry->offset0 = (uint16_t) (offset & 0x000000000000ffff);
|
||||
entry->offset1 = (uint16_t) ((offset & 0x00000000ffff0000) >> 16);
|
||||
|
@ -81,7 +107,7 @@ void idt_init() {
|
|||
g_idt_register.limit = 0x0FFF;
|
||||
g_idt_register.offset = (uint64_t)pframe_request();
|
||||
|
||||
|
||||
// Exceptions
|
||||
idt_set_gate((void*)interrupt_stub_0x00, 0x00, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
idt_set_gate((void*)interrupt_stub_0x01, 0x01, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
idt_set_gate((void*)interrupt_stub_0x02, 0x02, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
|
@ -115,16 +141,119 @@ void idt_init() {
|
|||
idt_set_gate((void*)interrupt_stub_0x1E, 0x1E, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
idt_set_gate((void*)interrupt_stub_0x1F, 0x1F, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
|
||||
// IRQs on Master PIC
|
||||
idt_set_gate((void*)interrupt_stub_0x20, 0x20, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
idt_set_gate((void*)interrupt_stub_0x21, 0x21, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
idt_set_gate((void*)interrupt_stub_0x22, 0x22, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
idt_set_gate((void*)interrupt_stub_0x23, 0x23, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
idt_set_gate((void*)interrupt_stub_0x24, 0x24, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
idt_set_gate((void*)interrupt_stub_0x25, 0x25, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
idt_set_gate((void*)interrupt_stub_0x26, 0x26, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
idt_set_gate((void*)interrupt_stub_0x27, 0x27, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
|
||||
// IRQs on Slave PIC
|
||||
idt_set_gate((void*)interrupt_stub_0x28, 0x28, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
idt_set_gate((void*)interrupt_stub_0x29, 0x29, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
idt_set_gate((void*)interrupt_stub_0x2A, 0x2A, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
idt_set_gate((void*)interrupt_stub_0x2B, 0x2B, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
idt_set_gate((void*)interrupt_stub_0x2C, 0x2C, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
idt_set_gate((void*)interrupt_stub_0x2D, 0x2D, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
idt_set_gate((void*)interrupt_stub_0x2E, 0x2E, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
idt_set_gate((void*)interrupt_stub_0x2F, 0x2F, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
|
||||
// Custom
|
||||
idt_set_gate((void*)interrupt_stub_0x80, 0x80, IDT_ENTRY_INTR_GATE, GDT_SELECTOR_KERNEL_CODE);
|
||||
|
||||
idt_load(&g_idt_register);
|
||||
log(LOG_INFO, "Interrupts initialized");
|
||||
}
|
||||
|
||||
void pic_init() {
|
||||
pic_remap();
|
||||
|
||||
pic_unmask_irq(IRQ_PIT);
|
||||
}
|
||||
|
||||
void pic_remap() {
|
||||
uint8_t master_masks = io_in_byte(PIC_MASTER_DATA); io_wait();
|
||||
uint8_t slave_masks = io_in_byte(PIC_SLAVE_DATA); io_wait();
|
||||
|
||||
io_out_byte(PIC_MASTER_COMMAND, ICW1_INIT | ICW1_ICW4); io_wait();
|
||||
io_out_byte(PIC_SLAVE_COMMAND, ICW1_INIT | ICW1_ICW4); io_wait();
|
||||
|
||||
// set the IRQ offsets
|
||||
io_out_byte(PIC_MASTER_DATA, 0x20); io_wait();
|
||||
io_out_byte(PIC_SLAVE_DATA, 0x28); io_wait();
|
||||
|
||||
io_out_byte(PIC_MASTER_DATA, 4); io_wait();
|
||||
io_out_byte(PIC_SLAVE_DATA, 2); io_wait();
|
||||
|
||||
io_out_byte(PIC_MASTER_DATA, ICW4_8086); io_wait();
|
||||
io_out_byte(PIC_SLAVE_DATA, ICW4_8086); io_wait();
|
||||
|
||||
io_out_byte(PIC_MASTER_DATA, master_masks);
|
||||
io_out_byte(PIC_SLAVE_DATA, slave_masks);
|
||||
}
|
||||
|
||||
void pic_send_end_of_interrupt(pic_irq_E irq) {
|
||||
if (irq >= 8) {
|
||||
io_out_byte(PIC_SLAVE_COMMAND, PIC_END_OF_INTERRUPT);
|
||||
}
|
||||
io_out_byte(PIC_MASTER_COMMAND, PIC_END_OF_INTERRUPT);
|
||||
}
|
||||
|
||||
void pic_mask_irq(pic_irq_E irq) {
|
||||
uint16_t port = PIC_MASTER_DATA;
|
||||
|
||||
if (irq >= 8) {
|
||||
port = PIC_SLAVE_DATA;
|
||||
irq -= 8;
|
||||
}
|
||||
|
||||
uint8_t value = io_in_byte(port) | (1 << irq);
|
||||
io_out_byte(port, value);
|
||||
}
|
||||
|
||||
void pic_unmask_irq(pic_irq_E irq) {
|
||||
uint16_t port = PIC_MASTER_DATA;
|
||||
|
||||
if (irq >= 8) {
|
||||
port = PIC_SLAVE_DATA;
|
||||
irq -= 8;
|
||||
}
|
||||
|
||||
uint8_t value = io_in_byte(port) & ~(1 << irq);
|
||||
io_out_byte(port, value);
|
||||
}
|
||||
|
||||
cpu_state_T* irq_handle(cpu_state_T* state, pic_irq_E irq) {
|
||||
cpu_state_T* return_state = state;
|
||||
|
||||
switch (irq) {
|
||||
case IRQ_PIT: {
|
||||
log(LOG_DEBUG, "PIT -> Tick");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
log(LOG_WARNING, "Unhandled IRQ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pic_send_end_of_interrupt(irq);
|
||||
return return_state;
|
||||
}
|
||||
|
||||
cpu_state_T* interrupts_handle(cpu_state_T* state) {
|
||||
if (state->interrupt_id < EXCEPTIONS_ENUM_END) {
|
||||
return exception_handle(state);
|
||||
}
|
||||
|
||||
log(LOG_WARNING, "Non exception interrupt detected ID: 0x%xb", state->interrupt_id);
|
||||
if (state->interrupt_id < IRQ_MASTER_OFFSET + 0x10 && state->interrupt_id >= IRQ_MASTER_OFFSET) {
|
||||
return irq_handle(state, state->interrupt_id - IRQ_MASTER_OFFSET);
|
||||
}
|
||||
|
||||
log(LOG_WARNING, "Unhandled interrupt: 0x%xb", state->interrupt_id);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ interrupt_common_handler:
|
|||
call interrupts_handle
|
||||
mov rsp, rax
|
||||
|
||||
; load cpu_state
|
||||
; load page map
|
||||
pop rax
|
||||
mov cr3, rax
|
||||
|
||||
|
@ -91,3 +91,25 @@ interrupt_stub 0x1C
|
|||
interrupt_stub 0x1D
|
||||
interrupt_stub 0x1E
|
||||
interrupt_stub 0x1F
|
||||
|
||||
;IRQs
|
||||
interrupt_stub 0x20 ; PIT
|
||||
interrupt_stub 0x21 ; Keyboard
|
||||
interrupt_stub 0x22 ; Cascade
|
||||
interrupt_stub 0x23 ; COM2
|
||||
interrupt_stub 0x24 ; COM1
|
||||
interrupt_stub 0x25 ; LPT2
|
||||
interrupt_stub 0x26 ; Floppy
|
||||
interrupt_stub 0x27 ; Spurious
|
||||
|
||||
interrupt_stub 0x28 ; CMOS RTC
|
||||
interrupt_stub 0x29 ; Free 0
|
||||
interrupt_stub 0x2A ; Free 1
|
||||
interrupt_stub 0x2B ; Free 2
|
||||
interrupt_stub 0x2C ; PS/2 Mouse
|
||||
interrupt_stub 0x2D ; FPU
|
||||
interrupt_stub 0x2E ; Primary ATA
|
||||
interrupt_stub 0x2F ; Secondary ATA
|
||||
|
||||
; Custom
|
||||
interrupt_stub 0x80 ; Syscall
|
Loading…
Reference in New Issue