rustubs/arch/x86_64/interrupt/
pit.rsuse crate::machine::device_io::IOPort;
use crate::machine::time;
use crate::proc::sched::SET_NEED_RESCHEDULE;
use crate::proc::sync::bellringer::BellRinger;
use crate::proc::sync::IRQHandlerEpilogue;
use crate::proc::task::Task;
pub struct PIT {}
impl PIT {
const CTRL_PORT: IOPort = IOPort::new(0x43);
const DATA_PORT: IOPort = IOPort::new(0x40);
const PIT_BASE_NS: u64 = 838;
pub fn set_interval(us: u64) -> u64 {
let mut divider =
(us * 1000 + Self::PIT_BASE_NS / 2) / Self::PIT_BASE_NS;
if divider == 0 {
panic!("how on earth can you make a zero divider?")
}
if divider >= 65535 {
divider = 65535;
}
Self::CTRL_PORT.outb(0x34);
Self::DATA_PORT.outb((divider & 0xff) as u8);
Self::DATA_PORT.outb(((divider & 0xff00) >> 8) as u8);
divider * Self::PIT_BASE_NS
}
}
impl IRQHandlerEpilogue for PIT {
unsafe fn do_prologue() {
time::tick();
let _task = Task::current();
if _task.is_none() {
return;
}
let _ = SET_NEED_RESCHEDULE();
}
unsafe fn do_epilogue() { BellRinger::check_all(); }
}