device.cc revision 13342
1793SN/A/* 211193SN/A * Copyright (c) 2013, 2015 ARM Limited 39957SN/A * All rights reserved 49957SN/A * 59957SN/A * The license below extends only to copyright in the software and shall 69957SN/A * not be construed as granting a license to any other intellectual 79957SN/A * property including but not limited to intellectual property relating 89957SN/A * to a hardware implementation of the functionality of the software 99957SN/A * licensed hereunder. You may use the software subject to the license 109957SN/A * terms below provided that you ensure that this notice is replicated 119957SN/A * unmodified and in its entirety in all distributions of the software, 129957SN/A * modified or unmodified, in source code or in binary form. 139957SN/A * 141762SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 15793SN/A * All rights reserved. 16793SN/A * 17793SN/A * Redistribution and use in source and binary forms, with or without 18793SN/A * modification, are permitted provided that the following conditions are 19793SN/A * met: redistributions of source code must retain the above copyright 20793SN/A * notice, this list of conditions and the following disclaimer; 21793SN/A * redistributions in binary form must reproduce the above copyright 22793SN/A * notice, this list of conditions and the following disclaimer in the 23793SN/A * documentation and/or other materials provided with the distribution; 24793SN/A * neither the name of the copyright holders nor the names of its 25793SN/A * contributors may be used to endorse or promote products derived from 26793SN/A * this software without specific prior written permission. 27793SN/A * 28793SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29793SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30793SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31793SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32793SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33793SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34793SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35793SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36793SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37793SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38793SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392665SN/A * 402665SN/A * Authors: Ali Saidi 412665SN/A * Andrew Schultz 422665SN/A * Miguel Serrano 43793SN/A */ 44793SN/A 45793SN/A/* @file 46793SN/A * A single PCI device configuration space entry. 47793SN/A */ 48793SN/A 4911260Sandreas.sandberg@arm.com#include "dev/pci/device.hh" 5011260Sandreas.sandberg@arm.com 51793SN/A#include <list> 52793SN/A#include <string> 53793SN/A#include <vector> 54793SN/A 55793SN/A#include "base/inifile.hh" 567676SN/A#include "base/intmath.hh" 5712334Sgabeblack@google.com#include "base/logging.hh" 587676SN/A#include "base/str.hh" 59793SN/A#include "base/trace.hh" 6011260Sandreas.sandberg@arm.com#include "debug/PciDevice.hh" 612565SN/A#include "mem/packet.hh" 623348SN/A#include "mem/packet_access.hh" 632565SN/A#include "sim/byteswap.hh" 644167SN/A#include "sim/core.hh" 65793SN/A 6611244SN/APciDevice::PciDevice(const PciDeviceParams *p) 679957SN/A : DmaDevice(p), 6811244SN/A _busAddr(p->pci_bus, p->pci_dev, p->pci_func), 699957SN/A PMCAP_BASE(p->PMCAPBaseOffset), 7010479SN/A PMCAP_ID_OFFSET(p->PMCAPBaseOffset+PMCAP_ID), 7110479SN/A PMCAP_PC_OFFSET(p->PMCAPBaseOffset+PMCAP_PC), 7210479SN/A PMCAP_PMCS_OFFSET(p->PMCAPBaseOffset+PMCAP_PMCS), 739957SN/A MSICAP_BASE(p->MSICAPBaseOffset), 749957SN/A MSIXCAP_BASE(p->MSIXCAPBaseOffset), 7510479SN/A MSIXCAP_ID_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_ID), 7610479SN/A MSIXCAP_MXC_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_MXC), 7710479SN/A MSIXCAP_MTAB_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_MTAB), 7810479SN/A MSIXCAP_MPBA_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_MPBA), 799957SN/A PXCAP_BASE(p->PXCAPBaseOffset), 8011244SN/A 8111244SN/A hostInterface(p->host->registerDevice(this, _busAddr, 8211244SN/A (PciIntPin)p->InterruptPin)), 839957SN/A pioDelay(p->pio_latency), 8411244SN/A configDelay(p->config_latency) 85793SN/A{ 8611244SN/A fatal_if(p->InterruptPin >= 5, 8711244SN/A "Invalid PCI interrupt '%i' specified.", p->InterruptPin); 8811244SN/A 894982SN/A config.vendor = htole(p->VendorID); 904982SN/A config.device = htole(p->DeviceID); 914982SN/A config.command = htole(p->Command); 924982SN/A config.status = htole(p->Status); 934982SN/A config.revision = htole(p->Revision); 944982SN/A config.progIF = htole(p->ProgIF); 954982SN/A config.subClassCode = htole(p->SubClassCode); 964982SN/A config.classCode = htole(p->ClassCode); 974982SN/A config.cacheLineSize = htole(p->CacheLineSize); 984982SN/A config.latencyTimer = htole(p->LatencyTimer); 994982SN/A config.headerType = htole(p->HeaderType); 1004982SN/A config.bist = htole(p->BIST); 1014982SN/A 1024982SN/A config.baseAddr[0] = htole(p->BAR0); 1034982SN/A config.baseAddr[1] = htole(p->BAR1); 1044982SN/A config.baseAddr[2] = htole(p->BAR2); 1054982SN/A config.baseAddr[3] = htole(p->BAR3); 1064982SN/A config.baseAddr[4] = htole(p->BAR4); 1074982SN/A config.baseAddr[5] = htole(p->BAR5); 1084982SN/A config.cardbusCIS = htole(p->CardbusCIS); 1094982SN/A config.subsystemVendorID = htole(p->SubsystemVendorID); 1104982SN/A config.subsystemID = htole(p->SubsystemID); 1114982SN/A config.expansionROM = htole(p->ExpansionROM); 1129957SN/A config.capabilityPtr = htole(p->CapabilityPtr); 1139957SN/A // Zero out the 7 bytes of reserved space in the PCI Config space register. 1149957SN/A bzero(config.reserved, 7*sizeof(uint8_t)); 1154982SN/A config.interruptLine = htole(p->InterruptLine); 1164982SN/A config.interruptPin = htole(p->InterruptPin); 1174982SN/A config.minimumGrant = htole(p->MinimumGrant); 1184982SN/A config.maximumLatency = htole(p->MaximumLatency); 1194982SN/A 1209957SN/A // Initialize the capability lists 1219957SN/A // These structs are bitunions, meaning the data is stored in host 1229957SN/A // endianess and must be converted to Little Endian when accessed 1239957SN/A // by the guest 1249957SN/A // PMCAP 12510479SN/A pmcap.pid = (uint16_t)p->PMCAPCapId; // pid.cid 12610479SN/A pmcap.pid |= (uint16_t)p->PMCAPNextCapability << 8; //pid.next 1279957SN/A pmcap.pc = p->PMCAPCapabilities; 1289957SN/A pmcap.pmcs = p->PMCAPCtrlStatus; 1299957SN/A 1309957SN/A // MSICAP 13110479SN/A msicap.mid = (uint16_t)p->MSICAPCapId; //mid.cid 13210479SN/A msicap.mid |= (uint16_t)p->MSICAPNextCapability << 8; //mid.next 1339957SN/A msicap.mc = p->MSICAPMsgCtrl; 1349957SN/A msicap.ma = p->MSICAPMsgAddr; 1359957SN/A msicap.mua = p->MSICAPMsgUpperAddr; 1369957SN/A msicap.md = p->MSICAPMsgData; 1379957SN/A msicap.mmask = p->MSICAPMaskBits; 1389957SN/A msicap.mpend = p->MSICAPPendingBits; 1399957SN/A 1409957SN/A // MSIXCAP 14110479SN/A msixcap.mxid = (uint16_t)p->MSIXCAPCapId; //mxid.cid 14210479SN/A msixcap.mxid |= (uint16_t)p->MSIXCAPNextCapability << 8; //mxid.next 1439957SN/A msixcap.mxc = p->MSIXMsgCtrl; 1449957SN/A msixcap.mtab = p->MSIXTableOffset; 1459957SN/A msixcap.mpba = p->MSIXPbaOffset; 1469957SN/A 1479957SN/A // allocate MSIX structures if MSIXCAP_BASE 1489957SN/A // indicates the MSIXCAP is being used by having a 1499957SN/A // non-zero base address. 1509957SN/A // The MSIX tables are stored by the guest in 1519957SN/A // little endian byte-order as according the 1529957SN/A // PCIe specification. Make sure to take the proper 1539957SN/A // actions when manipulating these tables on the host 15410479SN/A uint16_t msixcap_mxc_ts = msixcap.mxc & 0x07ff; 1559957SN/A if (MSIXCAP_BASE != 0x0) { 15610479SN/A int msix_vecs = msixcap_mxc_ts + 1; 1579957SN/A MSIXTable tmp1 = {{0UL,0UL,0UL,0UL}}; 1589957SN/A msix_table.resize(msix_vecs, tmp1); 1599957SN/A 1609957SN/A MSIXPbaEntry tmp2 = {0}; 1619957SN/A int pba_size = msix_vecs / MSIXVECS_PER_PBA; 1629957SN/A if ((msix_vecs % MSIXVECS_PER_PBA) > 0) { 1639957SN/A pba_size++; 1649957SN/A } 1659957SN/A msix_pba.resize(pba_size, tmp2); 1669957SN/A } 16710479SN/A MSIX_TABLE_OFFSET = msixcap.mtab & 0xfffffffc; 16810479SN/A MSIX_TABLE_END = MSIX_TABLE_OFFSET + 16910479SN/A (msixcap_mxc_ts + 1) * sizeof(MSIXTable); 17010479SN/A MSIX_PBA_OFFSET = msixcap.mpba & 0xfffffffc; 17110479SN/A MSIX_PBA_END = MSIX_PBA_OFFSET + 17210479SN/A ((msixcap_mxc_ts + 1) / MSIXVECS_PER_PBA) 17310479SN/A * sizeof(MSIXPbaEntry); 17410479SN/A if (((msixcap_mxc_ts + 1) % MSIXVECS_PER_PBA) > 0) { 17510479SN/A MSIX_PBA_END += sizeof(MSIXPbaEntry); 17610479SN/A } 1779957SN/A 1789957SN/A // PXCAP 17910479SN/A pxcap.pxid = (uint16_t)p->PXCAPCapId; //pxid.cid 18010479SN/A pxcap.pxid |= (uint16_t)p->PXCAPNextCapability << 8; //pxid.next 1819957SN/A pxcap.pxcap = p->PXCAPCapabilities; 1829957SN/A pxcap.pxdcap = p->PXCAPDevCapabilities; 1839957SN/A pxcap.pxdc = p->PXCAPDevCtrl; 1849957SN/A pxcap.pxds = p->PXCAPDevStatus; 1859957SN/A pxcap.pxlcap = p->PXCAPLinkCap; 1869957SN/A pxcap.pxlc = p->PXCAPLinkCtrl; 1879957SN/A pxcap.pxls = p->PXCAPLinkStatus; 1889957SN/A pxcap.pxdcap2 = p->PXCAPDevCap2; 1899957SN/A pxcap.pxdc2 = p->PXCAPDevCtrl2; 1909957SN/A 1914982SN/A BARSize[0] = p->BAR0Size; 1924982SN/A BARSize[1] = p->BAR1Size; 1934982SN/A BARSize[2] = p->BAR2Size; 1944982SN/A BARSize[3] = p->BAR3Size; 1954982SN/A BARSize[4] = p->BAR4Size; 1964982SN/A BARSize[5] = p->BAR5Size; 1974982SN/A 1985834SN/A legacyIO[0] = p->BAR0LegacyIO; 1995834SN/A legacyIO[1] = p->BAR1LegacyIO; 2005834SN/A legacyIO[2] = p->BAR2LegacyIO; 2015834SN/A legacyIO[3] = p->BAR3LegacyIO; 2025834SN/A legacyIO[4] = p->BAR4LegacyIO; 2035834SN/A legacyIO[5] = p->BAR5LegacyIO; 2045834SN/A 2054982SN/A for (int i = 0; i < 6; ++i) { 2065834SN/A if (legacyIO[i]) { 20710359SN/A BARAddrs[i] = p->LegacyIOBase + letoh(config.baseAddr[i]); 2085834SN/A config.baseAddr[i] = 0; 2095834SN/A } else { 2105834SN/A BARAddrs[i] = 0; 2115834SN/A uint32_t barsize = BARSize[i]; 2125834SN/A if (barsize != 0 && !isPowerOf2(barsize)) { 2135834SN/A fatal("BAR %d size %d is not a power of 2\n", i, BARSize[i]); 2145834SN/A } 2154982SN/A } 2164982SN/A } 2172846SN/A} 2182846SN/A 2192846SN/ATick 2209807SN/APciDevice::readConfig(PacketPtr pkt) 2212846SN/A{ 2222846SN/A int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 22310479SN/A 22410479SN/A /* Return 0 for accesses to unimplemented PCI configspace areas */ 22510479SN/A if (offset >= PCI_DEVICE_SPECIFIC && 22610479SN/A offset < PCI_CONFIG_SIZE) { 22710479SN/A warn_once("Device specific PCI config space " 22810479SN/A "not implemented for %s!\n", this->name()); 22910479SN/A switch (pkt->getSize()) { 23010479SN/A case sizeof(uint8_t): 23113342Sgabeblack@google.com pkt->setLE<uint8_t>(0); 23210479SN/A break; 23310479SN/A case sizeof(uint16_t): 23413342Sgabeblack@google.com pkt->setLE<uint16_t>(0); 23510479SN/A break; 23610479SN/A case sizeof(uint32_t): 23713342Sgabeblack@google.com pkt->setLE<uint32_t>(0); 23810479SN/A break; 23910479SN/A default: 24010479SN/A panic("invalid access size(?) for PCI configspace!\n"); 24110479SN/A } 24210479SN/A } else if (offset > PCI_CONFIG_SIZE) { 24310479SN/A panic("Out-of-range access to PCI config space!\n"); 24410479SN/A } 24510479SN/A 2462846SN/A switch (pkt->getSize()) { 2472846SN/A case sizeof(uint8_t): 24813342Sgabeblack@google.com pkt->setLE<uint8_t>(config.data[offset]); 24911260Sandreas.sandberg@arm.com DPRINTF(PciDevice, 2503083SN/A "readConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n", 25111244SN/A _busAddr.dev, _busAddr.func, offset, 25213342Sgabeblack@google.com (uint32_t)pkt->getLE<uint8_t>()); 2532846SN/A break; 2542846SN/A case sizeof(uint16_t): 25513342Sgabeblack@google.com pkt->setLE<uint16_t>(*(uint16_t*)&config.data[offset]); 25611260Sandreas.sandberg@arm.com DPRINTF(PciDevice, 2573083SN/A "readConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n", 25811244SN/A _busAddr.dev, _busAddr.func, offset, 25913342Sgabeblack@google.com (uint32_t)pkt->getLE<uint16_t>()); 2602846SN/A break; 2612846SN/A case sizeof(uint32_t): 26213342Sgabeblack@google.com pkt->setLE<uint32_t>(*(uint32_t*)&config.data[offset]); 26311260Sandreas.sandberg@arm.com DPRINTF(PciDevice, 2643083SN/A "readConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n", 26511244SN/A _busAddr.dev, _busAddr.func, offset, 26613342Sgabeblack@google.com (uint32_t)pkt->getLE<uint32_t>()); 2672846SN/A break; 2682846SN/A default: 2692846SN/A panic("invalid access size(?) for PCI configspace!\n"); 2702846SN/A } 2714870SN/A pkt->makeAtomicResponse(); 2722846SN/A return configDelay; 2732846SN/A 274793SN/A} 275793SN/A 2768711SN/AAddrRangeList 2779807SN/APciDevice::getAddrRanges() const 2782565SN/A{ 2798711SN/A AddrRangeList ranges; 2802565SN/A int x = 0; 2812565SN/A for (x = 0; x < 6; x++) 2822565SN/A if (BARAddrs[x] != 0) 2838711SN/A ranges.push_back(RangeSize(BARAddrs[x],BARSize[x])); 2848711SN/A return ranges; 2852565SN/A} 2862565SN/A 2872846SN/ATick 2889807SN/APciDevice::writeConfig(PacketPtr pkt) 289793SN/A{ 2902846SN/A int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 29110479SN/A 29210479SN/A /* No effect if we write to config space that is not implemented*/ 29310479SN/A if (offset >= PCI_DEVICE_SPECIFIC && 29410479SN/A offset < PCI_CONFIG_SIZE) { 29510479SN/A warn_once("Device specific PCI config space " 29610479SN/A "not implemented for %s!\n", this->name()); 29710479SN/A switch (pkt->getSize()) { 29810479SN/A case sizeof(uint8_t): 29910479SN/A case sizeof(uint16_t): 30010479SN/A case sizeof(uint32_t): 30110479SN/A break; 30210479SN/A default: 30310479SN/A panic("invalid access size(?) for PCI configspace!\n"); 30410479SN/A } 30510479SN/A } else if (offset > PCI_CONFIG_SIZE) { 30610479SN/A panic("Out-of-range access to PCI config space!\n"); 30710479SN/A } 3081155SN/A 3092846SN/A switch (pkt->getSize()) { 3102846SN/A case sizeof(uint8_t): 3112846SN/A switch (offset) { 3122846SN/A case PCI0_INTERRUPT_LINE: 31313342Sgabeblack@google.com config.interruptLine = pkt->getLE<uint8_t>(); 3145777SN/A break; 3152846SN/A case PCI_CACHE_LINE_SIZE: 31613342Sgabeblack@google.com config.cacheLineSize = pkt->getLE<uint8_t>(); 3175777SN/A break; 3182846SN/A case PCI_LATENCY_TIMER: 31913342Sgabeblack@google.com config.latencyTimer = pkt->getLE<uint8_t>(); 3202846SN/A break; 3212846SN/A /* Do nothing for these read-only registers */ 3222846SN/A case PCI0_INTERRUPT_PIN: 3232846SN/A case PCI0_MINIMUM_GRANT: 3242846SN/A case PCI0_MAXIMUM_LATENCY: 3252846SN/A case PCI_CLASS_CODE: 3262846SN/A case PCI_REVISION_ID: 3272846SN/A break; 3282846SN/A default: 3292846SN/A panic("writing to a read only register"); 3302846SN/A } 33111260Sandreas.sandberg@arm.com DPRINTF(PciDevice, 3323083SN/A "writeConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n", 33311244SN/A _busAddr.dev, _busAddr.func, offset, 33413342Sgabeblack@google.com (uint32_t)pkt->getLE<uint8_t>()); 3352846SN/A break; 3362846SN/A case sizeof(uint16_t): 3372846SN/A switch (offset) { 3382846SN/A case PCI_COMMAND: 33913342Sgabeblack@google.com config.command = pkt->getLE<uint8_t>(); 3405777SN/A break; 3412846SN/A case PCI_STATUS: 34213342Sgabeblack@google.com config.status = pkt->getLE<uint8_t>(); 3435777SN/A break; 3442846SN/A case PCI_CACHE_LINE_SIZE: 34513342Sgabeblack@google.com config.cacheLineSize = pkt->getLE<uint8_t>(); 3462846SN/A break; 3472846SN/A default: 3482846SN/A panic("writing to a read only register"); 3492846SN/A } 35011260Sandreas.sandberg@arm.com DPRINTF(PciDevice, 3513083SN/A "writeConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n", 35211244SN/A _busAddr.dev, _busAddr.func, offset, 35313342Sgabeblack@google.com (uint32_t)pkt->getLE<uint16_t>()); 3542846SN/A break; 3552846SN/A case sizeof(uint32_t): 3562846SN/A switch (offset) { 3572846SN/A case PCI0_BASE_ADDR0: 3582846SN/A case PCI0_BASE_ADDR1: 3592846SN/A case PCI0_BASE_ADDR2: 3602846SN/A case PCI0_BASE_ADDR3: 3612846SN/A case PCI0_BASE_ADDR4: 3622846SN/A case PCI0_BASE_ADDR5: 3633086SN/A { 3643086SN/A int barnum = BAR_NUMBER(offset); 365793SN/A 3665834SN/A if (!legacyIO[barnum]) { 3675834SN/A // convert BAR values to host endianness 3685834SN/A uint32_t he_old_bar = letoh(config.baseAddr[barnum]); 36913342Sgabeblack@google.com uint32_t he_new_bar = letoh(pkt->getLE<uint32_t>()); 370795SN/A 3715834SN/A uint32_t bar_mask = 3725834SN/A BAR_IO_SPACE(he_old_bar) ? BAR_IO_MASK : BAR_MEM_MASK; 3732565SN/A 3745834SN/A // Writing 0xffffffff to a BAR tells the card to set the 3755834SN/A // value of the bar to a bitmask indicating the size of 3765834SN/A // memory it needs 3775834SN/A if (he_new_bar == 0xffffffff) { 3785834SN/A he_new_bar = ~(BARSize[barnum] - 1); 3795834SN/A } else { 3805834SN/A // does it mean something special to write 0 to a BAR? 3815834SN/A he_new_bar &= ~bar_mask; 3825834SN/A if (he_new_bar) { 3835834SN/A BARAddrs[barnum] = BAR_IO_SPACE(he_old_bar) ? 38411244SN/A hostInterface.pioAddr(he_new_bar) : 38511244SN/A hostInterface.memAddr(he_new_bar); 3868851SN/A pioPort.sendRangeChange(); 3875834SN/A } 3883086SN/A } 3895834SN/A config.baseAddr[barnum] = htole((he_new_bar & ~bar_mask) | 3905834SN/A (he_old_bar & bar_mask)); 3912846SN/A } 3922846SN/A } 3932846SN/A break; 3942565SN/A 3952846SN/A case PCI0_ROM_BASE_ADDR: 39613342Sgabeblack@google.com if (letoh(pkt->getLE<uint32_t>()) == 0xfffffffe) 3972846SN/A config.expansionROM = htole((uint32_t)0xffffffff); 3982846SN/A else 39913342Sgabeblack@google.com config.expansionROM = pkt->getLE<uint32_t>(); 4002846SN/A break; 4012846SN/A 4022846SN/A case PCI_COMMAND: 4032846SN/A // This could also clear some of the error bits in the Status 4042846SN/A // register. However they should never get set, so lets ignore 4052846SN/A // it for now 40613342Sgabeblack@google.com config.command = pkt->getLE<uint32_t>(); 4072846SN/A break; 4082846SN/A 4092846SN/A default: 41011260Sandreas.sandberg@arm.com DPRINTF(PciDevice, "Writing to a read only register"); 4112846SN/A } 41211260Sandreas.sandberg@arm.com DPRINTF(PciDevice, 4133083SN/A "writeConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n", 41411244SN/A _busAddr.dev, _busAddr.func, offset, 41513342Sgabeblack@google.com (uint32_t)pkt->getLE<uint32_t>()); 4162565SN/A break; 4172565SN/A default: 4182846SN/A panic("invalid access size(?) for PCI configspace!\n"); 4192565SN/A } 4204870SN/A pkt->makeAtomicResponse(); 4212846SN/A return configDelay; 422793SN/A} 423793SN/A 424793SN/Avoid 42510905SN/APciDevice::serialize(CheckpointOut &cp) const 426793SN/A{ 4271854SN/A SERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0])); 4281854SN/A SERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0])); 4291854SN/A SERIALIZE_ARRAY(config.data, sizeof(config.data) / sizeof(config.data[0])); 4309957SN/A 4319957SN/A // serialize the capability list registers 43210905SN/A paramOut(cp, csprintf("pmcap.pid"), uint16_t(pmcap.pid)); 43310905SN/A paramOut(cp, csprintf("pmcap.pc"), uint16_t(pmcap.pc)); 43410905SN/A paramOut(cp, csprintf("pmcap.pmcs"), uint16_t(pmcap.pmcs)); 4359957SN/A 43610905SN/A paramOut(cp, csprintf("msicap.mid"), uint16_t(msicap.mid)); 43710905SN/A paramOut(cp, csprintf("msicap.mc"), uint16_t(msicap.mc)); 43810905SN/A paramOut(cp, csprintf("msicap.ma"), uint32_t(msicap.ma)); 4399957SN/A SERIALIZE_SCALAR(msicap.mua); 44010905SN/A paramOut(cp, csprintf("msicap.md"), uint16_t(msicap.md)); 4419957SN/A SERIALIZE_SCALAR(msicap.mmask); 4429957SN/A SERIALIZE_SCALAR(msicap.mpend); 4439957SN/A 44410905SN/A paramOut(cp, csprintf("msixcap.mxid"), uint16_t(msixcap.mxid)); 44510905SN/A paramOut(cp, csprintf("msixcap.mxc"), uint16_t(msixcap.mxc)); 44610905SN/A paramOut(cp, csprintf("msixcap.mtab"), uint32_t(msixcap.mtab)); 44710905SN/A paramOut(cp, csprintf("msixcap.mpba"), uint32_t(msixcap.mpba)); 4489957SN/A 4499957SN/A // Only serialize if we have a non-zero base address 4509957SN/A if (MSIXCAP_BASE != 0x0) { 45110479SN/A uint16_t msixcap_mxc_ts = msixcap.mxc & 0x07ff; 45210479SN/A int msix_array_size = msixcap_mxc_ts + 1; 4539957SN/A int pba_array_size = msix_array_size/MSIXVECS_PER_PBA; 4549957SN/A if ((msix_array_size % MSIXVECS_PER_PBA) > 0) { 4559957SN/A pba_array_size++; 4569957SN/A } 4579957SN/A 4589957SN/A SERIALIZE_SCALAR(msix_array_size); 4599957SN/A SERIALIZE_SCALAR(pba_array_size); 4609957SN/A 4619957SN/A for (int i = 0; i < msix_array_size; i++) { 46210905SN/A paramOut(cp, csprintf("msix_table[%d].addr_lo", i), 4639957SN/A msix_table[i].fields.addr_lo); 46410905SN/A paramOut(cp, csprintf("msix_table[%d].addr_hi", i), 4659957SN/A msix_table[i].fields.addr_hi); 46610905SN/A paramOut(cp, csprintf("msix_table[%d].msg_data", i), 4679957SN/A msix_table[i].fields.msg_data); 46810905SN/A paramOut(cp, csprintf("msix_table[%d].vec_ctrl", i), 4699957SN/A msix_table[i].fields.vec_ctrl); 4709957SN/A } 4719957SN/A for (int i = 0; i < pba_array_size; i++) { 47210905SN/A paramOut(cp, csprintf("msix_pba[%d].bits", i), 4739957SN/A msix_pba[i].bits); 4749957SN/A } 4759957SN/A } 4769957SN/A 47710905SN/A paramOut(cp, csprintf("pxcap.pxid"), uint16_t(pxcap.pxid)); 47810905SN/A paramOut(cp, csprintf("pxcap.pxcap"), uint16_t(pxcap.pxcap)); 47910905SN/A paramOut(cp, csprintf("pxcap.pxdcap"), uint32_t(pxcap.pxdcap)); 48010905SN/A paramOut(cp, csprintf("pxcap.pxdc"), uint16_t(pxcap.pxdc)); 48110905SN/A paramOut(cp, csprintf("pxcap.pxds"), uint16_t(pxcap.pxds)); 48210905SN/A paramOut(cp, csprintf("pxcap.pxlcap"), uint32_t(pxcap.pxlcap)); 48310905SN/A paramOut(cp, csprintf("pxcap.pxlc"), uint16_t(pxcap.pxlc)); 48410905SN/A paramOut(cp, csprintf("pxcap.pxls"), uint16_t(pxcap.pxls)); 48510905SN/A paramOut(cp, csprintf("pxcap.pxdcap2"), uint32_t(pxcap.pxdcap2)); 48610905SN/A paramOut(cp, csprintf("pxcap.pxdc2"), uint32_t(pxcap.pxdc2)); 487793SN/A} 488793SN/A 489793SN/Avoid 49010905SN/APciDevice::unserialize(CheckpointIn &cp) 491793SN/A{ 4921854SN/A UNSERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0])); 4931854SN/A UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0])); 4941854SN/A UNSERIALIZE_ARRAY(config.data, 4951854SN/A sizeof(config.data) / sizeof(config.data[0])); 4969957SN/A 4979957SN/A // unserialize the capability list registers 4989957SN/A uint16_t tmp16; 4999957SN/A uint32_t tmp32; 50010905SN/A paramIn(cp, csprintf("pmcap.pid"), tmp16); 5019957SN/A pmcap.pid = tmp16; 50210905SN/A paramIn(cp, csprintf("pmcap.pc"), tmp16); 5039957SN/A pmcap.pc = tmp16; 50410905SN/A paramIn(cp, csprintf("pmcap.pmcs"), tmp16); 5059957SN/A pmcap.pmcs = tmp16; 5069957SN/A 50710905SN/A paramIn(cp, csprintf("msicap.mid"), tmp16); 5089957SN/A msicap.mid = tmp16; 50910905SN/A paramIn(cp, csprintf("msicap.mc"), tmp16); 5109957SN/A msicap.mc = tmp16; 51110905SN/A paramIn(cp, csprintf("msicap.ma"), tmp32); 5129957SN/A msicap.ma = tmp32; 5139957SN/A UNSERIALIZE_SCALAR(msicap.mua); 51410905SN/A paramIn(cp, csprintf("msicap.md"), tmp16);; 5159957SN/A msicap.md = tmp16; 5169957SN/A UNSERIALIZE_SCALAR(msicap.mmask); 5179957SN/A UNSERIALIZE_SCALAR(msicap.mpend); 5189957SN/A 51910905SN/A paramIn(cp, csprintf("msixcap.mxid"), tmp16); 5209957SN/A msixcap.mxid = tmp16; 52110905SN/A paramIn(cp, csprintf("msixcap.mxc"), tmp16); 5229957SN/A msixcap.mxc = tmp16; 52310905SN/A paramIn(cp, csprintf("msixcap.mtab"), tmp32); 5249957SN/A msixcap.mtab = tmp32; 52510905SN/A paramIn(cp, csprintf("msixcap.mpba"), tmp32); 5269957SN/A msixcap.mpba = tmp32; 5279957SN/A 5289957SN/A // Only allocate if MSIXCAP_BASE is not 0x0 5299957SN/A if (MSIXCAP_BASE != 0x0) { 5309957SN/A int msix_array_size; 5319957SN/A int pba_array_size; 5329957SN/A 5339957SN/A UNSERIALIZE_SCALAR(msix_array_size); 5349957SN/A UNSERIALIZE_SCALAR(pba_array_size); 5359957SN/A 5369957SN/A MSIXTable tmp1 = {{0UL, 0UL, 0UL, 0UL}}; 5379957SN/A msix_table.resize(msix_array_size, tmp1); 5389957SN/A 5399957SN/A MSIXPbaEntry tmp2 = {0}; 5409957SN/A msix_pba.resize(pba_array_size, tmp2); 5419957SN/A 5429957SN/A for (int i = 0; i < msix_array_size; i++) { 54310905SN/A paramIn(cp, csprintf("msix_table[%d].addr_lo", i), 5449957SN/A msix_table[i].fields.addr_lo); 54510905SN/A paramIn(cp, csprintf("msix_table[%d].addr_hi", i), 5469957SN/A msix_table[i].fields.addr_hi); 54710905SN/A paramIn(cp, csprintf("msix_table[%d].msg_data", i), 5489957SN/A msix_table[i].fields.msg_data); 54910905SN/A paramIn(cp, csprintf("msix_table[%d].vec_ctrl", i), 5509957SN/A msix_table[i].fields.vec_ctrl); 5519957SN/A } 5529957SN/A for (int i = 0; i < pba_array_size; i++) { 55310905SN/A paramIn(cp, csprintf("msix_pba[%d].bits", i), 5549957SN/A msix_pba[i].bits); 5559957SN/A } 5569957SN/A } 5579957SN/A 55810905SN/A paramIn(cp, csprintf("pxcap.pxid"), tmp16); 5599957SN/A pxcap.pxid = tmp16; 56010905SN/A paramIn(cp, csprintf("pxcap.pxcap"), tmp16); 5619957SN/A pxcap.pxcap = tmp16; 56210905SN/A paramIn(cp, csprintf("pxcap.pxdcap"), tmp32); 5639957SN/A pxcap.pxdcap = tmp32; 56410905SN/A paramIn(cp, csprintf("pxcap.pxdc"), tmp16); 5659957SN/A pxcap.pxdc = tmp16; 56610905SN/A paramIn(cp, csprintf("pxcap.pxds"), tmp16); 5679957SN/A pxcap.pxds = tmp16; 56810905SN/A paramIn(cp, csprintf("pxcap.pxlcap"), tmp32); 5699957SN/A pxcap.pxlcap = tmp32; 57010905SN/A paramIn(cp, csprintf("pxcap.pxlc"), tmp16); 5719957SN/A pxcap.pxlc = tmp16; 57210905SN/A paramIn(cp, csprintf("pxcap.pxls"), tmp16); 5739957SN/A pxcap.pxls = tmp16; 57410905SN/A paramIn(cp, csprintf("pxcap.pxdcap2"), tmp32); 5759957SN/A pxcap.pxdcap2 = tmp32; 57610905SN/A paramIn(cp, csprintf("pxcap.pxdc2"), tmp32); 5779957SN/A pxcap.pxdc2 = tmp32; 5788851SN/A pioPort.sendRangeChange(); 579793SN/A} 580793SN/A 581