Skip to content

Commit

Permalink
feat(hal-x86_64): add PIT driver (#355)
Browse files Browse the repository at this point in the history
This commit adds a driver for configuring the Intel 8253/8254
Programmable Interval Timer (PIT). We are currently using the PIT in
periodic mode as the system timer interrupt, but we aren't doing any
actual configuration of the PIT. In order to use the local APIC timer
instead, however, we need to be able to use the PIT to calibrate
the APIC timer, since the PIT has a known frequency, while the local
APIC frequency depends on the system's bus frequency.

Therefore, this branch adds the ability to set the PIT in oneshot mode,
and a method that spins until that interrupt fires. In addition, it adds
a method to set the PIT in periodic mode with a configurable duration.

This commit was factored out of PR #351 so that it can merge as a
separate commit.
  • Loading branch information
hawkw committed Oct 22, 2022
1 parent 30431a9 commit 9994cd5
Show file tree
Hide file tree
Showing 2 changed files with 407 additions and 3 deletions.
16 changes: 13 additions & 3 deletions hal-x86_64/src/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ use mycelium_util::{bits, fmt};

pub mod idt;
pub mod pic;
pub mod pit;

pub use idt::Idt;
pub use pic::CascadedPic;
pub use pit::PIT;

pub type Control = &'static mut Idt;

Expand Down Expand Up @@ -221,8 +223,16 @@ impl hal_core::interrupt::Control for Idt {
});
}

extern "x86-interrupt" fn timer_isr<H: Handlers<Registers>>(_regs: Registers) {
H::timer_tick();
extern "x86-interrupt" fn pit_timer_isr<H: Handlers<Registers>>(_regs: Registers) {
use core::sync::atomic::Ordering;
// if we weren't trying to do a PIT sleep, handle the timer tick
// instead.
let was_sleeping = pit::SLEEPING
.compare_exchange(true, false, Ordering::AcqRel, Ordering::Acquire)
.is_ok();
if !was_sleeping {
H::timer_tick();
}
unsafe {
PIC.end_interrupt(0x20);
}
Expand Down Expand Up @@ -360,7 +370,7 @@ impl hal_core::interrupt::Control for Idt {
Self::X87_FPU_EXCEPTION => fn x87_exn_isr("x87 Floating-Point Exception (0x10)"),
}

self.set_isr(0x20, timer_isr::<H> as *const ());
self.set_isr(0x20, pit_timer_isr::<H> as *const ());
self.set_isr(0x21, keyboard_isr::<H> as *const ());
self.set_isr(69, test_isr::<H> as *const ());
self.set_isr(Self::PAGE_FAULT, page_fault_isr::<H> as *const ());
Expand Down
Loading

0 comments on commit 9994cd5

Please sign in to comment.