summaryrefslogtreecommitdiff
path: root/src/dev/pci/host.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/dev/pci/host.hh')
-rw-r--r--src/dev/pci/host.hh330
1 files changed, 330 insertions, 0 deletions
diff --git a/src/dev/pci/host.hh b/src/dev/pci/host.hh
new file mode 100644
index 000000000..0e6d580ab
--- /dev/null
+++ b/src/dev/pci/host.hh
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2015 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Andreas Sandberg
+ */
+
+#ifndef __DEV_PCI_HOST_HH__
+#define __DEV_PCI_HOST_HH__
+
+#include "dev/io_device.hh"
+#include "dev/pci/types.hh"
+
+struct PciHostParams;
+struct GenericPciHostParams;
+
+class PciDevice;
+class Platform;
+
+/**
+ * The PCI host describes the interface between PCI devices and a
+ * simulated system.
+ *
+ * The PCI host controller has three main responsibilities:
+ * <ol>
+ * <li>Expose a configuration memory space that allows devices to
+ * be discovered and configured.
+ * <li>Map and deliver interrupts to the CPU.
+ * <li>Map memory addresses from the PCI bus's various memory
+ * spaces (Legacy IO, non-prefetchable memory, and
+ * prefetchable memory) to physical memory.
+ * </ol>
+ *
+ * PCI devices need to register themselves with a PCI host using the
+ * PciHost::registerDevice() call. This call returns a
+ * PciHost::DeviceInterface that provides for common functionality
+ * such as interrupt delivery and memory mapping.
+ *
+ * The PciHost class itself provides very little functionality. Simple
+ * PciHost functionality is implemented by the GenericPciHost class.
+ */
+class PciHost : public PioDevice
+{
+ public:
+ PciHost(const PciHostParams *p);
+ virtual ~PciHost();
+
+ public:
+ /**
+ * @{
+ * @name Device interface
+ */
+
+ /**
+ * Callback interface from PCI devices to the host.
+ *
+ * Devices get an instance of this object when they register
+ * themselves with the host using the PciHost::registerDevice()
+ * call.
+ */
+ class DeviceInterface
+ {
+ friend class ::PciHost;
+
+ protected:
+ /**
+ * Instantiate a device interface
+ *
+ * @param host PCI host that this device belongs to.
+ * @param bus_addr The device's position on the PCI bus
+ * @param pin Interrupt pin
+ */
+ DeviceInterface(PciHost &host, PciBusAddr &bus_addr, PciIntPin pin);
+
+ public:
+ DeviceInterface() = delete;
+ void operator=(const DeviceInterface &) = delete;
+
+ const std::string name() const;
+
+ /**
+ * Post a PCI interrupt to the CPU.
+ */
+ void postInt();
+
+ /**
+ * Clear a posted PCI interrupt
+ */
+ void clearInt();
+
+ /**
+ * Calculate the physical address of an IO location on the PCI
+ * bus.
+ *
+ * @param addr Address in the PCI IO address space
+ * @return Address in the system's physical address space.
+ */
+ Addr pioAddr(Addr addr) const { return host.pioAddr(busAddr, addr); }
+
+ /**
+ * Calculate the physical address of a non-prefetchable memory
+ * location in the PCI address space.
+ *
+ * @param addr Address in the PCI memory address space
+ * @return Address in the system's physical address space.
+ */
+ Addr memAddr(Addr addr) const { return host.memAddr(busAddr, addr); }
+
+ /**
+ * Calculate the physical address of a prefetchable memory
+ * location in the PCI address space.
+ *
+ * @param addr Address in the PCI DMA memory address space
+ * @return Address in the system's physical address space.
+ */
+ Addr dmaAddr(Addr addr) const { return host.dmaAddr(busAddr, addr); }
+
+ protected:
+ PciHost &host;
+
+ const PciBusAddr busAddr;
+ const PciIntPin interruptPin;
+ };
+
+ /**
+ * Register a PCI device with the host.
+ *
+ * @param device Device to register
+ * @param bus_addr The device's position on the PCI bus
+ * @param pin Interrupt pin
+ * @return A device-specific DeviceInterface instance.
+ */
+ virtual DeviceInterface registerDevice(PciDevice *device,
+ PciBusAddr bus_addr, PciIntPin pin);
+
+ /** @} */
+
+ protected:
+ /**
+ * @{
+ * @name PciHost controller interface
+ */
+
+ /**
+ * Post an interrupt to the CPU.
+ *
+ * @param bus_addr The device's position on the PCI bus
+ * @param pin PCI interrupt pin
+ */
+ virtual void postInt(const PciBusAddr &bus_addr, PciIntPin pin) = 0;
+
+ /**
+ * Post an interrupt to the CPU.
+ *
+ * @param bus_addr The device's position on the PCI bus
+ * @param pin PCI interrupt pin
+ */
+ virtual void clearInt(const PciBusAddr &bus_addr, PciIntPin pin) = 0;
+
+ /**
+ * Calculate the physical address of an IO location on the PCI
+ * bus.
+ *
+ * @param bus_addr The device's position on the PCI bus
+ * @param pci_addr Address in the PCI IO address space
+ * @return Address in the system's physical address space.
+ */
+ virtual Addr pioAddr(const PciBusAddr &bus_addr, Addr pci_addr) const = 0;
+
+ /**
+ * Calculate the physical address of a non-prefetchable memory
+ * location in the PCI address space.
+ *
+ * @param bus_addr The device's position on the PCI bus
+ * @param pci_addr Address in the PCI memory address space
+ * @return Address in the system's physical address space.
+ */
+ virtual Addr memAddr(const PciBusAddr &bus_addr, Addr pci_addr) const = 0;
+
+
+ /**
+ * Calculate the physical address of a prefetchable memory
+ * location in the PCI address space.
+ *
+ * @param bus_addr The device's position on the PCI bus
+ * @param pci_addr Address in the PCI DMA memory address space
+ * @return Address in the system's physical address space.
+ */
+ virtual Addr dmaAddr(const PciBusAddr &bus_addr, Addr pci_addr) const = 0;
+
+ /** @} */
+
+ protected:
+ /**
+ * Retrieve a PCI device from its bus address.
+ *
+ * @return Pointer to a PciDevice instance or nullptr if the
+ * device doesn't exist.
+ */
+ PciDevice *getDevice(const PciBusAddr &addr);
+
+ /**
+ * Retrieve a PCI device from its bus address.
+ *
+ * @return Pointer to a constant PciDevice instance or nullptr if
+ * the device doesn't exist.
+ */
+ const PciDevice *getDevice(const PciBusAddr &addr) const;
+
+ private:
+ /** Currently registered PCI devices */
+ std::map<PciBusAddr, PciDevice *> devices;
+};
+
+/**
+ * Configurable generic PCI host interface
+ *
+ * The GenericPciHost provides a configurable generic PCI host
+ * implementation.
+ *
+ * The generic controller binds to one range of physical addresses to
+ * implement the PCI subsystem's configuraiton space. The base
+ * address, size and mapping between memory addresses and PCI devices
+ * are all configurable as simulation parameters. The basic
+ * implementation supports both the Configuration Access Mechanism
+ * (CAM) and Enhanced Configuration Access Mechanism (ECAM)
+ * configuration space layout. The layouts can be configured by
+ * changing the number of bits allocated to each device in the
+ * configuration space. ECAM uses 12 bits per device, while CAM uses 8
+ * bits per device.
+ *
+ * Interrupts are delivered via the Platform::postInt() and
+ * Platform::clearInt() calls. Interrupt numbers are mapped statically
+ * using the interrupt line (PciDevice::interruptLine()) returned from
+ * the device. Implementations may override mapPciInterrupt() to
+ * dynamically map a PciBusAddr and PciIntPin to a platform-specific
+ * interrupt.
+ *
+ * All PCI memory spaces (IO, prefetchable, and non-prefetchable)
+ * support a simple base+offset mapping that can be configured using
+ * simulation parameters. The base defaults to 0 for all of them.
+ */
+class GenericPciHost : public PciHost
+{
+ public:
+ GenericPciHost(const GenericPciHostParams *p);
+ virtual ~GenericPciHost();
+
+ public: // PioDevice
+ Tick read(PacketPtr pkt) override;
+ Tick write(PacketPtr pkt) override;
+
+ AddrRangeList getAddrRanges() const override;
+
+ protected: // PciHost
+ Addr pioAddr(const PciBusAddr &bus_addr, Addr pci_addr) const override {
+ return pciPioBase + pci_addr;
+ }
+
+ Addr memAddr(const PciBusAddr &bus_addr, Addr pci_addr) const override {
+ return pciMemBase + pci_addr;
+ }
+
+ Addr dmaAddr(const PciBusAddr &bus_addr, Addr pci_addr) const override {
+ return pciDmaBase + pci_addr;
+ }
+
+ protected: // Configuration address space handling
+ /**
+ * Decode a configuration space address.
+ *
+ *
+ * @param addr Offset into the configuration space
+ * @return Tuple containing the PCI bus address and an offset into
+ * the device's configuration space.
+ */
+ virtual std::pair<PciBusAddr, Addr> decodeAddress(Addr address);
+
+ protected: // Interrupt handling
+ void postInt(const PciBusAddr &addr, PciIntPin pin) override;
+ void clearInt(const PciBusAddr &addr, PciIntPin pin) override;
+
+ virtual uint32_t mapPciInterrupt(const PciBusAddr &bus_addr,
+ PciIntPin pin) const;
+
+ protected:
+ Platform &platform;
+
+ const Addr confBase;
+ const Addr confSize;
+ const uint8_t confDeviceBits;
+
+ const Addr pciPioBase;
+ const Addr pciMemBase;
+ const Addr pciDmaBase;
+};
+
+#endif // __DEV_PCI_HOST_HH__