use std::fs::{File, OpenOptions};
use std::io::{self};
#[cfg(unix)]
use std::os::unix::io::AsRawFd;
use std::ptr;
pub(crate) fn mmap_register(
address: u64,
map_size: usize,
) -> Result<(File, *mut u8, isize), String> {
let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) } as u64;
if page_size == 0 {
return Err("Could not determine system page size.".to_string());
}
let page_mask = !(page_size - 1);
let map_base = address & page_mask;
let register_offset = (address - map_base) as isize;
let file = match OpenOptions::new().read(true).write(true).open("/dev/mem") {
Ok(f) => f,
Err(_) => return Err("Failed to open /dev/mem. Check permissions.".to_string()),
};
let fd = file.as_raw_fd();
let map_ptr = unsafe {
libc::mmap(
ptr::null_mut(),
map_size,
libc::PROT_READ | libc::PROT_WRITE, libc::MAP_SHARED,
fd,
map_base as libc::off_t,
)
};
if map_ptr == libc::MAP_FAILED {
let err = io::Error::last_os_error();
return Err(format!("mmap failed: {}", err));
}
Ok((file, map_ptr as *mut u8, register_offset))
}
pub(crate) fn munmap_register(map_ptr: *mut u8, map_size: usize) {
unsafe {
libc::munmap(map_ptr as *mut libc::c_void, map_size);
}
}
pub(crate) fn read_u32_mapped(ptr: *mut u8, iface_offset: isize, reg_offset: u32) -> u32 {
let reg_ptr = unsafe { ptr.offset(iface_offset + reg_offset as isize) } as *const u32;
unsafe { std::ptr::read_volatile(reg_ptr) }
}
pub(crate) fn write_u32_mapped(ptr: *mut u8, iface_offset: isize, reg_offset: u32, value: u32) {
let reg_ptr = unsafe { ptr.offset(iface_offset + reg_offset as isize) } as *mut u32;
unsafe {
std::ptr::write_volatile(reg_ptr, value);
}
}