(&mut self, offset: u64, data: &[u8])
| 321 | } |
| 322 | |
| 323 | pub fn write_table(&mut self, offset: u64, data: &[u8]) { |
| 324 | if data.len() != 4 && data.len() != 8 { |
| 325 | error!( |
| 326 | "invalid MSI-X table write size: {} (allowed: 4 or 8)", |
| 327 | data.len() |
| 328 | ); |
| 329 | return; |
| 330 | } |
| 331 | |
| 332 | let index: usize = (offset / MSIX_TABLE_ENTRIES_MODULO) as usize; |
| 333 | let modulo_offset = offset % MSIX_TABLE_ENTRIES_MODULO; |
| 334 | |
| 335 | if index >= self.table_entries.len() { |
| 336 | debug!("Invalid MSI-X table entry index {index}"); |
| 337 | return; |
| 338 | } |
| 339 | |
| 340 | // Store the value of the entry before modification |
| 341 | let old_entry = self.table_entries[index].clone(); |
| 342 | |
| 343 | match data.len() { |
| 344 | 4 => { |
| 345 | let value = LittleEndian::read_u32(data); |
| 346 | match modulo_offset { |
| 347 | 0x0 => self.table_entries[index].msg_addr_lo = value, |
| 348 | 0x4 => self.table_entries[index].msg_addr_hi = value, |
| 349 | 0x8 => self.table_entries[index].msg_data = value, |
| 350 | 0xc => { |
| 351 | self.table_entries[index].vector_ctl = value; |
| 352 | } |
| 353 | _ => error!("invalid offset"), |
| 354 | } |
| 355 | |
| 356 | debug!("MSI_W TABLE offset 0x{offset:x} data 0x{value:x}"); |
| 357 | } |
| 358 | 8 => { |
| 359 | let value = LittleEndian::read_u64(data); |
| 360 | match modulo_offset { |
| 361 | 0x0 => { |
| 362 | self.table_entries[index].msg_addr_lo = (value & 0xffff_ffffu64) as u32; |
| 363 | self.table_entries[index].msg_addr_hi = (value >> 32) as u32; |
| 364 | } |
| 365 | 0x8 => { |
| 366 | self.table_entries[index].msg_data = (value & 0xffff_ffffu64) as u32; |
| 367 | self.table_entries[index].vector_ctl = (value >> 32) as u32; |
| 368 | } |
| 369 | _ => error!("invalid offset"), |
| 370 | } |
| 371 | |
| 372 | debug!("MSI_W TABLE offset 0x{offset:x} data 0x{value:x}"); |
| 373 | } |
| 374 | _ => error!("invalid data length"), |
| 375 | } |
| 376 | |
| 377 | let table_entry = &self.table_entries[index]; |
| 378 | |
| 379 | // Optimisation to avoid excessive updates |
| 380 | if &old_entry == table_entry { |
no test coverage detected