xref: /aosp_15_r20/external/crosvm/devices/src/register_space/register.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2018 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::boxed::Box;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp::max;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp::min;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp::Ord;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp::Ordering;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp::PartialOrd;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::size_of;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::MutexGuard;
14*bb4ee6a4SAndroid Build Coastguard Worker 
15*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
16*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
17*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::AsBytes;
18*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromBytes;
19*bb4ee6a4SAndroid Build Coastguard Worker 
20*bb4ee6a4SAndroid Build Coastguard Worker /// Type of offset in the register space.
21*bb4ee6a4SAndroid Build Coastguard Worker pub type RegisterOffset = u64;
22*bb4ee6a4SAndroid Build Coastguard Worker 
23*bb4ee6a4SAndroid Build Coastguard Worker /// This represents a range of memory in the register space starting.
24*bb4ee6a4SAndroid Build Coastguard Worker /// Both from and to are inclusive.
25*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Eq, PartialEq, Copy, Clone)]
26*bb4ee6a4SAndroid Build Coastguard Worker pub struct RegisterRange {
27*bb4ee6a4SAndroid Build Coastguard Worker     pub from: RegisterOffset,
28*bb4ee6a4SAndroid Build Coastguard Worker     pub to: RegisterOffset,
29*bb4ee6a4SAndroid Build Coastguard Worker }
30*bb4ee6a4SAndroid Build Coastguard Worker 
31*bb4ee6a4SAndroid Build Coastguard Worker impl Ord for RegisterRange {
cmp(&self, other: &RegisterRange) -> Ordering32*bb4ee6a4SAndroid Build Coastguard Worker     fn cmp(&self, other: &RegisterRange) -> Ordering {
33*bb4ee6a4SAndroid Build Coastguard Worker         self.from.cmp(&other.from)
34*bb4ee6a4SAndroid Build Coastguard Worker     }
35*bb4ee6a4SAndroid Build Coastguard Worker }
36*bb4ee6a4SAndroid Build Coastguard Worker 
37*bb4ee6a4SAndroid Build Coastguard Worker impl PartialOrd for RegisterRange {
partial_cmp(&self, other: &RegisterRange) -> Option<Ordering>38*bb4ee6a4SAndroid Build Coastguard Worker     fn partial_cmp(&self, other: &RegisterRange) -> Option<Ordering> {
39*bb4ee6a4SAndroid Build Coastguard Worker         Some(self.cmp(other))
40*bb4ee6a4SAndroid Build Coastguard Worker     }
41*bb4ee6a4SAndroid Build Coastguard Worker }
42*bb4ee6a4SAndroid Build Coastguard Worker 
43*bb4ee6a4SAndroid Build Coastguard Worker impl RegisterRange {
44*bb4ee6a4SAndroid Build Coastguard Worker     /// Return true if those range overlaps.
overlap_with(&self, other: &RegisterRange) -> bool45*bb4ee6a4SAndroid Build Coastguard Worker     pub fn overlap_with(&self, other: &RegisterRange) -> bool {
46*bb4ee6a4SAndroid Build Coastguard Worker         !(self.from > other.to || self.to < other.from)
47*bb4ee6a4SAndroid Build Coastguard Worker     }
48*bb4ee6a4SAndroid Build Coastguard Worker 
49*bb4ee6a4SAndroid Build Coastguard Worker     /// Get the overlapping part of two RegisterRange.
50*bb4ee6a4SAndroid Build Coastguard Worker     /// Return is Option(overlap_from, overlap_to).
51*bb4ee6a4SAndroid Build Coastguard Worker     /// For example, (4,7).overlap_range(5, 8) will be Some(5, 7).
overlap_range(&self, other: &RegisterRange) -> Option<RegisterRange>52*bb4ee6a4SAndroid Build Coastguard Worker     pub fn overlap_range(&self, other: &RegisterRange) -> Option<RegisterRange> {
53*bb4ee6a4SAndroid Build Coastguard Worker         if !self.overlap_with(other) {
54*bb4ee6a4SAndroid Build Coastguard Worker             return None;
55*bb4ee6a4SAndroid Build Coastguard Worker         }
56*bb4ee6a4SAndroid Build Coastguard Worker         Some(RegisterRange {
57*bb4ee6a4SAndroid Build Coastguard Worker             from: max(self.from, other.from),
58*bb4ee6a4SAndroid Build Coastguard Worker             to: min(self.to, other.to),
59*bb4ee6a4SAndroid Build Coastguard Worker         })
60*bb4ee6a4SAndroid Build Coastguard Worker     }
61*bb4ee6a4SAndroid Build Coastguard Worker }
62*bb4ee6a4SAndroid Build Coastguard Worker 
63*bb4ee6a4SAndroid Build Coastguard Worker /// RegisterValue trait should be satisfied by register value types.
64*bb4ee6a4SAndroid Build Coastguard Worker pub trait RegisterValue:
65*bb4ee6a4SAndroid Build Coastguard Worker     'static
66*bb4ee6a4SAndroid Build Coastguard Worker     + Into<u64>
67*bb4ee6a4SAndroid Build Coastguard Worker     + Clone
68*bb4ee6a4SAndroid Build Coastguard Worker     + AsBytes
69*bb4ee6a4SAndroid Build Coastguard Worker     + FromBytes
70*bb4ee6a4SAndroid Build Coastguard Worker     + Send
71*bb4ee6a4SAndroid Build Coastguard Worker     + Sync
72*bb4ee6a4SAndroid Build Coastguard Worker     + Copy
73*bb4ee6a4SAndroid Build Coastguard Worker     + std::ops::BitOr<Self, Output = Self>
74*bb4ee6a4SAndroid Build Coastguard Worker     + std::ops::BitAnd<Self, Output = Self>
75*bb4ee6a4SAndroid Build Coastguard Worker     + std::ops::Not<Output = Self>
76*bb4ee6a4SAndroid Build Coastguard Worker     + std::fmt::LowerHex
77*bb4ee6a4SAndroid Build Coastguard Worker {
78*bb4ee6a4SAndroid Build Coastguard Worker     // Get byte of the offset.
get_byte(&self, offset: usize) -> u879*bb4ee6a4SAndroid Build Coastguard Worker     fn get_byte(&self, offset: usize) -> u8 {
80*bb4ee6a4SAndroid Build Coastguard Worker         let val: u64 = (*self).into();
81*bb4ee6a4SAndroid Build Coastguard Worker         (val >> (offset * 8)) as u8
82*bb4ee6a4SAndroid Build Coastguard Worker     }
83*bb4ee6a4SAndroid Build Coastguard Worker     // Set masked bits.
set_bits(&mut self, mask: Self)84*bb4ee6a4SAndroid Build Coastguard Worker     fn set_bits(&mut self, mask: Self) {
85*bb4ee6a4SAndroid Build Coastguard Worker         *self = *self | mask;
86*bb4ee6a4SAndroid Build Coastguard Worker     }
87*bb4ee6a4SAndroid Build Coastguard Worker     // Clear masked bits.
clear_bits(&mut self, mask: Self)88*bb4ee6a4SAndroid Build Coastguard Worker     fn clear_bits(&mut self, mask: Self) {
89*bb4ee6a4SAndroid Build Coastguard Worker         *self = *self & (!mask);
90*bb4ee6a4SAndroid Build Coastguard Worker     }
91*bb4ee6a4SAndroid Build Coastguard Worker }
92*bb4ee6a4SAndroid Build Coastguard Worker impl RegisterValue for u8 {}
93*bb4ee6a4SAndroid Build Coastguard Worker impl RegisterValue for u16 {}
94*bb4ee6a4SAndroid Build Coastguard Worker impl RegisterValue for u32 {}
95*bb4ee6a4SAndroid Build Coastguard Worker impl RegisterValue for u64 {}
96*bb4ee6a4SAndroid Build Coastguard Worker 
97*bb4ee6a4SAndroid Build Coastguard Worker // Helper function to read a register. If the read range overlaps with value's range, it will load
98*bb4ee6a4SAndroid Build Coastguard Worker // corresponding bytes into data.
read_reg_helper<T: RegisterValue>( val: T, val_range: RegisterRange, addr: RegisterOffset, data: &mut [u8], )99*bb4ee6a4SAndroid Build Coastguard Worker fn read_reg_helper<T: RegisterValue>(
100*bb4ee6a4SAndroid Build Coastguard Worker     val: T,
101*bb4ee6a4SAndroid Build Coastguard Worker     val_range: RegisterRange,
102*bb4ee6a4SAndroid Build Coastguard Worker     addr: RegisterOffset,
103*bb4ee6a4SAndroid Build Coastguard Worker     data: &mut [u8],
104*bb4ee6a4SAndroid Build Coastguard Worker ) {
105*bb4ee6a4SAndroid Build Coastguard Worker     let read_range = RegisterRange {
106*bb4ee6a4SAndroid Build Coastguard Worker         from: addr,
107*bb4ee6a4SAndroid Build Coastguard Worker         to: addr + data.len() as u64 - 1,
108*bb4ee6a4SAndroid Build Coastguard Worker     };
109*bb4ee6a4SAndroid Build Coastguard Worker 
110*bb4ee6a4SAndroid Build Coastguard Worker     let overlap = match val_range.overlap_range(&read_range) {
111*bb4ee6a4SAndroid Build Coastguard Worker         Some(overlap) => overlap,
112*bb4ee6a4SAndroid Build Coastguard Worker         None => {
113*bb4ee6a4SAndroid Build Coastguard Worker             error!("calling read_reg_helper with non overlapping range. mmio_register might have a bug");
114*bb4ee6a4SAndroid Build Coastguard Worker             return;
115*bb4ee6a4SAndroid Build Coastguard Worker         }
116*bb4ee6a4SAndroid Build Coastguard Worker     };
117*bb4ee6a4SAndroid Build Coastguard Worker     let val_start_idx = (overlap.from - val_range.from) as usize;
118*bb4ee6a4SAndroid Build Coastguard Worker     let read_start_idx = (overlap.from - read_range.from) as usize;
119*bb4ee6a4SAndroid Build Coastguard Worker     let total_size = (overlap.to - overlap.from) as usize + 1;
120*bb4ee6a4SAndroid Build Coastguard Worker     for i in 0..total_size {
121*bb4ee6a4SAndroid Build Coastguard Worker         data[read_start_idx + i] = val.get_byte(val_start_idx + i);
122*bb4ee6a4SAndroid Build Coastguard Worker     }
123*bb4ee6a4SAndroid Build Coastguard Worker }
124*bb4ee6a4SAndroid Build Coastguard Worker 
125*bb4ee6a4SAndroid Build Coastguard Worker /// Interface for register, as seen by guest driver.
126*bb4ee6a4SAndroid Build Coastguard Worker pub trait RegisterInterface: Send {
127*bb4ee6a4SAndroid Build Coastguard Worker     /// Range of this register.
range(&self) -> RegisterRange128*bb4ee6a4SAndroid Build Coastguard Worker     fn range(&self) -> RegisterRange;
129*bb4ee6a4SAndroid Build Coastguard Worker     /// Handle read.
read(&self, addr: RegisterOffset, data: &mut [u8])130*bb4ee6a4SAndroid Build Coastguard Worker     fn read(&self, addr: RegisterOffset, data: &mut [u8]);
131*bb4ee6a4SAndroid Build Coastguard Worker     /// Handle write.
write(&self, _addr: RegisterOffset, _data: &[u8])132*bb4ee6a4SAndroid Build Coastguard Worker     fn write(&self, _addr: RegisterOffset, _data: &[u8]) {}
133*bb4ee6a4SAndroid Build Coastguard Worker     /// Reset this register to default value.
134*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(dead_code)]
reset(&self)135*bb4ee6a4SAndroid Build Coastguard Worker     fn reset(&self) {}
136*bb4ee6a4SAndroid Build Coastguard Worker }
137*bb4ee6a4SAndroid Build Coastguard Worker 
138*bb4ee6a4SAndroid Build Coastguard Worker // Spec for hardware init Read Only Registers.
139*bb4ee6a4SAndroid Build Coastguard Worker // The value of this register won't change.
140*bb4ee6a4SAndroid Build Coastguard Worker pub struct StaticRegisterSpec<T: RegisterValue> {
141*bb4ee6a4SAndroid Build Coastguard Worker     pub offset: RegisterOffset,
142*bb4ee6a4SAndroid Build Coastguard Worker     pub value: T,
143*bb4ee6a4SAndroid Build Coastguard Worker }
144*bb4ee6a4SAndroid Build Coastguard Worker 
145*bb4ee6a4SAndroid Build Coastguard Worker /// A static register is a register inited by hardware. The value won't change in it's lifetime.
146*bb4ee6a4SAndroid Build Coastguard Worker /// All functions implemented on this one is thread safe.
147*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone)]
148*bb4ee6a4SAndroid Build Coastguard Worker pub struct StaticRegister<T>
149*bb4ee6a4SAndroid Build Coastguard Worker where
150*bb4ee6a4SAndroid Build Coastguard Worker     T: RegisterValue,
151*bb4ee6a4SAndroid Build Coastguard Worker {
152*bb4ee6a4SAndroid Build Coastguard Worker     spec: &'static StaticRegisterSpec<T>,
153*bb4ee6a4SAndroid Build Coastguard Worker }
154*bb4ee6a4SAndroid Build Coastguard Worker 
155*bb4ee6a4SAndroid Build Coastguard Worker impl<T> StaticRegister<T>
156*bb4ee6a4SAndroid Build Coastguard Worker where
157*bb4ee6a4SAndroid Build Coastguard Worker     T: RegisterValue,
158*bb4ee6a4SAndroid Build Coastguard Worker {
159*bb4ee6a4SAndroid Build Coastguard Worker     /// Create an new static register from spec.
new(spec: &'static StaticRegisterSpec<T>) -> StaticRegister<T>160*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(spec: &'static StaticRegisterSpec<T>) -> StaticRegister<T> {
161*bb4ee6a4SAndroid Build Coastguard Worker         StaticRegister { spec }
162*bb4ee6a4SAndroid Build Coastguard Worker     }
163*bb4ee6a4SAndroid Build Coastguard Worker }
164*bb4ee6a4SAndroid Build Coastguard Worker 
165*bb4ee6a4SAndroid Build Coastguard Worker impl<T> RegisterInterface for StaticRegister<T>
166*bb4ee6a4SAndroid Build Coastguard Worker where
167*bb4ee6a4SAndroid Build Coastguard Worker     T: RegisterValue,
168*bb4ee6a4SAndroid Build Coastguard Worker {
range(&self) -> RegisterRange169*bb4ee6a4SAndroid Build Coastguard Worker     fn range(&self) -> RegisterRange {
170*bb4ee6a4SAndroid Build Coastguard Worker         RegisterRange {
171*bb4ee6a4SAndroid Build Coastguard Worker             from: self.spec.offset,
172*bb4ee6a4SAndroid Build Coastguard Worker             to: self.spec.offset + (size_of::<T>() as u64) - 1,
173*bb4ee6a4SAndroid Build Coastguard Worker         }
174*bb4ee6a4SAndroid Build Coastguard Worker     }
175*bb4ee6a4SAndroid Build Coastguard Worker 
read(&self, addr: RegisterOffset, data: &mut [u8])176*bb4ee6a4SAndroid Build Coastguard Worker     fn read(&self, addr: RegisterOffset, data: &mut [u8]) {
177*bb4ee6a4SAndroid Build Coastguard Worker         let val_range = self.range();
178*bb4ee6a4SAndroid Build Coastguard Worker         read_reg_helper(self.spec.value, val_range, addr, data);
179*bb4ee6a4SAndroid Build Coastguard Worker     }
180*bb4ee6a4SAndroid Build Coastguard Worker }
181*bb4ee6a4SAndroid Build Coastguard Worker 
182*bb4ee6a4SAndroid Build Coastguard Worker /// Macro helps to build a static register.
183*bb4ee6a4SAndroid Build Coastguard Worker #[macro_export]
184*bb4ee6a4SAndroid Build Coastguard Worker macro_rules! static_register {
185*bb4ee6a4SAndroid Build Coastguard Worker     (ty: $ty:ty,offset: $offset:expr,value: $value:expr,) => {{
186*bb4ee6a4SAndroid Build Coastguard Worker         use $crate::register_space::*;
187*bb4ee6a4SAndroid Build Coastguard Worker         static REG_SPEC: StaticRegisterSpec<$ty> = StaticRegisterSpec::<$ty> {
188*bb4ee6a4SAndroid Build Coastguard Worker             offset: $offset,
189*bb4ee6a4SAndroid Build Coastguard Worker             value: $value,
190*bb4ee6a4SAndroid Build Coastguard Worker         };
191*bb4ee6a4SAndroid Build Coastguard Worker         StaticRegister::new(&REG_SPEC)
192*bb4ee6a4SAndroid Build Coastguard Worker     }};
193*bb4ee6a4SAndroid Build Coastguard Worker }
194*bb4ee6a4SAndroid Build Coastguard Worker 
195*bb4ee6a4SAndroid Build Coastguard Worker /// Spec for a regular register. It specifies it's location on register space, guest writable mask
196*bb4ee6a4SAndroid Build Coastguard Worker /// and guest write to clear mask.
197*bb4ee6a4SAndroid Build Coastguard Worker pub struct RegisterSpec<T> {
198*bb4ee6a4SAndroid Build Coastguard Worker     pub name: String,
199*bb4ee6a4SAndroid Build Coastguard Worker     pub offset: RegisterOffset,
200*bb4ee6a4SAndroid Build Coastguard Worker     pub reset_value: T,
201*bb4ee6a4SAndroid Build Coastguard Worker     /// Only masked bits could be written by guest.
202*bb4ee6a4SAndroid Build Coastguard Worker     pub guest_writeable_mask: T,
203*bb4ee6a4SAndroid Build Coastguard Worker     /// When write 1 to bits masked, those bits will be cleared. See Xhci spec 5.1
204*bb4ee6a4SAndroid Build Coastguard Worker     /// for more details.
205*bb4ee6a4SAndroid Build Coastguard Worker     pub guest_write_1_to_clear_mask: T,
206*bb4ee6a4SAndroid Build Coastguard Worker }
207*bb4ee6a4SAndroid Build Coastguard Worker 
208*bb4ee6a4SAndroid Build Coastguard Worker struct RegisterInner<T: RegisterValue> {
209*bb4ee6a4SAndroid Build Coastguard Worker     spec: RegisterSpec<T>,
210*bb4ee6a4SAndroid Build Coastguard Worker     value: T,
211*bb4ee6a4SAndroid Build Coastguard Worker     write_cb: Option<Box<dyn Fn(T) -> T + Send>>,
212*bb4ee6a4SAndroid Build Coastguard Worker }
213*bb4ee6a4SAndroid Build Coastguard Worker 
214*bb4ee6a4SAndroid Build Coastguard Worker /// Register is a thread safe struct. It can be safely changed from any thread.
215*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone)]
216*bb4ee6a4SAndroid Build Coastguard Worker pub struct Register<T: RegisterValue> {
217*bb4ee6a4SAndroid Build Coastguard Worker     inner: Arc<Mutex<RegisterInner<T>>>,
218*bb4ee6a4SAndroid Build Coastguard Worker }
219*bb4ee6a4SAndroid Build Coastguard Worker 
220*bb4ee6a4SAndroid Build Coastguard Worker impl<T: RegisterValue> Register<T> {
new(spec: RegisterSpec<T>, val: T) -> Self221*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(spec: RegisterSpec<T>, val: T) -> Self {
222*bb4ee6a4SAndroid Build Coastguard Worker         Register {
223*bb4ee6a4SAndroid Build Coastguard Worker             inner: Arc::new(Mutex::new(RegisterInner {
224*bb4ee6a4SAndroid Build Coastguard Worker                 spec,
225*bb4ee6a4SAndroid Build Coastguard Worker                 value: val,
226*bb4ee6a4SAndroid Build Coastguard Worker                 write_cb: None,
227*bb4ee6a4SAndroid Build Coastguard Worker             })),
228*bb4ee6a4SAndroid Build Coastguard Worker         }
229*bb4ee6a4SAndroid Build Coastguard Worker     }
230*bb4ee6a4SAndroid Build Coastguard Worker 
lock(&self) -> MutexGuard<RegisterInner<T>>231*bb4ee6a4SAndroid Build Coastguard Worker     fn lock(&self) -> MutexGuard<RegisterInner<T>> {
232*bb4ee6a4SAndroid Build Coastguard Worker         self.inner.lock()
233*bb4ee6a4SAndroid Build Coastguard Worker     }
234*bb4ee6a4SAndroid Build Coastguard Worker }
235*bb4ee6a4SAndroid Build Coastguard Worker 
236*bb4ee6a4SAndroid Build Coastguard Worker // All functions implemented on this one is thread safe.
237*bb4ee6a4SAndroid Build Coastguard Worker impl<T: RegisterValue> RegisterInterface for Register<T> {
range(&self) -> RegisterRange238*bb4ee6a4SAndroid Build Coastguard Worker     fn range(&self) -> RegisterRange {
239*bb4ee6a4SAndroid Build Coastguard Worker         let locked = self.lock();
240*bb4ee6a4SAndroid Build Coastguard Worker         let spec = &locked.spec;
241*bb4ee6a4SAndroid Build Coastguard Worker         RegisterRange {
242*bb4ee6a4SAndroid Build Coastguard Worker             from: spec.offset,
243*bb4ee6a4SAndroid Build Coastguard Worker             to: spec.offset + (size_of::<T>() as u64) - 1,
244*bb4ee6a4SAndroid Build Coastguard Worker         }
245*bb4ee6a4SAndroid Build Coastguard Worker     }
246*bb4ee6a4SAndroid Build Coastguard Worker 
read(&self, addr: RegisterOffset, data: &mut [u8])247*bb4ee6a4SAndroid Build Coastguard Worker     fn read(&self, addr: RegisterOffset, data: &mut [u8]) {
248*bb4ee6a4SAndroid Build Coastguard Worker         let val_range = self.range();
249*bb4ee6a4SAndroid Build Coastguard Worker         let value = self.lock().value;
250*bb4ee6a4SAndroid Build Coastguard Worker         read_reg_helper(value, val_range, addr, data);
251*bb4ee6a4SAndroid Build Coastguard Worker     }
252*bb4ee6a4SAndroid Build Coastguard Worker 
write(&self, addr: RegisterOffset, data: &[u8])253*bb4ee6a4SAndroid Build Coastguard Worker     fn write(&self, addr: RegisterOffset, data: &[u8]) {
254*bb4ee6a4SAndroid Build Coastguard Worker         let my_range = self.range();
255*bb4ee6a4SAndroid Build Coastguard Worker         let write_range = RegisterRange {
256*bb4ee6a4SAndroid Build Coastguard Worker             from: addr,
257*bb4ee6a4SAndroid Build Coastguard Worker             to: addr + data.len() as u64 - 1,
258*bb4ee6a4SAndroid Build Coastguard Worker         };
259*bb4ee6a4SAndroid Build Coastguard Worker 
260*bb4ee6a4SAndroid Build Coastguard Worker         let overlap = match my_range.overlap_range(&write_range) {
261*bb4ee6a4SAndroid Build Coastguard Worker             Some(range) => range,
262*bb4ee6a4SAndroid Build Coastguard Worker             None => {
263*bb4ee6a4SAndroid Build Coastguard Worker                 error!("write should not be invoked on this register");
264*bb4ee6a4SAndroid Build Coastguard Worker                 return;
265*bb4ee6a4SAndroid Build Coastguard Worker             }
266*bb4ee6a4SAndroid Build Coastguard Worker         };
267*bb4ee6a4SAndroid Build Coastguard Worker         let my_start_idx = (overlap.from - my_range.from) as usize;
268*bb4ee6a4SAndroid Build Coastguard Worker         let write_start_idx = (overlap.from - write_range.from) as usize;
269*bb4ee6a4SAndroid Build Coastguard Worker         let total_size = (overlap.to - overlap.from) as usize + 1;
270*bb4ee6a4SAndroid Build Coastguard Worker 
271*bb4ee6a4SAndroid Build Coastguard Worker         let mut reg_value: T = self.lock().value;
272*bb4ee6a4SAndroid Build Coastguard Worker         let value: &mut [u8] = reg_value.as_bytes_mut();
273*bb4ee6a4SAndroid Build Coastguard Worker         for i in 0..total_size {
274*bb4ee6a4SAndroid Build Coastguard Worker             value[my_start_idx + i] = self.apply_write_masks_to_byte(
275*bb4ee6a4SAndroid Build Coastguard Worker                 value[my_start_idx + i],
276*bb4ee6a4SAndroid Build Coastguard Worker                 data[write_start_idx + i],
277*bb4ee6a4SAndroid Build Coastguard Worker                 my_start_idx + i,
278*bb4ee6a4SAndroid Build Coastguard Worker             );
279*bb4ee6a4SAndroid Build Coastguard Worker         }
280*bb4ee6a4SAndroid Build Coastguard Worker 
281*bb4ee6a4SAndroid Build Coastguard Worker         // A single u64 register is done by write to lower 32 bit and then higher 32 bit. Callback
282*bb4ee6a4SAndroid Build Coastguard Worker         // should only be invoked when higher is written.
283*bb4ee6a4SAndroid Build Coastguard Worker         if my_range.to != overlap.to {
284*bb4ee6a4SAndroid Build Coastguard Worker             self.lock().value = reg_value;
285*bb4ee6a4SAndroid Build Coastguard Worker             return;
286*bb4ee6a4SAndroid Build Coastguard Worker         }
287*bb4ee6a4SAndroid Build Coastguard Worker 
288*bb4ee6a4SAndroid Build Coastguard Worker         // Taking the callback out of register when executing it. This prevent dead lock if
289*bb4ee6a4SAndroid Build Coastguard Worker         // callback want to read current register value.
290*bb4ee6a4SAndroid Build Coastguard Worker         // Note that the only source of callback comes from mmio writing, which is synchronized.
291*bb4ee6a4SAndroid Build Coastguard Worker         let cb = {
292*bb4ee6a4SAndroid Build Coastguard Worker             let mut inner = self.lock();
293*bb4ee6a4SAndroid Build Coastguard Worker             match inner.write_cb.take() {
294*bb4ee6a4SAndroid Build Coastguard Worker                 Some(cb) => cb,
295*bb4ee6a4SAndroid Build Coastguard Worker                 None => {
296*bb4ee6a4SAndroid Build Coastguard Worker                     // Write value if there is no callback.
297*bb4ee6a4SAndroid Build Coastguard Worker                     inner.value = reg_value;
298*bb4ee6a4SAndroid Build Coastguard Worker                     return;
299*bb4ee6a4SAndroid Build Coastguard Worker                 }
300*bb4ee6a4SAndroid Build Coastguard Worker             }
301*bb4ee6a4SAndroid Build Coastguard Worker         };
302*bb4ee6a4SAndroid Build Coastguard Worker         // Callback is invoked without holding any lock.
303*bb4ee6a4SAndroid Build Coastguard Worker         let value = cb(reg_value);
304*bb4ee6a4SAndroid Build Coastguard Worker         let mut inner = self.lock();
305*bb4ee6a4SAndroid Build Coastguard Worker         inner.value = value;
306*bb4ee6a4SAndroid Build Coastguard Worker         inner.write_cb = Some(cb);
307*bb4ee6a4SAndroid Build Coastguard Worker     }
308*bb4ee6a4SAndroid Build Coastguard Worker 
reset(&self)309*bb4ee6a4SAndroid Build Coastguard Worker     fn reset(&self) {
310*bb4ee6a4SAndroid Build Coastguard Worker         let mut locked = self.lock();
311*bb4ee6a4SAndroid Build Coastguard Worker         locked.value = locked.spec.reset_value;
312*bb4ee6a4SAndroid Build Coastguard Worker     }
313*bb4ee6a4SAndroid Build Coastguard Worker }
314*bb4ee6a4SAndroid Build Coastguard Worker 
315*bb4ee6a4SAndroid Build Coastguard Worker impl<T: RegisterValue> Register<T> {
316*bb4ee6a4SAndroid Build Coastguard Worker     /// Get current value of this register.
get_value(&self) -> T317*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_value(&self) -> T {
318*bb4ee6a4SAndroid Build Coastguard Worker         self.lock().value
319*bb4ee6a4SAndroid Build Coastguard Worker     }
320*bb4ee6a4SAndroid Build Coastguard Worker 
321*bb4ee6a4SAndroid Build Coastguard Worker     /// This function apply "write 1 to clear mask" and "guest writeable mask".
322*bb4ee6a4SAndroid Build Coastguard Worker     /// All write operations should go through this, the result of this function
323*bb4ee6a4SAndroid Build Coastguard Worker     /// is the new state of correspoding byte.
apply_write_masks_to_byte(&self, old_byte: u8, write_byte: u8, offset: usize) -> u8324*bb4ee6a4SAndroid Build Coastguard Worker     pub fn apply_write_masks_to_byte(&self, old_byte: u8, write_byte: u8, offset: usize) -> u8 {
325*bb4ee6a4SAndroid Build Coastguard Worker         let locked = self.lock();
326*bb4ee6a4SAndroid Build Coastguard Worker         let spec = &locked.spec;
327*bb4ee6a4SAndroid Build Coastguard Worker         let guest_write_1_to_clear_mask: u64 = spec.guest_write_1_to_clear_mask.into();
328*bb4ee6a4SAndroid Build Coastguard Worker         let guest_writeable_mask: u64 = spec.guest_writeable_mask.into();
329*bb4ee6a4SAndroid Build Coastguard Worker         // Mask with w1c mask.
330*bb4ee6a4SAndroid Build Coastguard Worker         let w1c_mask = (guest_write_1_to_clear_mask >> (offset * 8)) as u8;
331*bb4ee6a4SAndroid Build Coastguard Worker         let val = (!w1c_mask & write_byte) | (w1c_mask & old_byte & !write_byte);
332*bb4ee6a4SAndroid Build Coastguard Worker         // Mask with writable mask.
333*bb4ee6a4SAndroid Build Coastguard Worker         let w_mask = (guest_writeable_mask >> (offset * 8)) as u8;
334*bb4ee6a4SAndroid Build Coastguard Worker         (old_byte & (!w_mask)) | (val & w_mask)
335*bb4ee6a4SAndroid Build Coastguard Worker     }
336*bb4ee6a4SAndroid Build Coastguard Worker 
337*bb4ee6a4SAndroid Build Coastguard Worker     /// Set a callback. It will be invoked when write happens.
set_write_cb<C: 'static + Fn(T) -> T + Send>(&self, callback: C)338*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_write_cb<C: 'static + Fn(T) -> T + Send>(&self, callback: C) {
339*bb4ee6a4SAndroid Build Coastguard Worker         self.lock().write_cb = Some(Box::new(callback));
340*bb4ee6a4SAndroid Build Coastguard Worker     }
341*bb4ee6a4SAndroid Build Coastguard Worker 
342*bb4ee6a4SAndroid Build Coastguard Worker     /// Set value from device side. Callback won't be invoked.
set_value(&self, val: T)343*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_value(&self, val: T) {
344*bb4ee6a4SAndroid Build Coastguard Worker         self.lock().value = val;
345*bb4ee6a4SAndroid Build Coastguard Worker     }
346*bb4ee6a4SAndroid Build Coastguard Worker 
347*bb4ee6a4SAndroid Build Coastguard Worker     /// Set masked bits.
set_bits(&self, mask: T)348*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_bits(&self, mask: T) {
349*bb4ee6a4SAndroid Build Coastguard Worker         self.lock().value.set_bits(mask);
350*bb4ee6a4SAndroid Build Coastguard Worker     }
351*bb4ee6a4SAndroid Build Coastguard Worker 
352*bb4ee6a4SAndroid Build Coastguard Worker     /// Clear masked bits.
clear_bits(&self, mask: T)353*bb4ee6a4SAndroid Build Coastguard Worker     pub fn clear_bits(&self, mask: T) {
354*bb4ee6a4SAndroid Build Coastguard Worker         self.lock().value.clear_bits(mask);
355*bb4ee6a4SAndroid Build Coastguard Worker     }
356*bb4ee6a4SAndroid Build Coastguard Worker }
357*bb4ee6a4SAndroid Build Coastguard Worker 
358*bb4ee6a4SAndroid Build Coastguard Worker #[macro_export]
359*bb4ee6a4SAndroid Build Coastguard Worker macro_rules! register {
360*bb4ee6a4SAndroid Build Coastguard Worker     (
361*bb4ee6a4SAndroid Build Coastguard Worker         name: $name:tt,
362*bb4ee6a4SAndroid Build Coastguard Worker         ty: $ty:ty,
363*bb4ee6a4SAndroid Build Coastguard Worker         offset: $offset:expr,
364*bb4ee6a4SAndroid Build Coastguard Worker         reset_value: $rv:expr,
365*bb4ee6a4SAndroid Build Coastguard Worker         guest_writeable_mask: $mask:expr,
366*bb4ee6a4SAndroid Build Coastguard Worker         guest_write_1_to_clear_mask: $w1tcm:expr,
367*bb4ee6a4SAndroid Build Coastguard Worker     ) => {{
368*bb4ee6a4SAndroid Build Coastguard Worker         use $crate::register_space::*;
369*bb4ee6a4SAndroid Build Coastguard Worker         let spec: RegisterSpec<$ty> = RegisterSpec::<$ty> {
370*bb4ee6a4SAndroid Build Coastguard Worker             name: String::from($name),
371*bb4ee6a4SAndroid Build Coastguard Worker             offset: $offset,
372*bb4ee6a4SAndroid Build Coastguard Worker             reset_value: $rv,
373*bb4ee6a4SAndroid Build Coastguard Worker             guest_writeable_mask: $mask,
374*bb4ee6a4SAndroid Build Coastguard Worker             guest_write_1_to_clear_mask: $w1tcm,
375*bb4ee6a4SAndroid Build Coastguard Worker         };
376*bb4ee6a4SAndroid Build Coastguard Worker         Register::<$ty>::new(spec, $rv)
377*bb4ee6a4SAndroid Build Coastguard Worker     }};
378*bb4ee6a4SAndroid Build Coastguard Worker     (name: $name:tt, ty: $ty:ty,offset: $offset:expr,reset_value: $rv:expr,) => {{
379*bb4ee6a4SAndroid Build Coastguard Worker         use $crate::register_space::*;
380*bb4ee6a4SAndroid Build Coastguard Worker         let spec: RegisterSpec<$ty> = RegisterSpec::<$ty> {
381*bb4ee6a4SAndroid Build Coastguard Worker             name: String::from($name),
382*bb4ee6a4SAndroid Build Coastguard Worker             offset: $offset,
383*bb4ee6a4SAndroid Build Coastguard Worker             reset_value: $rv,
384*bb4ee6a4SAndroid Build Coastguard Worker             guest_writeable_mask: !0,
385*bb4ee6a4SAndroid Build Coastguard Worker             guest_write_1_to_clear_mask: 0,
386*bb4ee6a4SAndroid Build Coastguard Worker         };
387*bb4ee6a4SAndroid Build Coastguard Worker         Register::<$ty>::new(spec, $rv)
388*bb4ee6a4SAndroid Build Coastguard Worker     }};
389*bb4ee6a4SAndroid Build Coastguard Worker }
390*bb4ee6a4SAndroid Build Coastguard Worker 
391*bb4ee6a4SAndroid Build Coastguard Worker #[macro_export]
392*bb4ee6a4SAndroid Build Coastguard Worker macro_rules! register_array {
393*bb4ee6a4SAndroid Build Coastguard Worker     (
394*bb4ee6a4SAndroid Build Coastguard Worker         name: $name:tt,
395*bb4ee6a4SAndroid Build Coastguard Worker         ty:
396*bb4ee6a4SAndroid Build Coastguard Worker         $ty:ty,cnt:
397*bb4ee6a4SAndroid Build Coastguard Worker         $cnt:expr,base_offset:
398*bb4ee6a4SAndroid Build Coastguard Worker         $base_offset:expr,stride:
399*bb4ee6a4SAndroid Build Coastguard Worker         $stride:expr,reset_value:
400*bb4ee6a4SAndroid Build Coastguard Worker         $rv:expr,guest_writeable_mask:
401*bb4ee6a4SAndroid Build Coastguard Worker         $gwm:expr,guest_write_1_to_clear_mask:
402*bb4ee6a4SAndroid Build Coastguard Worker         $gw1tcm:expr,
403*bb4ee6a4SAndroid Build Coastguard Worker     ) => {{
404*bb4ee6a4SAndroid Build Coastguard Worker         use $crate::register_space::*;
405*bb4ee6a4SAndroid Build Coastguard Worker         let mut v: Vec<Register<$ty>> = Vec::new();
406*bb4ee6a4SAndroid Build Coastguard Worker         for i in 0..$cnt {
407*bb4ee6a4SAndroid Build Coastguard Worker             let offset = $base_offset + ($stride * i) as RegisterOffset;
408*bb4ee6a4SAndroid Build Coastguard Worker             let spec: RegisterSpec<$ty> = RegisterSpec::<$ty> {
409*bb4ee6a4SAndroid Build Coastguard Worker                 name: format!("{}-{}", $name, i),
410*bb4ee6a4SAndroid Build Coastguard Worker                 offset,
411*bb4ee6a4SAndroid Build Coastguard Worker                 reset_value: $rv,
412*bb4ee6a4SAndroid Build Coastguard Worker                 guest_writeable_mask: $gwm,
413*bb4ee6a4SAndroid Build Coastguard Worker                 guest_write_1_to_clear_mask: $gw1tcm,
414*bb4ee6a4SAndroid Build Coastguard Worker             };
415*bb4ee6a4SAndroid Build Coastguard Worker             v.push(Register::<$ty>::new(spec, $rv));
416*bb4ee6a4SAndroid Build Coastguard Worker         }
417*bb4ee6a4SAndroid Build Coastguard Worker         v
418*bb4ee6a4SAndroid Build Coastguard Worker     }};
419*bb4ee6a4SAndroid Build Coastguard Worker }
420*bb4ee6a4SAndroid Build Coastguard Worker 
421*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
422*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
423*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
424*bb4ee6a4SAndroid Build Coastguard Worker 
425*bb4ee6a4SAndroid Build Coastguard Worker     static REG_SPEC0: StaticRegisterSpec<u8> = StaticRegisterSpec::<u8> {
426*bb4ee6a4SAndroid Build Coastguard Worker         offset: 3,
427*bb4ee6a4SAndroid Build Coastguard Worker         value: 32,
428*bb4ee6a4SAndroid Build Coastguard Worker     };
429*bb4ee6a4SAndroid Build Coastguard Worker 
430*bb4ee6a4SAndroid Build Coastguard Worker     static REG_SPEC1: StaticRegisterSpec<u16> = StaticRegisterSpec::<u16> {
431*bb4ee6a4SAndroid Build Coastguard Worker         offset: 3,
432*bb4ee6a4SAndroid Build Coastguard Worker         value: 32,
433*bb4ee6a4SAndroid Build Coastguard Worker     };
434*bb4ee6a4SAndroid Build Coastguard Worker 
435*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
static_register_basic_test_u8()436*bb4ee6a4SAndroid Build Coastguard Worker     fn static_register_basic_test_u8() {
437*bb4ee6a4SAndroid Build Coastguard Worker         let r = StaticRegister::<u8> { spec: &REG_SPEC0 };
438*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 4] = [0, 0, 0, 0];
439*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.range().from, 3);
440*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.range().to, 3);
441*bb4ee6a4SAndroid Build Coastguard Worker         r.read(0, &mut data);
442*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data, [0, 0, 0, 32]);
443*bb4ee6a4SAndroid Build Coastguard Worker         r.read(2, &mut data);
444*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data, [0, 32, 0, 32]);
445*bb4ee6a4SAndroid Build Coastguard Worker     }
446*bb4ee6a4SAndroid Build Coastguard Worker 
447*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
static_register_basic_test_u16()448*bb4ee6a4SAndroid Build Coastguard Worker     fn static_register_basic_test_u16() {
449*bb4ee6a4SAndroid Build Coastguard Worker         let r = StaticRegister::<u16> { spec: &REG_SPEC1 };
450*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 4] = [0, 0, 0, 0];
451*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.range().from, 3);
452*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.range().to, 4);
453*bb4ee6a4SAndroid Build Coastguard Worker         r.read(0, &mut data);
454*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data, [0, 0, 0, 32]);
455*bb4ee6a4SAndroid Build Coastguard Worker         r.read(2, &mut data);
456*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data, [0, 32, 0, 32]);
457*bb4ee6a4SAndroid Build Coastguard Worker     }
458*bb4ee6a4SAndroid Build Coastguard Worker 
459*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
static_register_interface_test()460*bb4ee6a4SAndroid Build Coastguard Worker     fn static_register_interface_test() {
461*bb4ee6a4SAndroid Build Coastguard Worker         let r: Box<dyn RegisterInterface> = Box::new(static_register! {
462*bb4ee6a4SAndroid Build Coastguard Worker             ty: u8,
463*bb4ee6a4SAndroid Build Coastguard Worker             offset: 3,
464*bb4ee6a4SAndroid Build Coastguard Worker             value: 32,
465*bb4ee6a4SAndroid Build Coastguard Worker         });
466*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 4] = [0, 0, 0, 0];
467*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.range().from, 3);
468*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.range().to, 3);
469*bb4ee6a4SAndroid Build Coastguard Worker         r.read(0, &mut data);
470*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data, [0, 0, 0, 32]);
471*bb4ee6a4SAndroid Build Coastguard Worker         r.read(2, &mut data);
472*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data, [0, 32, 0, 32]);
473*bb4ee6a4SAndroid Build Coastguard Worker     }
474*bb4ee6a4SAndroid Build Coastguard Worker 
475*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
register_basic_rw_test()476*bb4ee6a4SAndroid Build Coastguard Worker     fn register_basic_rw_test() {
477*bb4ee6a4SAndroid Build Coastguard Worker         let r = register! {
478*bb4ee6a4SAndroid Build Coastguard Worker             name: "",
479*bb4ee6a4SAndroid Build Coastguard Worker             ty: u8,
480*bb4ee6a4SAndroid Build Coastguard Worker             offset: 3,
481*bb4ee6a4SAndroid Build Coastguard Worker             reset_value: 0xf1,
482*bb4ee6a4SAndroid Build Coastguard Worker             guest_writeable_mask: 0xff,
483*bb4ee6a4SAndroid Build Coastguard Worker             guest_write_1_to_clear_mask: 0x0,
484*bb4ee6a4SAndroid Build Coastguard Worker         };
485*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 4] = [0, 0, 0, 0];
486*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.range().from, 3);
487*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.range().to, 3);
488*bb4ee6a4SAndroid Build Coastguard Worker         r.read(0, &mut data);
489*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data, [0, 0, 0, 0xf1]);
490*bb4ee6a4SAndroid Build Coastguard Worker         r.read(2, &mut data);
491*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data, [0, 0xf1, 0, 0xf1]);
492*bb4ee6a4SAndroid Build Coastguard Worker         data = [0, 0, 0, 0xab];
493*bb4ee6a4SAndroid Build Coastguard Worker         r.write(0, &data);
494*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.get_value(), 0xab);
495*bb4ee6a4SAndroid Build Coastguard Worker         r.reset();
496*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.get_value(), 0xf1);
497*bb4ee6a4SAndroid Build Coastguard Worker         r.set_value(0xcc);
498*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.get_value(), 0xcc);
499*bb4ee6a4SAndroid Build Coastguard Worker     }
500*bb4ee6a4SAndroid Build Coastguard Worker 
501*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
register_basic_writeable_mask_test()502*bb4ee6a4SAndroid Build Coastguard Worker     fn register_basic_writeable_mask_test() {
503*bb4ee6a4SAndroid Build Coastguard Worker         let r = register! {
504*bb4ee6a4SAndroid Build Coastguard Worker             name: "",
505*bb4ee6a4SAndroid Build Coastguard Worker             ty: u8,
506*bb4ee6a4SAndroid Build Coastguard Worker             offset: 3,
507*bb4ee6a4SAndroid Build Coastguard Worker             reset_value: 0x0,
508*bb4ee6a4SAndroid Build Coastguard Worker             guest_writeable_mask: 0xf,
509*bb4ee6a4SAndroid Build Coastguard Worker             guest_write_1_to_clear_mask: 0x0,
510*bb4ee6a4SAndroid Build Coastguard Worker         };
511*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 4] = [0, 0, 0, 0];
512*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.range().from, 3);
513*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.range().to, 3);
514*bb4ee6a4SAndroid Build Coastguard Worker         r.read(0, &mut data);
515*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data, [0, 0, 0, 0]);
516*bb4ee6a4SAndroid Build Coastguard Worker         data = [0, 0, 0, 0xab];
517*bb4ee6a4SAndroid Build Coastguard Worker         r.write(0, &data);
518*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.get_value(), 0x0b);
519*bb4ee6a4SAndroid Build Coastguard Worker         r.reset();
520*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.get_value(), 0x0);
521*bb4ee6a4SAndroid Build Coastguard Worker         r.set_value(0xcc);
522*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.get_value(), 0xcc);
523*bb4ee6a4SAndroid Build Coastguard Worker     }
524*bb4ee6a4SAndroid Build Coastguard Worker 
525*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
register_basic_write_1_to_clear_mask_test()526*bb4ee6a4SAndroid Build Coastguard Worker     fn register_basic_write_1_to_clear_mask_test() {
527*bb4ee6a4SAndroid Build Coastguard Worker         let r = register! {
528*bb4ee6a4SAndroid Build Coastguard Worker             name: "",
529*bb4ee6a4SAndroid Build Coastguard Worker             ty: u8,
530*bb4ee6a4SAndroid Build Coastguard Worker             offset: 3,
531*bb4ee6a4SAndroid Build Coastguard Worker             reset_value: 0xf1,
532*bb4ee6a4SAndroid Build Coastguard Worker             guest_writeable_mask: 0xff,
533*bb4ee6a4SAndroid Build Coastguard Worker             guest_write_1_to_clear_mask: 0xf0,
534*bb4ee6a4SAndroid Build Coastguard Worker         };
535*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 4] = [0, 0, 0, 0];
536*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.range().from, 3);
537*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.range().to, 3);
538*bb4ee6a4SAndroid Build Coastguard Worker         r.read(0, &mut data);
539*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data, [0, 0, 0, 0xf1]);
540*bb4ee6a4SAndroid Build Coastguard Worker         data = [0, 0, 0, 0xfa];
541*bb4ee6a4SAndroid Build Coastguard Worker         r.write(0, &data);
542*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.get_value(), 0x0a);
543*bb4ee6a4SAndroid Build Coastguard Worker         r.reset();
544*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.get_value(), 0xf1);
545*bb4ee6a4SAndroid Build Coastguard Worker         r.set_value(0xcc);
546*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.get_value(), 0xcc);
547*bb4ee6a4SAndroid Build Coastguard Worker     }
548*bb4ee6a4SAndroid Build Coastguard Worker 
549*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
register_basic_write_1_to_clear_mask_test_u32()550*bb4ee6a4SAndroid Build Coastguard Worker     fn register_basic_write_1_to_clear_mask_test_u32() {
551*bb4ee6a4SAndroid Build Coastguard Worker         let r = register! {
552*bb4ee6a4SAndroid Build Coastguard Worker             name: "",
553*bb4ee6a4SAndroid Build Coastguard Worker             ty: u32,
554*bb4ee6a4SAndroid Build Coastguard Worker             offset: 0,
555*bb4ee6a4SAndroid Build Coastguard Worker             reset_value: 0xfff1,
556*bb4ee6a4SAndroid Build Coastguard Worker             guest_writeable_mask: 0xff,
557*bb4ee6a4SAndroid Build Coastguard Worker             guest_write_1_to_clear_mask: 0xf0,
558*bb4ee6a4SAndroid Build Coastguard Worker         };
559*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 4] = [0, 0, 0, 0];
560*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.range().from, 0);
561*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.range().to, 3);
562*bb4ee6a4SAndroid Build Coastguard Worker         r.read(0, &mut data);
563*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(data, [0xf1, 0xff, 0, 0]);
564*bb4ee6a4SAndroid Build Coastguard Worker         data = [0xfa, 0, 0, 0];
565*bb4ee6a4SAndroid Build Coastguard Worker         r.write(0, &data);
566*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.get_value(), 0xff0a);
567*bb4ee6a4SAndroid Build Coastguard Worker         r.reset();
568*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.get_value(), 0xfff1);
569*bb4ee6a4SAndroid Build Coastguard Worker         r.set_value(0xcc);
570*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(r.get_value(), 0xcc);
571*bb4ee6a4SAndroid Build Coastguard Worker     }
572*bb4ee6a4SAndroid Build Coastguard Worker 
573*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
register_callback_test()574*bb4ee6a4SAndroid Build Coastguard Worker     fn register_callback_test() {
575*bb4ee6a4SAndroid Build Coastguard Worker         let state = Arc::new(Mutex::new(0u8));
576*bb4ee6a4SAndroid Build Coastguard Worker         let r = register! {
577*bb4ee6a4SAndroid Build Coastguard Worker             name: "",
578*bb4ee6a4SAndroid Build Coastguard Worker             ty: u8,
579*bb4ee6a4SAndroid Build Coastguard Worker             offset: 3,
580*bb4ee6a4SAndroid Build Coastguard Worker             reset_value: 0xf1,
581*bb4ee6a4SAndroid Build Coastguard Worker             guest_writeable_mask: 0xff,
582*bb4ee6a4SAndroid Build Coastguard Worker             guest_write_1_to_clear_mask: 0xf0,
583*bb4ee6a4SAndroid Build Coastguard Worker         };
584*bb4ee6a4SAndroid Build Coastguard Worker 
585*bb4ee6a4SAndroid Build Coastguard Worker         let s2 = state.clone();
586*bb4ee6a4SAndroid Build Coastguard Worker         r.set_write_cb(move |val: u8| {
587*bb4ee6a4SAndroid Build Coastguard Worker             *s2.lock() = val;
588*bb4ee6a4SAndroid Build Coastguard Worker             val
589*bb4ee6a4SAndroid Build Coastguard Worker         });
590*bb4ee6a4SAndroid Build Coastguard Worker         let data: [u8; 4] = [0, 0, 0, 0xff];
591*bb4ee6a4SAndroid Build Coastguard Worker         r.write(0, &data);
592*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*state.lock(), 0xf);
593*bb4ee6a4SAndroid Build Coastguard Worker         r.set_value(0xab);
594*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*state.lock(), 0xf);
595*bb4ee6a4SAndroid Build Coastguard Worker         let data: [u8; 1] = [0xfc];
596*bb4ee6a4SAndroid Build Coastguard Worker         r.write(3, &data);
597*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(*state.lock(), 0xc);
598*bb4ee6a4SAndroid Build Coastguard Worker     }
599*bb4ee6a4SAndroid Build Coastguard Worker }
600