1use log::{trace, warn};
2use std::error::Error;
3use std::fs::File;
4
5use memmap::{Mmap, MmapMut};
6
7use crate::constant::*;
8
9pub const SIZEOF_U32: usize = 4;
10
11#[derive(Debug, Copy, Clone)]
12pub struct RegisterError {}
13
14pub fn map_physical_mem_read(
15 addr_space: &str,
16 addr: u32,
17 len: usize,
18) -> Result<Mmap, Box<dyn Error>> {
19 let m = unsafe {
20 memmap::MmapOptions::new()
21 .offset(addr as u64)
22 .len(len)
23 .map(&File::open(addr_space)?)?
24 };
25 Ok(m)
26}
27
28pub fn map_physical_mem_write(
29 addr_space: &str,
30 addr: u32,
31 len: usize,
32) -> Result<MmapMut, Box<dyn Error>> {
33 let m = unsafe {
34 memmap::MmapOptions::new()
35 .offset(addr as u64)
36 .len(len)
37 .map_mut(&File::options().read(true).write(true).open(addr_space)?)?
38 };
39 Ok(m)
40}
41
42pub fn read_control_reg(addr: u32) -> Result<u32, RegisterError>
43where
44 u32: std::fmt::LowerHex,
45{
46 let m = match map_physical_mem_read(RB_UIO0, addr, SIZEOF_U32) {
47 Ok(m) => m,
48 Err(err) => {
49 let error = RegisterError {};
50 warn!("Failed to mmap: Err={:?}", err);
51 return Err(error);
52 }
53 };
54 let p = m.as_ptr() as *const u32;
55 let value: u32;
56 unsafe {
57 value = std::ptr::read_volatile(p.offset(0));
58 }
59 Ok(value)
60}
61
62pub fn write_control_reg(addr: u32, data: u32) -> Result<(), RegisterError>
63where
64 u32: std::fmt::LowerHex,
65{
66 trace!("Attempting to write {data} at addr {addr}");
67
68 let m = match map_physical_mem_write(RB_UIO0, addr, SIZEOF_U32) {
69 Ok(m) => m,
70 Err(err) => {
71 let error = RegisterError {};
72 warn!("[write_control_reg] Failed to mmap: Err={:?}", err);
73 return Err(error);
74 }
75 };
76 let p = m.as_ptr() as *mut u32;
77 unsafe {
78 std::ptr::write_volatile(p.offset(0), data);
79 }
80 Ok(())
81}