host.cc revision 11244
111244Sandreas.sandberg@arm.com/* 211244Sandreas.sandberg@arm.com * Copyright (c) 2015 ARM Limited 311244Sandreas.sandberg@arm.com * All rights reserved 411244Sandreas.sandberg@arm.com * 511244Sandreas.sandberg@arm.com * The license below extends only to copyright in the software and shall 611244Sandreas.sandberg@arm.com * not be construed as granting a license to any other intellectual 711244Sandreas.sandberg@arm.com * property including but not limited to intellectual property relating 811244Sandreas.sandberg@arm.com * to a hardware implementation of the functionality of the software 911244Sandreas.sandberg@arm.com * licensed hereunder. You may use the software subject to the license 1011244Sandreas.sandberg@arm.com * terms below provided that you ensure that this notice is replicated 1111244Sandreas.sandberg@arm.com * unmodified and in its entirety in all distributions of the software, 1211244Sandreas.sandberg@arm.com * modified or unmodified, in source code or in binary form. 1311244Sandreas.sandberg@arm.com * 1411244Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without 1511244Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are 1611244Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright 1711244Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer; 1811244Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright 1911244Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the 2011244Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution; 2111244Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its 2211244Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from 2311244Sandreas.sandberg@arm.com * this software without specific prior written permission. 2411244Sandreas.sandberg@arm.com * 2511244Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2611244Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2711244Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2811244Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2911244Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3011244Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3111244Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3211244Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3311244Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3411244Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3511244Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3611244Sandreas.sandberg@arm.com * 3711244Sandreas.sandberg@arm.com * Authors: Andreas Sandberg 3811244Sandreas.sandberg@arm.com */ 3911244Sandreas.sandberg@arm.com 4011244Sandreas.sandberg@arm.com#include "dev/pci/host.hh" 4111244Sandreas.sandberg@arm.com 4211244Sandreas.sandberg@arm.com#include <utility> 4311244Sandreas.sandberg@arm.com 4411244Sandreas.sandberg@arm.com#include "debug/PciHost.hh" 4511244Sandreas.sandberg@arm.com#include "dev/pcidev.hh" 4611244Sandreas.sandberg@arm.com#include "dev/platform.hh" 4711244Sandreas.sandberg@arm.com#include "params/GenericPciHost.hh" 4811244Sandreas.sandberg@arm.com#include "params/PciHost.hh" 4911244Sandreas.sandberg@arm.com 5011244Sandreas.sandberg@arm.com 5111244Sandreas.sandberg@arm.comPciHost::PciHost(const PciHostParams *p) 5211244Sandreas.sandberg@arm.com : PioDevice(p) 5311244Sandreas.sandberg@arm.com{ 5411244Sandreas.sandberg@arm.com} 5511244Sandreas.sandberg@arm.com 5611244Sandreas.sandberg@arm.comPciHost::~PciHost() 5711244Sandreas.sandberg@arm.com{ 5811244Sandreas.sandberg@arm.com} 5911244Sandreas.sandberg@arm.com 6011244Sandreas.sandberg@arm.comPciHost::DeviceInterface 6111244Sandreas.sandberg@arm.comPciHost::registerDevice(PciDevice *device, PciBusAddr bus_addr, PciIntPin pin) 6211244Sandreas.sandberg@arm.com{ 6311244Sandreas.sandberg@arm.com auto map_entry = devices.emplace(bus_addr, device); 6411244Sandreas.sandberg@arm.com 6511244Sandreas.sandberg@arm.com DPRINTF(PciHost, "%02x:%02x.%i: Registering device\n", 6611244Sandreas.sandberg@arm.com bus_addr.bus, bus_addr.dev, bus_addr.func); 6711244Sandreas.sandberg@arm.com 6811244Sandreas.sandberg@arm.com fatal_if(!map_entry.second, 6911244Sandreas.sandberg@arm.com "%02x:%02x.%i: PCI bus ID collision\n", 7011244Sandreas.sandberg@arm.com bus_addr.bus, bus_addr.dev, bus_addr.func); 7111244Sandreas.sandberg@arm.com 7211244Sandreas.sandberg@arm.com return DeviceInterface(*this, bus_addr, pin); 7311244Sandreas.sandberg@arm.com} 7411244Sandreas.sandberg@arm.com 7511244Sandreas.sandberg@arm.comPciDevice * 7611244Sandreas.sandberg@arm.comPciHost::getDevice(const PciBusAddr &addr) 7711244Sandreas.sandberg@arm.com{ 7811244Sandreas.sandberg@arm.com auto device = devices.find(addr); 7911244Sandreas.sandberg@arm.com return device != devices.end() ? device->second : nullptr; 8011244Sandreas.sandberg@arm.com} 8111244Sandreas.sandberg@arm.com 8211244Sandreas.sandberg@arm.comconst PciDevice * 8311244Sandreas.sandberg@arm.comPciHost::getDevice(const PciBusAddr &addr) const 8411244Sandreas.sandberg@arm.com{ 8511244Sandreas.sandberg@arm.com auto device = devices.find(addr); 8611244Sandreas.sandberg@arm.com return device != devices.end() ? device->second : nullptr; 8711244Sandreas.sandberg@arm.com} 8811244Sandreas.sandberg@arm.com 8911244Sandreas.sandberg@arm.comPciHost::DeviceInterface::DeviceInterface( 9011244Sandreas.sandberg@arm.com PciHost &_host, 9111244Sandreas.sandberg@arm.com PciBusAddr &bus_addr, PciIntPin interrupt_pin) 9211244Sandreas.sandberg@arm.com : host(_host), 9311244Sandreas.sandberg@arm.com busAddr(bus_addr), interruptPin(interrupt_pin) 9411244Sandreas.sandberg@arm.com{ 9511244Sandreas.sandberg@arm.com} 9611244Sandreas.sandberg@arm.com 9711244Sandreas.sandberg@arm.comconst std::string 9811244Sandreas.sandberg@arm.comPciHost::DeviceInterface::name() const 9911244Sandreas.sandberg@arm.com{ 10011244Sandreas.sandberg@arm.com return csprintf("%s.interface[%02x:%02x.%i]", 10111244Sandreas.sandberg@arm.com host.name(), busAddr.bus, busAddr.dev, busAddr.func); 10211244Sandreas.sandberg@arm.com} 10311244Sandreas.sandberg@arm.com 10411244Sandreas.sandberg@arm.comvoid 10511244Sandreas.sandberg@arm.comPciHost::DeviceInterface::postInt() 10611244Sandreas.sandberg@arm.com{ 10711244Sandreas.sandberg@arm.com DPRINTF(PciHost, "postInt\n"); 10811244Sandreas.sandberg@arm.com 10911244Sandreas.sandberg@arm.com host.postInt(busAddr, interruptPin); 11011244Sandreas.sandberg@arm.com} 11111244Sandreas.sandberg@arm.com 11211244Sandreas.sandberg@arm.comvoid 11311244Sandreas.sandberg@arm.comPciHost::DeviceInterface::clearInt() 11411244Sandreas.sandberg@arm.com{ 11511244Sandreas.sandberg@arm.com DPRINTF(PciHost, "clearInt\n"); 11611244Sandreas.sandberg@arm.com 11711244Sandreas.sandberg@arm.com host.clearInt(busAddr, interruptPin); 11811244Sandreas.sandberg@arm.com} 11911244Sandreas.sandberg@arm.com 12011244Sandreas.sandberg@arm.com 12111244Sandreas.sandberg@arm.comGenericPciHost::GenericPciHost(const GenericPciHostParams *p) 12211244Sandreas.sandberg@arm.com : PciHost(p), 12311244Sandreas.sandberg@arm.com platform(*p->platform), 12411244Sandreas.sandberg@arm.com confBase(p->conf_base), confSize(p->conf_size), 12511244Sandreas.sandberg@arm.com confDeviceBits(p->conf_device_bits), 12611244Sandreas.sandberg@arm.com pciPioBase(p->pci_pio_base), pciMemBase(p->pci_mem_base), 12711244Sandreas.sandberg@arm.com pciDmaBase(p->pci_dma_base) 12811244Sandreas.sandberg@arm.com{ 12911244Sandreas.sandberg@arm.com} 13011244Sandreas.sandberg@arm.com 13111244Sandreas.sandberg@arm.comGenericPciHost::~GenericPciHost() 13211244Sandreas.sandberg@arm.com{ 13311244Sandreas.sandberg@arm.com} 13411244Sandreas.sandberg@arm.com 13511244Sandreas.sandberg@arm.com 13611244Sandreas.sandberg@arm.comTick 13711244Sandreas.sandberg@arm.comGenericPciHost::read(PacketPtr pkt) 13811244Sandreas.sandberg@arm.com{ 13911244Sandreas.sandberg@arm.com const auto dev_addr(decodeAddress(pkt->getAddr() - confBase)); 14011244Sandreas.sandberg@arm.com const Addr size(pkt->getSize()); 14111244Sandreas.sandberg@arm.com 14211244Sandreas.sandberg@arm.com DPRINTF(PciHost, "%02x:%02x.%i: read: offset=0x%x, size=0x%x\n", 14311244Sandreas.sandberg@arm.com dev_addr.first.bus, dev_addr.first.dev, dev_addr.first.func, 14411244Sandreas.sandberg@arm.com dev_addr.second, 14511244Sandreas.sandberg@arm.com size); 14611244Sandreas.sandberg@arm.com 14711244Sandreas.sandberg@arm.com PciDevice *const pci_dev(getDevice(dev_addr.first)); 14811244Sandreas.sandberg@arm.com if (pci_dev) { 14911244Sandreas.sandberg@arm.com // @todo Remove this after testing 15011244Sandreas.sandberg@arm.com pkt->headerDelay = pkt->payloadDelay = 0; 15111244Sandreas.sandberg@arm.com return pci_dev->readConfig(pkt); 15211244Sandreas.sandberg@arm.com } else { 15311244Sandreas.sandberg@arm.com uint8_t *pkt_data(pkt->getPtr<uint8_t>()); 15411244Sandreas.sandberg@arm.com std::fill(pkt_data, pkt_data + size, 0xFF); 15511244Sandreas.sandberg@arm.com pkt->makeAtomicResponse(); 15611244Sandreas.sandberg@arm.com return 0; 15711244Sandreas.sandberg@arm.com } 15811244Sandreas.sandberg@arm.com} 15911244Sandreas.sandberg@arm.com 16011244Sandreas.sandberg@arm.comTick 16111244Sandreas.sandberg@arm.comGenericPciHost::write(PacketPtr pkt) 16211244Sandreas.sandberg@arm.com{ 16311244Sandreas.sandberg@arm.com const auto dev_addr(decodeAddress(pkt->getAddr() - confBase)); 16411244Sandreas.sandberg@arm.com 16511244Sandreas.sandberg@arm.com DPRINTF(PciHost, "%02x:%02x.%i: write: offset=0x%x, size=0x%x\n", 16611244Sandreas.sandberg@arm.com dev_addr.first.bus, dev_addr.first.dev, dev_addr.first.func, 16711244Sandreas.sandberg@arm.com dev_addr.second, 16811244Sandreas.sandberg@arm.com pkt->getSize()); 16911244Sandreas.sandberg@arm.com 17011244Sandreas.sandberg@arm.com PciDevice *const pci_dev(getDevice(dev_addr.first)); 17111244Sandreas.sandberg@arm.com panic_if(!pci_dev, 17211244Sandreas.sandberg@arm.com "%02x:%02x.%i: Write to config space on non-existent PCI device\n", 17311244Sandreas.sandberg@arm.com dev_addr.first.bus, dev_addr.first.dev, dev_addr.first.func); 17411244Sandreas.sandberg@arm.com 17511244Sandreas.sandberg@arm.com // @todo Remove this after testing 17611244Sandreas.sandberg@arm.com pkt->headerDelay = pkt->payloadDelay = 0; 17711244Sandreas.sandberg@arm.com 17811244Sandreas.sandberg@arm.com return pci_dev->writeConfig(pkt); 17911244Sandreas.sandberg@arm.com} 18011244Sandreas.sandberg@arm.com 18111244Sandreas.sandberg@arm.comAddrRangeList 18211244Sandreas.sandberg@arm.comGenericPciHost::getAddrRanges() const 18311244Sandreas.sandberg@arm.com{ 18411244Sandreas.sandberg@arm.com return AddrRangeList({ RangeSize(confBase, confSize) }); 18511244Sandreas.sandberg@arm.com} 18611244Sandreas.sandberg@arm.com 18711244Sandreas.sandberg@arm.comstd::pair<PciBusAddr, Addr> 18811244Sandreas.sandberg@arm.comGenericPciHost::decodeAddress(Addr addr) 18911244Sandreas.sandberg@arm.com{ 19011244Sandreas.sandberg@arm.com const Addr offset(addr & mask(confDeviceBits)); 19111244Sandreas.sandberg@arm.com const Addr bus_addr(addr >> confDeviceBits); 19211244Sandreas.sandberg@arm.com 19311244Sandreas.sandberg@arm.com return std::make_pair( 19411244Sandreas.sandberg@arm.com PciBusAddr(bits(bus_addr, 15, 8), 19511244Sandreas.sandberg@arm.com bits(bus_addr, 7, 3), 19611244Sandreas.sandberg@arm.com bits(bus_addr, 2, 0)), 19711244Sandreas.sandberg@arm.com offset); 19811244Sandreas.sandberg@arm.com} 19911244Sandreas.sandberg@arm.com 20011244Sandreas.sandberg@arm.com 20111244Sandreas.sandberg@arm.comvoid 20211244Sandreas.sandberg@arm.comGenericPciHost::postInt(const PciBusAddr &addr, PciIntPin pin) 20311244Sandreas.sandberg@arm.com{ 20411244Sandreas.sandberg@arm.com platform.postPciInt(mapPciInterrupt(addr, pin)); 20511244Sandreas.sandberg@arm.com} 20611244Sandreas.sandberg@arm.com 20711244Sandreas.sandberg@arm.comvoid 20811244Sandreas.sandberg@arm.comGenericPciHost::clearInt(const PciBusAddr &addr, PciIntPin pin) 20911244Sandreas.sandberg@arm.com{ 21011244Sandreas.sandberg@arm.com platform.clearPciInt(mapPciInterrupt(addr, pin)); 21111244Sandreas.sandberg@arm.com} 21211244Sandreas.sandberg@arm.com 21311244Sandreas.sandberg@arm.com 21411244Sandreas.sandberg@arm.comuint32_t 21511244Sandreas.sandberg@arm.comGenericPciHost::mapPciInterrupt(const PciBusAddr &addr, PciIntPin pin) const 21611244Sandreas.sandberg@arm.com{ 21711244Sandreas.sandberg@arm.com const PciDevice *dev(getDevice(addr)); 21811244Sandreas.sandberg@arm.com assert(dev); 21911244Sandreas.sandberg@arm.com 22011244Sandreas.sandberg@arm.com return dev->interruptLine(); 22111244Sandreas.sandberg@arm.com} 22211244Sandreas.sandberg@arm.com 22311244Sandreas.sandberg@arm.com 22411244Sandreas.sandberg@arm.comGenericPciHost * 22511244Sandreas.sandberg@arm.comGenericPciHostParams::create() 22611244Sandreas.sandberg@arm.com{ 22711244Sandreas.sandberg@arm.com return new GenericPciHost(this); 22811244Sandreas.sandberg@arm.com} 229