//! Device registers. Devices are reached at their physical address while //! the MMU is off; once paging.rs has mapped them into the higher half too, //! `use_high_half` makes every driver go through that mapping instead (the //! identity mapping stays, so nothing breaks in between). use core::sync::atomic::{AtomicU64, Ordering}; static OFFSET: AtomicU64 = AtomicU64::new(0); /// From now on reach devices at `phys + offset` (paging::HIGH_BASE). pub fn use_high_half(offset: u64) { OFFSET.store(offset, Ordering::SeqCst); } /// Where the CPU reaches physical address `phys` right now. pub fn virt(phys: usize) -> usize { phys.wrapping_add(OFFSET.load(Ordering::Relaxed) as usize) } pub fn read32(phys: usize) -> u32 { unsafe { core::ptr::read_volatile(virt(phys) as *const u32) } } pub fn write32(phys: usize, value: u32) { unsafe { core::ptr::write_volatile(virt(phys) as *mut u32, value) } } pub fn write8(phys: usize, value: u8) { unsafe { core::ptr::write_volatile(virt(phys) as *mut u8, value) } }