Add a bunch of functions to manage the BAR addresses. This
makes it easier to implement PCI device models. dev/pcidev.cc: default implementations for read/write and readBarX/writeBarX functions --HG-- extra : convert_revision : bbe2e2a2a506e2dd94d98f8e0feaefef96380be9
This commit is contained in:
parent
d3a4781ac5
commit
48863a1a43
2 changed files with 153 additions and 6 deletions
|
@ -70,6 +70,62 @@ PciDev::PciDev(Params *p)
|
||||||
p->configSpace->registerDevice(p->deviceNum, p->functionNum, this);
|
p->configSpace->registerDevice(p->deviceNum, p->functionNum, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Fault
|
||||||
|
PciDev::read(MemReqPtr &req, uint8_t *data)
|
||||||
|
{ return No_Fault; }
|
||||||
|
|
||||||
|
Fault
|
||||||
|
PciDev::write(MemReqPtr &req, const uint8_t *data)
|
||||||
|
{ return No_Fault; }
|
||||||
|
|
||||||
|
Fault
|
||||||
|
PciDev::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data)
|
||||||
|
{ panic("not implemented"); }
|
||||||
|
|
||||||
|
Fault
|
||||||
|
PciDev::readBar1(MemReqPtr &req, Addr daddr, uint8_t *data)
|
||||||
|
{ panic("not implemented"); }
|
||||||
|
|
||||||
|
Fault
|
||||||
|
PciDev::readBar2(MemReqPtr &req, Addr daddr, uint8_t *data)
|
||||||
|
{ panic("not implemented"); }
|
||||||
|
|
||||||
|
Fault
|
||||||
|
PciDev::readBar3(MemReqPtr &req, Addr daddr, uint8_t *data)
|
||||||
|
{ panic("not implemented"); }
|
||||||
|
|
||||||
|
Fault
|
||||||
|
PciDev::readBar4(MemReqPtr &req, Addr daddr, uint8_t *data)
|
||||||
|
{ panic("not implemented"); }
|
||||||
|
|
||||||
|
Fault
|
||||||
|
PciDev::readBar5(MemReqPtr &req, Addr daddr, uint8_t *data)
|
||||||
|
{ panic("not implemented"); }
|
||||||
|
|
||||||
|
Fault
|
||||||
|
PciDev::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
|
||||||
|
{ panic("not implemented"); }
|
||||||
|
|
||||||
|
Fault
|
||||||
|
PciDev::writeBar1(MemReqPtr &req, Addr daddr, const uint8_t *data)
|
||||||
|
{ panic("not implemented"); }
|
||||||
|
|
||||||
|
Fault
|
||||||
|
PciDev::writeBar2(MemReqPtr &req, Addr daddr, const uint8_t *data)
|
||||||
|
{ panic("not implemented"); }
|
||||||
|
|
||||||
|
Fault
|
||||||
|
PciDev::writeBar3(MemReqPtr &req, Addr daddr, const uint8_t *data)
|
||||||
|
{ panic("not implemented"); }
|
||||||
|
|
||||||
|
Fault
|
||||||
|
PciDev::writeBar4(MemReqPtr &req, Addr daddr, const uint8_t *data)
|
||||||
|
{ panic("not implemented"); }
|
||||||
|
|
||||||
|
Fault
|
||||||
|
PciDev::writeBar5(MemReqPtr &req, Addr daddr, const uint8_t *data)
|
||||||
|
{ panic("not implemented"); }
|
||||||
|
|
||||||
void
|
void
|
||||||
PciDev::readConfig(int offset, int size, uint8_t *data)
|
PciDev::readConfig(int offset, int size, uint8_t *data)
|
||||||
{
|
{
|
||||||
|
|
103
dev/pcidev.hh
103
dev/pcidev.hh
|
@ -132,6 +132,35 @@ class PciDev : public DmaDevice
|
||||||
/** The current address mapping of the BARs */
|
/** The current address mapping of the BARs */
|
||||||
Addr BARAddrs[6];
|
Addr BARAddrs[6];
|
||||||
|
|
||||||
|
bool
|
||||||
|
isBAR(Addr addr, int bar) const
|
||||||
|
{
|
||||||
|
assert(bar >= 0 && bar < 6);
|
||||||
|
return BARAddrs[bar] <= addr && addr < BARAddrs[bar] + BARSize[bar];
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
getBAR(Addr addr)
|
||||||
|
{
|
||||||
|
for (int i = 0; i <= 5; ++i)
|
||||||
|
if (isBAR(addr, i))
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
getBAR(Addr paddr, Addr &daddr, int &bar)
|
||||||
|
{
|
||||||
|
int b = getBAR(paddr);
|
||||||
|
if (b < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
daddr = paddr - BARAddrs[b];
|
||||||
|
bar = b;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Platform *plat;
|
Platform *plat;
|
||||||
PciConfigData *configData;
|
PciConfigData *configData;
|
||||||
|
@ -160,13 +189,39 @@ class PciDev : public DmaDevice
|
||||||
*/
|
*/
|
||||||
PciDev(Params *params);
|
PciDev(Params *params);
|
||||||
|
|
||||||
virtual Fault read(MemReqPtr &req, uint8_t *data) {
|
virtual Fault read(MemReqPtr &req, uint8_t *data);
|
||||||
return No_Fault;
|
virtual Fault write(MemReqPtr &req, const uint8_t *data);
|
||||||
}
|
|
||||||
virtual Fault write(MemReqPtr &req, const uint8_t *data) {
|
|
||||||
return No_Fault;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Implement the read/write as BAR accesses
|
||||||
|
*/
|
||||||
|
Fault readBar(MemReqPtr &req, uint8_t *data);
|
||||||
|
Fault writeBar(MemReqPtr &req, const uint8_t *data);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Read from a specific BAR
|
||||||
|
*/
|
||||||
|
virtual Fault readBar0(MemReqPtr &req, Addr daddr, uint8_t *data);
|
||||||
|
virtual Fault readBar1(MemReqPtr &req, Addr daddr, uint8_t *data);
|
||||||
|
virtual Fault readBar2(MemReqPtr &req, Addr daddr, uint8_t *data);
|
||||||
|
virtual Fault readBar3(MemReqPtr &req, Addr daddr, uint8_t *data);
|
||||||
|
virtual Fault readBar4(MemReqPtr &req, Addr daddr, uint8_t *data);
|
||||||
|
virtual Fault readBar5(MemReqPtr &req, Addr daddr, uint8_t *data);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Write to a specific BAR
|
||||||
|
*/
|
||||||
|
virtual Fault writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data);
|
||||||
|
virtual Fault writeBar1(MemReqPtr &req, Addr daddr, const uint8_t *data);
|
||||||
|
virtual Fault writeBar2(MemReqPtr &req, Addr daddr, const uint8_t *data);
|
||||||
|
virtual Fault writeBar3(MemReqPtr &req, Addr daddr, const uint8_t *data);
|
||||||
|
virtual Fault writeBar4(MemReqPtr &req, Addr daddr, const uint8_t *data);
|
||||||
|
virtual Fault writeBar5(MemReqPtr &req, Addr daddr, const uint8_t *data);
|
||||||
|
|
||||||
|
public:
|
||||||
/**
|
/**
|
||||||
* Write to the PCI config space data that is stored locally. This may be
|
* Write to the PCI config space data that is stored locally. This may be
|
||||||
* overridden by the device but at some point it will eventually call this
|
* overridden by the device but at some point it will eventually call this
|
||||||
|
@ -202,4 +257,40 @@ class PciDev : public DmaDevice
|
||||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline Fault
|
||||||
|
PciDev::readBar(MemReqPtr &req, uint8_t *data)
|
||||||
|
{
|
||||||
|
if (isBAR(req->paddr, 0))
|
||||||
|
return readBar0(req, req->paddr - BARAddrs[0], data);
|
||||||
|
if (isBAR(req->paddr, 1))
|
||||||
|
return readBar1(req, req->paddr - BARAddrs[1], data);
|
||||||
|
if (isBAR(req->paddr, 2))
|
||||||
|
return readBar2(req, req->paddr - BARAddrs[2], data);
|
||||||
|
if (isBAR(req->paddr, 3))
|
||||||
|
return readBar3(req, req->paddr - BARAddrs[3], data);
|
||||||
|
if (isBAR(req->paddr, 4))
|
||||||
|
return readBar4(req, req->paddr - BARAddrs[4], data);
|
||||||
|
if (isBAR(req->paddr, 5))
|
||||||
|
return readBar5(req, req->paddr - BARAddrs[5], data);
|
||||||
|
return Machine_Check_Fault;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Fault
|
||||||
|
PciDev::writeBar(MemReqPtr &req, const uint8_t *data)
|
||||||
|
{
|
||||||
|
if (isBAR(req->paddr, 0))
|
||||||
|
return writeBar0(req, req->paddr - BARAddrs[0], data);
|
||||||
|
if (isBAR(req->paddr, 1))
|
||||||
|
return writeBar1(req, req->paddr - BARAddrs[1], data);
|
||||||
|
if (isBAR(req->paddr, 2))
|
||||||
|
return writeBar2(req, req->paddr - BARAddrs[2], data);
|
||||||
|
if (isBAR(req->paddr, 3))
|
||||||
|
return writeBar3(req, req->paddr - BARAddrs[3], data);
|
||||||
|
if (isBAR(req->paddr, 4))
|
||||||
|
return writeBar4(req, req->paddr - BARAddrs[4], data);
|
||||||
|
if (isBAR(req->paddr, 5))
|
||||||
|
return writeBar5(req, req->paddr - BARAddrs[5], data);
|
||||||
|
return Machine_Check_Fault;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // __DEV_PCIDEV_HH__
|
#endif // __DEV_PCIDEV_HH__
|
||||||
|
|
Loading…
Reference in a new issue