blob: a14808f87d20ff248261112a1e6e222118c32ab3 [file] [log] [blame]
// 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 zx;
struct PciBdf {
uint8 bus_id;
uint8 device_id;
uint8 function_id;
};
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.
resource 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|.
resource 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(PciBdf address, uint16 offset) -> (zx.status s, uint8 value);
/// Read 16 bytes from config space for device at bdf address |address|, offset |offset|.
ConfigRead16(PciBdf address, uint16 offset) -> (zx.status s, uint16 value);
/// Read 32 bytes from config space for device at bdf address |address|, offset |offset|.
ConfigRead32(PciBdf address, uint16 offset) -> (zx.status s, uint32 value);
/// Write 8 bytes to config space for device at bdf |address| offset |offset|.
ConfigWrite8(PciBdf address, uint16 offset, uint8 value) -> (zx.status s);
/// Write 16 bytes to config space for device at bdf |address| offset |offset|.
ConfigWrite16(PciBdf address, uint16 offset, uint16 value) -> (zx.status s);
/// Write 32 bytes to config space for device at bdf |address| offset |offset|.
ConfigWrite32(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);
};