(&mut self, offset: u64, data: &[u8])
| 305 | } |
| 306 | |
| 307 | pub fn config_space_write(&mut self, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { |
| 308 | if offset as usize + data.len() > 4 { |
| 309 | return None; |
| 310 | } |
| 311 | |
| 312 | let enabled = (self.config_address & 0x8000_0000) != 0; |
| 313 | if !enabled { |
| 314 | return None; |
| 315 | } |
| 316 | |
| 317 | let (bus, device, _function, register) = |
| 318 | parse_io_config_address(self.config_address & !0x8000_0000); |
| 319 | |
| 320 | // Only support one bus. |
| 321 | if bus != 0 { |
| 322 | return None; |
| 323 | } |
| 324 | |
| 325 | let pci_bus = self.pci_bus.as_ref().lock().unwrap(); |
| 326 | if let Some(d) = pci_bus.devices.get(&(device as u8)) { |
| 327 | let mut device = d.lock().unwrap(); |
| 328 | |
| 329 | // Update the register value |
| 330 | let (bar_reprogram, ret) = device.write_config_register(register, offset, data); |
| 331 | |
| 332 | // Move the device's BAR if needed |
| 333 | for params in &bar_reprogram { |
| 334 | if let Err(e) = pci_bus.device_reloc.move_bar( |
| 335 | params.old_base, |
| 336 | params.new_base, |
| 337 | params.len, |
| 338 | device.deref_mut(), |
| 339 | params.region_type, |
| 340 | ) { |
| 341 | warn!( |
| 342 | "Failed moving device BAR: {}: 0x{:x}->0x{:x}(0x{:x}), keeping old BAR", |
| 343 | e, params.old_base, params.new_base, params.len |
| 344 | ); |
| 345 | // Rollback: the config register was already updated to |
| 346 | // new_base by detect_bar_reprogramming(). Restore it by |
| 347 | // writing back the old address so device state stays |
| 348 | // consistent with the MMIO bus mapping. |
| 349 | device.restore_bar_addr(params); |
| 350 | } |
| 351 | } |
| 352 | |
| 353 | ret |
| 354 | } else { |
| 355 | None |
| 356 | } |
| 357 | } |
| 358 | |
| 359 | fn set_config_address(&mut self, offset: u64, data: &[u8]) { |
| 360 | if offset as usize + data.len() > 4 { |
no test coverage detected