47#include <initializer_list>
57#include "debug/PciDevice.hh"
66 std::initializer_list<PciBar *> BARs_init)
87 "Invalid PCI interrupt '%i' specified.",
p.InterruptPin);
90 for (
auto *bar:
BARs) {
96 "First BAR in %s is upper 32 bits of a memory BAR.", idx);
98 fatal_if(!ml,
"Upper 32 bits of memory BAR in %s doesn't come "
99 "after the lower 32.");
126 pmcap.pid = (uint16_t)
p.PMCAPCapId;
127 pmcap.pid |= (uint16_t)
p.PMCAPNextCapability << 8;
128 pmcap.pc =
p.PMCAPCapabilities;
129 pmcap.pmcs =
p.PMCAPCtrlStatus;
132 msicap.mid = (uint16_t)
p.MSICAPCapId;
133 msicap.mid |= (uint16_t)
p.MSICAPNextCapability << 8;
136 msicap.mua =
p.MSICAPMsgUpperAddr;
138 msicap.mmask =
p.MSICAPMaskBits;
139 msicap.mpend =
p.MSICAPPendingBits;
142 msixcap.mxid = (uint16_t)
p.MSIXCAPCapId;
143 msixcap.mxid |= (uint16_t)
p.MSIXCAPNextCapability << 8;
155 uint16_t msixcap_mxc_ts =
msixcap.mxc & 0x07ff;
157 int msix_vecs = msixcap_mxc_ts + 1;
170 (msixcap_mxc_ts + 1) *
sizeof(
MSIXTable);
180 pxcap.pxid = (uint16_t)
p.PXCAPCapId;
181 pxcap.pxid |= (uint16_t)
p.PXCAPNextCapability << 8;
182 pxcap.pxcap =
p.PXCAPCapabilities;
183 pxcap.pxdcap =
p.PXCAPDevCapabilities;
184 pxcap.pxdc =
p.PXCAPDevCtrl;
185 pxcap.pxds =
p.PXCAPDevStatus;
186 pxcap.pxlcap =
p.PXCAPLinkCap;
187 pxcap.pxlc =
p.PXCAPLinkCtrl;
188 pxcap.pxls =
p.PXCAPLinkStatus;
189 pxcap.pxscap =
p.PXCAPSlotCap;
190 pxcap.pxsc =
p.PXCAPSlotCtrl;
191 pxcap.pxss =
p.PXCAPSlotStatus;
192 pxcap.pxrcap =
p.PXCAPRootCap;
193 pxcap.pxrc =
p.PXCAPRootCtrl;
194 pxcap.pxrs =
p.PXCAPRootStatus;
195 pxcap.pxdcap2 =
p.PXCAPDevCap2;
196 pxcap.pxdc2 =
p.PXCAPDevCtrl2;
197 pxcap.pxds2 =
p.PXCAPDevStatus2;
198 pxcap.pxlcap2 =
p.PXCAPLinkCap2;
199 pxcap.pxlc2 =
p.PXCAPLinkCtrl2;
200 pxcap.pxls2 =
p.PXCAPLinkStatus2;
201 pxcap.pxscap2 =
p.PXCAPSlotCap2;
202 pxcap.pxsc2 =
p.PXCAPSlotCtrl2;
203 pxcap.pxss2 =
p.PXCAPSlotStatus2;
214 warn_once(
"Device specific PCI config space "
215 "not implemented for %s!\n", this->
name());
217 case sizeof(uint8_t):
218 pkt->
setLE<uint8_t>(0);
220 case sizeof(uint16_t):
221 pkt->
setLE<uint16_t>(0);
223 case sizeof(uint32_t):
224 pkt->
setLE<uint32_t>(0);
227 panic(
"invalid access size(?) for PCI configspace!\n");
230 panic(
"Out-of-range access to PCI config space!\n");
234 case sizeof(uint8_t):
237 "readConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n",
239 (uint32_t)pkt->
getLE<uint8_t>());
241 case sizeof(uint16_t):
244 "readConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n",
246 (uint32_t)pkt->
getLE<uint16_t>());
248 case sizeof(uint32_t):
251 "readConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n",
253 (uint32_t)pkt->
getLE<uint32_t>());
256 panic(
"invalid access size(?) for PCI configspace!\n");
277 PciCommandRegister command =
letoh(
_config.common.command);
278 for (
auto *bar:
BARs) {
279 if (command.ioSpace && bar->isIo())
280 ranges.push_back(bar->range());
281 if (command.memorySpace && bar->isMem())
282 ranges.push_back(bar->range());
298 warn_once(
"Device specific PCI config space "
299 "not implemented for %s!\n", this->
name());
301 case sizeof(uint8_t):
302 case sizeof(uint16_t):
303 case sizeof(uint32_t):
306 panic(
"invalid access size(?) for PCI configspace!\n");
309 warn_once(
"Device specific PCI config header "
310 "not implemented for %s!\n", this->
name());
312 case sizeof(uint8_t):
313 case sizeof(uint16_t):
314 case sizeof(uint32_t):
317 panic(
"invalid access size(?) for PCI configspace!\n");
320 panic(
"Out-of-range access to PCI config space!\n");
324 case sizeof(uint8_t):
341 panic(
"writing to a read only register");
344 "writeConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n",
346 (uint32_t)pkt->
getLE<uint8_t>());
348 case sizeof(uint16_t):
362 panic(
"writing to a read only register");
365 "writeConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n",
367 (uint32_t)pkt->
getLE<uint16_t>());
369 case sizeof(uint32_t):
384 "writeConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n",
386 (uint32_t)pkt->
getLE<uint32_t>());
389 panic(
"invalid access size(?) for PCI configspace!\n");
437 uint16_t msixcap_mxc_ts =
msixcap.mxc & 0x07ff;
438 int msix_array_size = msixcap_mxc_ts + 1;
447 for (
int i = 0;
i < msix_array_size;
i++) {
457 for (
int i = 0;
i < pba_array_size;
i++) {
537 msix_pba.resize(pba_array_size, tmp2);
539 for (
int i = 0;
i < msix_array_size;
i++) {
549 for (
int i = 0;
i < pba_array_size;
i++) {
560 pxcap.pxdcap = tmp32;
566 pxcap.pxlcap = tmp32;
572 pxcap.pxscap = tmp32;
578 pxcap.pxrcap = tmp16;
584 pxcap.pxdcap2 = tmp32;
590 pxcap.pxlcap2 = tmp32;
596 pxcap.pxscap2 = tmp32;
606 fatal_if((_config.common.headerType & 0x7F) != 0,
"HeaderType is invalid");
609 for (
auto *bar : BARs)
610 _config.type0.baseAddr[idx++] = bar->write(upstreamInterface, 0);
612 _config.type0.cardbusCIS =
htole(
p.CardbusCIS);
613 _config.type0.subsystemVendorID =
htole(
p.SubsystemVendorID);
614 _config.type0.subsystemID =
htole(
p.SubsystemID);
615 _config.type0.expansionROM =
htole(
p.ExpansionROM);
618 bzero(_config.type0.reserved, 7 *
sizeof(uint8_t));
620 _config.type0.minimumGrant =
htole(
p.MinimumGrant);
621 _config.type0.maximumLatency =
htole(
p.MaximumLatency);
632 warn_once(
"Device specific PCI config space "
633 "not implemented for %s!\n", this->
name());
635 case sizeof(uint8_t):
636 case sizeof(uint16_t):
637 case sizeof(uint32_t):
640 panic(
"invalid access size(?) for PCI configspace!\n");
643 panic(
"Out-of-range access to PCI config space!\n");
647 case sizeof(uint8_t):
654 panic(
"writing to a read only register");
657 "writeConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n",
659 (uint32_t)pkt->
getLE<uint8_t>());
661 case sizeof(uint16_t):
662 panic(
"writing to a read only register");
663 case sizeof(uint32_t):
673 auto *bar =
BARs[num];
681 if (
letoh(pkt->
getLE<uint32_t>()) == 0xfffffffe)
682 _config.type0.expansionROM =
htole((uint32_t)0xffffffff);
691 "writeConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n",
693 (uint32_t)pkt->
getLE<uint32_t>());
696 panic(
"invalid access size(?) for PCI configspace!\n");
707 for (
int idx = 0; idx <
BARs.size(); idx++)
716 fatal_if((_config.common.headerType & 0x7F) != 1,
"HeaderType is invalid");
719 for (
auto *bar : BARs)
720 _config.type1.baseAddr[idx++] = bar->write(upstreamInterface, 0);
722 _config.type1.primaryBusNum =
htole(
p.PrimaryBusNumber);
723 _config.type1.secondaryBusNum =
htole(
p.SecondaryBusNumber);
724 _config.type1.subordinateBusNum =
htole(
p.SubordinateBusNumber);
725 _config.type1.secondaryLatencyTimer =
htole(
p.SecondaryLatencyTimer);
726 _config.type1.ioBase =
htole(
p.IOBase);
727 _config.type1.ioLimit =
htole(
p.IOLimit);
728 _config.type1.secondaryStatus =
htole(
p.SecondaryStatus);
729 _config.type1.memBase =
htole(
p.MemoryBase);
730 _config.type1.memLimit =
htole(
p.MemoryLimit);
731 _config.type1.prefetchMemBase =
htole(
p.PrefetchableMemoryBase);
732 _config.type1.prefetchMemLimit =
htole(
p.PrefetchableMemoryLimit);
733 _config.type1.prefetchBaseUpper =
htole(
p.PrefetchableBaseUpper);
734 _config.type1.prefetchLimitUpper =
htole(
p.PrefetchableLimitUpper);
735 _config.type1.ioBaseUpper =
htole(
p.IOBaseUpper);
736 _config.type1.ioLimitUpper =
htole(
p.IOLimitUpper);
737 _config.type1.expansionROM =
htole(
p.ExpansionROM);
738 _config.type1.bridgeControl =
htole(
p.BridgeControl);
749 warn_once(
"Device specific PCI config space "
750 "not implemented for %s!\n", this->
name());
752 case sizeof(uint8_t):
753 case sizeof(uint16_t):
754 case sizeof(uint32_t):
757 panic(
"invalid access size(?) for PCI configspace!\n");
760 panic(
"Out-of-range access to PCI config space!\n");
764 case sizeof(uint8_t):
776 _config.type1.secondaryLatencyTimer = pkt->
getLE<uint8_t>();
785 panic(
"writing to a read only register");
788 "writeConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n",
790 (uint32_t)pkt->
getLE<uint8_t>());
792 case sizeof(uint16_t):
807 _config.type1.prefetchMemLimit = pkt->
getLE<uint16_t>();
819 panic(
"writing to a read only register");
822 "writeConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n",
824 (uint32_t)pkt->
getLE<uint16_t>());
826 case sizeof(uint32_t):
832 auto *bar =
BARs[num];
839 _config.type1.prefetchBaseUpper = pkt->
getLE<uint32_t>();
842 _config.type1.prefetchLimitUpper = pkt->
getLE<uint32_t>();
845 if (
letoh(pkt->
getLE<uint32_t>()) == 0xfffffffe)
846 _config.type1.expansionROM =
htole((uint32_t)0xffffffff);
851 panic(
"writing to a read only register");
854 "writeConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n",
856 (uint32_t)pkt->
getLE<uint32_t>());
859 panic(
"invalid access size(?) for PCI configspace!\n");
870 for (
int idx = 0; idx <
BARs.size(); idx++)
DmaDevice(const Params &p)
void setLE(T v)
Set the value in the data pointer to v as little endian.
void makeAtomicResponse()
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
const int PMCAP_PC_OFFSET
Tick write(PacketPtr pkt) final
Final implementation of write access from DmaDevice.
const int MSIXCAP_MTAB_OFFSET
PciDevice(const PciDeviceParams ¶ms, std::initializer_list< PciBar * > BARs_init)
Constructor for PCI Dev.
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
std::vector< MSIXTable > msix_table
MSIX Table and PBA Structures.
PciUpstream::DeviceInterface upstreamInterface
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
void recvBusChange()
Called to receive a bus number change from the PCI upstream.
Tick read(PacketPtr pkt) final
Final implementation of read access from PioDevice.
const int PMCAP_BASE
The capability list structures and base addresses.
AddrRangeList getAddrRanges() const override
Determine the address ranges that this device responds to.
const int PMCAP_PMCS_OFFSET
virtual Tick writeDevice(PacketPtr pkt)=0
Write to the PCI device.
std::vector< MSIXPbaEntry > msix_pba
virtual Tick readConfig(PacketPtr pkt)
Read from the PCI config space data that is stored locally.
PCIConfig _config
The current config space.
virtual Tick readDevice(PacketPtr pkt)=0
Read from the PCI device.
virtual Tick writeConfig(PacketPtr pkt)
Write to the PCI config space data that is stored locally.
const int MSIXCAP_ID_OFFSET
const int MSIXCAP_MPBA_OFFSET
std::vector< PciBar * > BARs
bool isCommonConfig(Addr offs)
const int PMCAP_ID_OFFSET
const int MSIXCAP_MXC_OFFSET
const PciDevAddr _devAddr
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
Tick writeConfig(PacketPtr pkt) override
Write to the PCI config space data that is stored locally.
Tick writeConfig(PacketPtr pkt) override
Write to the PCI config space data that is stored locally.
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
PioPort< PioDevice > pioPort
The pioPort that handles the requests for us and provides us requests that it sees.
#define PCI1_BAR_NUMBER(x)
#define PCI0_BAR_NUMBER(x)
std::list< AddrRange > AddrRangeList
Convenience typedef for a collection of address ranges.
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
#define panic(...)
This implements a cprintf based panic() function.
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
#define UNSERIALIZE_ARRAY(member, size)
#define SERIALIZE_ARRAY(member, size)
Declaration of IniFile object.
Copyright (c) 2024 Arm Limited All rights reserved.
std::ostream CheckpointOut
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
uint64_t Tick
Tick count type.
std::string csprintf(const char *format, const Args &...args)
Declaration of the Packet class.
#define PCI1_IO_LIMIT_UPPER
#define PCI1_PRF_MEM_BASE
#define PCI1_ROM_BASE_ADDR
#define PCI0_MINIMUM_GRANT
#define PCI0_MAXIMUM_LATENCY
#define PCI1_SEC_LAT_TIMER
#define PCI0_ROM_BASE_ADDR
#define PCI_INTERRUPT_PIN
#define PCI_INTERRUPT_LINE
#define PMCAP_ID
PCIe capability list offsets internal to the entry.
#define PCI1_PRF_BASE_UPPER
#define PCI_CACHE_LINE_SIZE
#define PCI_DEVICE_SPECIFIC
#define PCI1_PRF_MEM_LIMIT
#define PCI1_PRF_LIMIT_UPPER
#define PCI1_IO_BASE_UPPER
#define PCI1_SECONDARY_STATUS
#define PCI_LATENCY_TIMER
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)
const std::string & name()