47#include <initializer_list>
57#include "debug/PciBridge.hh"
58#include "debug/PciDevice.hh"
59#include "debug/PciEndpoint.hh"
68 std::initializer_list<PciBar *> BARs_init)
90 "Invalid PCI interrupt '%i' specified.",
p.InterruptPin);
93 for (
auto *bar:
BARs) {
99 "First BAR in %s is upper 32 bits of a memory BAR.", idx);
101 fatal_if(!ml,
"Upper 32 bits of memory BAR in %s doesn't come "
102 "after the lower 32.");
129 pmcap.pid = (uint16_t)
p.PMCAPCapId;
130 pmcap.pid |= (uint16_t)
p.PMCAPNextCapability << 8;
131 pmcap.pc =
p.PMCAPCapabilities;
132 pmcap.pmcs =
p.PMCAPCtrlStatus;
135 msicap.mid = (uint16_t)
p.MSICAPCapId;
136 msicap.mid |= (uint16_t)
p.MSICAPNextCapability << 8;
139 msicap.mua =
p.MSICAPMsgUpperAddr;
141 msicap.mmask =
p.MSICAPMaskBits;
142 msicap.mpend =
p.MSICAPPendingBits;
145 msixcap.mxid = (uint16_t)
p.MSIXCAPCapId;
146 msixcap.mxid |= (uint16_t)
p.MSIXCAPNextCapability << 8;
158 uint16_t msixcap_mxc_ts =
msixcap.mxc & 0x07ff;
160 int msix_vecs = msixcap_mxc_ts + 1;
173 (msixcap_mxc_ts + 1) *
sizeof(
MSIXTable);
183 pxcap.pxid = (uint16_t)
p.PXCAPCapId;
184 pxcap.pxid |= (uint16_t)
p.PXCAPNextCapability << 8;
185 pxcap.pxcap =
p.PXCAPCapabilities;
186 pxcap.pxdcap =
p.PXCAPDevCapabilities;
187 pxcap.pxdc =
p.PXCAPDevCtrl;
188 pxcap.pxds =
p.PXCAPDevStatus;
189 pxcap.pxlcap =
p.PXCAPLinkCap;
190 pxcap.pxlc =
p.PXCAPLinkCtrl;
191 pxcap.pxls =
p.PXCAPLinkStatus;
192 pxcap.pxscap =
p.PXCAPSlotCap;
193 pxcap.pxsc =
p.PXCAPSlotCtrl;
194 pxcap.pxss =
p.PXCAPSlotStatus;
195 pxcap.pxrcap =
p.PXCAPRootCap;
196 pxcap.pxrc =
p.PXCAPRootCtrl;
197 pxcap.pxrs =
p.PXCAPRootStatus;
198 pxcap.pxdcap2 =
p.PXCAPDevCap2;
199 pxcap.pxdc2 =
p.PXCAPDevCtrl2;
200 pxcap.pxds2 =
p.PXCAPDevStatus2;
201 pxcap.pxlcap2 =
p.PXCAPLinkCap2;
202 pxcap.pxlc2 =
p.PXCAPLinkCtrl2;
203 pxcap.pxls2 =
p.PXCAPLinkStatus2;
204 pxcap.pxscap2 =
p.PXCAPSlotCap2;
205 pxcap.pxsc2 =
p.PXCAPSlotCtrl2;
206 pxcap.pxss2 =
p.PXCAPSlotStatus2;
217 warn_once(
"Device specific PCI config space "
218 "not implemented for %s!\n", this->
name());
220 case sizeof(uint8_t):
221 pkt->
setLE<uint8_t>(0);
223 case sizeof(uint16_t):
224 pkt->
setLE<uint16_t>(0);
226 case sizeof(uint32_t):
227 pkt->
setLE<uint32_t>(0);
230 panic(
"invalid access size(?) for PCI configspace!\n");
233 panic(
"Out-of-range access to PCI config space!\n");
237 case sizeof(uint8_t):
240 "readConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n",
242 (uint32_t)pkt->
getLE<uint8_t>());
244 case sizeof(uint16_t):
247 "readConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n",
249 (uint32_t)pkt->
getLE<uint16_t>());
251 case sizeof(uint32_t):
254 "readConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n",
256 (uint32_t)pkt->
getLE<uint32_t>());
259 panic(
"invalid access size(?) for PCI configspace!\n");
270 PciCommandRegister command =
letoh(
_config.common.command);
271 for (
auto *bar:
BARs) {
272 if (command.ioSpace && bar->isIo())
273 ranges.push_back(bar->range());
274 if (command.memorySpace && bar->isMem())
275 ranges.push_back(bar->range());
288 warn_once(
"Device specific PCI config space "
289 "not implemented for %s!\n", this->
name());
291 case sizeof(uint8_t):
292 case sizeof(uint16_t):
293 case sizeof(uint32_t):
296 panic(
"invalid access size(?) for PCI configspace!\n");
299 warn_once(
"Device specific PCI config header "
300 "not implemented for %s!\n", this->
name());
302 case sizeof(uint8_t):
303 case sizeof(uint16_t):
304 case sizeof(uint32_t):
307 panic(
"invalid access size(?) for PCI configspace!\n");
310 panic(
"Out-of-range access to PCI config space!\n");
314 case sizeof(uint8_t):
331 panic(
"writing to a read only register");
334 "writeConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n",
336 (uint32_t)pkt->
getLE<uint8_t>());
338 case sizeof(uint16_t):
352 panic(
"writing to a read only register");
355 "writeConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n",
357 (uint32_t)pkt->
getLE<uint16_t>());
359 case sizeof(uint32_t):
374 "writeConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n",
376 (uint32_t)pkt->
getLE<uint32_t>());
379 panic(
"invalid access size(?) for PCI configspace!\n");
411 uint16_t msixcap_mxc_ts =
msixcap.mxc & 0x07ff;
412 int msix_array_size = msixcap_mxc_ts + 1;
421 for (
int i = 0;
i < msix_array_size;
i++) {
431 for (
int i = 0;
i < pba_array_size;
i++) {
511 msix_pba.resize(pba_array_size, tmp2);
513 for (
int i = 0;
i < msix_array_size;
i++) {
523 for (
int i = 0;
i < pba_array_size;
i++) {
534 pxcap.pxdcap = tmp32;
540 pxcap.pxlcap = tmp32;
546 pxcap.pxscap = tmp32;
552 pxcap.pxrcap = tmp16;
558 pxcap.pxdcap2 = tmp32;
564 pxcap.pxlcap2 = tmp32;
570 pxcap.pxscap2 = tmp32;
580 fatal_if((_config.common.headerType & 0x7F) != 0,
"HeaderType is invalid");
583 for (
auto *bar : BARs)
584 _config.type0.baseAddr[idx++] = bar->write(hostInterface, 0);
586 _config.type0.cardbusCIS =
htole(
p.CardbusCIS);
587 _config.type0.subsystemVendorID =
htole(
p.SubsystemVendorID);
588 _config.type0.subsystemID =
htole(
p.SubsystemID);
589 _config.type0.expansionROM =
htole(
p.ExpansionROM);
592 bzero(_config.type0.reserved, 7 *
sizeof(uint8_t));
594 _config.type0.minimumGrant =
htole(
p.MinimumGrant);
595 _config.type0.maximumLatency =
htole(
p.MaximumLatency);
606 warn_once(
"Device specific PCI config space "
607 "not implemented for %s!\n", this->
name());
609 case sizeof(uint8_t):
610 case sizeof(uint16_t):
611 case sizeof(uint32_t):
614 panic(
"invalid access size(?) for PCI configspace!\n");
617 panic(
"Out-of-range access to PCI config space!\n");
621 case sizeof(uint8_t):
628 panic(
"writing to a read only register");
631 "writeConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n",
633 (uint32_t)pkt->
getLE<uint8_t>());
635 case sizeof(uint16_t):
636 panic(
"writing to a read only register");
637 case sizeof(uint32_t):
647 auto *bar =
BARs[num];
655 if (
letoh(pkt->
getLE<uint32_t>()) == 0xfffffffe)
656 _config.type0.expansionROM =
htole((uint32_t)0xffffffff);
665 "writeConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n",
667 (uint32_t)pkt->
getLE<uint32_t>());
670 panic(
"invalid access size(?) for PCI configspace!\n");
681 for (
int idx = 0; idx <
BARs.size(); idx++)
690 fatal_if((_config.common.headerType & 0x7F) != 1,
"HeaderType is invalid");
693 for (
auto *bar : BARs)
694 _config.type1.baseAddr[idx++] = bar->write(hostInterface, 0);
696 _config.type1.primaryBusNum =
htole(
p.PrimaryBusNumber);
697 _config.type1.secondaryBusNum =
htole(
p.SecondaryBusNumber);
698 _config.type1.subordinateBusNum =
htole(
p.SubordinateBusNumber);
699 _config.type1.secondaryLatencyTimer =
htole(
p.SecondaryLatencyTimer);
700 _config.type1.ioBase =
htole(
p.IOBase);
701 _config.type1.ioLimit =
htole(
p.IOLimit);
702 _config.type1.secondaryStatus =
htole(
p.SecondaryStatus);
703 _config.type1.memBase =
htole(
p.MemoryBase);
704 _config.type1.memLimit =
htole(
p.MemoryLimit);
705 _config.type1.prefetchMemBase =
htole(
p.PrefetchableMemoryBase);
706 _config.type1.prefetchMemLimit =
htole(
p.PrefetchableMemoryLimit);
707 _config.type1.prefetchBaseUpper =
htole(
p.PrefetchableBaseUpper);
708 _config.type1.prefetchLimitUpper =
htole(
p.PrefetchableLimitUpper);
709 _config.type1.ioBaseUpper =
htole(
p.IOBaseUpper);
710 _config.type1.ioLimitUpper =
htole(
p.IOLimitUpper);
711 _config.type1.expansionROM =
htole(
p.ExpansionROM);
712 _config.type1.bridgeControl =
htole(
p.BridgeControl);
723 warn_once(
"Device specific PCI config space "
724 "not implemented for %s!\n", this->
name());
726 case sizeof(uint8_t):
727 case sizeof(uint16_t):
728 case sizeof(uint32_t):
731 panic(
"invalid access size(?) for PCI configspace!\n");
734 panic(
"Out-of-range access to PCI config space!\n");
738 case sizeof(uint8_t):
750 _config.type1.secondaryLatencyTimer = pkt->
getLE<uint8_t>();
759 panic(
"writing to a read only register");
762 "writeConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n",
764 (uint32_t)pkt->
getLE<uint8_t>());
766 case sizeof(uint16_t):
781 _config.type1.prefetchMemLimit = pkt->
getLE<uint16_t>();
793 panic(
"writing to a read only register");
796 "writeConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n",
798 (uint32_t)pkt->
getLE<uint16_t>());
800 case sizeof(uint32_t):
806 auto *bar =
BARs[num];
813 _config.type1.prefetchBaseUpper = pkt->
getLE<uint32_t>();
816 _config.type1.prefetchLimitUpper = pkt->
getLE<uint32_t>();
819 if (
letoh(pkt->
getLE<uint32_t>()) == 0xfffffffe)
820 _config.type1.expansionROM =
htole((uint32_t)0xffffffff);
825 panic(
"writing to a read only register");
828 "writeConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n",
830 (uint32_t)pkt->
getLE<uint32_t>());
833 panic(
"invalid access size(?) for PCI configspace!\n");
844 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.
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.
PciBridge(const PciBridgeParams ¶ms)
Constructor for PCI Dev.
const int PMCAP_PC_OFFSET
PciHost::DeviceInterface hostInterface
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.
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
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
const PciBusAddr _busAddr
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 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
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
PciEndpoint(const PciEndpointParams ¶ms)
Constructor for PCI Dev.
Tick writeConfig(PacketPtr pkt) override
Write to the PCI config space data that is stored locally.
PioPort< PioDevice > pioPort
The pioPort that handles the requests for us and provides us requests that it sees.
virtual Tick write(PacketPtr pkt)=0
Pure virtual function that the device must implement.
#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()