1 /* 2 * Copyright 2020 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "config.h" 18 19 #pragma once 20 21 #include "data.hpp" 22 #include "internal/sys.hpp" 23 #include "pciaccess.hpp" 24 25 #include <linux/pci_regs.h> 26 27 #include <span> 28 29 // Some versions of the linux/pci_regs.h header don't define this 30 #ifndef PCI_STD_NUM_BARS 31 #define PCI_STD_NUM_BARS 6 32 #endif // !PCI_STD_NUM_BARS 33 34 namespace host_tool 35 { 36 37 class PciBridgeIntf 38 { 39 public: 40 virtual ~PciBridgeIntf() = default; 41 42 virtual void write(const std::span<const std::uint8_t> data) = 0; 43 virtual void configure(const ipmi_flash::PciConfigResponse& config) = 0; 44 45 virtual std::size_t getDataLength() = 0; 46 }; 47 48 class PciAccessBridge : public PciBridgeIntf 49 { 50 public: 51 virtual ~PciAccessBridge(); 52 53 virtual void write(const std::span<const std::uint8_t> data) override; configure(const ipmi_flash::PciConfigResponse &)54 virtual void configure(const ipmi_flash::PciConfigResponse&) override {}; 55 getDataLength()56 std::size_t getDataLength() override 57 { 58 return dataLength; 59 } 60 61 protected: 62 /** 63 * Finds the PCI device matching @a match and saves a reference to it in @a 64 * dev. Also maps the memory region described in BAR number @a bar to 65 * address @a addr, 66 */ 67 PciAccessBridge(const struct pci_id_match* match, int bar, 68 std::size_t dataOffset, std::size_t dataLength, 69 const PciAccess* pci); 70 71 struct pci_device* dev = nullptr; 72 std::uint8_t* addr = nullptr; 73 std::size_t size = 0; 74 75 private: 76 std::size_t dataOffset; 77 std::size_t dataLength; 78 79 protected: 80 const PciAccess* pci; 81 }; 82 83 class NuvotonPciBridge : public PciAccessBridge 84 { 85 public: NuvotonPciBridge(const PciAccess * pciAccess,bool skipBridgeDisable=false)86 explicit NuvotonPciBridge(const PciAccess* pciAccess, 87 bool skipBridgeDisable = false) : 88 PciAccessBridge(&match, bar, dataOffset, dataLength, pciAccess), 89 skipBridgeDisable(skipBridgeDisable) 90 { 91 enableBridge(); 92 } 93 ~NuvotonPciBridge()94 ~NuvotonPciBridge() 95 { 96 if (!skipBridgeDisable) 97 disableBridge(); 98 } 99 100 private: 101 static constexpr std::uint32_t vid = 0x1050; 102 static constexpr std::uint32_t did = NUVOTON_PCI_DID; 103 static constexpr int bar = 0; 104 static constexpr struct pci_id_match match{ 105 vid, did, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0}; 106 107 static constexpr pciaddr_t bridge = 0x04; 108 static constexpr std::uint8_t bridgeEnabled = 0x02; 109 110 static constexpr std::size_t dataOffset = 0x0; 111 static constexpr std::size_t dataLength = 0x4000; 112 113 void enableBridge(); 114 void disableBridge(); 115 116 bool skipBridgeDisable; 117 }; 118 119 class AspeedPciBridge : public PciAccessBridge 120 { 121 public: AspeedPciBridge(const PciAccess * pciAccess,bool skipBridgeDisable=false)122 explicit AspeedPciBridge(const PciAccess* pciAccess, 123 bool skipBridgeDisable = false) : 124 PciAccessBridge(&match, bar, dataOffset, dataLength, pciAccess), 125 skipBridgeDisable(skipBridgeDisable) 126 { 127 enableBridge(); 128 } 129 ~AspeedPciBridge()130 ~AspeedPciBridge() 131 { 132 if (!skipBridgeDisable) 133 disableBridge(); 134 } 135 136 void configure(const ipmi_flash::PciConfigResponse& configResp) override; 137 138 private: 139 static constexpr std::uint32_t vid = 0x1a03; 140 static constexpr std::uint32_t did = 0x2000; 141 static constexpr int bar = 1; 142 static constexpr struct pci_id_match match{ 143 vid, did, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0}; 144 145 static constexpr std::size_t config = 0x0f000; 146 static constexpr std::size_t bridge = 0x0f004; 147 static constexpr std::uint32_t bridgeEnabled = 0x1; 148 149 static constexpr std::size_t dataOffset = 0x10000; 150 static constexpr std::size_t dataLength = 0x10000; 151 152 void enableBridge(); 153 void disableBridge(); 154 155 bool skipBridgeDisable; 156 }; 157 158 } // namespace host_tool 159