device.cc revision 3348
16019Shines@cs.fsu.edu/* 27399SAli.Saidi@ARM.com * Copyright (c) 2004-2005 The Regents of The University of Michigan 37399SAli.Saidi@ARM.com * All rights reserved. 47399SAli.Saidi@ARM.com * 57399SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 67399SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 77399SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 87399SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 97399SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 107399SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 117399SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 127399SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 137399SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 146019Shines@cs.fsu.edu * this software without specific prior written permission. 156019Shines@cs.fsu.edu * 166019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276019Shines@cs.fsu.edu * 286019Shines@cs.fsu.edu * Authors: Ali Saidi 296019Shines@cs.fsu.edu * Andrew Schultz 306019Shines@cs.fsu.edu * Miguel Serrano 316019Shines@cs.fsu.edu */ 326019Shines@cs.fsu.edu 336019Shines@cs.fsu.edu/* @file 346019Shines@cs.fsu.edu * A single PCI device configuration space entry. 356019Shines@cs.fsu.edu */ 366019Shines@cs.fsu.edu 376019Shines@cs.fsu.edu#include <list> 386019Shines@cs.fsu.edu#include <string> 396019Shines@cs.fsu.edu#include <vector> 407399SAli.Saidi@ARM.com 416019Shines@cs.fsu.edu#include "base/inifile.hh" 426019Shines@cs.fsu.edu#include "base/intmath.hh" // for isPowerOf2( 436019Shines@cs.fsu.edu#include "base/misc.hh" 446019Shines@cs.fsu.edu#include "base/str.hh" // for to_number 456019Shines@cs.fsu.edu#include "base/trace.hh" 466019Shines@cs.fsu.edu#include "dev/pciconfigall.hh" 476019Shines@cs.fsu.edu#include "dev/pcidev.hh" 486019Shines@cs.fsu.edu#include "dev/tsunamireg.h" 496019Shines@cs.fsu.edu#include "mem/packet.hh" 506019Shines@cs.fsu.edu#include "mem/packet_access.hh" 516019Shines@cs.fsu.edu#include "sim/builder.hh" 526019Shines@cs.fsu.edu#include "sim/byteswap.hh" 536019Shines@cs.fsu.edu#include "sim/param.hh" 546116Snate@binkert.org#include "sim/root.hh" 557678Sgblack@eecs.umich.edu 566019Shines@cs.fsu.eduusing namespace std; 576019Shines@cs.fsu.edu 586019Shines@cs.fsu.edu 596019Shines@cs.fsu.eduPciDev::PciConfigPort::PciConfigPort(PciDev *dev, int busid, int devid, 606019Shines@cs.fsu.edu int funcid, Platform *p) 616019Shines@cs.fsu.edu : SimpleTimingPort(dev->name() + "-pciconf"), device(dev), platform(p), 627404SAli.Saidi@ARM.com busId(busid), deviceId(devid), functionId(funcid) 637404SAli.Saidi@ARM.com{ 646019Shines@cs.fsu.edu configAddr = platform->calcConfigAddr(busId, deviceId, functionId); 656019Shines@cs.fsu.edu} 667294Sgblack@eecs.umich.edu 677294Sgblack@eecs.umich.edu 687639Sgblack@eecs.umich.eduTick 697294Sgblack@eecs.umich.eduPciDev::PciConfigPort::recvAtomic(Packet *pkt) 707294Sgblack@eecs.umich.edu{ 717294Sgblack@eecs.umich.edu assert(pkt->result == Packet::Unknown); 727294Sgblack@eecs.umich.edu assert(pkt->getAddr() >= configAddr && 737294Sgblack@eecs.umich.edu pkt->getAddr() < configAddr + PCI_CONFIG_SIZE); 747639Sgblack@eecs.umich.edu return pkt->isRead() ? device->readConfig(pkt) : device->writeConfig(pkt); 757639Sgblack@eecs.umich.edu} 767294Sgblack@eecs.umich.edu 777639Sgblack@eecs.umich.eduvoid 787404SAli.Saidi@ARM.comPciDev::PciConfigPort::getDeviceAddressRanges(AddrRangeList &resp, 797639Sgblack@eecs.umich.edu AddrRangeList &snoop) 807294Sgblack@eecs.umich.edu{ 817294Sgblack@eecs.umich.edu snoop.clear(); 827294Sgblack@eecs.umich.edu resp.push_back(RangeSize(configAddr, PCI_CONFIG_SIZE+1)); 837639Sgblack@eecs.umich.edu} 847294Sgblack@eecs.umich.edu 856019Shines@cs.fsu.edu 866019Shines@cs.fsu.eduPciDev::PciDev(Params *p) 876019Shines@cs.fsu.edu : DmaDevice(p), plat(p->platform), configData(p->configData), 886019Shines@cs.fsu.edu pioDelay(p->pio_delay), configDelay(p->config_delay), 897404SAli.Saidi@ARM.com configPort(NULL) 906019Shines@cs.fsu.edu{ 917406SAli.Saidi@ARM.com // copy the config data from the PciConfigData object 927436Sdam.sunwoo@arm.com if (configData) { 937436Sdam.sunwoo@arm.com memcpy(config.data, configData->config.data, sizeof(config.data)); 947406SAli.Saidi@ARM.com memcpy(BARSize, configData->BARSize, sizeof(BARSize)); 957404SAli.Saidi@ARM.com } else 967406SAli.Saidi@ARM.com panic("NULL pointer to configuration data"); 976019Shines@cs.fsu.edu 987694SAli.Saidi@ARM.com memset(BARAddrs, 0, sizeof(BARAddrs)); 997694SAli.Saidi@ARM.com 1007694SAli.Saidi@ARM.com plat->registerPciDevice(0, p->deviceNum, p->functionNum, 1017694SAli.Saidi@ARM.com letoh(configData->config.interruptLine)); 1027694SAli.Saidi@ARM.com} 1037694SAli.Saidi@ARM.com 1047694SAli.Saidi@ARM.comvoid 1056019Shines@cs.fsu.eduPciDev::init() 1067399SAli.Saidi@ARM.com{ 1076020Sgblack@eecs.umich.edu if (!configPort) 1086020Sgblack@eecs.umich.edu panic("pci config port not connected to anything!"); 1096020Sgblack@eecs.umich.edu configPort->sendStatusChange(Port::RangeChange); 1106020Sgblack@eecs.umich.edu PioDevice::init(); 1116020Sgblack@eecs.umich.edu} 1126020Sgblack@eecs.umich.edu 1136020Sgblack@eecs.umich.eduunsigned int 1146020Sgblack@eecs.umich.eduPciDev::drain(Event *de) 1156019Shines@cs.fsu.edu{ 1166019Shines@cs.fsu.edu unsigned int count; 1176019Shines@cs.fsu.edu count = pioPort->drain(de) + dmaPort->drain(de) + configPort->drain(de); 1186019Shines@cs.fsu.edu if (count) 1197697SAli.Saidi@ARM.com changeState(Draining); 1207404SAli.Saidi@ARM.com else 1216019Shines@cs.fsu.edu changeState(Drained); 1226019Shines@cs.fsu.edu return count; 1236019Shines@cs.fsu.edu} 1246019Shines@cs.fsu.edu 1256019Shines@cs.fsu.eduTick 1266019Shines@cs.fsu.eduPciDev::readConfig(Packet *pkt) 1276019Shines@cs.fsu.edu{ 1287404SAli.Saidi@ARM.com int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 1297404SAli.Saidi@ARM.com if (offset >= PCI_DEVICE_SPECIFIC) 1307404SAli.Saidi@ARM.com panic("Device specific PCI config space not implemented!\n"); 1316019Shines@cs.fsu.edu 1327404SAli.Saidi@ARM.com pkt->allocate(); 1337404SAli.Saidi@ARM.com 1347404SAli.Saidi@ARM.com switch (pkt->getSize()) { 1357404SAli.Saidi@ARM.com case sizeof(uint8_t): 1367404SAli.Saidi@ARM.com pkt->set<uint8_t>(config.data[offset]); 1377404SAli.Saidi@ARM.com DPRINTF(PCIDEV, 1387404SAli.Saidi@ARM.com "readConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n", 1397404SAli.Saidi@ARM.com params()->deviceNum, params()->functionNum, offset, 1407404SAli.Saidi@ARM.com (uint32_t)pkt->get<uint8_t>()); 1417404SAli.Saidi@ARM.com break; 1427404SAli.Saidi@ARM.com case sizeof(uint16_t): 1437404SAli.Saidi@ARM.com pkt->set<uint16_t>(*(uint16_t*)&config.data[offset]); 1447404SAli.Saidi@ARM.com DPRINTF(PCIDEV, 1457404SAli.Saidi@ARM.com "readConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n", 1467404SAli.Saidi@ARM.com params()->deviceNum, params()->functionNum, offset, 1477404SAli.Saidi@ARM.com (uint32_t)pkt->get<uint16_t>()); 1487404SAli.Saidi@ARM.com break; 1497404SAli.Saidi@ARM.com case sizeof(uint32_t): 1507406SAli.Saidi@ARM.com pkt->set<uint32_t>(*(uint32_t*)&config.data[offset]); 1517406SAli.Saidi@ARM.com DPRINTF(PCIDEV, 1527404SAli.Saidi@ARM.com "readConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n", 1537404SAli.Saidi@ARM.com params()->deviceNum, params()->functionNum, offset, 1547404SAli.Saidi@ARM.com (uint32_t)pkt->get<uint32_t>()); 1556019Shines@cs.fsu.edu break; 1566019Shines@cs.fsu.edu default: 1577404SAli.Saidi@ARM.com panic("invalid access size(?) for PCI configspace!\n"); 1586019Shines@cs.fsu.edu } 1596019Shines@cs.fsu.edu pkt->result = Packet::Success; 1606019Shines@cs.fsu.edu return configDelay; 1616019Shines@cs.fsu.edu 1627694SAli.Saidi@ARM.com} 1637694SAli.Saidi@ARM.com 1647694SAli.Saidi@ARM.comvoid 1657694SAli.Saidi@ARM.comPciDev::addressRanges(AddrRangeList &range_list) 1667694SAli.Saidi@ARM.com{ 1677694SAli.Saidi@ARM.com int x = 0; 1687694SAli.Saidi@ARM.com range_list.clear(); 1697694SAli.Saidi@ARM.com for (x = 0; x < 6; x++) 1707694SAli.Saidi@ARM.com if (BARAddrs[x] != 0) 1717694SAli.Saidi@ARM.com range_list.push_back(RangeSize(BARAddrs[x],BARSize[x])); 1727436Sdam.sunwoo@arm.com} 1737436Sdam.sunwoo@arm.com 1747436Sdam.sunwoo@arm.comTick 1757436Sdam.sunwoo@arm.comPciDev::writeConfig(Packet *pkt) 1767436Sdam.sunwoo@arm.com{ 1777436Sdam.sunwoo@arm.com int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 1787436Sdam.sunwoo@arm.com if (offset >= PCI_DEVICE_SPECIFIC) 1797436Sdam.sunwoo@arm.com panic("Device specific PCI config space not implemented!\n"); 1807436Sdam.sunwoo@arm.com 1817436Sdam.sunwoo@arm.com switch (pkt->getSize()) { 1827436Sdam.sunwoo@arm.com case sizeof(uint8_t): 1837436Sdam.sunwoo@arm.com switch (offset) { 1847436Sdam.sunwoo@arm.com case PCI0_INTERRUPT_LINE: 1857404SAli.Saidi@ARM.com config.interruptLine = pkt->get<uint8_t>(); 1867404SAli.Saidi@ARM.com case PCI_CACHE_LINE_SIZE: 1877404SAli.Saidi@ARM.com config.cacheLineSize = pkt->get<uint8_t>(); 1887404SAli.Saidi@ARM.com case PCI_LATENCY_TIMER: 1897404SAli.Saidi@ARM.com config.latencyTimer = pkt->get<uint8_t>(); 1907404SAli.Saidi@ARM.com break; 1917404SAli.Saidi@ARM.com /* Do nothing for these read-only registers */ 1926116Snate@binkert.org case PCI0_INTERRUPT_PIN: 1937404SAli.Saidi@ARM.com case PCI0_MINIMUM_GRANT: 1946116Snate@binkert.org case PCI0_MAXIMUM_LATENCY: 1956116Snate@binkert.org case PCI_CLASS_CODE: 1966019Shines@cs.fsu.edu case PCI_REVISION_ID: 1976019Shines@cs.fsu.edu break; 1986019Shines@cs.fsu.edu default: 1996019Shines@cs.fsu.edu panic("writing to a read only register"); 2006019Shines@cs.fsu.edu } 2016019Shines@cs.fsu.edu DPRINTF(PCIDEV, 2026019Shines@cs.fsu.edu "writeConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n", 2036116Snate@binkert.org params()->deviceNum, params()->functionNum, offset, 2046019Shines@cs.fsu.edu (uint32_t)pkt->get<uint8_t>()); 2056019Shines@cs.fsu.edu break; 206 case sizeof(uint16_t): 207 switch (offset) { 208 case PCI_COMMAND: 209 config.command = pkt->get<uint8_t>(); 210 case PCI_STATUS: 211 config.status = pkt->get<uint8_t>(); 212 case PCI_CACHE_LINE_SIZE: 213 config.cacheLineSize = pkt->get<uint8_t>(); 214 break; 215 default: 216 panic("writing to a read only register"); 217 } 218 DPRINTF(PCIDEV, 219 "writeConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n", 220 params()->deviceNum, params()->functionNum, offset, 221 (uint32_t)pkt->get<uint16_t>()); 222 break; 223 case sizeof(uint32_t): 224 switch (offset) { 225 case PCI0_BASE_ADDR0: 226 case PCI0_BASE_ADDR1: 227 case PCI0_BASE_ADDR2: 228 case PCI0_BASE_ADDR3: 229 case PCI0_BASE_ADDR4: 230 case PCI0_BASE_ADDR5: 231 { 232 int barnum = BAR_NUMBER(offset); 233 234 // convert BAR values to host endianness 235 uint32_t he_old_bar = letoh(config.baseAddr[barnum]); 236 uint32_t he_new_bar = letoh(pkt->get<uint32_t>()); 237 238 uint32_t bar_mask = 239 BAR_IO_SPACE(he_old_bar) ? BAR_IO_MASK : BAR_MEM_MASK; 240 241 // Writing 0xffffffff to a BAR tells the card to set the 242 // value of the bar to a bitmask indicating the size of 243 // memory it needs 244 if (he_new_bar == 0xffffffff) { 245 he_new_bar = ~(BARSize[barnum] - 1); 246 } else { 247 // does it mean something special to write 0 to a BAR? 248 he_new_bar &= ~bar_mask; 249 if (he_new_bar) { 250 Addr space_base = BAR_IO_SPACE(he_old_bar) ? 251 TSUNAMI_PCI0_IO : TSUNAMI_PCI0_MEMORY; 252 BARAddrs[barnum] = he_new_bar + space_base; 253 pioPort->sendStatusChange(Port::RangeChange); 254 } 255 } 256 config.baseAddr[barnum] = htole((he_new_bar & ~bar_mask) | 257 (he_old_bar & bar_mask)); 258 } 259 break; 260 261 case PCI0_ROM_BASE_ADDR: 262 if (letoh(pkt->get<uint32_t>()) == 0xfffffffe) 263 config.expansionROM = htole((uint32_t)0xffffffff); 264 else 265 config.expansionROM = pkt->get<uint32_t>(); 266 break; 267 268 case PCI_COMMAND: 269 // This could also clear some of the error bits in the Status 270 // register. However they should never get set, so lets ignore 271 // it for now 272 config.command = pkt->get<uint32_t>(); 273 break; 274 275 default: 276 DPRINTF(PCIDEV, "Writing to a read only register"); 277 } 278 DPRINTF(PCIDEV, 279 "writeConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n", 280 params()->deviceNum, params()->functionNum, offset, 281 (uint32_t)pkt->get<uint32_t>()); 282 break; 283 default: 284 panic("invalid access size(?) for PCI configspace!\n"); 285 } 286 pkt->result = Packet::Success; 287 return configDelay; 288 289} 290 291void 292PciDev::serialize(ostream &os) 293{ 294 SERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0])); 295 SERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0])); 296 SERIALIZE_ARRAY(config.data, sizeof(config.data) / sizeof(config.data[0])); 297} 298 299void 300PciDev::unserialize(Checkpoint *cp, const std::string §ion) 301{ 302 UNSERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0])); 303 UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0])); 304 UNSERIALIZE_ARRAY(config.data, 305 sizeof(config.data) / sizeof(config.data[0])); 306 pioPort->sendStatusChange(Port::RangeChange); 307 308} 309 310#ifndef DOXYGEN_SHOULD_SKIP_THIS 311 312BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigData) 313 314 Param<uint16_t> VendorID; 315 Param<uint16_t> DeviceID; 316 Param<uint16_t> Command; 317 Param<uint16_t> Status; 318 Param<uint8_t> Revision; 319 Param<uint8_t> ProgIF; 320 Param<uint8_t> SubClassCode; 321 Param<uint8_t> ClassCode; 322 Param<uint8_t> CacheLineSize; 323 Param<uint8_t> LatencyTimer; 324 Param<uint8_t> HeaderType; 325 Param<uint8_t> BIST; 326 Param<uint32_t> BAR0; 327 Param<uint32_t> BAR1; 328 Param<uint32_t> BAR2; 329 Param<uint32_t> BAR3; 330 Param<uint32_t> BAR4; 331 Param<uint32_t> BAR5; 332 Param<uint32_t> CardbusCIS; 333 Param<uint16_t> SubsystemVendorID; 334 Param<uint16_t> SubsystemID; 335 Param<uint32_t> ExpansionROM; 336 Param<uint8_t> InterruptLine; 337 Param<uint8_t> InterruptPin; 338 Param<uint8_t> MinimumGrant; 339 Param<uint8_t> MaximumLatency; 340 Param<uint32_t> BAR0Size; 341 Param<uint32_t> BAR1Size; 342 Param<uint32_t> BAR2Size; 343 Param<uint32_t> BAR3Size; 344 Param<uint32_t> BAR4Size; 345 Param<uint32_t> BAR5Size; 346 347END_DECLARE_SIM_OBJECT_PARAMS(PciConfigData) 348 349BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigData) 350 351 INIT_PARAM(VendorID, "Vendor ID"), 352 INIT_PARAM(DeviceID, "Device ID"), 353 INIT_PARAM_DFLT(Command, "Command Register", 0x00), 354 INIT_PARAM_DFLT(Status, "Status Register", 0x00), 355 INIT_PARAM_DFLT(Revision, "Device Revision", 0x00), 356 INIT_PARAM_DFLT(ProgIF, "Programming Interface", 0x00), 357 INIT_PARAM(SubClassCode, "Sub-Class Code"), 358 INIT_PARAM(ClassCode, "Class Code"), 359 INIT_PARAM_DFLT(CacheLineSize, "System Cacheline Size", 0x00), 360 INIT_PARAM_DFLT(LatencyTimer, "PCI Latency Timer", 0x00), 361 INIT_PARAM_DFLT(HeaderType, "PCI Header Type", 0x00), 362 INIT_PARAM_DFLT(BIST, "Built In Self Test", 0x00), 363 INIT_PARAM_DFLT(BAR0, "Base Address Register 0", 0x00), 364 INIT_PARAM_DFLT(BAR1, "Base Address Register 1", 0x00), 365 INIT_PARAM_DFLT(BAR2, "Base Address Register 2", 0x00), 366 INIT_PARAM_DFLT(BAR3, "Base Address Register 3", 0x00), 367 INIT_PARAM_DFLT(BAR4, "Base Address Register 4", 0x00), 368 INIT_PARAM_DFLT(BAR5, "Base Address Register 5", 0x00), 369 INIT_PARAM_DFLT(CardbusCIS, "Cardbus Card Information Structure", 0x00), 370 INIT_PARAM_DFLT(SubsystemVendorID, "Subsystem Vendor ID", 0x00), 371 INIT_PARAM_DFLT(SubsystemID, "Subsystem ID", 0x00), 372 INIT_PARAM_DFLT(ExpansionROM, "Expansion ROM Base Address Register", 0x00), 373 INIT_PARAM(InterruptLine, "Interrupt Line Register"), 374 INIT_PARAM(InterruptPin, "Interrupt Pin Register"), 375 INIT_PARAM_DFLT(MinimumGrant, "Minimum Grant", 0x00), 376 INIT_PARAM_DFLT(MaximumLatency, "Maximum Latency", 0x00), 377 INIT_PARAM_DFLT(BAR0Size, "Base Address Register 0 Size", 0x00), 378 INIT_PARAM_DFLT(BAR1Size, "Base Address Register 1 Size", 0x00), 379 INIT_PARAM_DFLT(BAR2Size, "Base Address Register 2 Size", 0x00), 380 INIT_PARAM_DFLT(BAR3Size, "Base Address Register 3 Size", 0x00), 381 INIT_PARAM_DFLT(BAR4Size, "Base Address Register 4 Size", 0x00), 382 INIT_PARAM_DFLT(BAR5Size, "Base Address Register 5 Size", 0x00) 383 384END_INIT_SIM_OBJECT_PARAMS(PciConfigData) 385 386CREATE_SIM_OBJECT(PciConfigData) 387{ 388 PciConfigData *data = new PciConfigData(getInstanceName()); 389 390 data->config.vendor = htole(VendorID); 391 data->config.device = htole(DeviceID); 392 data->config.command = htole(Command); 393 data->config.status = htole(Status); 394 data->config.revision = htole(Revision); 395 data->config.progIF = htole(ProgIF); 396 data->config.subClassCode = htole(SubClassCode); 397 data->config.classCode = htole(ClassCode); 398 data->config.cacheLineSize = htole(CacheLineSize); 399 data->config.latencyTimer = htole(LatencyTimer); 400 data->config.headerType = htole(HeaderType); 401 data->config.bist = htole(BIST); 402 403 data->config.baseAddr[0] = htole(BAR0); 404 data->config.baseAddr[1] = htole(BAR1); 405 data->config.baseAddr[2] = htole(BAR2); 406 data->config.baseAddr[3] = htole(BAR3); 407 data->config.baseAddr[4] = htole(BAR4); 408 data->config.baseAddr[5] = htole(BAR5); 409 data->config.cardbusCIS = htole(CardbusCIS); 410 data->config.subsystemVendorID = htole(SubsystemVendorID); 411 data->config.subsystemID = htole(SubsystemID); 412 data->config.expansionROM = htole(ExpansionROM); 413 data->config.interruptLine = htole(InterruptLine); 414 data->config.interruptPin = htole(InterruptPin); 415 data->config.minimumGrant = htole(MinimumGrant); 416 data->config.maximumLatency = htole(MaximumLatency); 417 418 data->BARSize[0] = BAR0Size; 419 data->BARSize[1] = BAR1Size; 420 data->BARSize[2] = BAR2Size; 421 data->BARSize[3] = BAR3Size; 422 data->BARSize[4] = BAR4Size; 423 data->BARSize[5] = BAR5Size; 424 425 for (int i = 0; i < 6; ++i) { 426 uint32_t barsize = data->BARSize[i]; 427 if (barsize != 0 && !isPowerOf2(barsize)) { 428 fatal("%s: BAR %d size %d is not a power of 2\n", 429 getInstanceName(), i, data->BARSize[i]); 430 } 431 } 432 433 return data; 434} 435 436REGISTER_SIM_OBJECT("PciConfigData", PciConfigData) 437 438#endif // DOXYGEN_SHOULD_SKIP_THIS 439