From 491f9d0d4a9367da00422a84a570e3c12a7d5ddf Mon Sep 17 00:00:00 2001 From: WangRunji Date: Tue, 17 Apr 2018 21:34:36 +0800 Subject: [PATCH] PIT working --- src/arch/x86_64/driver/mod.rs | 2 ++ src/arch/x86_64/driver/pit.rs | 43 ++++++++++++++++++++++++++++++++ src/arch/x86_64/interrupt/irq.rs | 10 +++++++- 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 src/arch/x86_64/driver/pit.rs diff --git a/src/arch/x86_64/driver/mod.rs b/src/arch/x86_64/driver/mod.rs index f36812d..5535ab8 100644 --- a/src/arch/x86_64/driver/mod.rs +++ b/src/arch/x86_64/driver/mod.rs @@ -5,6 +5,7 @@ pub mod mp; pub mod serial; pub mod pic; pub mod keyboard; +pub mod pit; pub fn init(mut page_map: F) where F: FnMut(usize) { @@ -31,6 +32,7 @@ pub fn init(mut page_map: F) } else { pic::init(); } + pit::init(); serial::init(); keyboard::init(); } \ No newline at end of file diff --git a/src/arch/x86_64/driver/pit.rs b/src/arch/x86_64/driver/pit.rs new file mode 100644 index 0000000..c151095 --- /dev/null +++ b/src/arch/x86_64/driver/pit.rs @@ -0,0 +1,43 @@ +use syscall::io::{Io, Pio}; + +static mut PIT: Pit = Pit::new(0x40); + +pub fn init() { + assert_has_not_been_called!("pit::init must be called only once"); + unsafe{ PIT.init(100); } + debug!("pit: init end"); +} + +struct Pit { + chan0: Pio, + chan1: Pio, + chan2: Pio, + command: Pio, +} + +impl Pit { + const fn new(port: u16) -> Self { + Pit { + chan0: Pio::new(port), + chan1: Pio::new(port+1), + chan2: Pio::new(port+2), + command: Pio::new(port+3), + } + } + pub fn init(&mut self, freq: u32) { + self.command.write(TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); + let div = Pit::divisor(freq); + self.chan0.write((div & 0xFF) as u8); + self.chan0.write((div >> 8) as u8); + } + fn divisor(freq: u32) -> u16 { + let div = (TIMER_FREQ + freq / 2) / freq; + assert!(div < 0x10000); + div as u16 + } +} + +const TIMER_FREQ : u32 = 1193182; +const TIMER_SEL0 : u8 = 0x00; // select counter 0 +const TIMER_RATEGEN : u8 = 0x04; // mode 2, rate generator +const TIMER_16BIT : u8 = 0x30; // r/w counter 16 bits, LSB first \ No newline at end of file diff --git a/src/arch/x86_64/interrupt/irq.rs b/src/arch/x86_64/interrupt/irq.rs index 0780344..087e3d1 100644 --- a/src/arch/x86_64/interrupt/irq.rs +++ b/src/arch/x86_64/interrupt/irq.rs @@ -55,9 +55,17 @@ pub extern "x86-interrupt" fn com2_handler( ack(IRQ_COM2); } +use spin::Mutex; +static TICK: Mutex = Mutex::new(0); + pub extern "x86-interrupt" fn timer_handler( stack_frame: &mut ExceptionStackFrame) { -// println!("\nInterupt: Timer \n{:#?}", stack_frame); + let mut tick = TICK.lock(); + *tick += 1; + let tick = *tick; + if tick % 100 == 0 { + println!("\nInterupt: Timer\ntick = {}", tick); + } ack(IRQ_TIMER); } \ No newline at end of file