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; 54 virtual void configure(const ipmi_flash::PciConfigResponse&) override {}; 55 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: 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 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 { 106 vid, did, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0 107 }; 108 109 static constexpr pciaddr_t bridge = 0x04; 110 static constexpr std::uint8_t bridgeEnabled = 0x02; 111 112 static constexpr std::size_t dataOffset = 0x0; 113 static constexpr std::size_t dataLength = 0x4000; 114 115 void enableBridge(); 116 void disableBridge(); 117 118 bool skipBridgeDisable; 119 }; 120 121 class AspeedPciBridge : public PciAccessBridge 122 { 123 public: 124 explicit AspeedPciBridge(const PciAccess* pciAccess, 125 bool skipBridgeDisable = false) : 126 PciAccessBridge(&match, bar, dataOffset, dataLength, pciAccess), 127 skipBridgeDisable(skipBridgeDisable) 128 { 129 enableBridge(); 130 } 131 132 ~AspeedPciBridge() 133 { 134 if (!skipBridgeDisable) 135 disableBridge(); 136 } 137 138 void configure(const ipmi_flash::PciConfigResponse& configResp) override; 139 140 private: 141 static constexpr std::uint32_t vid = 0x1a03; 142 static constexpr std::uint32_t did = 0x2000; 143 static constexpr int bar = 1; 144 static constexpr struct pci_id_match match 145 { 146 vid, did, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0 147 }; 148 149 static constexpr std::size_t config = 0x0f000; 150 static constexpr std::size_t bridge = 0x0f004; 151 static constexpr std::uint32_t bridgeEnabled = 0x1; 152 153 static constexpr std::size_t dataOffset = 0x10000; 154 static constexpr std::size_t dataLength = 0x10000; 155 156 void enableBridge(); 157 void disableBridge(); 158 159 bool skipBridgeDisable; 160 }; 161 162 } // namespace host_tool 163