host.cc revision 11244:a2af58a06c4e
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#include "dev/pci/host.hh" 41 42#include <utility> 43 44#include "debug/PciHost.hh" 45#include "dev/pcidev.hh" 46#include "dev/platform.hh" 47#include "params/GenericPciHost.hh" 48#include "params/PciHost.hh" 49 50 51PciHost::PciHost(const PciHostParams *p) 52 : PioDevice(p) 53{ 54} 55 56PciHost::~PciHost() 57{ 58} 59 60PciHost::DeviceInterface 61PciHost::registerDevice(PciDevice *device, PciBusAddr bus_addr, PciIntPin pin) 62{ 63 auto map_entry = devices.emplace(bus_addr, device); 64 65 DPRINTF(PciHost, "%02x:%02x.%i: Registering device\n", 66 bus_addr.bus, bus_addr.dev, bus_addr.func); 67 68 fatal_if(!map_entry.second, 69 "%02x:%02x.%i: PCI bus ID collision\n", 70 bus_addr.bus, bus_addr.dev, bus_addr.func); 71 72 return DeviceInterface(*this, bus_addr, pin); 73} 74 75PciDevice * 76PciHost::getDevice(const PciBusAddr &addr) 77{ 78 auto device = devices.find(addr); 79 return device != devices.end() ? device->second : nullptr; 80} 81 82const PciDevice * 83PciHost::getDevice(const PciBusAddr &addr) const 84{ 85 auto device = devices.find(addr); 86 return device != devices.end() ? device->second : nullptr; 87} 88 89PciHost::DeviceInterface::DeviceInterface( 90 PciHost &_host, 91 PciBusAddr &bus_addr, PciIntPin interrupt_pin) 92 : host(_host), 93 busAddr(bus_addr), interruptPin(interrupt_pin) 94{ 95} 96 97const std::string 98PciHost::DeviceInterface::name() const 99{ 100 return csprintf("%s.interface[%02x:%02x.%i]", 101 host.name(), busAddr.bus, busAddr.dev, busAddr.func); 102} 103 104void 105PciHost::DeviceInterface::postInt() 106{ 107 DPRINTF(PciHost, "postInt\n"); 108 109 host.postInt(busAddr, interruptPin); 110} 111 112void 113PciHost::DeviceInterface::clearInt() 114{ 115 DPRINTF(PciHost, "clearInt\n"); 116 117 host.clearInt(busAddr, interruptPin); 118} 119 120 121GenericPciHost::GenericPciHost(const GenericPciHostParams *p) 122 : PciHost(p), 123 platform(*p->platform), 124 confBase(p->conf_base), confSize(p->conf_size), 125 confDeviceBits(p->conf_device_bits), 126 pciPioBase(p->pci_pio_base), pciMemBase(p->pci_mem_base), 127 pciDmaBase(p->pci_dma_base) 128{ 129} 130 131GenericPciHost::~GenericPciHost() 132{ 133} 134 135 136Tick 137GenericPciHost::read(PacketPtr pkt) 138{ 139 const auto dev_addr(decodeAddress(pkt->getAddr() - confBase)); 140 const Addr size(pkt->getSize()); 141 142 DPRINTF(PciHost, "%02x:%02x.%i: read: offset=0x%x, size=0x%x\n", 143 dev_addr.first.bus, dev_addr.first.dev, dev_addr.first.func, 144 dev_addr.second, 145 size); 146 147 PciDevice *const pci_dev(getDevice(dev_addr.first)); 148 if (pci_dev) { 149 // @todo Remove this after testing 150 pkt->headerDelay = pkt->payloadDelay = 0; 151 return pci_dev->readConfig(pkt); 152 } else { 153 uint8_t *pkt_data(pkt->getPtr<uint8_t>()); 154 std::fill(pkt_data, pkt_data + size, 0xFF); 155 pkt->makeAtomicResponse(); 156 return 0; 157 } 158} 159 160Tick 161GenericPciHost::write(PacketPtr pkt) 162{ 163 const auto dev_addr(decodeAddress(pkt->getAddr() - confBase)); 164 165 DPRINTF(PciHost, "%02x:%02x.%i: write: offset=0x%x, size=0x%x\n", 166 dev_addr.first.bus, dev_addr.first.dev, dev_addr.first.func, 167 dev_addr.second, 168 pkt->getSize()); 169 170 PciDevice *const pci_dev(getDevice(dev_addr.first)); 171 panic_if(!pci_dev, 172 "%02x:%02x.%i: Write to config space on non-existent PCI device\n", 173 dev_addr.first.bus, dev_addr.first.dev, dev_addr.first.func); 174 175 // @todo Remove this after testing 176 pkt->headerDelay = pkt->payloadDelay = 0; 177 178 return pci_dev->writeConfig(pkt); 179} 180 181AddrRangeList 182GenericPciHost::getAddrRanges() const 183{ 184 return AddrRangeList({ RangeSize(confBase, confSize) }); 185} 186 187std::pair<PciBusAddr, Addr> 188GenericPciHost::decodeAddress(Addr addr) 189{ 190 const Addr offset(addr & mask(confDeviceBits)); 191 const Addr bus_addr(addr >> confDeviceBits); 192 193 return std::make_pair( 194 PciBusAddr(bits(bus_addr, 15, 8), 195 bits(bus_addr, 7, 3), 196 bits(bus_addr, 2, 0)), 197 offset); 198} 199 200 201void 202GenericPciHost::postInt(const PciBusAddr &addr, PciIntPin pin) 203{ 204 platform.postPciInt(mapPciInterrupt(addr, pin)); 205} 206 207void 208GenericPciHost::clearInt(const PciBusAddr &addr, PciIntPin pin) 209{ 210 platform.clearPciInt(mapPciInterrupt(addr, pin)); 211} 212 213 214uint32_t 215GenericPciHost::mapPciInterrupt(const PciBusAddr &addr, PciIntPin pin) const 216{ 217 const PciDevice *dev(getDevice(addr)); 218 assert(dev); 219 220 return dev->interruptLine(); 221} 222 223 224GenericPciHost * 225GenericPciHostParams::create() 226{ 227 return new GenericPciHost(this); 228} 229