| // 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 = 32; |
| 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 { |
| NONE = 0; |
| MEMORY = 1; |
| IO = 2; |
| }; |
| |
| @transport("Banjo") |
| @banjo_layout("ddk-protocol") |
| closed protocol Pciroot { |
| /// Legacy methods |
| strict 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. |
| strict 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. |
| strict DriverShouldProxyConfig() -> (struct { |
| use_proxy bool; |
| }); |
| /// Read 8 bytes from config space for device at bdf address |address|:we, offset |offset|. |
| strict 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|. |
| strict 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|. |
| strict 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|. |
| strict 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|. |
| strict 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|. |
| strict 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. |
| strict GetAddressSpace(struct { |
| in_base uint64; |
| size uint64; |
| type PciAddressSpace; |
| low bool; |
| }) -> (resource struct { |
| s zx.Status; |
| base uint64; |
| resource zx.Handle:RESOURCE; |
| token zx.Handle:EVENTPAIR; |
| }); |
| /// Allocate |msi_count| MSIs and return a handle to the backing MsiAllocation. |
| strict AllocateMsi(struct { |
| msi_count uint32; |
| can_target_64bit bool; |
| }) -> (resource struct { |
| s zx.Status; |
| allocation zx.Handle:MSI; |
| }); |
| }; |