| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| library fuchsia.hardware.pciroot; |
| using zircon.hw.pci; |
| using zx; |
| |
| const uint8 DEVICES_PER_BUS = 64; |
| const uint8 FUNCTIONS_PER_DEVICE = 8; |
| const uint8 PINS_PER_FUNCTION = 4; |
| |
| /// Used to indicate within a routing entry that there is no parent bridge/port |
| /// device, it is connected directly at the root. |
| const uint8 PCI_IRQ_ROUTING_NO_PARENT = 0xFF; |
| /// An entry corresponds to all functions for the given device. |
| const uint8 PCI_IRQ_ROUTING_ALL_FUNCTIONS = 0xF; |
| |
| /// A protocol representation of a routing entry. |
| /// It is intentionally very similar to an ACPI _PRT entry to reduce the complexity of |
| /// the data structure that needs to be passed over the 'wire'. Endpoints |
| /// directly connected to a root complex will have port device and function_ids |
| /// of PCI_IRQ_ROUTING_NO_PARENT. For other endpoints hanging off root ports or |
| /// bridges their upstream port address will be contained in these fields. |
| struct PciIrqRoutingEntry { |
| uint8 port_device_id; |
| uint8 port_function_id; |
| uint8 device_id; |
| array<uint8>:PINS_PER_FUNCTION pins; |
| }; |
| |
| /// This represents one of the vectors wired up for PCI legacy interrupts. How |
| /// the bus driver uses them depends on the irq routing table provided to them. |
| /// The vector is supplied because interrupt objects cannot be inspected with |
| /// zx_get_object_info. |
| struct PciLegacyIrq { |
| zx.handle:INTERRUPT interrupt; |
| uint32 vector; |
| }; |
| |
| /// This structure is the primary means of passing PCI platform information from |
| /// the platform bus implementation to the PCI bus driver. If an ecam is found |
| /// for this segment group then a handle to a VMO for it will be provided via |
| /// |ecam_vmo|. The VMO's start address will correspond to the base address of |
| /// the bus number specified by |start_bus_num|. |
| struct PciPlatformInfo { |
| string:8 name; |
| uint8 start_bus_num; |
| uint8 end_bus_num; |
| uint16 segment_group; |
| zx.handle:VMO ecam_vmo; |
| vector<PciLegacyIrq> legacy_irqs; |
| vector<PciIrqRoutingEntry> irq_routing; |
| }; |
| |
| enum PciAddressSpace : uint8 { |
| Memory = 0; |
| Io = 0x1; |
| }; |
| |
| [Transport = "Banjo", BanjoLayout = "ddk-protocol"] |
| protocol Pciroot { |
| /// Legacy methods |
| /// Create a sysmem connection - used to implement fuchsia.hardware.sysmem. |
| ConnectSysmem(zx.handle:CHANNEL connection) -> (zx.status s); |
| GetBti(uint32 bdf, uint32 index) -> (zx.status s, zx.handle:BTI bti); |
| /// Get the platform information structure from the pciroot protocol to be used for bus init. |
| GetPciPlatformInfo() -> (zx.status s, PciPlatformInfo info); |
| |
| /// Contemporary methods: |
| /// Returns true if the bus driver should proxy all device config access to pciroot. This is |
| /// necessary in cases of IO config on x86, or for controllers that require configuration to |
| /// map in device config headers. |
| DriverShouldProxyConfig() -> (bool use_proxy); |
| /// Read 8 bytes from config space for device at bdf address |address|:we, offset |offset|. |
| ConfigRead8(zircon.hw.pci.PciBdf address, uint16 offset) -> (zx.status s, uint8 value); |
| /// Read 16 bytes from config space for device at bdf address |address|, offset |offset|. |
| ConfigRead16(zircon.hw.pci.PciBdf address, uint16 offset) -> (zx.status s, uint16 value); |
| /// Read 32 bytes from config space for device at bdf address |address|, offset |offset|. |
| ConfigRead32(zircon.hw.pci.PciBdf address, uint16 offset) -> (zx.status s, uint32 value); |
| /// Write 8 bytes to config space for device at bdf |address| offset |offset|. |
| ConfigWrite8(zircon.hw.pci.PciBdf address, uint16 offset, uint8 value) -> (zx.status s); |
| /// Write 16 bytes to config space for device at bdf |address| offset |offset|. |
| ConfigWrite16(zircon.hw.pci.PciBdf address, uint16 offset, uint16 value) -> (zx.status s); |
| /// Write 32 bytes to config space for device at bdf |address| offset |offset|. |
| ConfigWrite32(zircon.hw.pci.PciBdf address, uint16 offset, uint32 value) -> (zx.status s); |
| /// Request address space reservations from platform bus to use for mapping bars / bridges |
| /// |in_base| is an optional requested start address which should otherwise be 0. |size| is the |
| /// size of the request in bytes. |low| dictates whether the allocation should be an address |
| /// below 4 GB or not. |
| /// |
| /// On success, the base address is provided in |out_base| and the size is |size|. |
| /// |
| /// An error will be returned if |size| cannot be fulfilled, |low| is set with |in_base|+|size| |
| /// being >=4GB, or if a requested |in_base| cannot be provided. |
| GetAddressSpace(zx.paddr in_base, uint64 size, PciAddressSpace type, bool low) |
| -> (zx.status s, zx.paddr base, zx.handle:RESOURCE resource, zx.handle:EVENTPAIR token); |
| /// Allocate |msi_count| MSIs and return a handle to the backing MsiAllocation. |
| AllocateMsi(uint32 msi_count, bool can_target_64bit) -> (zx.status s, zx.handle:MSI_ALLOCATION allocation); |
| }; |