56#include "debug/PciDevice.hh"
66 _busAddr(
p.pci_bus,
p.pci_dev,
p.pci_func),
67 PMCAP_BASE(
p.PMCAPBaseOffset),
68 PMCAP_ID_OFFSET(
p.PMCAPBaseOffset+
PMCAP_ID),
69 PMCAP_PC_OFFSET(
p.PMCAPBaseOffset+
PMCAP_PC),
71 MSICAP_BASE(
p.MSICAPBaseOffset),
72 MSIXCAP_BASE(
p.MSIXCAPBaseOffset),
77 PXCAP_BASE(
p.PXCAPBaseOffset),
79 hostInterface(
p.host->registerDevice(this, _busAddr,
81 pioDelay(
p.pio_latency),
82 configDelay(
p.config_latency)
85 "Invalid PCI interrupt '%i' specified.",
p.InterruptPin);
95 for (
auto *bar:
BARs) {
101 "First BAR in %s is upper 32 bits of a memory BAR.", idx);
103 fatal_if(!ml,
"Upper 32 bits of memory BAR in %s doesn't come "
104 "after the lower 32.");
124 for (
auto *bar:
BARs)
133 bzero(
config.reserved, 7*
sizeof(uint8_t));
145 pmcap.
pid |= (uint16_t)
p.PMCAPNextCapability << 8;
151 msicap.
mid |= (uint16_t)
p.MSICAPNextCapability << 8;
173 uint16_t msixcap_mxc_ts =
msixcap.
mxc & 0x07ff;
175 int msix_vecs = msixcap_mxc_ts + 1;
188 (msixcap_mxc_ts + 1) *
sizeof(
MSIXTable);
199 pxcap.
pxid |= (uint16_t)
p.PXCAPNextCapability << 8;
219 warn_once(
"Device specific PCI config space "
220 "not implemented for %s!\n", this->
name());
222 case sizeof(uint8_t):
223 pkt->
setLE<uint8_t>(0);
225 case sizeof(uint16_t):
226 pkt->
setLE<uint16_t>(0);
228 case sizeof(uint32_t):
229 pkt->
setLE<uint32_t>(0);
232 panic(
"invalid access size(?) for PCI configspace!\n");
235 panic(
"Out-of-range access to PCI config space!\n");
239 case sizeof(uint8_t):
242 "readConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n",
244 (uint32_t)pkt->
getLE<uint8_t>());
246 case sizeof(uint16_t):
249 "readConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n",
251 (uint32_t)pkt->
getLE<uint16_t>());
253 case sizeof(uint32_t):
256 "readConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n",
258 (uint32_t)pkt->
getLE<uint32_t>());
261 panic(
"invalid access size(?) for PCI configspace!\n");
272 PciCommandRegister command =
letoh(
config.command);
273 for (
auto *bar:
BARs) {
274 if (command.ioSpace && bar->isIo())
275 ranges.push_back(bar->range());
276 if (command.memorySpace && bar->isMem())
277 ranges.push_back(bar->range());
290 warn_once(
"Device specific PCI config space "
291 "not implemented for %s!\n", this->
name());
293 case sizeof(uint8_t):
294 case sizeof(uint16_t):
295 case sizeof(uint32_t):
298 panic(
"invalid access size(?) for PCI configspace!\n");
301 panic(
"Out-of-range access to PCI config space!\n");
305 case sizeof(uint8_t):
324 panic(
"writing to a read only register");
327 "writeConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n",
329 (uint32_t)pkt->
getLE<uint8_t>());
331 case sizeof(uint16_t):
345 panic(
"writing to a read only register");
348 "writeConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n",
350 (uint32_t)pkt->
getLE<uint16_t>());
352 case sizeof(uint32_t):
362 auto *bar =
BARs[num];
370 if (
letoh(pkt->
getLE<uint32_t>()) == 0xfffffffe)
389 "writeConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n",
391 (uint32_t)pkt->
getLE<uint32_t>());
394 panic(
"invalid access size(?) for PCI configspace!\n");
425 uint16_t msixcap_mxc_ts =
msixcap.
mxc & 0x07ff;
426 int msix_array_size = msixcap_mxc_ts + 1;
435 for (
int i = 0;
i < msix_array_size;
i++) {
445 for (
int i = 0;
i < pba_array_size;
i++) {
469 for (
int idx = 0; idx <
BARs.size(); idx++)
515 msix_pba.resize(pba_array_size, tmp2);
517 for (
int i = 0;
i < msix_array_size;
i++) {
527 for (
int i = 0;
i < pba_array_size;
i++) {
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
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.
PCI device, base implementation is only config space.
PciHost::DeviceInterface hostInterface
PCIConfig config
The current config space.
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.
std::array< PciBar *, 6 > BARs
AddrRangeList getAddrRanges() const override
Determine the address ranges that this device responds to.
const PciBusAddr _busAddr
std::vector< MSIXPbaEntry > msix_pba
virtual Tick readConfig(PacketPtr pkt)
Read from the PCI config space data that is stored locally.
virtual Tick writeConfig(PacketPtr pkt)
Write to the PCI config space data that is stored locally.
PciDevice(const PciDeviceParams ¶ms)
Constructor for PCI Dev.
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.
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 - Pranith Kumar Copyright (c) 2020 Inria 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 PCI0_INTERRUPT_PIN
#define PCI0_MINIMUM_GRANT
#define PCI0_INTERRUPT_LINE
#define PCI0_MAXIMUM_LATENCY
#define PCI0_ROM_BASE_ADDR
#define PMCAP_ID
PCIe capability list offsets internal to the entry.
#define PCI_CACHE_LINE_SIZE
#define PCI_DEVICE_SPECIFIC
#define PCI_LATENCY_TIMER
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)
const std::string & name()