liftof_rb/
memory.rs

1//! On-board memory management for readoutboards
2//! 
3//! The DRS4 is able to map its registers and the 
4//! data buffer directly into OS memory.
5//!
6//! memory locations for the control 
7//! registers
8//! /dev/uio0 - DRS4 control
9//! /dev/uio1 - buffer 1 for blobs
10//! /dev/uio2 - buffer 2 for blobs
11
12extern crate memmap;
13
14use std::error::Error;
15use std::fs::File;
16use std::fmt;
17
18use memmap::{Mmap,
19             MmapMut};
20
21use std::ptr;
22
23use tof_dataclasses::io::RBEventMemoryStreamer;
24
25pub const UIO0 : &'static str = "/dev/uio0";
26pub const UIO1 : &'static str = "/dev/uio1";
27pub const UIO2 : &'static str = "/dev/uio2";
28
29/// Data buffer related constants
30/// The data buffer is /dev/uio1 
31/// and /dev/uio2 are internally
32/// a single buffer but with 2 halves.
33/// 
34/// Interestingly, there is a discrepancy 
35/// between the dma_reset when it writes
36/// 68176064
37pub const DATABUF_TOTAL_SIZE : usize = 66524928;
38pub const EVENT_SIZE         : usize = 18530; 
39//pub const UIO1_MIN_OCCUPANCY : u32 = 68176064;
40pub const UIO1_MIN_OCCUPANCY : u32 = 68157440;
41pub const UIO2_MIN_OCCUPANCY : u32 = 135266304;
42
43pub const UIO1_MAX_OCCUPANCY : u32 = 117089408;
44pub const UIO2_MAX_OCCUPANCY : u32 = 201788800;
45
46/// The size of a 32bit unsigned int in byte
47/// (all words in registers are u32)
48pub const SIZEOF_U32 : usize = 4;
49
50
51#[derive(Debug, Copy, Clone)]
52pub enum RegisterError {
53  RegisterTimeOut,
54  MMapFail,
55  Unknown,
56}
57
58impl fmt::Display for RegisterError {
59  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
60    let etype : String;
61    match self {
62      RegisterError::RegisterTimeOut => {
63        etype = String::from("RegisterTimeOut");
64      },
65      RegisterError::Unknown => {
66        etype = String::from("Unknown");
67      },
68      _ => {
69        etype = String::from("not defined");
70      }
71    }
72    write!(f, "<RegisterError: {}>", etype)
73  }
74}
75
76impl Error for RegisterError {
77}
78
79
80///! There are 2 data buffers, commonly 
81///  denoted as "A" and "B".
82///  A -> /dev/uio1
83///  B -> /dev/uio2
84#[derive(Debug, Copy, Clone)]
85pub enum RamBuffer {
86  A,
87  B,
88  //Both
89}
90
91impl RamBuffer {
92  pub fn invert(&self) -> RamBuffer {
93    match self {
94      RamBuffer::A => {return RamBuffer::B},
95      RamBuffer::B => {return RamBuffer::A}
96    }
97  }
98}
99
100/// Get a size which accomodates nevents
101///
102/// This means if the given size is too small
103/// make sure that at least the whole next
104/// event "fits in"
105pub fn size_in_events(size : usize) -> usize {
106  size/EVENT_SIZE
107}
108
109/// Allow READ access to the memory registers at /dev/uio**
110///
111/// Remember we have a 32bit system
112///
113///
114pub fn map_physical_mem_read(addr_space : &str,
115                             addr: u32,
116                             len: usize) -> Result<Mmap, Box<dyn Error>> {
117  let m = unsafe {
118    memmap::MmapOptions::new()
119      .offset(addr as u64)
120      .len(len)
121      .map(&File::open(addr_space)?)?
122    };
123  Ok(m)
124}
125
126/// Allow WRITE access to the memory registers at /dev/uio0
127/// 
128/// Write control registers.
129/// Remember we have a 32bit system
130///
131/// # Arguments
132///
133/// addr : The memory address (address8) the register
134///        is mapped to.
135///
136///
137pub fn map_physical_mem_write(addr_space : &str,
138                              addr       : u32,
139                              len        : usize)
140  -> Result<MmapMut, Box<dyn Error>> {
141  let m = unsafe {
142    memmap::MmapOptions::new()
143      .offset(addr as u64)
144      .len(len)
145      .map_mut(&File::options()
146        .read(true)
147        .write(true)
148        .open(addr_space)?)?
149    };
150  Ok(m)
151}
152
153///! Get a single value from a 32bit (1 word) register
154///  This reads ONLY control registers 
155///  (in /dev/uio0)
156///  
157///  # Arguments:
158///
159///  * addr : The addr8 of the register 
160///           in /dev/uio0
161/// 
162pub fn read_control_reg(addr : u32) 
163  -> Result<u32, RegisterError> 
164  where
165    u32: std::fmt::LowerHex, {
166  
167  //let sz = std::mem::size_of::<u32>();
168  let m = match map_physical_mem_read(UIO0, addr, SIZEOF_U32) {
169    Ok(m) => m,
170    Err(err) => {
171      error!("Failed to mmap: {:?}", err);
172      return Err(RegisterError::MMapFail);
173    }
174  };
175  let p = m.as_ptr() as *const u32;
176  let value : u32;
177  unsafe {
178    value = std::ptr::read_volatile(p.offset(0));
179  }
180  Ok(value)
181}
182
183/// 
184pub fn write_control_reg(addr       : u32,
185                         data       : u32) 
186  -> Result<(), RegisterError> 
187  where
188    u32: std::fmt::LowerHex, {
189  
190  trace!("Attempting to write {data} at addr {addr}");
191  //let sz = std::mem::size_of::<u32>();
192  let m = match map_physical_mem_write(UIO0,addr,SIZEOF_U32) {
193    Ok(m) => m,
194    Err(err) => {
195      warn!("[write_control_reg] Failed to mmap! {:?}", err);
196      return Err(RegisterError::MMapFail);
197    }
198  };
199  let p = m.as_ptr() as *mut u32;
200  unsafe {
201    std::ptr::write_volatile(p.offset(0), data);
202  }
203  Ok(())
204}
205
206
207///  Read one of the data buffers and return a bytestream 
208///  from the given address with the length in events.
209///  
210///  # Arguments
211///
212///  * which : Select data buffer to read 
213///  * size  : in bytes
214///
215pub fn read_data_buffer(which : &RamBuffer, 
216                        size  : usize)
217    -> Result<Vec::<u8>, RegisterError> 
218  where
219    u32: std::fmt::LowerHex, {
220
221  let addr_space;
222  match which {
223    RamBuffer::A => addr_space = UIO1,
224    RamBuffer::B => addr_space = UIO2
225  }
226  //let blobsize = BlobData::SERIALIZED_SIZE;
227  //let vec_size = blobsize*len;
228  // FIXME - allocate the vector elsewhere and 
229  // pass it by reference
230  let mut bytestream = Vec::<u8>::with_capacity(size);
231  let m = match map_physical_mem_read(addr_space, 0x0, size) {
232  //let mut m = match map_physical_mem_write(addr_space, 0x0, size) {
233    Ok(m) => m,
234    Err(err) => {
235      //let error = RegisterError {};
236      warn!("Failed to mmap! {:?}", err);
237      return Err(RegisterError::MMapFail);
238    }
239  };
240 
241  //ptr::slice_from_raw_parts(raw_pointer, 3) 
242
243  let p = m.as_ptr() as *const u8;
244  //let p = m.as_mut_ptr() as *mut u8;
245  let slice = ptr::slice_from_raw_parts(p, size);
246  unsafe {
247    //bytestream  = Vec::<u8>::from_raw_parts(p, size, size);
248    bytestream.extend_from_slice(&*slice); 
249  }
250  Ok(bytestream)
251}
252
253///  Read a data buffer directly into a RBEventMemory streamer,
254///  avoiding the detour over vector.extend (which performs 
255///  clones), so this *should* actually be much more efficient.
256///
257///  # Arguments
258///     * which    : Select data buffer to read 
259///     * size     : in bytes
260///     * streamer : an instance of a RBEventMemoryStreamer
261pub fn read_buffer_into_streamer(which    : &RamBuffer, 
262                                 size     : usize,
263                                 streamer : &mut RBEventMemoryStreamer)
264    -> Result<(), RegisterError> 
265  where
266    u32: std::fmt::LowerHex, {
267
268  let addr_space;
269  match which {
270    RamBuffer::A => addr_space = UIO1,
271    RamBuffer::B => addr_space = UIO2
272  }
273  let m = match map_physical_mem_read(addr_space, 0x0, size) {
274  //let mut m = match map_physical_mem_write(addr_space, 0x0, size) {
275    Ok(m) => m,
276    Err(err) => {
277      warn!("Failed to mmap: {:?}", err);
278      return Err(RegisterError::MMapFail);
279    }
280  };
281  let p = m.as_ptr() as *const u8;
282  //println!("Trying to get slice from raw parts");
283  let slice = ptr::slice_from_raw_parts(p, size);
284  //let mut bytestream : Vec::<u8>;
285  let mut bytestream = Vec::<u8>::with_capacity(200000);
286  println!("Trying to get bytestream from raw parts!");
287  unsafe {
288    //bytestream = Vec::from_raw_parts(p as *mut u8, size, size);
289    bytestream.extend_from_slice(&*slice); 
290  }
291  streamer.consume(&mut bytestream);
292  println!(".. done!");
293  //Ok(bytestream)
294  Ok(())
295}
296
297