2022-12-07 02:41:18 +02:00
|
|
|
#include <kernel/IDT.h>
|
2023-01-23 20:13:57 +02:00
|
|
|
#include <kernel/InterruptController.h>
|
2022-12-07 02:41:18 +02:00
|
|
|
#include <kernel/IO.h>
|
2023-02-01 01:53:35 +02:00
|
|
|
#include <kernel/Scheduler.h>
|
2023-08-04 10:22:20 +03:00
|
|
|
#include <kernel/Timer/PIT.h>
|
2022-12-07 02:41:18 +02:00
|
|
|
|
|
|
|
#define TIMER0_CTL 0x40
|
|
|
|
#define TIMER1_CTL 0x41
|
|
|
|
#define TIMER2_CTL 0x42
|
|
|
|
#define PIT_CTL 0x43
|
|
|
|
|
|
|
|
#define SELECT_CHANNEL0 0x00
|
|
|
|
#define SELECT_CHANNEL1 0x40
|
|
|
|
#define SELECT_CHANNEL2 0x80
|
|
|
|
|
|
|
|
#define ACCESS_HI 0x10
|
|
|
|
#define ACCESS_LO 0x20
|
|
|
|
|
|
|
|
#define MODE_SQUARE_WAVE 0x06
|
|
|
|
|
|
|
|
#define BASE_FREQUENCY 1193182
|
|
|
|
#define TICKS_PER_SECOND 1000
|
|
|
|
|
2023-08-04 15:44:32 +03:00
|
|
|
#define MS_PER_S 1'000
|
|
|
|
#define NS_PER_S 1'000'000'000
|
|
|
|
|
2023-08-04 10:22:20 +03:00
|
|
|
namespace Kernel
|
2022-12-07 02:41:18 +02:00
|
|
|
{
|
2023-03-07 19:17:49 +02:00
|
|
|
|
2023-03-07 23:22:25 +02:00
|
|
|
static volatile uint64_t s_system_time = 0;
|
2022-12-07 02:41:18 +02:00
|
|
|
|
2023-02-01 01:53:35 +02:00
|
|
|
void irq_handler()
|
2022-12-07 02:41:18 +02:00
|
|
|
{
|
2023-03-07 23:22:25 +02:00
|
|
|
s_system_time = s_system_time + 1;
|
2023-06-09 00:41:43 +03:00
|
|
|
Kernel::Scheduler::get().timer_reschedule();
|
2022-12-07 02:41:18 +02:00
|
|
|
}
|
|
|
|
|
2023-08-04 10:22:20 +03:00
|
|
|
BAN::ErrorOr<BAN::UniqPtr<PIT>> PIT::create()
|
2022-12-07 02:41:18 +02:00
|
|
|
{
|
2023-08-04 15:44:32 +03:00
|
|
|
PIT* pit = new PIT();
|
2023-08-04 10:22:20 +03:00
|
|
|
if (pit == nullptr)
|
|
|
|
return BAN::Error::from_errno(ENOMEM);
|
|
|
|
pit->initialize();
|
|
|
|
return BAN::UniqPtr<PIT>::adopt(pit);
|
2022-12-07 02:41:18 +02:00
|
|
|
}
|
|
|
|
|
2023-08-04 10:22:20 +03:00
|
|
|
void PIT::initialize()
|
2022-12-07 02:41:18 +02:00
|
|
|
{
|
|
|
|
constexpr uint16_t timer_reload = BASE_FREQUENCY / TICKS_PER_SECOND;
|
2023-09-09 22:52:03 +03:00
|
|
|
|
2022-12-07 02:41:18 +02:00
|
|
|
IO::outb(PIT_CTL, SELECT_CHANNEL0 | ACCESS_LO | ACCESS_HI | MODE_SQUARE_WAVE);
|
|
|
|
|
|
|
|
IO::outb(TIMER0_CTL, (timer_reload >> 0) & 0xff);
|
|
|
|
IO::outb(TIMER0_CTL, (timer_reload >> 8) & 0xff);
|
|
|
|
|
2023-02-01 01:53:35 +02:00
|
|
|
IDT::register_irq_handler(PIT_IRQ, irq_handler);
|
2022-12-07 02:41:18 +02:00
|
|
|
|
2023-02-01 21:05:44 +02:00
|
|
|
InterruptController::get().enable_irq(PIT_IRQ);
|
2022-12-07 02:41:18 +02:00
|
|
|
}
|
|
|
|
|
2023-08-04 10:22:20 +03:00
|
|
|
uint64_t PIT::ms_since_boot() const
|
|
|
|
{
|
2023-08-04 15:44:32 +03:00
|
|
|
return s_system_time * (MS_PER_S / TICKS_PER_SECOND);
|
|
|
|
}
|
|
|
|
|
|
|
|
timespec PIT::time_since_boot() const
|
|
|
|
{
|
|
|
|
uint64_t ticks = s_system_time;
|
|
|
|
return timespec {
|
|
|
|
.tv_sec = ticks / TICKS_PER_SECOND,
|
|
|
|
.tv_nsec = (long)((ticks % TICKS_PER_SECOND) * (NS_PER_S / TICKS_PER_SECOND))
|
|
|
|
};
|
2023-08-04 10:22:20 +03:00
|
|
|
}
|
|
|
|
|
2022-12-07 02:41:18 +02:00
|
|
|
}
|