diff options
Diffstat (limited to 'devices/src/pci/msix.rs')
-rw-r--r-- | devices/src/pci/msix.rs | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/devices/src/pci/msix.rs b/devices/src/pci/msix.rs new file mode 100644 index 0000000..55e71ba --- /dev/null +++ b/devices/src/pci/msix.rs @@ -0,0 +1,69 @@ +// Copyright 2019 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +use crate::pci::{PciCapability, PciCapabilityID}; + +use data_model::DataInit; + +const MAX_MSIX_VECTORS_PER_DEVICE: u16 = 2048; + +// It is safe to implement DataInit; all members are simple numbers and any value is valid. +unsafe impl DataInit for MsixCap {} + +#[allow(dead_code)] +#[repr(C)] +#[derive(Clone, Copy, Default)] +/// MSI-X Capability Structure +pub struct MsixCap { + // To make add_capability() happy + _cap_vndr: u8, + _cap_next: u8, + // Message Control Register + // 10-0: MSI-X Table size + // 13-11: Reserved + // 14: Mask. Mask all MSI-X when set. + // 15: Enable. Enable all MSI-X when set. + msg_ctl: u16, + // Table. Contains the offset and the BAR indicator (BIR) + // 2-0: Table BAR indicator (BIR). Can be 0 to 5. + // 31-3: Table offset in the BAR pointed by the BIR. + table: u32, + // Pending Bit Array. Contains the offset and the BAR indicator (BIR) + // 2-0: PBA BAR indicator (BIR). Can be 0 to 5. + // 31-3: PBA offset in the BAR pointed by the BIR. + pba: u32, +} + +impl PciCapability for MsixCap { + fn bytes(&self) -> &[u8] { + self.as_slice() + } + + fn id(&self) -> PciCapabilityID { + PciCapabilityID::MSIX + } +} + +impl MsixCap { + pub fn new( + table_pci_bar: u8, + table_size: u16, + table_off: u32, + pba_pci_bar: u8, + pba_off: u32, + ) -> Self { + assert!(table_size < MAX_MSIX_VECTORS_PER_DEVICE); + + // Set the table size and enable MSI-X. + let msg_ctl: u16 = 0x8000u16 + table_size - 1; + + MsixCap { + _cap_vndr: 0, + _cap_next: 0, + msg_ctl, + table: (table_off & 0xffff_fff8u32) | u32::from(table_pci_bar & 0x7u8), + pba: (pba_off & 0xffff_fff8u32) | u32::from(pba_pci_bar & 0x7u8), + } + } +} |