diff --git a/src/impl/kernel/main.c b/src/impl/kernel/main.c index 7be0660..e87b85f 100644 --- a/src/impl/kernel/main.c +++ b/src/impl/kernel/main.c @@ -4,6 +4,7 @@ #include "dt.h" #include "ps2.h" #include "rtc.h" +#include "pit.h" #include "sb16.h" MultibootInfo systemInfo; @@ -13,6 +14,9 @@ extern FBImage popcorn_logo; extern u16 popcorn_chime[]; extern u32 popcorn_chime_length; +static u8 s_pit_counter = 0; +static u8 s_swap_counter = 0; + void kernel_main(u32 magic, void *addr) { BIOSGreeting(); @@ -27,6 +31,7 @@ void kernel_main(u32 magic, void *addr) InitDescriptorTables(); RTCInit(); + PITInit(); // Initialize framebuffer and display greeting FBInit(systemInfo.framebufferWidth, systemInfo.framebufferHeight, (void *)systemInfo.framebufferAddress); @@ -34,10 +39,12 @@ void kernel_main(u32 magic, void *addr) FBBlit(systemInfo.framebufferWidth / 2 - popcorn_logo.width / 2, systemInfo.framebufferHeight / 2 - popcorn_logo.height / 2, &popcorn_logo); FBOutput(); + // As of right now this shuts down the emulator + // when ESC is pressed. PS2Init(); SB16Init(); - SB16DirectPlay(popcorn_chime, popcorn_chime_length); + // SB16DirectPlay(popcorn_chime, popcorn_chime_length); while (true) { diff --git a/src/impl/kernel/pit.c b/src/impl/kernel/pit.c new file mode 100644 index 0000000..985ad0f --- /dev/null +++ b/src/impl/kernel/pit.c @@ -0,0 +1,66 @@ +#include "pit.h" + +static ISRHandler s_pit_handler = NULL; + +void __pit_handler(registers_t reg) +{ + if (s_pit_handler != NULL) + s_pit_handler(reg); +} + +void __pit_cmd_tx(u8 cmd) +{ + outb(PIT_REG_COMMAND, cmd); +} + +void __pit_data_tx(u8 data, u8 counter) +{ + u8 port = (counter == PIT_OCW_COUNTER_0) ? PIT_REG_COUNTER0 : ((counter == PIT_OCW_COUNTER_1) ? PIT_REG_COUNTER1 : PIT_REG_COUNTER2); + outb(port, data); +} + +void __pit_start_counter(u32 freq, u8 counter, u8 mode) +{ + if (freq == 0) + return; + + BIOSPrintf("PIT counter %d stared with frequency %dHz\n", counter / 0x40, freq); + + uint16_t divisor = (uint16_t)(1193181 / (uint16_t)freq); + + // send operational command words + uint8_t ocw = 0; + ocw = (ocw & ~PIT_OCW_MASK_MODE) | mode; + ocw = (ocw & ~PIT_OCW_MASK_RL) | PIT_OCW_RL_DATA; + ocw = (ocw & ~PIT_OCW_MASK_COUNTER) | counter; + __pit_cmd_tx(ocw); + + // set frequency rate + __pit_data_tx(divisor & 0xff, 0); + __pit_data_tx((divisor >> 8) & 0xff, 0); +} + +void PITInit() +{ + BIOSPrintf("Initializing PIT...\n"); + + ISRRegisterHandler(IRQ_0, __pit_handler); + + __pit_start_counter(60, PIT_OCW_COUNTER_0, PIT_OCW_MODE_SQUAREWAVEGEN); + + BIOSPrintf("PIT initialized\n"); +} + +void PITAttach(ISRHandler handler) +{ + if (s_pit_handler != NULL) + { + BIOSPrint("Warning: PIT handler overwritten\n"); + } + s_pit_handler = handler; +} + +void PITDetach() +{ + s_pit_handler = NULL; +} diff --git a/src/intf/pit.h b/src/intf/pit.h new file mode 100644 index 0000000..16ee77c --- /dev/null +++ b/src/intf/pit.h @@ -0,0 +1,39 @@ +#pragma once + +#include "io.h" +#include "isr.h" + +// Defines borrowed from levos +// https://github.com/levex/osdev/blob/master/include/pit.h + +#define PIT_REG_COUNTER0 0x40 +#define PIT_REG_COUNTER1 0x41 +#define PIT_REG_COUNTER2 0x42 +#define PIT_REG_COMMAND 0x43 + +#define PIT_OCW_MASK_BINCOUNT 1 //00000001 +#define PIT_OCW_MASK_MODE 0xE //00001110 +#define PIT_OCW_MASK_RL 0x30 //00110000 +#define PIT_OCW_MASK_COUNTER 0xC0 //11000000 + +#define PIT_OCW_BINCOUNT_BINARY 0 //0 +#define PIT_OCW_BINCOUNT_BCD 1 //1 + +#define PIT_OCW_MODE_TERMINALCOUNT 0 //0000 +#define PIT_OCW_MODE_ONESHOT 0x2 //0010 +#define PIT_OCW_MODE_RATEGEN 0x4 //0100 +#define PIT_OCW_MODE_SQUAREWAVEGEN 0x6 //0110 +#define PIT_OCW_MODE_SOFTWARETRIG 0x8 //1000 +#define PIT_OCW_MODE_HARDWARETRIG 0xA //1010 + +#define PIT_OCW_RL_LATCH 0 //000000 +#define PIT_OCW_RL_LSBONLY 0x10 //010000 +#define PIT_OCW_RL_MSBONLY 0x20 //100000 +#define PIT_OCW_RL_DATA 0x30 //110000 + +#define PIT_OCW_COUNTER_0 0 //00000000 +#define PIT_OCW_COUNTER_1 0x40 //01000000 +#define PIT_OCW_COUNTER_2 0x80 //10000000 + +void PITInit(); +void PITAttach(ISRHandler); \ No newline at end of file