55 lines
1.8 KiB
Rust
55 lines
1.8 KiB
Rust
use crate::{
|
|
interrupts::{self, EoiGuard},
|
|
println, TASKING,
|
|
};
|
|
use spin::Mutex;
|
|
use x86_64::instructions::port::{Port, PortWriteOnly};
|
|
|
|
static DATA: Mutex<Port<u8>> = Mutex::new(Port::new(0x40));
|
|
static CMD: Mutex<PortWriteOnly<u8>> = Mutex::new(PortWriteOnly::new(0x43));
|
|
|
|
const MAX_FREQ: u32 = 1_193_180;
|
|
|
|
pub fn init(mut freq: u32) {
|
|
assert_ne!(freq, 0);
|
|
#[expect(
|
|
clippy::unwrap_used,
|
|
reason = "register_handler requires the interrupt number to be less than 16, which it is."
|
|
)]
|
|
interrupts::register_handler(0, handler).unwrap();
|
|
#[expect(clippy::arithmetic_side_effects, reason = "freq has been checked to not be 0")]
|
|
let mut div = MAX_FREQ / freq;
|
|
if div > 65535 {
|
|
println!("[PIT] Frequency of {}Hz too slow, min freq is 18 Hz", freq);
|
|
div = 65535;
|
|
freq = 18;
|
|
} else if div == 0 {
|
|
println!("[PIT] Frequency of {}Hz too fast, max freq is {} Hz", freq, MAX_FREQ);
|
|
div = 1;
|
|
freq = MAX_FREQ;
|
|
}
|
|
#[expect(
|
|
clippy::unwrap_used,
|
|
reason = "div has been checked to be in u16 range above, so this cannot panic"
|
|
)]
|
|
let div_bytes = u16::try_from(div).unwrap().to_le_bytes();
|
|
|
|
println!("[PIT] Setting PIT to {}Hz with divisor of {}", freq, div);
|
|
// Command breakdown (MSB to LSB):
|
|
// 00 - Channel 0
|
|
// 11 - lobyte/hibyte access mode - set both bytes in one command
|
|
// 011 - Mode 3, sqaure wave generator at frequency MAX_FREQ/div, generates interrupts at that
|
|
// frequency
|
|
// 0 - binary mode, always used
|
|
unsafe { CMD.lock().write(0b0011_0110_u8) };
|
|
unsafe { DATA.lock().write(div_bytes[0]) };
|
|
unsafe { DATA.lock().write(div_bytes[1]) };
|
|
}
|
|
|
|
fn handler(_irq: u8, eoi_guard: EoiGuard) {
|
|
drop(eoi_guard);
|
|
if TASKING.ok_to_yield() {
|
|
TASKING.task_yield();
|
|
}
|
|
}
|