xref: /aosp_15_r20/external/crosvm/devices/src/register_space/mod.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::collections::btree_map::BTreeMap;
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker #[macro_use]
8*bb4ee6a4SAndroid Build Coastguard Worker mod register;
9*bb4ee6a4SAndroid Build Coastguard Worker 
10*bb4ee6a4SAndroid Build Coastguard Worker pub use self::register::*;
11*bb4ee6a4SAndroid Build Coastguard Worker 
12*bb4ee6a4SAndroid Build Coastguard Worker /// Register space repesents a set of registers. It can handle read/write operations.
13*bb4ee6a4SAndroid Build Coastguard Worker pub struct RegisterSpace {
14*bb4ee6a4SAndroid Build Coastguard Worker     regs: BTreeMap<RegisterRange, Box<dyn RegisterInterface>>,
15*bb4ee6a4SAndroid Build Coastguard Worker }
16*bb4ee6a4SAndroid Build Coastguard Worker 
17*bb4ee6a4SAndroid Build Coastguard Worker impl RegisterSpace {
18*bb4ee6a4SAndroid Build Coastguard Worker     /// Creates a new empty RegisterSpace.
new() -> RegisterSpace19*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new() -> RegisterSpace {
20*bb4ee6a4SAndroid Build Coastguard Worker         RegisterSpace {
21*bb4ee6a4SAndroid Build Coastguard Worker             regs: BTreeMap::new(),
22*bb4ee6a4SAndroid Build Coastguard Worker         }
23*bb4ee6a4SAndroid Build Coastguard Worker     }
24*bb4ee6a4SAndroid Build Coastguard Worker 
25*bb4ee6a4SAndroid Build Coastguard Worker     /// Add a register to register space.
add_register<T: RegisterInterface + 'static>(&mut self, reg: T)26*bb4ee6a4SAndroid Build Coastguard Worker     pub fn add_register<T: RegisterInterface + 'static>(&mut self, reg: T) {
27*bb4ee6a4SAndroid Build Coastguard Worker         let range = reg.range();
28*bb4ee6a4SAndroid Build Coastguard Worker         debug_assert!(self.get_register(range.from).is_none());
29*bb4ee6a4SAndroid Build Coastguard Worker         if cfg!(debug_assertions) {
30*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(r) = self.first_before(range.to) {
31*bb4ee6a4SAndroid Build Coastguard Worker                 debug_assert!(r.range().to < range.to);
32*bb4ee6a4SAndroid Build Coastguard Worker             }
33*bb4ee6a4SAndroid Build Coastguard Worker         }
34*bb4ee6a4SAndroid Build Coastguard Worker 
35*bb4ee6a4SAndroid Build Coastguard Worker         let insert_result = self.regs.insert(range, Box::new(reg)).is_none();
36*bb4ee6a4SAndroid Build Coastguard Worker         debug_assert!(insert_result);
37*bb4ee6a4SAndroid Build Coastguard Worker     }
38*bb4ee6a4SAndroid Build Coastguard Worker 
39*bb4ee6a4SAndroid Build Coastguard Worker     /// Add an array of registers.
add_register_array<T: RegisterValue>(&mut self, regs: &[Register<T>])40*bb4ee6a4SAndroid Build Coastguard Worker     pub fn add_register_array<T: RegisterValue>(&mut self, regs: &[Register<T>]) {
41*bb4ee6a4SAndroid Build Coastguard Worker         for r in regs {
42*bb4ee6a4SAndroid Build Coastguard Worker             self.add_register(r.clone());
43*bb4ee6a4SAndroid Build Coastguard Worker         }
44*bb4ee6a4SAndroid Build Coastguard Worker     }
45*bb4ee6a4SAndroid Build Coastguard Worker 
46*bb4ee6a4SAndroid Build Coastguard Worker     /// Read range.
read(&self, addr: RegisterOffset, data: &mut [u8])47*bb4ee6a4SAndroid Build Coastguard Worker     pub fn read(&self, addr: RegisterOffset, data: &mut [u8]) {
48*bb4ee6a4SAndroid Build Coastguard Worker         let mut current_addr: RegisterOffset = addr;
49*bb4ee6a4SAndroid Build Coastguard Worker         while current_addr < addr + data.len() as RegisterOffset {
50*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(r) = self.get_register(current_addr) {
51*bb4ee6a4SAndroid Build Coastguard Worker                 // Next addr to read is.
52*bb4ee6a4SAndroid Build Coastguard Worker                 current_addr = r.range().to + 1;
53*bb4ee6a4SAndroid Build Coastguard Worker                 r.read(addr, data);
54*bb4ee6a4SAndroid Build Coastguard Worker             } else {
55*bb4ee6a4SAndroid Build Coastguard Worker                 // TODO(jkwang) Add logging for debug here.
56*bb4ee6a4SAndroid Build Coastguard Worker                 current_addr += 1;
57*bb4ee6a4SAndroid Build Coastguard Worker             }
58*bb4ee6a4SAndroid Build Coastguard Worker         }
59*bb4ee6a4SAndroid Build Coastguard Worker     }
60*bb4ee6a4SAndroid Build Coastguard Worker 
61*bb4ee6a4SAndroid Build Coastguard Worker     /// Write range. If the targeted register has a callback, it will be invoked with the new
62*bb4ee6a4SAndroid Build Coastguard Worker     /// value.
write(&self, addr: RegisterOffset, data: &[u8])63*bb4ee6a4SAndroid Build Coastguard Worker     pub fn write(&self, addr: RegisterOffset, data: &[u8]) {
64*bb4ee6a4SAndroid Build Coastguard Worker         let mut current_addr: RegisterOffset = addr;
65*bb4ee6a4SAndroid Build Coastguard Worker         while current_addr < addr + data.len() as RegisterOffset {
66*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(r) = self.get_register(current_addr) {
67*bb4ee6a4SAndroid Build Coastguard Worker                 // Next addr to read is, range is inclusive.
68*bb4ee6a4SAndroid Build Coastguard Worker                 current_addr = r.range().to + 1;
69*bb4ee6a4SAndroid Build Coastguard Worker                 r.write(addr, data);
70*bb4ee6a4SAndroid Build Coastguard Worker             } else {
71*bb4ee6a4SAndroid Build Coastguard Worker                 current_addr += 1;
72*bb4ee6a4SAndroid Build Coastguard Worker             }
73*bb4ee6a4SAndroid Build Coastguard Worker         }
74*bb4ee6a4SAndroid Build Coastguard Worker     }
75*bb4ee6a4SAndroid Build Coastguard Worker 
76*bb4ee6a4SAndroid Build Coastguard Worker     /// Get first register before this addr.
first_before(&self, addr: RegisterOffset) -> Option<&dyn RegisterInterface>77*bb4ee6a4SAndroid Build Coastguard Worker     fn first_before(&self, addr: RegisterOffset) -> Option<&dyn RegisterInterface> {
78*bb4ee6a4SAndroid Build Coastguard Worker         for (range, r) in self.regs.iter().rev() {
79*bb4ee6a4SAndroid Build Coastguard Worker             if range.from <= addr {
80*bb4ee6a4SAndroid Build Coastguard Worker                 return Some(r.as_ref());
81*bb4ee6a4SAndroid Build Coastguard Worker             }
82*bb4ee6a4SAndroid Build Coastguard Worker         }
83*bb4ee6a4SAndroid Build Coastguard Worker         None
84*bb4ee6a4SAndroid Build Coastguard Worker     }
85*bb4ee6a4SAndroid Build Coastguard Worker 
86*bb4ee6a4SAndroid Build Coastguard Worker     /// Get register at this addr.
get_register(&self, addr: RegisterOffset) -> Option<&dyn RegisterInterface>87*bb4ee6a4SAndroid Build Coastguard Worker     fn get_register(&self, addr: RegisterOffset) -> Option<&dyn RegisterInterface> {
88*bb4ee6a4SAndroid Build Coastguard Worker         let r = self.first_before(addr)?;
89*bb4ee6a4SAndroid Build Coastguard Worker         let range = r.range();
90*bb4ee6a4SAndroid Build Coastguard Worker         if addr <= range.to {
91*bb4ee6a4SAndroid Build Coastguard Worker             Some(r)
92*bb4ee6a4SAndroid Build Coastguard Worker         } else {
93*bb4ee6a4SAndroid Build Coastguard Worker             None
94*bb4ee6a4SAndroid Build Coastguard Worker         }
95*bb4ee6a4SAndroid Build Coastguard Worker     }
96*bb4ee6a4SAndroid Build Coastguard Worker }
97*bb4ee6a4SAndroid Build Coastguard Worker 
98*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
99*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
100*bb4ee6a4SAndroid Build Coastguard Worker     use std::sync::Arc;
101*bb4ee6a4SAndroid Build Coastguard Worker 
102*bb4ee6a4SAndroid Build Coastguard Worker     use sync::Mutex;
103*bb4ee6a4SAndroid Build Coastguard Worker 
104*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
105*bb4ee6a4SAndroid Build Coastguard Worker 
106*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
regs_no_reg()107*bb4ee6a4SAndroid Build Coastguard Worker     fn regs_no_reg() {
108*bb4ee6a4SAndroid Build Coastguard Worker         let regs = RegisterSpace::new();
109*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 4] = [4, 3, 2, 1];
110*bb4ee6a4SAndroid Build Coastguard Worker         // Read should be no op cause no register.
111*bb4ee6a4SAndroid Build Coastguard Worker         regs.read(0, &mut data);
112*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!([4, 3, 2, 1], data);
113*bb4ee6a4SAndroid Build Coastguard Worker         // Write should be no op.
114*bb4ee6a4SAndroid Build Coastguard Worker         regs.write(0, &[0, 0, 0, 0]);
115*bb4ee6a4SAndroid Build Coastguard Worker         regs.read(0, &mut data);
116*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!([4, 3, 2, 1], data);
117*bb4ee6a4SAndroid Build Coastguard Worker     }
118*bb4ee6a4SAndroid Build Coastguard Worker 
119*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
120*bb4ee6a4SAndroid Build Coastguard Worker     #[should_panic]
121*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(debug_assertions)]
regs_reg_overlap()122*bb4ee6a4SAndroid Build Coastguard Worker     fn regs_reg_overlap() {
123*bb4ee6a4SAndroid Build Coastguard Worker         let mut regs = RegisterSpace::new();
124*bb4ee6a4SAndroid Build Coastguard Worker         regs.add_register(static_register!(
125*bb4ee6a4SAndroid Build Coastguard Worker         ty: u32,
126*bb4ee6a4SAndroid Build Coastguard Worker         offset: 4,
127*bb4ee6a4SAndroid Build Coastguard Worker         value: 11,
128*bb4ee6a4SAndroid Build Coastguard Worker         ));
129*bb4ee6a4SAndroid Build Coastguard Worker 
130*bb4ee6a4SAndroid Build Coastguard Worker         regs.add_register(static_register!(
131*bb4ee6a4SAndroid Build Coastguard Worker         ty: u16,
132*bb4ee6a4SAndroid Build Coastguard Worker         offset: 7,
133*bb4ee6a4SAndroid Build Coastguard Worker         value: 11,
134*bb4ee6a4SAndroid Build Coastguard Worker         ));
135*bb4ee6a4SAndroid Build Coastguard Worker     }
136*bb4ee6a4SAndroid Build Coastguard Worker 
137*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
regs_static_reg()138*bb4ee6a4SAndroid Build Coastguard Worker     fn regs_static_reg() {
139*bb4ee6a4SAndroid Build Coastguard Worker         let mut regs = RegisterSpace::new();
140*bb4ee6a4SAndroid Build Coastguard Worker         regs.add_register(static_register!(
141*bb4ee6a4SAndroid Build Coastguard Worker             ty: u8,
142*bb4ee6a4SAndroid Build Coastguard Worker             offset: 0,
143*bb4ee6a4SAndroid Build Coastguard Worker             value: 11,
144*bb4ee6a4SAndroid Build Coastguard Worker         ));
145*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 4] = [4, 3, 2, 1];
146*bb4ee6a4SAndroid Build Coastguard Worker         regs.read(0, &mut data);
147*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!([11, 3, 2, 1], data);
148*bb4ee6a4SAndroid Build Coastguard Worker         // Write should be no op.
149*bb4ee6a4SAndroid Build Coastguard Worker         regs.write(0, &[0, 0, 0, 0]);
150*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 4] = [4, 3, 2, 1];
151*bb4ee6a4SAndroid Build Coastguard Worker         regs.read(0, &mut data);
152*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!([11, 3, 2, 1], data);
153*bb4ee6a4SAndroid Build Coastguard Worker     }
154*bb4ee6a4SAndroid Build Coastguard Worker 
155*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
regs_static_reg_offset()156*bb4ee6a4SAndroid Build Coastguard Worker     fn regs_static_reg_offset() {
157*bb4ee6a4SAndroid Build Coastguard Worker         let mut regs = RegisterSpace::new();
158*bb4ee6a4SAndroid Build Coastguard Worker         regs.add_register(static_register!(
159*bb4ee6a4SAndroid Build Coastguard Worker             ty: u32,
160*bb4ee6a4SAndroid Build Coastguard Worker             offset: 2,
161*bb4ee6a4SAndroid Build Coastguard Worker             value: 0xaabbccdd,
162*bb4ee6a4SAndroid Build Coastguard Worker         ));
163*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
164*bb4ee6a4SAndroid Build Coastguard Worker         regs.read(0, &mut data);
165*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
166*bb4ee6a4SAndroid Build Coastguard Worker         // Write should be no op.
167*bb4ee6a4SAndroid Build Coastguard Worker         regs.write(0, &[0, 0, 0, 0, 0, 0, 0, 0]);
168*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
169*bb4ee6a4SAndroid Build Coastguard Worker         regs.read(0, &mut data);
170*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
171*bb4ee6a4SAndroid Build Coastguard Worker     }
172*bb4ee6a4SAndroid Build Coastguard Worker 
173*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
regs_reg_write()174*bb4ee6a4SAndroid Build Coastguard Worker     fn regs_reg_write() {
175*bb4ee6a4SAndroid Build Coastguard Worker         let mut regs = RegisterSpace::new();
176*bb4ee6a4SAndroid Build Coastguard Worker         regs.add_register(register!(
177*bb4ee6a4SAndroid Build Coastguard Worker             name: "",
178*bb4ee6a4SAndroid Build Coastguard Worker             ty: u32,
179*bb4ee6a4SAndroid Build Coastguard Worker             offset: 2,
180*bb4ee6a4SAndroid Build Coastguard Worker             reset_value: 0xaabbccdd,
181*bb4ee6a4SAndroid Build Coastguard Worker         ));
182*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
183*bb4ee6a4SAndroid Build Coastguard Worker         regs.read(0, &mut data);
184*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
185*bb4ee6a4SAndroid Build Coastguard Worker         regs.write(0, &[0, 0, 0, 0, 0, 0, 0, 0]);
186*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
187*bb4ee6a4SAndroid Build Coastguard Worker         regs.read(0, &mut data);
188*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!([8, 7, 0, 0, 0, 0, 2, 1], data);
189*bb4ee6a4SAndroid Build Coastguard Worker     }
190*bb4ee6a4SAndroid Build Coastguard Worker 
191*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
regs_reg_writeable()192*bb4ee6a4SAndroid Build Coastguard Worker     fn regs_reg_writeable() {
193*bb4ee6a4SAndroid Build Coastguard Worker         let mut regs = RegisterSpace::new();
194*bb4ee6a4SAndroid Build Coastguard Worker         regs.add_register(register!(
195*bb4ee6a4SAndroid Build Coastguard Worker             name: "",
196*bb4ee6a4SAndroid Build Coastguard Worker             ty: u32,
197*bb4ee6a4SAndroid Build Coastguard Worker             offset: 2,
198*bb4ee6a4SAndroid Build Coastguard Worker             reset_value: 0xaabbccdd,
199*bb4ee6a4SAndroid Build Coastguard Worker             guest_writeable_mask: 0x00f0000f,
200*bb4ee6a4SAndroid Build Coastguard Worker             guest_write_1_to_clear_mask: 0,
201*bb4ee6a4SAndroid Build Coastguard Worker         ));
202*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
203*bb4ee6a4SAndroid Build Coastguard Worker         regs.read(0, &mut data);
204*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
205*bb4ee6a4SAndroid Build Coastguard Worker         regs.write(0, &[0, 0, 0, 0, 0, 0, 0, 0]);
206*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
207*bb4ee6a4SAndroid Build Coastguard Worker         regs.read(0, &mut data);
208*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!([8, 7, 0xd0, 0xcc, 0x0b, 0xaa, 2, 1], data);
209*bb4ee6a4SAndroid Build Coastguard Worker     }
210*bb4ee6a4SAndroid Build Coastguard Worker 
211*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
regs_reg_writeable_callback()212*bb4ee6a4SAndroid Build Coastguard Worker     fn regs_reg_writeable_callback() {
213*bb4ee6a4SAndroid Build Coastguard Worker         let state = Arc::new(Mutex::new(0u32));
214*bb4ee6a4SAndroid Build Coastguard Worker         let mut regs = RegisterSpace::new();
215*bb4ee6a4SAndroid Build Coastguard Worker         let reg = register!(
216*bb4ee6a4SAndroid Build Coastguard Worker             name: "",
217*bb4ee6a4SAndroid Build Coastguard Worker             ty: u32,
218*bb4ee6a4SAndroid Build Coastguard Worker             offset: 2,
219*bb4ee6a4SAndroid Build Coastguard Worker             reset_value: 0xaabbccdd,
220*bb4ee6a4SAndroid Build Coastguard Worker             guest_writeable_mask: 0x00f0000f,
221*bb4ee6a4SAndroid Build Coastguard Worker             guest_write_1_to_clear_mask: 0,
222*bb4ee6a4SAndroid Build Coastguard Worker         );
223*bb4ee6a4SAndroid Build Coastguard Worker         regs.add_register(reg.clone());
224*bb4ee6a4SAndroid Build Coastguard Worker         let state_clone = state.clone();
225*bb4ee6a4SAndroid Build Coastguard Worker         reg.set_write_cb(move |val: u32| {
226*bb4ee6a4SAndroid Build Coastguard Worker             *state_clone.lock() = val;
227*bb4ee6a4SAndroid Build Coastguard Worker             val
228*bb4ee6a4SAndroid Build Coastguard Worker         });
229*bb4ee6a4SAndroid Build Coastguard Worker 
230*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
231*bb4ee6a4SAndroid Build Coastguard Worker         regs.read(0, &mut data);
232*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
233*bb4ee6a4SAndroid Build Coastguard Worker         regs.write(0, &[0, 0, 0, 0, 0, 0, 0, 0]);
234*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(0xaa0bccd0, *state.lock());
235*bb4ee6a4SAndroid Build Coastguard Worker     }
236*bb4ee6a4SAndroid Build Coastguard Worker 
237*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
regs_reg_write_to_clear()238*bb4ee6a4SAndroid Build Coastguard Worker     fn regs_reg_write_to_clear() {
239*bb4ee6a4SAndroid Build Coastguard Worker         let mut regs = RegisterSpace::new();
240*bb4ee6a4SAndroid Build Coastguard Worker         regs.add_register(register!(
241*bb4ee6a4SAndroid Build Coastguard Worker         name: "",
242*bb4ee6a4SAndroid Build Coastguard Worker         ty: u32,
243*bb4ee6a4SAndroid Build Coastguard Worker         offset: 2,
244*bb4ee6a4SAndroid Build Coastguard Worker         reset_value: 0xaabbccdd,
245*bb4ee6a4SAndroid Build Coastguard Worker         guest_writeable_mask: 0xfff0000f,
246*bb4ee6a4SAndroid Build Coastguard Worker         guest_write_1_to_clear_mask: 0xf0000000,
247*bb4ee6a4SAndroid Build Coastguard Worker         ));
248*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
249*bb4ee6a4SAndroid Build Coastguard Worker         regs.read(0, &mut data);
250*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!([8, 7, 0xdd, 0xcc, 0xbb, 0xaa, 2, 1], data);
251*bb4ee6a4SAndroid Build Coastguard Worker         regs.write(0, &[0, 0, 0, 0, 0, 0xad, 0, 0]);
252*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 8] = [8, 7, 6, 5, 4, 3, 2, 1];
253*bb4ee6a4SAndroid Build Coastguard Worker         regs.read(0, &mut data);
254*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!([8, 7, 0xd0, 0xcc, 0x0b, 0x0d, 2, 1], data);
255*bb4ee6a4SAndroid Build Coastguard Worker     }
256*bb4ee6a4SAndroid Build Coastguard Worker 
257*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
regs_reg_array()258*bb4ee6a4SAndroid Build Coastguard Worker     fn regs_reg_array() {
259*bb4ee6a4SAndroid Build Coastguard Worker         let mut regs = RegisterSpace::new();
260*bb4ee6a4SAndroid Build Coastguard Worker         regs.add_register_array(&register_array!(
261*bb4ee6a4SAndroid Build Coastguard Worker             name: "",
262*bb4ee6a4SAndroid Build Coastguard Worker             ty: u8,
263*bb4ee6a4SAndroid Build Coastguard Worker             cnt: 8,
264*bb4ee6a4SAndroid Build Coastguard Worker             base_offset: 10,
265*bb4ee6a4SAndroid Build Coastguard Worker             stride: 2,
266*bb4ee6a4SAndroid Build Coastguard Worker             reset_value: 0xff,
267*bb4ee6a4SAndroid Build Coastguard Worker             guest_writeable_mask: !0,
268*bb4ee6a4SAndroid Build Coastguard Worker             guest_write_1_to_clear_mask: 0,
269*bb4ee6a4SAndroid Build Coastguard Worker         ));
270*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 8] = [0; 8];
271*bb4ee6a4SAndroid Build Coastguard Worker         regs.read(8, &mut data);
272*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!([0, 0, 0xff, 0, 0xff, 0, 0xff, 0], data);
273*bb4ee6a4SAndroid Build Coastguard Worker     }
274*bb4ee6a4SAndroid Build Coastguard Worker 
275*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
regs_reg_multi_array()276*bb4ee6a4SAndroid Build Coastguard Worker     fn regs_reg_multi_array() {
277*bb4ee6a4SAndroid Build Coastguard Worker         let mut regs = RegisterSpace::new();
278*bb4ee6a4SAndroid Build Coastguard Worker         regs.add_register_array(&register_array!(
279*bb4ee6a4SAndroid Build Coastguard Worker         name: "",
280*bb4ee6a4SAndroid Build Coastguard Worker         ty: u8,
281*bb4ee6a4SAndroid Build Coastguard Worker         cnt: 8,
282*bb4ee6a4SAndroid Build Coastguard Worker         base_offset: 10,
283*bb4ee6a4SAndroid Build Coastguard Worker         stride: 2,
284*bb4ee6a4SAndroid Build Coastguard Worker         reset_value: 0xff,
285*bb4ee6a4SAndroid Build Coastguard Worker         guest_writeable_mask: !0,
286*bb4ee6a4SAndroid Build Coastguard Worker         guest_write_1_to_clear_mask: 0,
287*bb4ee6a4SAndroid Build Coastguard Worker         ));
288*bb4ee6a4SAndroid Build Coastguard Worker         regs.add_register_array(&register_array!(
289*bb4ee6a4SAndroid Build Coastguard Worker         name: "",
290*bb4ee6a4SAndroid Build Coastguard Worker         ty: u8,
291*bb4ee6a4SAndroid Build Coastguard Worker         cnt: 8,
292*bb4ee6a4SAndroid Build Coastguard Worker         base_offset: 11,
293*bb4ee6a4SAndroid Build Coastguard Worker         stride: 2,
294*bb4ee6a4SAndroid Build Coastguard Worker         reset_value: 0xee,
295*bb4ee6a4SAndroid Build Coastguard Worker         guest_writeable_mask: !0,
296*bb4ee6a4SAndroid Build Coastguard Worker         guest_write_1_to_clear_mask: 0,
297*bb4ee6a4SAndroid Build Coastguard Worker         ));
298*bb4ee6a4SAndroid Build Coastguard Worker         let mut data: [u8; 8] = [0; 8];
299*bb4ee6a4SAndroid Build Coastguard Worker         regs.read(8, &mut data);
300*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!([0, 0, 0xff, 0xee, 0xff, 0xee, 0xff, 0xee], data);
301*bb4ee6a4SAndroid Build Coastguard Worker     }
302*bb4ee6a4SAndroid Build Coastguard Worker }
303