blob: e54c4a0d4798352fe3bd53777df91fac4b1eaae2 [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;
type PciBdf = struct {
bus_id uint8;
device_id uint8;
function_id uint8;
};
const DEVICES_PER_BUS uint8 = 64;
const FUNCTIONS_PER_DEVICE uint8 = 8;
const PINS_PER_FUNCTION uint8 = 4;
/// Used to indicate within a routing entry that there is no parent bridge/port
/// device, it is connected directly at the root.
const PCI_IRQ_ROUTING_NO_PARENT uint8 = 0xFF;
/// An entry corresponds to all functions for the given device.
const PCI_IRQ_ROUTING_ALL_FUNCTIONS uint8 = 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.
type PciIrqRoutingEntry = struct {
port_device_id uint8;
port_function_id uint8;
device_id uint8;
pins array<uint8, PINS_PER_FUNCTION>;
};
/// 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.
type PciLegacyIrq = resource struct {
interrupt zx.handle:INTERRUPT;
vector uint32;
};
/// 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|.
type PciPlatformInfo = resource struct {
name string:8;
start_bus_num uint8;
end_bus_num uint8;
segment_group uint16;
ecam_vmo zx.handle:VMO;
legacy_irqs vector<PciLegacyIrq>:MAX;
irq_routing vector<PciIrqRoutingEntry>:MAX;
/// A vector of PciBdfs that are known to ACPI.
/// For each BDF in this list, the composite device published by the PCI bus
/// driver will bind to an ACPI device with ACPI_BUS_TYPE == PCI and a
/// matching PCI_BIND_TOPO.
acpi_bdfs vector<PciBdf>:MAX;
};
type PciAddressSpace = strict enum : uint8 {
MEMORY = 0;
IO = 0x1;
};
@transport("Banjo")
@banjo_layout("ddk-protocol")
protocol Pciroot {
/// Legacy methods
GetBti(struct {
bdf uint32;
index uint32;
}) -> (resource struct {
s zx.status;
bti zx.handle:BTI;
});
/// Get the platform information structure from the pciroot protocol to be used for bus init.
GetPciPlatformInfo() -> (resource struct {
s zx.status;
info PciPlatformInfo;
});
/// 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() -> (struct {
use_proxy bool;
});
/// Read 8 bytes from config space for device at bdf address |address|:we, offset |offset|.
ReadConfig8(struct {
address PciBdf;
offset uint16;
}) -> (struct {
s zx.status;
value uint8;
});
/// Read 16 bytes from config space for device at bdf address |address|, offset |offset|.
ReadConfig16(struct {
address PciBdf;
offset uint16;
}) -> (struct {
s zx.status;
value uint16;
});
/// Read 32 bytes from config space for device at bdf address |address|, offset |offset|.
ReadConfig32(struct {
address PciBdf;
offset uint16;
}) -> (struct {
s zx.status;
value uint32;
});
/// Write 8 bytes to config space for device at bdf |address| offset |offset|.
WriteConfig8(struct {
address PciBdf;
offset uint16;
value uint8;
}) -> (struct {
s zx.status;
});
/// Write 16 bytes to config space for device at bdf |address| offset |offset|.
WriteConfig16(struct {
address PciBdf;
offset uint16;
value uint16;
}) -> (struct {
s zx.status;
});
/// Write 32 bytes to config space for device at bdf |address| offset |offset|.
WriteConfig32(struct {
address PciBdf;
offset uint16;
value uint32;
}) -> (struct {
s zx.status;
});
/// 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(struct {
in_base zx.paddr;
size uint64;
type PciAddressSpace;
low bool;
}) -> (resource struct {
s zx.status;
base zx.paddr;
resource zx.handle:RESOURCE;
token zx.handle:EVENTPAIR;
});
/// Allocate |msi_count| MSIs and return a handle to the backing MsiAllocation.
AllocateMsi(struct {
msi_count uint32;
can_target_64bit bool;
}) -> (resource struct {
s zx.status;
allocation zx.handle:MSI;
});
};