Devices: Add support for legacy fixed IO locations in BARs.

This commit is contained in:
Gabe Black 2009-02-01 00:02:21 -08:00
parent bb7ad80bbe
commit 3ecc38cb8b
13 changed files with 139 additions and 35 deletions

View file

@ -73,6 +73,12 @@ class PciDevice(DmaDevice):
BAR3Size = Param.MemorySize32('0B', "Base Address Register 3 Size")
BAR4Size = Param.MemorySize32('0B', "Base Address Register 4 Size")
BAR5Size = Param.MemorySize32('0B', "Base Address Register 5 Size")
BAR0LegacyIO = Param.Bool(False, "Whether BAR0 is hardwired legacy IO")
BAR1LegacyIO = Param.Bool(False, "Whether BAR1 is hardwired legacy IO")
BAR2LegacyIO = Param.Bool(False, "Whether BAR2 is hardwired legacy IO")
BAR3LegacyIO = Param.Bool(False, "Whether BAR3 is hardwired legacy IO")
BAR4LegacyIO = Param.Bool(False, "Whether BAR4 is hardwired legacy IO")
BAR5LegacyIO = Param.Bool(False, "Whether BAR5 is hardwired legacy IO")
CardbusCIS = Param.UInt32(0x00, "Cardbus Card Information Structure")
SubsystemID = Param.UInt16(0x00, "Subsystem ID")

View file

@ -96,11 +96,23 @@ Tsunami::pciToDma(Addr pciAddr) const
Addr
Tsunami::calcConfigAddr(int bus, int dev, int func)
Tsunami::calcPciConfigAddr(int bus, int dev, int func)
{
return pchip->calcConfigAddr(bus, dev, func);
}
Addr
Tsunami::calcPciIOAddr(Addr addr)
{
return pchip->calcIOAddr(addr);
}
Addr
Tsunami::calcPciMemAddr(Addr addr)
{
return pchip->calcMemAddr(addr);
}
void
Tsunami::serialize(std::ostream &os)
{

View file

@ -116,7 +116,17 @@ class Tsunami : public Platform
/**
* Calculate the configuration address given a bus/dev/func.
*/
virtual Addr calcConfigAddr(int bus, int dev, int func);
virtual Addr calcPciConfigAddr(int bus, int dev, int func);
/**
* Calculate the address for an IO location on the PCI bus.
*/
virtual Addr calcPciIOAddr(Addr addr);
/**
* Calculate the address for a memory location on the PCI bus.
*/
virtual Addr calcPciMemAddr(Addr addr);
/**
* Serialize this object to the given output stream.

View file

@ -300,6 +300,7 @@ TsunamiPChip::translatePciToDma(Addr busAddr)
// if no match was found, then return the original address
return busAddr;
}
Addr
TsunamiPChip::calcConfigAddr(int bus, int dev, int func)
{
@ -310,7 +311,17 @@ TsunamiPChip::calcConfigAddr(int bus, int dev, int func)
return TsunamiPciBus0Config | (func << 8) | (dev << 11);
}
Addr
TsunamiPChip::calcIOAddr(Addr addr)
{
return TSUNAMI_PCI0_IO + addr;
}
Addr
TsunamiPChip::calcMemAddr(Addr addr)
{
return TSUNAMI_PCI0_MEMORY + addr;
}
void
TsunamiPChip::serialize(std::ostream &os)

View file

@ -84,6 +84,8 @@ class TsunamiPChip : public BasicPioDevice
Addr translatePciToDma(Addr busAddr);
Addr calcConfigAddr(int bus, int dev, int func);
Addr calcIOAddr(Addr addr);
Addr calcMemAddr(Addr addr);
virtual Tick read(PacketPtr pkt);
virtual Tick write(PacketPtr pkt);

View file

@ -47,7 +47,7 @@ using namespace std;
PciConfigAll::PciConfigAll(const Params *p)
: PioDevice(p)
{
pioAddr = p->platform->calcConfigAddr(params()->bus,0,0);
pioAddr = p->platform->calcPciConfigAddr(params()->bus,0,0);
}

View file

@ -59,7 +59,7 @@ PciDev::PciConfigPort::PciConfigPort(PciDev *dev, int busid, int devid,
: SimpleTimingPort(dev->name() + "-pciconf", dev), device(dev),
platform(p), busId(busid), deviceId(devid), functionId(funcid)
{
configAddr = platform->calcConfigAddr(busId, deviceId, functionId);
configAddr = platform->calcPciConfigAddr(busId, deviceId, functionId);
}
@ -121,15 +121,26 @@ PciDev::PciDev(const Params *p)
BARSize[4] = p->BAR4Size;
BARSize[5] = p->BAR5Size;
legacyIO[0] = p->BAR0LegacyIO;
legacyIO[1] = p->BAR1LegacyIO;
legacyIO[2] = p->BAR2LegacyIO;
legacyIO[3] = p->BAR3LegacyIO;
legacyIO[4] = p->BAR4LegacyIO;
legacyIO[5] = p->BAR5LegacyIO;
for (int i = 0; i < 6; ++i) {
uint32_t barsize = BARSize[i];
if (barsize != 0 && !isPowerOf2(barsize)) {
fatal("BAR %d size %d is not a power of 2\n", i, BARSize[i]);
if (legacyIO[i]) {
BARAddrs[i] = platform->calcPciIOAddr(letoh(config.baseAddr[i]));
config.baseAddr[i] = 0;
} else {
BARAddrs[i] = 0;
uint32_t barsize = BARSize[i];
if (barsize != 0 && !isPowerOf2(barsize)) {
fatal("BAR %d size %d is not a power of 2\n", i, BARSize[i]);
}
}
}
memset(BARAddrs, 0, sizeof(BARAddrs));
plat->registerPciDevice(0, p->pci_dev, p->pci_func,
letoh(config.interruptLine));
}
@ -268,30 +279,32 @@ PciDev::writeConfig(PacketPtr pkt)
{
int barnum = BAR_NUMBER(offset);
// convert BAR values to host endianness
uint32_t he_old_bar = letoh(config.baseAddr[barnum]);
uint32_t he_new_bar = letoh(pkt->get<uint32_t>());
if (!legacyIO[barnum]) {
// convert BAR values to host endianness
uint32_t he_old_bar = letoh(config.baseAddr[barnum]);
uint32_t he_new_bar = letoh(pkt->get<uint32_t>());
uint32_t bar_mask =
BAR_IO_SPACE(he_old_bar) ? BAR_IO_MASK : BAR_MEM_MASK;
uint32_t bar_mask =
BAR_IO_SPACE(he_old_bar) ? BAR_IO_MASK : BAR_MEM_MASK;
// Writing 0xffffffff to a BAR tells the card to set the
// value of the bar to a bitmask indicating the size of
// memory it needs
if (he_new_bar == 0xffffffff) {
he_new_bar = ~(BARSize[barnum] - 1);
} else {
// does it mean something special to write 0 to a BAR?
he_new_bar &= ~bar_mask;
if (he_new_bar) {
Addr space_base = BAR_IO_SPACE(he_old_bar) ?
TSUNAMI_PCI0_IO : TSUNAMI_PCI0_MEMORY;
BARAddrs[barnum] = he_new_bar + space_base;
pioPort->sendStatusChange(Port::RangeChange);
// Writing 0xffffffff to a BAR tells the card to set the
// value of the bar to a bitmask indicating the size of
// memory it needs
if (he_new_bar == 0xffffffff) {
he_new_bar = ~(BARSize[barnum] - 1);
} else {
// does it mean something special to write 0 to a BAR?
he_new_bar &= ~bar_mask;
if (he_new_bar) {
BARAddrs[barnum] = BAR_IO_SPACE(he_old_bar) ?
platform->calcPciIOAddr(he_new_bar) :
platform->calcPciMemAddr(he_new_bar);
pioPort->sendStatusChange(Port::RangeChange);
}
}
config.baseAddr[barnum] = htole((he_new_bar & ~bar_mask) |
(he_old_bar & bar_mask));
}
config.baseAddr[barnum] = htole((he_new_bar & ~bar_mask) |
(he_old_bar & bar_mask));
}
break;

View file

@ -99,6 +99,9 @@ class PciDev : public DmaDevice
/** The current address mapping of the BARs */
Addr BARAddrs[6];
/** Whether the BARs are really hardwired legacy IO locations. */
bool legacyIO[6];
/**
* Does the given address lie within the space mapped by the given
* base address register?

View file

@ -69,7 +69,9 @@ class Platform : public SimObject
virtual void postPciInt(int line);
virtual void clearPciInt(int line);
virtual Addr pciToDma(Addr pciAddr) const;
virtual Addr calcConfigAddr(int bus, int dev, int func) = 0;
virtual Addr calcPciConfigAddr(int bus, int dev, int func) = 0;
virtual Addr calcPciIOAddr(Addr addr) = 0;
virtual Addr calcPciMemAddr(Addr addr) = 0;
virtual void registerPciDevice(uint8_t bus, uint8_t dev, uint8_t func,
uint8_t intr);

View file

@ -94,7 +94,21 @@ T1000::pciToDma(Addr pciAddr) const
Addr
T1000::calcConfigAddr(int bus, int dev, int func)
T1000::calcPciConfigAddr(int bus, int dev, int func)
{
panic("Need implementation\n");
M5_DUMMY_RETURN
}
Addr
T1000::calcPciIOAddr(Addr addr)
{
panic("Need implementation\n");
M5_DUMMY_RETURN
}
Addr
T1000::calcPciMemAddr(Addr addr)
{
panic("Need implementation\n");
M5_DUMMY_RETURN

View file

@ -91,7 +91,17 @@ class T1000 : public Platform
/**
* Calculate the configuration address given a bus/dev/func.
*/
virtual Addr calcConfigAddr(int bus, int dev, int func);
virtual Addr calcPciConfigAddr(int bus, int dev, int func);
/**
* Calculate the address for an IO location on the PCI bus.
*/
virtual Addr calcPciIOAddr(Addr addr);
/**
* Calculate the address for a memory location on the PCI bus.
*/
virtual Addr calcPciMemAddr(Addr addr);
};
#endif // __DEV_T1000_HH__

View file

@ -143,9 +143,8 @@ Pc::pciToDma(Addr pciAddr) const
M5_DUMMY_RETURN
}
Addr
Pc::calcConfigAddr(int bus, int dev, int func)
Pc::calcPciConfigAddr(int bus, int dev, int func)
{
assert(func < 8);
assert(dev < 32);
@ -153,6 +152,18 @@ Pc::calcConfigAddr(int bus, int dev, int func)
return (PhysAddrPrefixPciConfig | (func << 8) | (dev << 11));
}
Addr
Pc::calcPciIOAddr(Addr addr)
{
return PhysAddrPrefixIO + addr;
}
Addr
Pc::calcPciMemAddr(Addr addr)
{
return addr;
}
Pc *
PcParams::create()
{

View file

@ -93,7 +93,17 @@ class Pc : public Platform
/**
* Calculate the configuration address given a bus/dev/func.
*/
virtual Addr calcConfigAddr(int bus, int dev, int func);
virtual Addr calcPciConfigAddr(int bus, int dev, int func);
/**
* Calculate the address for an IO location on the PCI bus.
*/
virtual Addr calcPciIOAddr(Addr addr);
/**
* Calculate the address for a memory location on the PCI bus.
*/
virtual Addr calcPciMemAddr(Addr addr);
};
#endif // __DEV_PC_HH__