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(®_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: ®_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: ®_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