kernel/src/pit.rs

43 lines
1.4 KiB
Rust
Raw Normal View History

2022-11-01 07:24:50 -05:00
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) {
interrupts::register_handler(0, handler).unwrap();
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;
}
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 & 0xFF) as u8) };
unsafe { DATA.lock().write(((div >> 8) & 0xFF) as u8) };
}
fn handler(_irq: u8, eoi_guard: EoiGuard) {
drop(eoi_guard);
if let Some(mut tasking) = TASKING.try_lock() {
tasking.task_yield();
}
}