device.cc revision 11193
1/* 2 * Copyright (c) 2013, 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 * Copyright (c) 2004-2005 The Regents of The University of Michigan 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Ali Saidi 41 * Andrew Schultz 42 * Miguel Serrano 43 */ 44 45/* @file 46 * A single PCI device configuration space entry. 47 */ 48 49#include <list> 50#include <string> 51#include <vector> 52 53#include "base/inifile.hh" 54#include "base/intmath.hh" 55#include "base/misc.hh" 56#include "base/str.hh" 57#include "base/trace.hh" 58#include "debug/PCIDEV.hh" 59#include "dev/alpha/tsunamireg.h" 60#include "dev/pciconfigall.hh" 61#include "dev/pcidev.hh" 62#include "mem/packet.hh" 63#include "mem/packet_access.hh" 64#include "sim/byteswap.hh" 65#include "sim/core.hh" 66 67 68PciDevice::PciConfigPort::PciConfigPort(PciDevice *dev, int busid, int devid, 69 int funcid, Platform *p) 70 : SimpleTimingPort(dev->name() + "-pciconf", dev), device(dev), 71 platform(p), busId(busid), deviceId(devid), functionId(funcid) 72{ 73 configAddr = platform->calcPciConfigAddr(busId, deviceId, functionId); 74} 75 76 77Tick 78PciDevice::PciConfigPort::recvAtomic(PacketPtr pkt) 79{ 80 assert(pkt->getAddr() >= configAddr && 81 pkt->getAddr() < configAddr + PCI_CONFIG_SIZE); 82 83 // technically the packet only reaches us after the header delay, 84 // and typically we also need to deserialise any payload 85 Tick receive_delay = pkt->headerDelay + pkt->payloadDelay; 86 pkt->headerDelay = pkt->payloadDelay = 0; 87 88 const Tick delay(pkt->isRead() ? device->readConfig(pkt) : 89 device->writeConfig(pkt)); 90 return delay + receive_delay; 91} 92 93AddrRangeList 94PciDevice::PciConfigPort::getAddrRanges() const 95{ 96 AddrRangeList ranges; 97 if (configAddr != ULL(-1)) 98 ranges.push_back(RangeSize(configAddr, PCI_CONFIG_SIZE+1)); 99 return ranges; 100} 101 102 103PciDevice::PciDevice(const Params *p) 104 : DmaDevice(p), 105 PMCAP_BASE(p->PMCAPBaseOffset), 106 PMCAP_ID_OFFSET(p->PMCAPBaseOffset+PMCAP_ID), 107 PMCAP_PC_OFFSET(p->PMCAPBaseOffset+PMCAP_PC), 108 PMCAP_PMCS_OFFSET(p->PMCAPBaseOffset+PMCAP_PMCS), 109 MSICAP_BASE(p->MSICAPBaseOffset), 110 MSIXCAP_BASE(p->MSIXCAPBaseOffset), 111 MSIXCAP_ID_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_ID), 112 MSIXCAP_MXC_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_MXC), 113 MSIXCAP_MTAB_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_MTAB), 114 MSIXCAP_MPBA_OFFSET(p->MSIXCAPBaseOffset+MSIXCAP_MPBA), 115 PXCAP_BASE(p->PXCAPBaseOffset), 116 platform(p->platform), 117 pioDelay(p->pio_latency), 118 configDelay(p->config_latency), 119 configPort(this, params()->pci_bus, params()->pci_dev, 120 params()->pci_func, params()->platform) 121{ 122 config.vendor = htole(p->VendorID); 123 config.device = htole(p->DeviceID); 124 config.command = htole(p->Command); 125 config.status = htole(p->Status); 126 config.revision = htole(p->Revision); 127 config.progIF = htole(p->ProgIF); 128 config.subClassCode = htole(p->SubClassCode); 129 config.classCode = htole(p->ClassCode); 130 config.cacheLineSize = htole(p->CacheLineSize); 131 config.latencyTimer = htole(p->LatencyTimer); 132 config.headerType = htole(p->HeaderType); 133 config.bist = htole(p->BIST); 134 135 config.baseAddr[0] = htole(p->BAR0); 136 config.baseAddr[1] = htole(p->BAR1); 137 config.baseAddr[2] = htole(p->BAR2); 138 config.baseAddr[3] = htole(p->BAR3); 139 config.baseAddr[4] = htole(p->BAR4); 140 config.baseAddr[5] = htole(p->BAR5); 141 config.cardbusCIS = htole(p->CardbusCIS); 142 config.subsystemVendorID = htole(p->SubsystemVendorID); 143 config.subsystemID = htole(p->SubsystemID); 144 config.expansionROM = htole(p->ExpansionROM); 145 config.capabilityPtr = htole(p->CapabilityPtr); 146 // Zero out the 7 bytes of reserved space in the PCI Config space register. 147 bzero(config.reserved, 7*sizeof(uint8_t)); 148 config.interruptLine = htole(p->InterruptLine); 149 config.interruptPin = htole(p->InterruptPin); 150 config.minimumGrant = htole(p->MinimumGrant); 151 config.maximumLatency = htole(p->MaximumLatency); 152 153 // Initialize the capability lists 154 // These structs are bitunions, meaning the data is stored in host 155 // endianess and must be converted to Little Endian when accessed 156 // by the guest 157 // PMCAP 158 pmcap.pid = (uint16_t)p->PMCAPCapId; // pid.cid 159 pmcap.pid |= (uint16_t)p->PMCAPNextCapability << 8; //pid.next 160 pmcap.pc = p->PMCAPCapabilities; 161 pmcap.pmcs = p->PMCAPCtrlStatus; 162 163 // MSICAP 164 msicap.mid = (uint16_t)p->MSICAPCapId; //mid.cid 165 msicap.mid |= (uint16_t)p->MSICAPNextCapability << 8; //mid.next 166 msicap.mc = p->MSICAPMsgCtrl; 167 msicap.ma = p->MSICAPMsgAddr; 168 msicap.mua = p->MSICAPMsgUpperAddr; 169 msicap.md = p->MSICAPMsgData; 170 msicap.mmask = p->MSICAPMaskBits; 171 msicap.mpend = p->MSICAPPendingBits; 172 173 // MSIXCAP 174 msixcap.mxid = (uint16_t)p->MSIXCAPCapId; //mxid.cid 175 msixcap.mxid |= (uint16_t)p->MSIXCAPNextCapability << 8; //mxid.next 176 msixcap.mxc = p->MSIXMsgCtrl; 177 msixcap.mtab = p->MSIXTableOffset; 178 msixcap.mpba = p->MSIXPbaOffset; 179 180 // allocate MSIX structures if MSIXCAP_BASE 181 // indicates the MSIXCAP is being used by having a 182 // non-zero base address. 183 // The MSIX tables are stored by the guest in 184 // little endian byte-order as according the 185 // PCIe specification. Make sure to take the proper 186 // actions when manipulating these tables on the host 187 uint16_t msixcap_mxc_ts = msixcap.mxc & 0x07ff; 188 if (MSIXCAP_BASE != 0x0) { 189 int msix_vecs = msixcap_mxc_ts + 1; 190 MSIXTable tmp1 = {{0UL,0UL,0UL,0UL}}; 191 msix_table.resize(msix_vecs, tmp1); 192 193 MSIXPbaEntry tmp2 = {0}; 194 int pba_size = msix_vecs / MSIXVECS_PER_PBA; 195 if ((msix_vecs % MSIXVECS_PER_PBA) > 0) { 196 pba_size++; 197 } 198 msix_pba.resize(pba_size, tmp2); 199 } 200 MSIX_TABLE_OFFSET = msixcap.mtab & 0xfffffffc; 201 MSIX_TABLE_END = MSIX_TABLE_OFFSET + 202 (msixcap_mxc_ts + 1) * sizeof(MSIXTable); 203 MSIX_PBA_OFFSET = msixcap.mpba & 0xfffffffc; 204 MSIX_PBA_END = MSIX_PBA_OFFSET + 205 ((msixcap_mxc_ts + 1) / MSIXVECS_PER_PBA) 206 * sizeof(MSIXPbaEntry); 207 if (((msixcap_mxc_ts + 1) % MSIXVECS_PER_PBA) > 0) { 208 MSIX_PBA_END += sizeof(MSIXPbaEntry); 209 } 210 211 // PXCAP 212 pxcap.pxid = (uint16_t)p->PXCAPCapId; //pxid.cid 213 pxcap.pxid |= (uint16_t)p->PXCAPNextCapability << 8; //pxid.next 214 pxcap.pxcap = p->PXCAPCapabilities; 215 pxcap.pxdcap = p->PXCAPDevCapabilities; 216 pxcap.pxdc = p->PXCAPDevCtrl; 217 pxcap.pxds = p->PXCAPDevStatus; 218 pxcap.pxlcap = p->PXCAPLinkCap; 219 pxcap.pxlc = p->PXCAPLinkCtrl; 220 pxcap.pxls = p->PXCAPLinkStatus; 221 pxcap.pxdcap2 = p->PXCAPDevCap2; 222 pxcap.pxdc2 = p->PXCAPDevCtrl2; 223 224 BARSize[0] = p->BAR0Size; 225 BARSize[1] = p->BAR1Size; 226 BARSize[2] = p->BAR2Size; 227 BARSize[3] = p->BAR3Size; 228 BARSize[4] = p->BAR4Size; 229 BARSize[5] = p->BAR5Size; 230 231 legacyIO[0] = p->BAR0LegacyIO; 232 legacyIO[1] = p->BAR1LegacyIO; 233 legacyIO[2] = p->BAR2LegacyIO; 234 legacyIO[3] = p->BAR3LegacyIO; 235 legacyIO[4] = p->BAR4LegacyIO; 236 legacyIO[5] = p->BAR5LegacyIO; 237 238 for (int i = 0; i < 6; ++i) { 239 if (legacyIO[i]) { 240 BARAddrs[i] = p->LegacyIOBase + letoh(config.baseAddr[i]); 241 config.baseAddr[i] = 0; 242 } else { 243 BARAddrs[i] = 0; 244 uint32_t barsize = BARSize[i]; 245 if (barsize != 0 && !isPowerOf2(barsize)) { 246 fatal("BAR %d size %d is not a power of 2\n", i, BARSize[i]); 247 } 248 } 249 } 250 251 platform->registerPciDevice(p->pci_bus, p->pci_dev, p->pci_func, 252 letoh(config.interruptLine)); 253} 254 255void 256PciDevice::init() 257{ 258 if (!configPort.isConnected()) 259 panic("PCI config port on %s not connected to anything!\n", name()); 260 configPort.sendRangeChange(); 261 DmaDevice::init(); 262} 263 264Tick 265PciDevice::readConfig(PacketPtr pkt) 266{ 267 int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 268 269 /* Return 0 for accesses to unimplemented PCI configspace areas */ 270 if (offset >= PCI_DEVICE_SPECIFIC && 271 offset < PCI_CONFIG_SIZE) { 272 warn_once("Device specific PCI config space " 273 "not implemented for %s!\n", this->name()); 274 switch (pkt->getSize()) { 275 case sizeof(uint8_t): 276 pkt->set<uint8_t>(0); 277 break; 278 case sizeof(uint16_t): 279 pkt->set<uint16_t>(0); 280 break; 281 case sizeof(uint32_t): 282 pkt->set<uint32_t>(0); 283 break; 284 default: 285 panic("invalid access size(?) for PCI configspace!\n"); 286 } 287 } else if (offset > PCI_CONFIG_SIZE) { 288 panic("Out-of-range access to PCI config space!\n"); 289 } 290 291 switch (pkt->getSize()) { 292 case sizeof(uint8_t): 293 pkt->set<uint8_t>(config.data[offset]); 294 DPRINTF(PCIDEV, 295 "readConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n", 296 params()->pci_dev, params()->pci_func, offset, 297 (uint32_t)pkt->get<uint8_t>()); 298 break; 299 case sizeof(uint16_t): 300 pkt->set<uint16_t>(*(uint16_t*)&config.data[offset]); 301 DPRINTF(PCIDEV, 302 "readConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n", 303 params()->pci_dev, params()->pci_func, offset, 304 (uint32_t)pkt->get<uint16_t>()); 305 break; 306 case sizeof(uint32_t): 307 pkt->set<uint32_t>(*(uint32_t*)&config.data[offset]); 308 DPRINTF(PCIDEV, 309 "readConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n", 310 params()->pci_dev, params()->pci_func, offset, 311 (uint32_t)pkt->get<uint32_t>()); 312 break; 313 default: 314 panic("invalid access size(?) for PCI configspace!\n"); 315 } 316 pkt->makeAtomicResponse(); 317 return configDelay; 318 319} 320 321AddrRangeList 322PciDevice::getAddrRanges() const 323{ 324 AddrRangeList ranges; 325 int x = 0; 326 for (x = 0; x < 6; x++) 327 if (BARAddrs[x] != 0) 328 ranges.push_back(RangeSize(BARAddrs[x],BARSize[x])); 329 return ranges; 330} 331 332Tick 333PciDevice::writeConfig(PacketPtr pkt) 334{ 335 int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 336 337 /* No effect if we write to config space that is not implemented*/ 338 if (offset >= PCI_DEVICE_SPECIFIC && 339 offset < PCI_CONFIG_SIZE) { 340 warn_once("Device specific PCI config space " 341 "not implemented for %s!\n", this->name()); 342 switch (pkt->getSize()) { 343 case sizeof(uint8_t): 344 case sizeof(uint16_t): 345 case sizeof(uint32_t): 346 break; 347 default: 348 panic("invalid access size(?) for PCI configspace!\n"); 349 } 350 } else if (offset > PCI_CONFIG_SIZE) { 351 panic("Out-of-range access to PCI config space!\n"); 352 } 353 354 switch (pkt->getSize()) { 355 case sizeof(uint8_t): 356 switch (offset) { 357 case PCI0_INTERRUPT_LINE: 358 config.interruptLine = pkt->get<uint8_t>(); 359 break; 360 case PCI_CACHE_LINE_SIZE: 361 config.cacheLineSize = pkt->get<uint8_t>(); 362 break; 363 case PCI_LATENCY_TIMER: 364 config.latencyTimer = pkt->get<uint8_t>(); 365 break; 366 /* Do nothing for these read-only registers */ 367 case PCI0_INTERRUPT_PIN: 368 case PCI0_MINIMUM_GRANT: 369 case PCI0_MAXIMUM_LATENCY: 370 case PCI_CLASS_CODE: 371 case PCI_REVISION_ID: 372 break; 373 default: 374 panic("writing to a read only register"); 375 } 376 DPRINTF(PCIDEV, 377 "writeConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n", 378 params()->pci_dev, params()->pci_func, offset, 379 (uint32_t)pkt->get<uint8_t>()); 380 break; 381 case sizeof(uint16_t): 382 switch (offset) { 383 case PCI_COMMAND: 384 config.command = pkt->get<uint8_t>(); 385 break; 386 case PCI_STATUS: 387 config.status = pkt->get<uint8_t>(); 388 break; 389 case PCI_CACHE_LINE_SIZE: 390 config.cacheLineSize = pkt->get<uint8_t>(); 391 break; 392 default: 393 panic("writing to a read only register"); 394 } 395 DPRINTF(PCIDEV, 396 "writeConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n", 397 params()->pci_dev, params()->pci_func, offset, 398 (uint32_t)pkt->get<uint16_t>()); 399 break; 400 case sizeof(uint32_t): 401 switch (offset) { 402 case PCI0_BASE_ADDR0: 403 case PCI0_BASE_ADDR1: 404 case PCI0_BASE_ADDR2: 405 case PCI0_BASE_ADDR3: 406 case PCI0_BASE_ADDR4: 407 case PCI0_BASE_ADDR5: 408 { 409 int barnum = BAR_NUMBER(offset); 410 411 if (!legacyIO[barnum]) { 412 // convert BAR values to host endianness 413 uint32_t he_old_bar = letoh(config.baseAddr[barnum]); 414 uint32_t he_new_bar = letoh(pkt->get<uint32_t>()); 415 416 uint32_t bar_mask = 417 BAR_IO_SPACE(he_old_bar) ? BAR_IO_MASK : BAR_MEM_MASK; 418 419 // Writing 0xffffffff to a BAR tells the card to set the 420 // value of the bar to a bitmask indicating the size of 421 // memory it needs 422 if (he_new_bar == 0xffffffff) { 423 he_new_bar = ~(BARSize[barnum] - 1); 424 } else { 425 // does it mean something special to write 0 to a BAR? 426 he_new_bar &= ~bar_mask; 427 if (he_new_bar) { 428 BARAddrs[barnum] = BAR_IO_SPACE(he_old_bar) ? 429 platform->calcPciIOAddr(he_new_bar) : 430 platform->calcPciMemAddr(he_new_bar); 431 pioPort.sendRangeChange(); 432 } 433 } 434 config.baseAddr[barnum] = htole((he_new_bar & ~bar_mask) | 435 (he_old_bar & bar_mask)); 436 } 437 } 438 break; 439 440 case PCI0_ROM_BASE_ADDR: 441 if (letoh(pkt->get<uint32_t>()) == 0xfffffffe) 442 config.expansionROM = htole((uint32_t)0xffffffff); 443 else 444 config.expansionROM = pkt->get<uint32_t>(); 445 break; 446 447 case PCI_COMMAND: 448 // This could also clear some of the error bits in the Status 449 // register. However they should never get set, so lets ignore 450 // it for now 451 config.command = pkt->get<uint32_t>(); 452 break; 453 454 default: 455 DPRINTF(PCIDEV, "Writing to a read only register"); 456 } 457 DPRINTF(PCIDEV, 458 "writeConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n", 459 params()->pci_dev, params()->pci_func, offset, 460 (uint32_t)pkt->get<uint32_t>()); 461 break; 462 default: 463 panic("invalid access size(?) for PCI configspace!\n"); 464 } 465 pkt->makeAtomicResponse(); 466 return configDelay; 467} 468 469void 470PciDevice::serialize(CheckpointOut &cp) const 471{ 472 SERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0])); 473 SERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0])); 474 SERIALIZE_ARRAY(config.data, sizeof(config.data) / sizeof(config.data[0])); 475 476 // serialize the capability list registers 477 paramOut(cp, csprintf("pmcap.pid"), uint16_t(pmcap.pid)); 478 paramOut(cp, csprintf("pmcap.pc"), uint16_t(pmcap.pc)); 479 paramOut(cp, csprintf("pmcap.pmcs"), uint16_t(pmcap.pmcs)); 480 481 paramOut(cp, csprintf("msicap.mid"), uint16_t(msicap.mid)); 482 paramOut(cp, csprintf("msicap.mc"), uint16_t(msicap.mc)); 483 paramOut(cp, csprintf("msicap.ma"), uint32_t(msicap.ma)); 484 SERIALIZE_SCALAR(msicap.mua); 485 paramOut(cp, csprintf("msicap.md"), uint16_t(msicap.md)); 486 SERIALIZE_SCALAR(msicap.mmask); 487 SERIALIZE_SCALAR(msicap.mpend); 488 489 paramOut(cp, csprintf("msixcap.mxid"), uint16_t(msixcap.mxid)); 490 paramOut(cp, csprintf("msixcap.mxc"), uint16_t(msixcap.mxc)); 491 paramOut(cp, csprintf("msixcap.mtab"), uint32_t(msixcap.mtab)); 492 paramOut(cp, csprintf("msixcap.mpba"), uint32_t(msixcap.mpba)); 493 494 // Only serialize if we have a non-zero base address 495 if (MSIXCAP_BASE != 0x0) { 496 uint16_t msixcap_mxc_ts = msixcap.mxc & 0x07ff; 497 int msix_array_size = msixcap_mxc_ts + 1; 498 int pba_array_size = msix_array_size/MSIXVECS_PER_PBA; 499 if ((msix_array_size % MSIXVECS_PER_PBA) > 0) { 500 pba_array_size++; 501 } 502 503 SERIALIZE_SCALAR(msix_array_size); 504 SERIALIZE_SCALAR(pba_array_size); 505 506 for (int i = 0; i < msix_array_size; i++) { 507 paramOut(cp, csprintf("msix_table[%d].addr_lo", i), 508 msix_table[i].fields.addr_lo); 509 paramOut(cp, csprintf("msix_table[%d].addr_hi", i), 510 msix_table[i].fields.addr_hi); 511 paramOut(cp, csprintf("msix_table[%d].msg_data", i), 512 msix_table[i].fields.msg_data); 513 paramOut(cp, csprintf("msix_table[%d].vec_ctrl", i), 514 msix_table[i].fields.vec_ctrl); 515 } 516 for (int i = 0; i < pba_array_size; i++) { 517 paramOut(cp, csprintf("msix_pba[%d].bits", i), 518 msix_pba[i].bits); 519 } 520 } 521 522 paramOut(cp, csprintf("pxcap.pxid"), uint16_t(pxcap.pxid)); 523 paramOut(cp, csprintf("pxcap.pxcap"), uint16_t(pxcap.pxcap)); 524 paramOut(cp, csprintf("pxcap.pxdcap"), uint32_t(pxcap.pxdcap)); 525 paramOut(cp, csprintf("pxcap.pxdc"), uint16_t(pxcap.pxdc)); 526 paramOut(cp, csprintf("pxcap.pxds"), uint16_t(pxcap.pxds)); 527 paramOut(cp, csprintf("pxcap.pxlcap"), uint32_t(pxcap.pxlcap)); 528 paramOut(cp, csprintf("pxcap.pxlc"), uint16_t(pxcap.pxlc)); 529 paramOut(cp, csprintf("pxcap.pxls"), uint16_t(pxcap.pxls)); 530 paramOut(cp, csprintf("pxcap.pxdcap2"), uint32_t(pxcap.pxdcap2)); 531 paramOut(cp, csprintf("pxcap.pxdc2"), uint32_t(pxcap.pxdc2)); 532} 533 534void 535PciDevice::unserialize(CheckpointIn &cp) 536{ 537 UNSERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0])); 538 UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0])); 539 UNSERIALIZE_ARRAY(config.data, 540 sizeof(config.data) / sizeof(config.data[0])); 541 542 // unserialize the capability list registers 543 uint16_t tmp16; 544 uint32_t tmp32; 545 paramIn(cp, csprintf("pmcap.pid"), tmp16); 546 pmcap.pid = tmp16; 547 paramIn(cp, csprintf("pmcap.pc"), tmp16); 548 pmcap.pc = tmp16; 549 paramIn(cp, csprintf("pmcap.pmcs"), tmp16); 550 pmcap.pmcs = tmp16; 551 552 paramIn(cp, csprintf("msicap.mid"), tmp16); 553 msicap.mid = tmp16; 554 paramIn(cp, csprintf("msicap.mc"), tmp16); 555 msicap.mc = tmp16; 556 paramIn(cp, csprintf("msicap.ma"), tmp32); 557 msicap.ma = tmp32; 558 UNSERIALIZE_SCALAR(msicap.mua); 559 paramIn(cp, csprintf("msicap.md"), tmp16);; 560 msicap.md = tmp16; 561 UNSERIALIZE_SCALAR(msicap.mmask); 562 UNSERIALIZE_SCALAR(msicap.mpend); 563 564 paramIn(cp, csprintf("msixcap.mxid"), tmp16); 565 msixcap.mxid = tmp16; 566 paramIn(cp, csprintf("msixcap.mxc"), tmp16); 567 msixcap.mxc = tmp16; 568 paramIn(cp, csprintf("msixcap.mtab"), tmp32); 569 msixcap.mtab = tmp32; 570 paramIn(cp, csprintf("msixcap.mpba"), tmp32); 571 msixcap.mpba = tmp32; 572 573 // Only allocate if MSIXCAP_BASE is not 0x0 574 if (MSIXCAP_BASE != 0x0) { 575 int msix_array_size; 576 int pba_array_size; 577 578 UNSERIALIZE_SCALAR(msix_array_size); 579 UNSERIALIZE_SCALAR(pba_array_size); 580 581 MSIXTable tmp1 = {{0UL, 0UL, 0UL, 0UL}}; 582 msix_table.resize(msix_array_size, tmp1); 583 584 MSIXPbaEntry tmp2 = {0}; 585 msix_pba.resize(pba_array_size, tmp2); 586 587 for (int i = 0; i < msix_array_size; i++) { 588 paramIn(cp, csprintf("msix_table[%d].addr_lo", i), 589 msix_table[i].fields.addr_lo); 590 paramIn(cp, csprintf("msix_table[%d].addr_hi", i), 591 msix_table[i].fields.addr_hi); 592 paramIn(cp, csprintf("msix_table[%d].msg_data", i), 593 msix_table[i].fields.msg_data); 594 paramIn(cp, csprintf("msix_table[%d].vec_ctrl", i), 595 msix_table[i].fields.vec_ctrl); 596 } 597 for (int i = 0; i < pba_array_size; i++) { 598 paramIn(cp, csprintf("msix_pba[%d].bits", i), 599 msix_pba[i].bits); 600 } 601 } 602 603 paramIn(cp, csprintf("pxcap.pxid"), tmp16); 604 pxcap.pxid = tmp16; 605 paramIn(cp, csprintf("pxcap.pxcap"), tmp16); 606 pxcap.pxcap = tmp16; 607 paramIn(cp, csprintf("pxcap.pxdcap"), tmp32); 608 pxcap.pxdcap = tmp32; 609 paramIn(cp, csprintf("pxcap.pxdc"), tmp16); 610 pxcap.pxdc = tmp16; 611 paramIn(cp, csprintf("pxcap.pxds"), tmp16); 612 pxcap.pxds = tmp16; 613 paramIn(cp, csprintf("pxcap.pxlcap"), tmp32); 614 pxcap.pxlcap = tmp32; 615 paramIn(cp, csprintf("pxcap.pxlc"), tmp16); 616 pxcap.pxlc = tmp16; 617 paramIn(cp, csprintf("pxcap.pxls"), tmp16); 618 pxcap.pxls = tmp16; 619 paramIn(cp, csprintf("pxcap.pxdcap2"), tmp32); 620 pxcap.pxdcap2 = tmp32; 621 paramIn(cp, csprintf("pxcap.pxdc2"), tmp32); 622 pxcap.pxdc2 = tmp32; 623 pioPort.sendRangeChange(); 624} 625 626