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