1 // Copyright 2018 The Fuchsia Authors 2 // Copyright (c) 2016, Google, Inc. All rights reserved 3 // 4 // Use of this source code is governed by a MIT-style 5 // license that can be found in the LICENSE file or at 6 // https://opensource.org/licenses/MIT 7 8 #pragma once 9 10 #include <dev/address_provider/ecam_region.h> 11 #include <dev/pci_config.h> 12 #include <fbl/intrusive_wavl_tree.h> 13 #include <fbl/mutex.h> 14 #include <sys/types.h> 15 #include <zircon/types.h> 16 17 // PcieAddressProvider is an interface that implements translation from a BDF to 18 // a PCI ECAM address. 19 class PcieAddressProvider { 20 public: ~PcieAddressProvider()21 virtual ~PcieAddressProvider() {} 22 23 // Accepts a PCI BDF triple and returns ZX_OK if it is able to translate it 24 // into an ECAM address. 25 // Upon success, virt will contain the ECAM address provided by the 26 // translation. phys will optionally contain the corresponding physical 27 // address. 28 // On failure, result must not be touched by the implementation. 29 virtual zx_status_t Translate(uint8_t bus_id, uint8_t device_id, uint8_t function_id, 30 vaddr_t* virt, paddr_t* phys) = 0; 31 32 // Creates a config that corresponds to the type of the PcieAddressProvider. 33 // For example, a PioAddressProvider will return a PioConfig whereas an 34 // MmioAddressProvider will return an MmioConfig. 35 virtual fbl::RefPtr<PciConfig> CreateConfig(const uintptr_t addr) = 0; 36 37 protected: PcieAddressProvider()38 PcieAddressProvider() {} 39 }; 40 41 // Concrete implementations. 42 43 // Systems that have memory mapped Config Spaces 44 class MmioPcieAddressProvider : public PcieAddressProvider { 45 public: MmioPcieAddressProvider()46 MmioPcieAddressProvider() {} 47 ~MmioPcieAddressProvider(); 48 49 zx_status_t Translate(uint8_t bus_id, uint8_t device_id, uint8_t function_id, 50 vaddr_t* virt, paddr_t* phys) override; 51 fbl::RefPtr<PciConfig> CreateConfig(const uintptr_t addr) override; 52 53 zx_status_t AddEcamRegion(const PciEcamRegion& ecam); 54 55 private: 56 mutable fbl::Mutex ecam_region_lock_; 57 fbl::WAVLTree<uint8_t, ktl::unique_ptr<MappedEcamRegion>> ecam_regions_; 58 }; 59 60 // Systems that have PIO mapped Config Spaces 61 class PioPcieAddressProvider : public PcieAddressProvider { 62 public: PioPcieAddressProvider()63 PioPcieAddressProvider() {} 64 65 zx_status_t Translate(uint8_t bus_id, uint8_t device_id, uint8_t function_id, 66 vaddr_t* virt, paddr_t* phys) override; 67 fbl::RefPtr<PciConfig> CreateConfig(const uintptr_t addr) override; 68 }; 69 70 71 class DesignWarePcieAddressProvider : public PcieAddressProvider { 72 public: DesignWarePcieAddressProvider()73 DesignWarePcieAddressProvider() {} ~DesignWarePcieAddressProvider()74 ~DesignWarePcieAddressProvider() {} 75 76 zx_status_t Init(const PciEcamRegion& root_bridge, 77 const PciEcamRegion& downstream_device); 78 79 zx_status_t Translate(uint8_t bus_id, uint8_t device_id, uint8_t function_id, 80 vaddr_t* virt, paddr_t* phys) override; 81 fbl::RefPtr<PciConfig> CreateConfig(const uintptr_t addr) override; 82 83 private: 84 ktl::unique_ptr<MappedEcamRegion> root_bridge_region_; 85 ktl::unique_ptr<MappedEcamRegion> downstream_region_; 86 }; 87