1/* 2 * Copyright (c) 2015 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Andreas Sandberg 38 */ 39 40#ifndef __DEV_PCI_HOST_HH__ 41#define __DEV_PCI_HOST_HH__ 42 43#include "dev/io_device.hh" 44#include "dev/pci/types.hh" 45 46struct PciHostParams; 47struct GenericPciHostParams; 48 49class PciDevice; 50class Platform; 51 52/** 53 * The PCI host describes the interface between PCI devices and a 54 * simulated system. 55 * 56 * The PCI host controller has three main responsibilities: 57 * <ol> 58 * <li>Expose a configuration memory space that allows devices to 59 * be discovered and configured. 60 * <li>Map and deliver interrupts to the CPU. 61 * <li>Map memory addresses from the PCI bus's various memory 62 * spaces (Legacy IO, non-prefetchable memory, and 63 * prefetchable memory) to physical memory. 64 * </ol> 65 * 66 * PCI devices need to register themselves with a PCI host using the 67 * PciHost::registerDevice() call. This call returns a 68 * PciHost::DeviceInterface that provides for common functionality 69 * such as interrupt delivery and memory mapping. 70 * 71 * The PciHost class itself provides very little functionality. Simple 72 * PciHost functionality is implemented by the GenericPciHost class. 73 */ 74class PciHost : public PioDevice 75{ 76 public: 77 PciHost(const PciHostParams *p); 78 virtual ~PciHost(); 79 80 public: 81 /** 82 * @{ 83 * @name Device interface 84 */ 85 86 /** 87 * Callback interface from PCI devices to the host. 88 * 89 * Devices get an instance of this object when they register 90 * themselves with the host using the PciHost::registerDevice() 91 * call. 92 */ 93 class DeviceInterface 94 { 95 friend class ::PciHost; 96 97 protected: 98 /** 99 * Instantiate a device interface 100 * 101 * @param host PCI host that this device belongs to. 102 * @param bus_addr The device's position on the PCI bus 103 * @param pin Interrupt pin 104 */ 105 DeviceInterface(PciHost &host, PciBusAddr &bus_addr, PciIntPin pin); 106 107 public: 108 DeviceInterface() = delete; 109 void operator=(const DeviceInterface &) = delete; 110 111 const std::string name() const; 112 113 /** 114 * Post a PCI interrupt to the CPU. 115 */ 116 void postInt(); 117 118 /** 119 * Clear a posted PCI interrupt 120 */ 121 void clearInt(); 122 123 /** 124 * Calculate the physical address of an IO location on the PCI 125 * bus. 126 * 127 * @param addr Address in the PCI IO address space 128 * @return Address in the system's physical address space. 129 */ 130 Addr pioAddr(Addr addr) const { return host.pioAddr(busAddr, addr); } 131 132 /** 133 * Calculate the physical address of a non-prefetchable memory 134 * location in the PCI address space. 135 * 136 * @param addr Address in the PCI memory address space 137 * @return Address in the system's physical address space. 138 */ 139 Addr memAddr(Addr addr) const { return host.memAddr(busAddr, addr); } 140 141 /** 142 * Calculate the physical address of a prefetchable memory 143 * location in the PCI address space. 144 * 145 * @param addr Address in the PCI DMA memory address space 146 * @return Address in the system's physical address space. 147 */ 148 Addr dmaAddr(Addr addr) const { return host.dmaAddr(busAddr, addr); } 149 150 protected: 151 PciHost &host; 152 153 const PciBusAddr busAddr; 154 const PciIntPin interruptPin; 155 }; 156 157 /** 158 * Register a PCI device with the host. 159 * 160 * @param device Device to register 161 * @param bus_addr The device's position on the PCI bus 162 * @param pin Interrupt pin 163 * @return A device-specific DeviceInterface instance. 164 */ 165 virtual DeviceInterface registerDevice(PciDevice *device, 166 PciBusAddr bus_addr, PciIntPin pin); 167 168 /** @} */ 169 170 protected: 171 /** 172 * @{ 173 * @name PciHost controller interface 174 */ 175 176 /** 177 * Post an interrupt to the CPU. 178 * 179 * @param bus_addr The device's position on the PCI bus 180 * @param pin PCI interrupt pin 181 */ 182 virtual void postInt(const PciBusAddr &bus_addr, PciIntPin pin) = 0; 183 184 /** 185 * Post an interrupt to the CPU. 186 * 187 * @param bus_addr The device's position on the PCI bus 188 * @param pin PCI interrupt pin 189 */ 190 virtual void clearInt(const PciBusAddr &bus_addr, PciIntPin pin) = 0; 191 192 /** 193 * Calculate the physical address of an IO location on the PCI 194 * bus. 195 * 196 * @param bus_addr The device's position on the PCI bus 197 * @param pci_addr Address in the PCI IO address space 198 * @return Address in the system's physical address space. 199 */ 200 virtual Addr pioAddr(const PciBusAddr &bus_addr, Addr pci_addr) const = 0; 201 202 /** 203 * Calculate the physical address of a non-prefetchable memory 204 * location in the PCI address space. 205 * 206 * @param bus_addr The device's position on the PCI bus 207 * @param pci_addr Address in the PCI memory address space 208 * @return Address in the system's physical address space. 209 */ 210 virtual Addr memAddr(const PciBusAddr &bus_addr, Addr pci_addr) const = 0; 211 212 213 /** 214 * Calculate the physical address of a prefetchable memory 215 * location in the PCI address space. 216 * 217 * @param bus_addr The device's position on the PCI bus 218 * @param pci_addr Address in the PCI DMA memory address space 219 * @return Address in the system's physical address space. 220 */ 221 virtual Addr dmaAddr(const PciBusAddr &bus_addr, Addr pci_addr) const = 0; 222 223 /** @} */ 224 225 protected: 226 /** 227 * Retrieve a PCI device from its bus address. 228 * 229 * @return Pointer to a PciDevice instance or nullptr if the 230 * device doesn't exist. 231 */ 232 PciDevice *getDevice(const PciBusAddr &addr); 233 234 /** 235 * Retrieve a PCI device from its bus address. 236 * 237 * @return Pointer to a constant PciDevice instance or nullptr if 238 * the device doesn't exist. 239 */ 240 const PciDevice *getDevice(const PciBusAddr &addr) const; 241 242 private: 243 /** Currently registered PCI devices */ 244 std::map<PciBusAddr, PciDevice *> devices; 245}; 246 247/** 248 * Configurable generic PCI host interface 249 * 250 * The GenericPciHost provides a configurable generic PCI host 251 * implementation. 252 * 253 * The generic controller binds to one range of physical addresses to 254 * implement the PCI subsystem's configuraiton space. The base 255 * address, size and mapping between memory addresses and PCI devices 256 * are all configurable as simulation parameters. The basic 257 * implementation supports both the Configuration Access Mechanism 258 * (CAM) and Enhanced Configuration Access Mechanism (ECAM) 259 * configuration space layout. The layouts can be configured by 260 * changing the number of bits allocated to each device in the 261 * configuration space. ECAM uses 12 bits per device, while CAM uses 8 262 * bits per device. 263 * 264 * Interrupts are delivered via the Platform::postInt() and 265 * Platform::clearInt() calls. Interrupt numbers are mapped statically 266 * using the interrupt line (PciDevice::interruptLine()) returned from 267 * the device. Implementations may override mapPciInterrupt() to 268 * dynamically map a PciBusAddr and PciIntPin to a platform-specific 269 * interrupt. 270 * 271 * All PCI memory spaces (IO, prefetchable, and non-prefetchable) 272 * support a simple base+offset mapping that can be configured using 273 * simulation parameters. The base defaults to 0 for all of them. 274 */ 275class GenericPciHost : public PciHost 276{ 277 public: 278 GenericPciHost(const GenericPciHostParams *p); 279 virtual ~GenericPciHost(); 280 281 public: // PioDevice 282 Tick read(PacketPtr pkt) override; 283 Tick write(PacketPtr pkt) override; 284 285 AddrRangeList getAddrRanges() const override; 286 287 protected: // PciHost 288 Addr pioAddr(const PciBusAddr &bus_addr, Addr pci_addr) const override { 289 return pciPioBase + pci_addr; 290 } 291 292 Addr memAddr(const PciBusAddr &bus_addr, Addr pci_addr) const override { 293 return pciMemBase + pci_addr; 294 } 295 296 Addr dmaAddr(const PciBusAddr &bus_addr, Addr pci_addr) const override { 297 return pciDmaBase + pci_addr; 298 } 299 300 protected: // Configuration address space handling 301 /** 302 * Decode a configuration space address. 303 * 304 * 305 * @param addr Offset into the configuration space 306 * @return Tuple containing the PCI bus address and an offset into 307 * the device's configuration space. 308 */ 309 virtual std::pair<PciBusAddr, Addr> decodeAddress(Addr address); 310 311 protected: // Interrupt handling 312 void postInt(const PciBusAddr &addr, PciIntPin pin) override; 313 void clearInt(const PciBusAddr &addr, PciIntPin pin) override; 314 315 virtual uint32_t mapPciInterrupt(const PciBusAddr &bus_addr, 316 PciIntPin pin) const; 317 318 protected: 319 Platform &platform; 320 321 const Addr confBase; 322 const Addr confSize; 323 const uint8_t confDeviceBits; 324 325 const Addr pciPioBase; 326 const Addr pciMemBase; 327 const Addr pciDmaBase; 328}; 329 330#endif // __DEV_PCI_HOST_HH__ 331