Go to the documentation of this file.
56 #include "debug/PciDevice.hh"
64 _busAddr(
p.pci_bus,
p.pci_dev,
p.pci_func),
65 PMCAP_BASE(
p.PMCAPBaseOffset),
66 PMCAP_ID_OFFSET(
p.PMCAPBaseOffset+
PMCAP_ID),
67 PMCAP_PC_OFFSET(
p.PMCAPBaseOffset+
PMCAP_PC),
69 MSICAP_BASE(
p.MSICAPBaseOffset),
70 MSIXCAP_BASE(
p.MSIXCAPBaseOffset),
75 PXCAP_BASE(
p.PXCAPBaseOffset),
77 hostInterface(
p.host->registerDevice(this, _busAddr,
79 pioDelay(
p.pio_latency),
80 configDelay(
p.config_latency)
83 "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.");
122 for (
auto *bar:
BARs)
131 bzero(
config.reserved, 7*
sizeof(uint8_t));
143 pmcap.
pid |= (uint16_t)
p.PMCAPNextCapability << 8;
149 msicap.
mid |= (uint16_t)
p.MSICAPNextCapability << 8;
171 uint16_t msixcap_mxc_ts =
msixcap.
mxc & 0x07ff;
173 int msix_vecs = msixcap_mxc_ts + 1;
186 (msixcap_mxc_ts + 1) *
sizeof(
MSIXTable);
197 pxcap.
pxid |= (uint16_t)
p.PXCAPNextCapability << 8;
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.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 panic(
"Out-of-range access to PCI config space!\n");
303 case sizeof(uint8_t):
322 panic(
"writing to a read only register");
325 "writeConfig: dev %#x func %#x reg %#x 1 bytes: data = %#x\n",
327 (uint32_t)pkt->
getLE<uint8_t>());
329 case sizeof(uint16_t):
343 panic(
"writing to a read only register");
346 "writeConfig: dev %#x func %#x reg %#x 2 bytes: data = %#x\n",
348 (uint32_t)pkt->
getLE<uint16_t>());
350 case sizeof(uint32_t):
360 auto *bar =
BARs[num];
368 if (
letoh(pkt->
getLE<uint32_t>()) == 0xfffffffe)
387 "writeConfig: dev %#x func %#x reg %#x 4 bytes: data = %#x\n",
389 (uint32_t)pkt->
getLE<uint32_t>());
392 panic(
"invalid access size(?) for PCI configspace!\n");
423 uint16_t msixcap_mxc_ts =
msixcap.
mxc & 0x07ff;
424 int msix_array_size = msixcap_mxc_ts + 1;
433 for (
int i = 0;
i < msix_array_size;
i++) {
443 for (
int i = 0;
i < pba_array_size;
i++) {
467 for (
int idx = 0; idx <
BARs.size(); idx++)
513 msix_pba.resize(pba_array_size, tmp2);
515 for (
int i = 0;
i < msix_array_size;
i++) {
525 for (
int i = 0;
i < pba_array_size;
i++) {
void makeAtomicResponse()
AddrRangeList getAddrRanges() const override
Determine the address ranges that this device responds to.
#define PCI0_MINIMUM_GRANT
#define UNSERIALIZE_SCALAR(scalar)
std::array< PciBar *, 6 > BARs
virtual Tick writeConfig(PacketPtr pkt)
Write to the PCI config space data that is stored locally.
virtual Tick readConfig(PacketPtr pkt)
Read from the PCI config space data that is stored locally.
uint64_t Tick
Tick count type.
PCIConfig config
The current config space.
const PciBusAddr _busAddr
#define PCI_LATENCY_TIMER
std::vector< MSIXPbaEntry > msix_pba
#define PCI_DEVICE_SPECIFIC
#define PCI0_INTERRUPT_LINE
#define PCI0_ROM_BASE_ADDR
PciHost::DeviceInterface hostInterface
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
virtual Tick write(PacketPtr pkt)=0
Pure virtual function that the device must implement.
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
#define SERIALIZE_ARRAY(member, size)
#define PCI0_MAXIMUM_LATENCY
#define SERIALIZE_SCALAR(scalar)
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
PciDevice(const PciDeviceParams ¶ms)
Constructor for PCI Dev.
virtual const std::string name() const
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
std::vector< MSIXTable > msix_table
MSIX Table and PBA Structures.
#define UNSERIALIZE_ARRAY(member, size)
#define PCI_CACHE_LINE_SIZE
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.
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
std::ostream CheckpointOut
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
void sendRangeChange() const
Called by the owner to send a range change.
std::string csprintf(const char *format, const Args &...args)
PCI device, base implementation is only config space.
#define PMCAP_ID
PCIe capability list offsets internal to the entry.
#define panic(...)
This implements a cprintf based panic() function.
PioPort< PioDevice > pioPort
The pioPort that handles the requests for us and provides us requests that it sees.
#define PCI0_INTERRUPT_PIN
Generated on Tue Mar 23 2021 19:41:24 for gem5 by doxygen 1.8.17