aboutsummaryrefslogtreecommitdiff
path: root/src/arch/x86_64/interrupt/pit.rs
diff options
context:
space:
mode:
authorTianhao Wang <shrik3@mailbox.org>2024-06-11 15:06:33 +0200
committerTianhao Wang <shrik3@mailbox.org>2024-06-11 15:17:15 +0200
commit49fc3b6df25bea2aaccbe2b26735204e3ee4b809 (patch)
treed16c76f6c62c6e268434efc4945135d431cb3fc2 /src/arch/x86_64/interrupt/pit.rs
parente148a5e329add10452d86ae8f2da97e545b7ecb2 (diff)
dev: add x86 PIT (programmable interrupt timer)
Signed-off-by: Tianhao Wang <shrik3@mailbox.org>
Diffstat (limited to 'src/arch/x86_64/interrupt/pit.rs')
-rw-r--r--src/arch/x86_64/interrupt/pit.rs26
1 files changed, 26 insertions, 0 deletions
diff --git a/src/arch/x86_64/interrupt/pit.rs b/src/arch/x86_64/interrupt/pit.rs
index 8b13789..c1b7c45 100644
--- a/src/arch/x86_64/interrupt/pit.rs
+++ b/src/arch/x86_64/interrupt/pit.rs
@@ -1 +1,27 @@
+// x86 programmable interrupt timer
+// TODO there should be an machine level timer abstraction
+use crate::machine::device_io::IOPort;
+pub struct PIT {}
+impl PIT {
+ const CTRL_PORT: IOPort = IOPort::new(0x43);
+ const DATA_PORT: IOPort = IOPort::new(0x40);
+ const PIT_BASE_FREQ: u64 = 1193182;
+ // 1193182 Hz is roughly 838 ns
+ const PIT_BASE_NS: u64 = 838;
+ // max is around 54918 us (54 ms)
+ 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;
+ }
+ // TODO 65536 actually translates to 0
+ Self::CTRL_PORT.outb(0x34);
+ Self::DATA_PORT.outb((divider & 0xff) as u8);
+ Self::DATA_PORT.outb(((divider & 0xff00) >> 8) as u8);
+ return divider * Self::PIT_BASE_NS;
+ }
+}