Add default responder to bus

Update configuration for new default responder on bus
Update to devices to handle their own pci config space without pciconfigall
Remove most of pciconfigall, it now is a dumbdevice which gets it's address based on the bus it's supposed to respond for
Remove need for pci config space from platform, add registerPciDevice function to prevent more than one device from having same
bus:dev:func and interrupt
Remove pciconfigspace from pci devices, and py files
Add calcConfigAddr that returns address for config space based on bus/dev/function + offset

configs/test/fs.py:
    Update configuration for new default responder on bus
src/dev/ide_ctrl.cc:
src/dev/ide_ctrl.hh:
src/dev/ns_gige.cc:
src/dev/ns_gige.hh:
src/dev/pcidev.cc:
src/dev/pcidev.hh:
    Update to handle it's own pci config space without pciconfigall
src/dev/io_device.cc:
src/dev/io_device.hh:
    change naming for pio port
    break out recvTiming into two functions to reuse code
src/dev/pciconfigall.cc:
src/dev/pciconfigall.hh:
    removing most of pciconfigall, it now is a dumbdevice which gets it's address based on the bus it's supposed to respond for
src/dev/pcireg.h:
    add a max size for PCI config space (per PCI spec)
src/dev/platform.cc:
src/dev/platform.hh:
    remove need for pci config space from platform, add registerPciDevice function to prevent more than one device from having same
    bus:dev:func and interrupt
src/dev/sinic.cc:
    remove pciconfigspace as it's no longer a needed parameter
src/dev/tsunami.cc:
src/dev/tsunami.hh:
src/dev/tsunami_pchip.cc:
src/dev/tsunami_pchip.hh:
    add calcConfigAddr that returns address for config space based on bus/dev/function + offset (per PCI spec)
src/mem/bus.cc:
src/mem/bus.hh:
src/python/m5/objects/Bus.py:
    add idea of default responder to bus
src/python/m5/objects/Pci.py:
    add config port for pci devices
    add latency, bus and size parameters for pci config all (min is 8MB, max is 256MB see pci spec)

--HG--
extra : convert_revision : 99db43b0a3a077f86611d6eaff6664a3885da7c9
This commit is contained in:
Ali Saidi 2006-07-06 14:41:01 -04:00
parent 4201ec84b2
commit 93839380e7
23 changed files with 615 additions and 568 deletions

View file

@ -1,6 +1,6 @@
import m5 import m5
from m5.objects import * from m5.objects import *
import os import os,optparse,sys
from SysPaths import * from SysPaths import *
parser = optparse.OptionParser(option_list=m5.standardOptions) parser = optparse.OptionParser(option_list=m5.standardOptions)
@ -98,7 +98,7 @@ class SpecwebFilesetDisk(IdeDisk):
class BaseTsunami(Tsunami): class BaseTsunami(Tsunami):
cchip = TsunamiCChip(pio_addr=0x801a0000000) cchip = TsunamiCChip(pio_addr=0x801a0000000)
pchip = TsunamiPChip(pio_addr=0x80180000000) pchip = TsunamiPChip(pio_addr=0x80180000000)
pciconfig = PciConfigAll(pio_addr=0x801fe000000) pciconfig = PciConfigAll()
fake_sm_chip = IsaFake(pio_addr=0x801fc000370) fake_sm_chip = IsaFake(pio_addr=0x801fc000370)
fake_uart1 = IsaFake(pio_addr=0x801fc0002f8) fake_uart1 = IsaFake(pio_addr=0x801fc0002f8)
@ -151,16 +151,18 @@ class MyLinuxAlphaSystem(LinuxAlphaSystem):
tsunami = LinuxTsunami() tsunami = LinuxTsunami()
tsunami.cchip.pio = magicbus.port tsunami.cchip.pio = magicbus.port
tsunami.pchip.pio = magicbus.port tsunami.pchip.pio = magicbus.port
tsunami.pciconfig.pio = magicbus.port tsunami.pciconfig.pio = magicbus.default
tsunami.fake_sm_chip.pio = magicbus.port tsunami.fake_sm_chip.pio = magicbus.port
tsunami.ethernet.pio = magicbus.port tsunami.ethernet.pio = magicbus.port
tsunami.ethernet.dma = magicbus.port tsunami.ethernet.dma = magicbus.port
tsunami.ethernet.config = magicbus.port
tsunami.fake_uart1.pio = magicbus.port tsunami.fake_uart1.pio = magicbus.port
tsunami.fake_uart2.pio = magicbus.port tsunami.fake_uart2.pio = magicbus.port
tsunami.fake_uart3.pio = magicbus.port tsunami.fake_uart3.pio = magicbus.port
tsunami.fake_uart4.pio = magicbus.port tsunami.fake_uart4.pio = magicbus.port
tsunami.ide.pio = magicbus.port tsunami.ide.pio = magicbus.port
tsunami.ide.dma = magicbus.port tsunami.ide.dma = magicbus.port
tsunami.ide.config = magicbus.port
tsunami.fake_ppc.pio = magicbus.port tsunami.fake_ppc.pio = magicbus.port
tsunami.fake_OROM.pio = magicbus.port tsunami.fake_OROM.pio = magicbus.port
tsunami.fake_pnp_addr.pio = magicbus.port tsunami.fake_pnp_addr.pio = magicbus.port

View file

@ -227,177 +227,143 @@ IdeController::setDmaComplete(IdeDisk *disk)
// Read and write handling // Read and write handling
//// ////
void Tick
IdeController::readConfig(int offset, uint8_t *data) IdeController::readConfig(Packet *pkt)
{ {
if (offset < PCI_DEVICE_SPECIFIC) { int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
PciDev::readConfig(offset, data); if (offset < PCI_DEVICE_SPECIFIC)
} else if (offset >= IDE_CTRL_CONF_START && return PciDev::readConfig(pkt);
(offset + 1) <= IDE_CTRL_CONF_END) { assert(offset >= IDE_CTRL_CONF_START && (offset + 1) <= IDE_CTRL_CONF_END);
pkt->allocate();
switch (pkt->getSize()) {
case sizeof(uint8_t):
switch (offset) { switch (offset) {
case IDE_CTRL_CONF_DEV_TIMING: case IDE_CTRL_CONF_DEV_TIMING:
*data = config_regs.sidetim; pkt->set<uint8_t>(config_regs.sidetim);
break; break;
case IDE_CTRL_CONF_UDMA_CNTRL: case IDE_CTRL_CONF_UDMA_CNTRL:
*data = config_regs.udmactl; pkt->set<uint8_t>(config_regs.udmactl);
break; break;
case IDE_CTRL_CONF_PRIM_TIMING+1: case IDE_CTRL_CONF_PRIM_TIMING+1:
*data = htole(config_regs.idetim0) >> 8; pkt->set<uint8_t>(htole(config_regs.idetim0) >> 8);
break; break;
case IDE_CTRL_CONF_SEC_TIMING+1: case IDE_CTRL_CONF_SEC_TIMING+1:
*data = htole(config_regs.idetim1) >> 8; pkt->set<uint8_t>(htole(config_regs.idetim1) >> 8);
break; break;
case IDE_CTRL_CONF_IDE_CONFIG: case IDE_CTRL_CONF_IDE_CONFIG:
*data = htole(config_regs.ideconfig) & 0xFF; pkt->set<uint8_t>(htole(config_regs.ideconfig) & 0xFF);
break; break;
case IDE_CTRL_CONF_IDE_CONFIG+1: case IDE_CTRL_CONF_IDE_CONFIG+1:
*data = htole(config_regs.ideconfig) >> 8; pkt->set<uint8_t>(htole(config_regs.ideconfig) >> 8);
break; break;
default: default:
panic("Invalid PCI configuration read for size 1 at offset: %#x!\n", panic("Invalid PCI configuration read for size 1 at offset: %#x!\n",
offset); offset);
} }
DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n", offset,
} else { (uint32_t)pkt->get<uint8_t>());
panic("Read of unimplemented PCI config. register: %x\n", offset); break;
} case sizeof(uint16_t):
DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n",
offset, (uint32_t)*data);
}
void
IdeController::readConfig(int offset, uint16_t *data)
{
if (offset < PCI_DEVICE_SPECIFIC) {
PciDev::readConfig(offset, data);
} else if (offset >= IDE_CTRL_CONF_START &&
(offset + 2) <= IDE_CTRL_CONF_END) {
switch (offset) { switch (offset) {
case IDE_CTRL_CONF_PRIM_TIMING: case IDE_CTRL_CONF_PRIM_TIMING:
*data = config_regs.idetim0; pkt->set<uint16_t>(config_regs.idetim0);
break; break;
case IDE_CTRL_CONF_SEC_TIMING: case IDE_CTRL_CONF_SEC_TIMING:
*data = config_regs.idetim1; pkt->set<uint16_t>(config_regs.idetim1);
break; break;
case IDE_CTRL_CONF_UDMA_TIMING: case IDE_CTRL_CONF_UDMA_TIMING:
*data = config_regs.udmatim; pkt->set<uint16_t>(config_regs.udmatim);
break; break;
case IDE_CTRL_CONF_IDE_CONFIG: case IDE_CTRL_CONF_IDE_CONFIG:
*data = config_regs.ideconfig; pkt->set<uint16_t>(config_regs.ideconfig);
break; break;
default: default:
panic("Invalid PCI configuration read for size 2 offset: %#x!\n", panic("Invalid PCI configuration read for size 2 offset: %#x!\n",
offset); offset);
} }
DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset,
} else { (uint32_t)pkt->get<uint16_t>());
panic("Read of unimplemented PCI config. register: %x\n", offset); break;
case sizeof(uint32_t):
panic("No 32bit reads implemented for this device.");
DPRINTF(IdeCtrl, "PCI read offset: %#x size: 4 data: %#x\n", offset,
(uint32_t)pkt->get<uint32_t>());
break;
default:
panic("invalid access size(?) for PCI configspace!\n");
} }
DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset, *data); pkt->result = Packet::Success;
return configDelay;
} }
void
IdeController::readConfig(int offset, uint32_t *data)
{
if (offset < PCI_DEVICE_SPECIFIC) {
PciDev::readConfig(offset, data);
} else {
panic("Read of unimplemented PCI config. register: %x\n", offset);
}
DPRINTF(IdeCtrl, "PCI read offset: %#x size: 4 data: %#x\n", offset, *data);
}
void
IdeController::writeConfig(int offset, const uint8_t data)
{
if (offset < PCI_DEVICE_SPECIFIC) {
PciDev::writeConfig(offset, data);
} else if (offset >= IDE_CTRL_CONF_START &&
(offset + 1) <= IDE_CTRL_CONF_END) {
switch (offset) { Tick
case IDE_CTRL_CONF_DEV_TIMING: IdeController::writeConfig(Packet *pkt)
config_regs.sidetim = data; {
int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
if (offset < PCI_DEVICE_SPECIFIC) {
PciDev::writeConfig(pkt);
} else {
assert(offset >= IDE_CTRL_CONF_START && (offset + 1) <= IDE_CTRL_CONF_END);
switch (pkt->getSize()) {
case sizeof(uint8_t):
switch (offset) {
case IDE_CTRL_CONF_DEV_TIMING:
config_regs.sidetim = pkt->get<uint8_t>();
break;
case IDE_CTRL_CONF_UDMA_CNTRL:
config_regs.udmactl = pkt->get<uint8_t>();
break;
case IDE_CTRL_CONF_IDE_CONFIG:
config_regs.ideconfig = (config_regs.ideconfig & 0xFF00) |
(pkt->get<uint8_t>());
break;
case IDE_CTRL_CONF_IDE_CONFIG+1:
config_regs.ideconfig = (config_regs.ideconfig & 0x00FF) |
pkt->get<uint8_t>() << 8;
break;
default:
panic("Invalid PCI configuration write for size 1 offset: %#x!\n",
offset);
}
DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n",
offset, (uint32_t)pkt->get<uint8_t>());
break; break;
case IDE_CTRL_CONF_UDMA_CNTRL: case sizeof(uint16_t):
config_regs.udmactl = data; switch (offset) {
case IDE_CTRL_CONF_PRIM_TIMING:
config_regs.idetim0 = pkt->get<uint16_t>();
break;
case IDE_CTRL_CONF_SEC_TIMING:
config_regs.idetim1 = pkt->get<uint16_t>();
break;
case IDE_CTRL_CONF_UDMA_TIMING:
config_regs.udmatim = pkt->get<uint16_t>();
break;
case IDE_CTRL_CONF_IDE_CONFIG:
config_regs.ideconfig = pkt->get<uint16_t>();
break;
default:
panic("Invalid PCI configuration write for size 2 offset: %#x!\n",
offset);
}
DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n",
offset, (uint32_t)pkt->get<uint16_t>());
break; break;
case IDE_CTRL_CONF_IDE_CONFIG: case sizeof(uint32_t):
config_regs.ideconfig = (config_regs.ideconfig & 0xFF00) | (data); panic("Write of unimplemented PCI config. register: %x\n", offset);
break;
case IDE_CTRL_CONF_IDE_CONFIG+1:
config_regs.ideconfig = (config_regs.ideconfig & 0x00FF) | data << 8;
break; break;
default: default:
panic("Invalid PCI configuration write for size 1 offset: %#x!\n", panic("invalid access size(?) for PCI configspace!\n");
offset);
} }
} else {
panic("Read of unimplemented PCI config. register: %x\n", offset);
}
DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n",
offset, (uint32_t)data);
}
void
IdeController::writeConfig(int offset, const uint16_t data)
{
if (offset < PCI_DEVICE_SPECIFIC) {
PciDev::writeConfig(offset, data);
} else if (offset >= IDE_CTRL_CONF_START &&
(offset + 2) <= IDE_CTRL_CONF_END) {
switch (offset) {
case IDE_CTRL_CONF_PRIM_TIMING:
config_regs.idetim0 = data;
break;
case IDE_CTRL_CONF_SEC_TIMING:
config_regs.idetim1 = data;
break;
case IDE_CTRL_CONF_UDMA_TIMING:
config_regs.udmatim = data;
break;
case IDE_CTRL_CONF_IDE_CONFIG:
config_regs.ideconfig = data;
break;
default:
panic("Invalid PCI configuration write for size 2 offset: %#x!\n",
offset);
}
} else {
panic("Write of unimplemented PCI config. register: %x\n", offset);
}
DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n", offset, data);
/* Trap command register writes and enable IO/BM as appropriate. */
if (offset == PCI_COMMAND) {
if (letoh(config.command) & PCI_CMD_IOSE)
io_enabled = true;
else
io_enabled = false;
if (letoh(config.command) & PCI_CMD_BME)
bm_enabled = true;
else
bm_enabled = false;
} }
} /* Trap command register writes and enable IO/BM as appropriate as well as
* BARs. */
void
IdeController::writeConfig(int offset, const uint32_t data)
{
if (offset < PCI_DEVICE_SPECIFIC) {
PciDev::writeConfig(offset, data);
} else {
panic("Read of unimplemented PCI config. register: %x\n", offset);
}
DPRINTF(IdeCtrl, "PCI write offset: %#x size: 4 data: %#x\n", offset, data);
switch(offset) { switch(offset) {
case PCI0_BASE_ADDR0: case PCI0_BASE_ADDR0:
if (BARAddrs[0] != 0) if (BARAddrs[0] != 0)
@ -423,9 +389,24 @@ IdeController::writeConfig(int offset, const uint32_t data)
if (BARAddrs[4] != 0) if (BARAddrs[4] != 0)
bmi_addr = BARAddrs[4]; bmi_addr = BARAddrs[4];
break; break;
case PCI_COMMAND:
if (letoh(config.command) & PCI_CMD_IOSE)
io_enabled = true;
else
io_enabled = false;
if (letoh(config.command) & PCI_CMD_BME)
bm_enabled = true;
else
bm_enabled = false;
break;
} }
pkt->result = Packet::Success;
return configDelay;
} }
Tick Tick
IdeController::read(Packet *pkt) IdeController::read(Packet *pkt)
{ {
@ -770,7 +751,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
SimObjectParam<System *> system; SimObjectParam<System *> system;
SimObjectParam<Platform *> platform; SimObjectParam<Platform *> platform;
SimObjectParam<PciConfigAll *> configspace;
SimObjectParam<PciConfigData *> configdata; SimObjectParam<PciConfigData *> configdata;
Param<uint32_t> pci_bus; Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev; Param<uint32_t> pci_dev;
@ -784,7 +764,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController)
INIT_PARAM(system, "System pointer"), INIT_PARAM(system, "System pointer"),
INIT_PARAM(platform, "Platform pointer"), INIT_PARAM(platform, "Platform pointer"),
INIT_PARAM(configspace, "PCI Configspace"),
INIT_PARAM(configdata, "PCI Config data"), INIT_PARAM(configdata, "PCI Config data"),
INIT_PARAM(pci_bus, "PCI bus ID"), INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"), INIT_PARAM(pci_dev, "PCI device number"),
@ -800,7 +779,6 @@ CREATE_SIM_OBJECT(IdeController)
params->name = getInstanceName(); params->name = getInstanceName();
params->platform = platform; params->platform = platform;
params->system = system; params->system = system;
params->configSpace = configspace;
params->configData = configdata; params->configData = configdata;
params->busNum = pci_bus; params->busNum = pci_bus;
params->deviceNum = pci_dev; params->deviceNum = pci_dev;

View file

@ -204,12 +204,8 @@ class IdeController : public PciDev
IdeController(Params *p); IdeController(Params *p);
~IdeController(); ~IdeController();
virtual void writeConfig(int offset, const uint8_t data); virtual Tick writeConfig(Packet *pkt);
virtual void writeConfig(int offset, const uint16_t data); virtual Tick readConfig(Packet *pkt);
virtual void writeConfig(int offset, const uint32_t data);
virtual void readConfig(int offset, uint8_t *data);
virtual void readConfig(int offset, uint16_t *data);
virtual void readConfig(int offset, uint32_t *data);
void setDmaComplete(IdeDisk *disk); void setDmaComplete(IdeDisk *disk);

View file

@ -34,8 +34,8 @@
#include "sim/builder.hh" #include "sim/builder.hh"
PioPort::PioPort(PioDevice *dev, Platform *p) PioPort::PioPort(PioDevice *dev, Platform *p, std::string pname)
: Port(dev->name() + "-pioport"), device(dev), platform(p) : Port(dev->name() + pname), device(dev), platform(p)
{ } { }
@ -79,19 +79,23 @@ PioPort::SendEvent::process()
port->transmitList.push_back(packet); port->transmitList.push_back(packet);
} }
void
PioPort::resendNacked(Packet *pkt) {
pkt->reinitNacked();
if (transmitList.size()) {
transmitList.push_front(pkt);
} else {
if (!Port::sendTiming(pkt))
transmitList.push_front(pkt);
}
};
bool bool
PioPort::recvTiming(Packet *pkt) PioPort::recvTiming(Packet *pkt)
{ {
if (pkt->result == Packet::Nacked) { if (pkt->result == Packet::Nacked) {
pkt->reinitNacked(); resendNacked(pkt);
if (transmitList.size()) {
transmitList.push_front(pkt);
} else {
if (!Port::sendTiming(pkt))
transmitList.push_front(pkt);
}
} else { } else {
Tick latency = device->recvAtomic(pkt); Tick latency = device->recvAtomic(pkt);
// turn packet around to go back to requester // turn packet around to go back to requester

View file

@ -82,6 +82,8 @@ class PioPort : public Port
virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop); virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
void resendNacked(Packet *pkt);
/** /**
* This class is used to implemented sendTiming() with a delay. When a delay * This class is used to implemented sendTiming() with a delay. When a delay
* is requested a new event is created. When the event time expires it * is requested a new event is created. When the event time expires it
@ -113,7 +115,7 @@ class PioPort : public Port
virtual void recvRetry(); virtual void recvRetry();
public: public:
PioPort(PioDevice *dev, Platform *p); PioPort(PioDevice *dev, Platform *p, std::string pname = "-pioport");
friend class PioPort::SendEvent; friend class PioPort::SendEvent;
}; };

View file

@ -465,11 +465,12 @@ NSGigE::regStats()
/** /**
* This is to write to the PCI general configuration registers * This is to write to the PCI general configuration registers
*/ */
void Tick
NSGigE::writeConfig(int offset, const uint16_t data) NSGigE::writeConfig(Packet *pkt)
{ {
int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
if (offset < PCI_DEVICE_SPECIFIC) if (offset < PCI_DEVICE_SPECIFIC)
PciDev::writeConfig(offset, data); PciDev::writeConfig(pkt);
else else
panic("Device specific PCI config space not implemented!\n"); panic("Device specific PCI config space not implemented!\n");
@ -484,6 +485,8 @@ NSGigE::writeConfig(int offset, const uint16_t data)
ioEnable = false; ioEnable = false;
break; break;
} }
pkt->result = Packet::Success;
return configDelay;
} }
/** /**
@ -508,14 +511,7 @@ NSGigE::read(Packet *pkt)
if (daddr > LAST && daddr <= RESERVED) { if (daddr > LAST && daddr <= RESERVED) {
panic("Accessing reserved register"); panic("Accessing reserved register");
} else if (daddr > RESERVED && daddr <= 0x3FC) { } else if (daddr > RESERVED && daddr <= 0x3FC) {
if (pkt->getSize() == sizeof(uint8_t)) return readConfig(pkt);
readConfig(daddr & 0xff, pkt->getPtr<uint8_t>());
if (pkt->getSize() == sizeof(uint16_t))
readConfig(daddr & 0xff, pkt->getPtr<uint16_t>());
if (pkt->getSize() == sizeof(uint32_t))
readConfig(daddr & 0xff, pkt->getPtr<uint32_t>());
pkt->result = Packet::Success;
return pioDelay;
} else if (daddr >= MIB_START && daddr <= MIB_END) { } else if (daddr >= MIB_START && daddr <= MIB_END) {
// don't implement all the MIB's. hopefully the kernel // don't implement all the MIB's. hopefully the kernel
// doesn't actually DEPEND upon their values // doesn't actually DEPEND upon their values
@ -733,14 +729,7 @@ NSGigE::write(Packet *pkt)
if (daddr > LAST && daddr <= RESERVED) { if (daddr > LAST && daddr <= RESERVED) {
panic("Accessing reserved register"); panic("Accessing reserved register");
} else if (daddr > RESERVED && daddr <= 0x3FC) { } else if (daddr > RESERVED && daddr <= 0x3FC) {
if (pkt->getSize() == sizeof(uint8_t)) return writeConfig(pkt);
writeConfig(daddr & 0xff, pkt->get<uint8_t>());
if (pkt->getSize() == sizeof(uint16_t))
writeConfig(daddr & 0xff, pkt->get<uint16_t>());
if (pkt->getSize() == sizeof(uint32_t))
writeConfig(daddr & 0xff, pkt->get<uint32_t>());
pkt->result = Packet::Success;
return pioDelay;
} else if (daddr > 0x3FC) } else if (daddr > 0x3FC)
panic("Something is messed up!\n"); panic("Something is messed up!\n");
@ -2807,7 +2796,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
SimObjectParam<System *> system; SimObjectParam<System *> system;
SimObjectParam<Platform *> platform; SimObjectParam<Platform *> platform;
SimObjectParam<PciConfigAll *> configspace;
SimObjectParam<PciConfigData *> configdata; SimObjectParam<PciConfigData *> configdata;
Param<uint32_t> pci_bus; Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev; Param<uint32_t> pci_dev;
@ -2841,7 +2829,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
INIT_PARAM(system, "System pointer"), INIT_PARAM(system, "System pointer"),
INIT_PARAM(platform, "Platform pointer"), INIT_PARAM(platform, "Platform pointer"),
INIT_PARAM(configspace, "PCI Configspace"),
INIT_PARAM(configdata, "PCI Config data"), INIT_PARAM(configdata, "PCI Config data"),
INIT_PARAM(pci_bus, "PCI bus ID"), INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"), INIT_PARAM(pci_dev, "PCI device number"),
@ -2879,7 +2866,6 @@ CREATE_SIM_OBJECT(NSGigE)
params->name = getInstanceName(); params->name = getInstanceName();
params->platform = platform; params->platform = platform;
params->system = system; params->system = system;
params->configSpace = configspace;
params->configData = configdata; params->configData = configdata;
params->busNum = pci_bus; params->busNum = pci_bus;
params->deviceNum = pci_dev; params->deviceNum = pci_dev;

View file

@ -114,7 +114,6 @@ struct dp_rom {
class NSGigEInt; class NSGigEInt;
class Packet; class Packet;
class PciConfigAll;
/** /**
* NS DP83820 Ethernet device model * NS DP83820 Ethernet device model
@ -376,7 +375,7 @@ class NSGigE : public PciDev
~NSGigE(); ~NSGigE();
const Params *params() const { return (const Params *)_params; } const Params *params() const { return (const Params *)_params; }
virtual void writeConfig(int offset, const uint16_t data); virtual Tick writeConfig(Packet *pkt);
virtual Tick read(Packet *pkt); virtual Tick read(Packet *pkt);
virtual Tick write(Packet *pkt); virtual Tick write(Packet *pkt);

View file

@ -33,14 +33,8 @@
* PCI Configspace implementation * PCI Configspace implementation
*/ */
#include <deque>
#include <string>
#include <vector>
#include <bitset>
#include "base/trace.hh" #include "base/trace.hh"
#include "dev/pciconfigall.hh" #include "dev/pciconfigall.hh"
#include "dev/pcidev.hh"
#include "dev/pcireg.h" #include "dev/pcireg.h"
#include "dev/platform.hh" #include "dev/platform.hh"
#include "mem/packet.hh" #include "mem/packet.hh"
@ -50,151 +44,61 @@
using namespace std; using namespace std;
PciConfigAll::PciConfigAll(Params *p) PciConfigAll::PciConfigAll(Params *p)
: BasicPioDevice(p) : PioDevice(p)
{ {
pioSize = 0xffffff; pioAddr = p->platform->calcConfigAddr(params()->bus,0,0);
// Set backpointer for pci config. Really the config stuff should be able to
// automagically do this
p->platform->pciconfig = this;
// Make all the pointers to devices null
for(int x=0; x < MAX_PCI_DEV; x++)
for(int y=0; y < MAX_PCI_FUNC; y++)
devices[x][y] = NULL;
} }
// If two interrupts share the same line largely bad things will happen.
// Since we don't track how many times an interrupt was set and correspondingly
// cleared two devices on the same interrupt line and assert and deassert each
// others interrupt "line". Interrupts will not work correctly.
void
PciConfigAll::startup()
{
bitset<256> intLines;
PciDev *tempDev;
uint8_t intline;
for (int x = 0; x < MAX_PCI_DEV; x++) {
for (int y = 0; y < MAX_PCI_FUNC; y++) {
if (devices[x][y] != NULL) {
tempDev = devices[x][y];
intline = tempDev->interruptLine();
if (intLines.test(intline))
warn("Interrupt line %#X is used multiple times"
"(You probably want to fix this).\n", (uint32_t)intline);
else
intLines.set(intline);
} // devices != NULL
} // PCI_FUNC
} // PCI_DEV
}
Tick Tick
PciConfigAll::read(Packet *pkt) PciConfigAll::read(Packet *pkt)
{ {
assert(pkt->result == Packet::Unknown); assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
Addr daddr = pkt->getAddr() - pioAddr;
int device = (daddr >> 11) & 0x1F;
int func = (daddr >> 8) & 0x7;
int reg = daddr & 0xFF;
pkt->allocate(); pkt->allocate();
DPRINTF(PciConfigAll, "read va=%#x da=%#x size=%d\n", pkt->getAddr(), daddr, DPRINTF(PciConfigAll, "read va=%#x size=%d\n", pkt->getAddr(),
pkt->getSize()); pkt->getSize());
switch (pkt->getSize()) { switch (pkt->getSize()) {
case sizeof(uint32_t): case sizeof(uint32_t):
if (devices[device][func] == NULL) pkt->set<uint32_t>(0xFFFFFFFF);
pkt->set<uint32_t>(0xFFFFFFFF);
else
devices[device][func]->readConfig(reg, pkt->getPtr<uint32_t>());
break; break;
case sizeof(uint16_t): case sizeof(uint16_t):
if (devices[device][func] == NULL) pkt->set<uint16_t>(0xFFFF);
pkt->set<uint16_t>(0xFFFF);
else
devices[device][func]->readConfig(reg, pkt->getPtr<uint16_t>());
break; break;
case sizeof(uint8_t): case sizeof(uint8_t):
if (devices[device][func] == NULL) pkt->set<uint8_t>(0xFF);
pkt->set<uint8_t>(0xFF);
else
devices[device][func]->readConfig(reg, pkt->getPtr<uint8_t>());
break; break;
default: default:
panic("invalid access size(?) for PCI configspace!\n"); panic("invalid access size(?) for PCI configspace!\n");
} }
pkt->result = Packet::Success; pkt->result = Packet::Success;
return pioDelay; return params()->pio_delay;
} }
Tick Tick
PciConfigAll::write(Packet *pkt) PciConfigAll::write(Packet *pkt)
{ {
assert(pkt->result == Packet::Unknown); assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); panic("Attempting to write to config space on non-existant device\n");
assert(pkt->getSize() == sizeof(uint8_t) || pkt->getSize() == sizeof(uint16_t) ||
pkt->getSize() == sizeof(uint32_t));
Addr daddr = pkt->getAddr() - pioAddr;
int device = (daddr >> 11) & 0x1F;
int func = (daddr >> 8) & 0x7;
int reg = daddr & 0xFF;
if (devices[device][func] == NULL)
panic("Attempting to write to config space on non-existant device\n");
DPRINTF(PciConfigAll, "write - va=%#x size=%d data=%#x\n",
pkt->getAddr(), pkt->getSize(), pkt->get<uint32_t>());
switch (pkt->getSize()) {
case sizeof(uint8_t):
devices[device][func]->writeConfig(reg, pkt->get<uint8_t>());
break;
case sizeof(uint16_t):
devices[device][func]->writeConfig(reg, pkt->get<uint16_t>());
break;
case sizeof(uint32_t):
devices[device][func]->writeConfig(reg, pkt->get<uint32_t>());
break;
default:
panic("invalid pci config write size\n");
}
pkt->result = Packet::Success;
return pioDelay;
} }
void void
PciConfigAll::serialize(std::ostream &os) PciConfigAll::addressRanges(AddrRangeList &range_list)
{ {
/* range_list.clear();
* There is no state associated with this object that requires range_list.push_back(RangeSize(pioAddr, params()->size));
* serialization. The only real state are the device pointers
* which are all setup by the constructor of the PciDev class
*/
} }
void
PciConfigAll::unserialize(Checkpoint *cp, const std::string &section)
{
/*
* There is no state associated with this object that requires
* serialization. The only real state are the device pointers
* which are all setup by the constructor of the PciDev class
*/
}
#ifndef DOXYGEN_SHOULD_SKIP_THIS #ifndef DOXYGEN_SHOULD_SKIP_THIS
BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll) BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll)
Param<Addr> pio_addr;
Param<Tick> pio_latency; Param<Tick> pio_latency;
Param<int> bus;
Param<Addr> size;
SimObjectParam<Platform *> platform; SimObjectParam<Platform *> platform;
SimObjectParam<System *> system; SimObjectParam<System *> system;
@ -202,8 +106,9 @@ END_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll)
BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigAll) BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigAll)
INIT_PARAM(pio_addr, "Device Address"),
INIT_PARAM(pio_latency, "Programmed IO latency"), INIT_PARAM(pio_latency, "Programmed IO latency"),
INIT_PARAM(bus, "Bus that this object handles config space for"),
INIT_PARAM(size, "The size of config space"),
INIT_PARAM(platform, "platform"), INIT_PARAM(platform, "platform"),
INIT_PARAM(system, "system object") INIT_PARAM(system, "system object")
@ -211,11 +116,13 @@ END_INIT_SIM_OBJECT_PARAMS(PciConfigAll)
CREATE_SIM_OBJECT(PciConfigAll) CREATE_SIM_OBJECT(PciConfigAll)
{ {
BasicPioDevice::Params *p = new BasicPioDevice::Params; PciConfigAll::Params *p = new PciConfigAll::Params;
p->pio_addr = pio_addr;
p->pio_delay = pio_latency; p->pio_delay = pio_latency;
p->platform = platform; p->platform = platform;
p->system = system; p->system = system;
p->bus = bus;
p->size = size;
return new PciConfigAll(p); return new PciConfigAll(p);
} }

View file

@ -42,11 +42,6 @@
#include "dev/io_device.hh" #include "dev/io_device.hh"
static const uint32_t MAX_PCI_DEV = 32;
static const uint32_t MAX_PCI_FUNC = 8;
class PciDev;
/** /**
* PCI Config Space * PCI Config Space
* All of PCI config space needs to return -1 on Tsunami, except * All of PCI config space needs to return -1 on Tsunami, except
@ -54,45 +49,28 @@ class PciDev;
* space and passes the requests on to TsunamiPCIDev devices as * space and passes the requests on to TsunamiPCIDev devices as
* appropriate. * appropriate.
*/ */
class PciConfigAll : public BasicPioDevice class PciConfigAll : public PioDevice
{ {
private:
/**
* Pointers to all the devices that are registered with this
* particular config space.
*/
PciDev* devices[MAX_PCI_DEV][MAX_PCI_FUNC];
public: public:
struct Params : public PioDevice::Params
{
Tick pio_delay;
Addr size;
int bus;
};
const Params *params() const { return (const Params *)_params; }
/** /**
* Constructor for PCIConfigAll * Constructor for PCIConfigAll
* @param p parameters structure * @param p parameters structure
*/ */
PciConfigAll(Params *p); PciConfigAll(Params *p);
/**
* Check if a device exists.
* @param pcidev PCI device to check
* @param pcifunc PCI function to check
* @return true if device exists, false otherwise
*/
bool deviceExists(uint32_t pcidev, uint32_t pcifunc)
{ return devices[pcidev][pcifunc] != NULL ? true : false; }
/**
* Registers a device with the config space object.
* @param pcidev PCI device to register
* @param pcifunc PCI function to register
* @param device device to register
*/
void registerDevice(uint8_t pcidev, uint8_t pcifunc, PciDev *device)
{ devices[pcidev][pcifunc] = device; }
/** /**
* Read something in PCI config space. If the device does not exist * Read something in PCI config space. If the device does not exist
* -1 is returned, if the device does exist its PciDev::ReadConfig (or the * -1 is returned, if the device does exist its PciDev::ReadConfig (or the
* virtual function that overrides) it is called. * virtual function that overrides) it is called.
* @param pkt Contains the address of the field to read. * @param pkt Contains information about the read operation
* @return Amount of time to do the read * @return Amount of time to do the read
*/ */
virtual Tick read(Packet *pkt); virtual Tick read(Packet *pkt);
@ -101,31 +79,17 @@ class PciConfigAll : public BasicPioDevice
* Write to PCI config spcae. If the device does not exit the simulator * Write to PCI config spcae. If the device does not exit the simulator
* panics. If it does it is passed on the PciDev::WriteConfig (or the virtual * panics. If it does it is passed on the PciDev::WriteConfig (or the virtual
* function that overrides it). * function that overrides it).
* @param req Contains the address to write to. * @param pkt Contains information about the write operation
* @param data The data to write. * @return Amount of time to do the read
* @return The fault condition of the access.
*/ */
virtual Tick write(Packet *pkt); virtual Tick write(Packet *pkt);
/** void addressRanges(AddrRangeList &range_list);
* Start up function to check if more than one person is using an interrupt line
* and print a warning if such a case exists
*/
virtual void startup();
/** private:
* Serialize this object to the given output stream. Addr pioAddr;
* @param os The stream to serialize to.
*/
virtual void serialize(std::ostream &os);
/**
* Reconstruct the state of this object from a checkpoint.
* @param cp The checkpoint use.
* @param section The section name of this object
*/
virtual void unserialize(Checkpoint *cp, const std::string &section);
}; };
#endif // __PCICONFIGALL_HH__ #endif // __PCICONFIGALL_HH__

View file

@ -53,9 +53,63 @@
using namespace std; using namespace std;
PciDev::PciConfigPort::PciConfigPort(PciDev *dev, int busid, int devid,
int funcid, Platform *p)
: PioPort(dev,p,"-pciconf"), device(dev), busId(busid), deviceId(devid),
functionId(funcid)
{
configAddr = platform->calcConfigAddr(busId, deviceId, functionId);
}
Tick
PciDev::PciConfigPort::recvAtomic(Packet *pkt)
{
assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= configAddr && pkt->getAddr() < configAddr +
PCI_CONFIG_SIZE);
return device->recvConfig(pkt);
}
void
PciDev::PciConfigPort::recvFunctional(Packet *pkt)
{
assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= configAddr && pkt->getAddr() < configAddr +
PCI_CONFIG_SIZE);
device->recvConfig(pkt);
}
void
PciDev::PciConfigPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
{
snoop.clear();
resp.push_back(RangeSize(configAddr, PCI_CONFIG_SIZE+1));
}
bool
PciDev::PciConfigPort::recvTiming(Packet *pkt)
{
if (pkt->result == Packet::Nacked) {
resendNacked(pkt);
} else {
assert(pkt->result == Packet::Unknown);
assert(pkt->getAddr() >= configAddr && pkt->getAddr() < configAddr +
PCI_CONFIG_SIZE);
Tick latency = device->recvConfig(pkt);
// turn packet around to go back to requester
pkt->makeTimingResponse();
sendTiming(pkt, latency);
}
return true;
}
PciDev::PciDev(Params *p) PciDev::PciDev(Params *p)
: DmaDevice(p), plat(p->platform), configData(p->configData), : DmaDevice(p), plat(p->platform), configData(p->configData),
pioDelay(p->pio_delay) pioDelay(p->pio_delay), configDelay(p->config_delay),
configPort(NULL)
{ {
// copy the config data from the PciConfigData object // copy the config data from the PciConfigData object
if (configData) { if (configData) {
@ -65,25 +119,56 @@ PciDev::PciDev(Params *p)
} else } else
panic("NULL pointer to configuration data"); panic("NULL pointer to configuration data");
// Setup pointer in config space to point to this entry plat->registerPciDevice(0, p->deviceNum, p->functionNum,
if (p->configSpace->deviceExists(p->deviceNum, p->functionNum)) letoh(configData->config.interruptLine));
panic("Two PCI devices occuping same dev: %#x func: %#x",
p->deviceNum, p->functionNum);
else
p->configSpace->registerDevice(p->deviceNum, p->functionNum, this);
} }
void void
PciDev::readConfig(int offset, uint8_t *data) PciDev::init()
{ {
if (!configPort)
panic("pci config port not connected to anything!");
configPort->sendStatusChange(Port::RangeChange);
PioDevice::init();
}
Tick
PciDev::readConfig(Packet *pkt)
{
int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
if (offset >= PCI_DEVICE_SPECIFIC) if (offset >= PCI_DEVICE_SPECIFIC)
panic("Device specific PCI config space not implemented!\n"); panic("Device specific PCI config space not implemented!\n");
*data = config.data[offset]; pkt->allocate();
DPRINTF(PCIDEV, switch (pkt->getSize()) {
case sizeof(uint8_t):
pkt->set<uint8_t>(config.data[offset]);
DPRINTF(PCIDEV,
"read device: %#x function: %#x register: %#x 1 bytes: data: %#x\n", "read device: %#x function: %#x register: %#x 1 bytes: data: %#x\n",
params()->deviceNum, params()->functionNum, offset, *data); params()->deviceNum, params()->functionNum, offset,
(uint32_t)pkt->get<uint8_t>());
break;
case sizeof(uint16_t):
pkt->set<uint16_t>(*(uint16_t*)&config.data[offset]);
DPRINTF(PCIDEV,
"read device: %#x function: %#x register: %#x 2 bytes: data: %#x\n",
params()->deviceNum, params()->functionNum, offset,
(uint32_t)pkt->get<uint16_t>());
break;
case sizeof(uint32_t):
pkt->set<uint32_t>(*(uint32_t*)&config.data[offset]);
DPRINTF(PCIDEV,
"read device: %#x function: %#x register: %#x 4 bytes: data: %#x\n",
params()->deviceNum, params()->functionNum, offset,
(uint32_t)pkt->get<uint32_t>());
break;
default:
panic("invalid access size(?) for PCI configspace!\n");
}
pkt->result = Packet::Success;
return configDelay;
} }
void void
@ -96,158 +181,128 @@ PciDev::addressRanges(AddrRangeList &range_list)
range_list.push_back(RangeSize(BARAddrs[x],BARSize[x])); range_list.push_back(RangeSize(BARAddrs[x],BARSize[x]));
} }
void Tick
PciDev::readConfig(int offset, uint16_t *data) PciDev::writeConfig(Packet *pkt)
{ {
int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
if (offset >= PCI_DEVICE_SPECIFIC) if (offset >= PCI_DEVICE_SPECIFIC)
panic("Device specific PCI config space not implemented!\n"); panic("Device specific PCI config space not implemented!\n");
*data = *(uint16_t*)&config.data[offset]; switch (pkt->getSize()) {
case sizeof(uint8_t):
DPRINTF(PCIDEV, switch (offset) {
"read device: %#x function: %#x register: %#x 2 bytes: data: %#x\n", case PCI0_INTERRUPT_LINE:
params()->deviceNum, params()->functionNum, offset, *data); config.interruptLine = pkt->get<uint8_t>();
} case PCI_CACHE_LINE_SIZE:
config.cacheLineSize = pkt->get<uint8_t>();
void case PCI_LATENCY_TIMER:
PciDev::readConfig(int offset, uint32_t *data) config.latencyTimer = pkt->get<uint8_t>();
{ break;
if (offset >= PCI_DEVICE_SPECIFIC) /* Do nothing for these read-only registers */
panic("Device specific PCI config space not implemented!\n"); case PCI0_INTERRUPT_PIN:
case PCI0_MINIMUM_GRANT:
*data = *(uint32_t*)&config.data[offset]; case PCI0_MAXIMUM_LATENCY:
case PCI_CLASS_CODE:
DPRINTF(PCIDEV, case PCI_REVISION_ID:
"read device: %#x function: %#x register: %#x 4 bytes: data: %#x\n", break;
params()->deviceNum, params()->functionNum, offset, *data); default:
} panic("writing to a read only register");
void
PciDev::writeConfig(int offset, const uint8_t data)
{
if (offset >= PCI_DEVICE_SPECIFIC)
panic("Device specific PCI config space not implemented!\n");
DPRINTF(PCIDEV,
"write device: %#x function: %#x reg: %#x size: 1 data: %#x\n",
params()->deviceNum, params()->functionNum, offset, data);
switch (offset) {
case PCI0_INTERRUPT_LINE:
config.interruptLine = data;
case PCI_CACHE_LINE_SIZE:
config.cacheLineSize = data;
case PCI_LATENCY_TIMER:
config.latencyTimer = data;
break;
/* Do nothing for these read-only registers */
case PCI0_INTERRUPT_PIN:
case PCI0_MINIMUM_GRANT:
case PCI0_MAXIMUM_LATENCY:
case PCI_CLASS_CODE:
case PCI_REVISION_ID:
break;
default:
panic("writing to a read only register");
}
}
void
PciDev::writeConfig(int offset, const uint16_t data)
{
if (offset >= PCI_DEVICE_SPECIFIC)
panic("Device specific PCI config space not implemented!\n");
DPRINTF(PCIDEV,
"write device: %#x function: %#x reg: %#x size: 2 data: %#x\n",
params()->deviceNum, params()->functionNum, offset, data);
switch (offset) {
case PCI_COMMAND:
config.command = data;
case PCI_STATUS:
config.status = data;
case PCI_CACHE_LINE_SIZE:
config.cacheLineSize = data;
break;
default:
panic("writing to a read only register");
}
}
void
PciDev::writeConfig(int offset, const uint32_t data)
{
if (offset >= PCI_DEVICE_SPECIFIC)
panic("Device specific PCI config space not implemented!\n");
DPRINTF(PCIDEV,
"write device: %#x function: %#x reg: %#x size: 4 data: %#x\n",
params()->deviceNum, params()->functionNum, offset, data);
switch (offset) {
case PCI0_BASE_ADDR0:
case PCI0_BASE_ADDR1:
case PCI0_BASE_ADDR2:
case PCI0_BASE_ADDR3:
case PCI0_BASE_ADDR4:
case PCI0_BASE_ADDR5:
uint32_t barnum, bar_mask;
Addr base_addr, base_size, space_base;
barnum = BAR_NUMBER(offset);
if (BAR_IO_SPACE(letoh(config.baseAddr[barnum]))) {
bar_mask = BAR_IO_MASK;
space_base = TSUNAMI_PCI0_IO;
} else {
bar_mask = BAR_MEM_MASK;
space_base = TSUNAMI_PCI0_MEMORY;
} }
DPRINTF(PCIDEV,
"write device: %#x function: %#x register: %#x 1 bytes: data: %#x\n",
params()->deviceNum, params()->functionNum, offset,
(uint32_t)pkt->get<uint8_t>());
break;
case sizeof(uint16_t):
switch (offset) {
case PCI_COMMAND:
config.command = pkt->get<uint8_t>();
case PCI_STATUS:
config.status = pkt->get<uint8_t>();
case PCI_CACHE_LINE_SIZE:
config.cacheLineSize = pkt->get<uint8_t>();
break;
default:
panic("writing to a read only register");
}
DPRINTF(PCIDEV,
"write device: %#x function: %#x register: %#x 2 bytes: data: %#x\n",
params()->deviceNum, params()->functionNum, offset,
(uint32_t)pkt->get<uint16_t>());
break;
case sizeof(uint32_t):
switch (offset) {
case PCI0_BASE_ADDR0:
case PCI0_BASE_ADDR1:
case PCI0_BASE_ADDR2:
case PCI0_BASE_ADDR3:
case PCI0_BASE_ADDR4:
case PCI0_BASE_ADDR5:
// Writing 0xffffffff to a BAR tells the card to set the uint32_t barnum, bar_mask;
// value of the bar to size of memory it needs Addr base_addr, base_size, space_base;
if (letoh(data) == 0xffffffff) {
// This is I/O Space, bottom two bits are read only
config.baseAddr[barnum] = letoh( barnum = BAR_NUMBER(offset);
(~(BARSize[barnum] - 1) & ~bar_mask) |
(letoh(config.baseAddr[barnum]) & bar_mask));
} else {
config.baseAddr[barnum] = letoh(
(letoh(data) & ~bar_mask) |
(letoh(config.baseAddr[barnum]) & bar_mask));
if (letoh(config.baseAddr[barnum]) & ~bar_mask) { if (BAR_IO_SPACE(letoh(config.baseAddr[barnum]))) {
base_addr = (letoh(data) & ~bar_mask) + space_base; bar_mask = BAR_IO_MASK;
base_size = BARSize[barnum]; space_base = TSUNAMI_PCI0_IO;
BARAddrs[barnum] = base_addr; } else {
bar_mask = BAR_MEM_MASK;
pioPort->sendStatusChange(Port::RangeChange); space_base = TSUNAMI_PCI0_MEMORY;
} }
// Writing 0xffffffff to a BAR tells the card to set the
// value of the bar to size of memory it needs
if (letoh(pkt->get<uint32_t>()) == 0xffffffff) {
// This is I/O Space, bottom two bits are read only
config.baseAddr[barnum] = letoh(
(~(BARSize[barnum] - 1) & ~bar_mask) |
(letoh(config.baseAddr[barnum]) & bar_mask));
} else {
config.baseAddr[barnum] = letoh(
(letoh(pkt->get<uint32_t>()) & ~bar_mask) |
(letoh(config.baseAddr[barnum]) & bar_mask));
if (letoh(config.baseAddr[barnum]) & ~bar_mask) {
base_addr = (letoh(pkt->get<uint32_t>()) & ~bar_mask) + space_base;
base_size = BARSize[barnum];
BARAddrs[barnum] = base_addr;
pioPort->sendStatusChange(Port::RangeChange);
}
}
break;
case PCI0_ROM_BASE_ADDR:
if (letoh(pkt->get<uint32_t>()) == 0xfffffffe)
config.expansionROM = htole((uint32_t)0xffffffff);
else
config.expansionROM = pkt->get<uint32_t>();
break;
case PCI_COMMAND:
// This could also clear some of the error bits in the Status
// register. However they should never get set, so lets ignore
// it for now
config.command = pkt->get<uint32_t>();
break;
default:
DPRINTF(PCIDEV, "Writing to a read only register");
} }
DPRINTF(PCIDEV,
"write device: %#x function: %#x register: %#x 4 bytes: data: %#x\n",
params()->deviceNum, params()->functionNum, offset,
(uint32_t)pkt->get<uint32_t>());
break; break;
case PCI0_ROM_BASE_ADDR:
if (letoh(data) == 0xfffffffe)
config.expansionROM = htole((uint32_t)0xffffffff);
else
config.expansionROM = data;
break;
case PCI_COMMAND:
// This could also clear some of the error bits in the Status
// register. However they should never get set, so lets ignore
// it for now
config.command = data;
break;
default: default:
DPRINTF(PCIDEV, "Writing to a read only register"); panic("invalid access size(?) for PCI configspace!\n");
} }
pkt->result = Packet::Success;
return configDelay;
} }
void void

View file

@ -47,8 +47,6 @@
#define BAR_IO_SPACE(x) ((x) & BAR_IO_SPACE_BIT) #define BAR_IO_SPACE(x) ((x) & BAR_IO_SPACE_BIT)
#define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2); #define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2);
class PciConfigAll;
/** /**
* This class encapulates the first 64 bytes of a singles PCI * This class encapulates the first 64 bytes of a singles PCI
@ -78,24 +76,41 @@ class PciConfigData : public SimObject
Addr BARAddrs[6]; Addr BARAddrs[6];
}; };
/** /**
* PCI device, base implemnation is only config space. * PCI device, base implemnation is only config space.
* Each device is connected to a PCIConfigSpace device
* which returns -1 for everything but the pcidevs that
* register with it. This object registers with the PCIConfig space
* object.
*/ */
class PciDev : public DmaDevice class PciDev : public DmaDevice
{ {
public: class PciConfigPort : public PioPort
struct Params : public ::PioDevice::Params
{ {
/** protected:
* A pointer to the configspace all object that calls us when PciDev *device;
* a read comes to this particular device/function.
*/
PciConfigAll *configSpace;
virtual bool recvTiming(Packet *pkt);
virtual Tick recvAtomic(Packet *pkt);
virtual void recvFunctional(Packet *pkt) ;
virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
int busId;
int deviceId;
int functionId;
Addr configAddr;
public:
PciConfigPort(PciDev *dev, int busid, int devid, int funcid,
Platform *p);
friend class PioPort::SendEvent;
};
public:
struct Params : public PioDevice::Params
{
/** /**
* A pointer to the object that contains the first 64 bytes of * A pointer to the object that contains the first 64 bytes of
* config space * config space
@ -113,6 +128,9 @@ class PciDev : public DmaDevice
/** The latency for pio accesses. */ /** The latency for pio accesses. */
Tick pio_delay; Tick pio_delay;
/** The latency for a config access. */
Tick config_delay;
}; };
public: public:
@ -164,6 +182,25 @@ class PciDev : public DmaDevice
Platform *plat; Platform *plat;
PciConfigData *configData; PciConfigData *configData;
Tick pioDelay; Tick pioDelay;
Tick configDelay;
PciConfigPort *configPort;
/**
* 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
* for normal operations that it does not need to override.
* @param pkt packet containing the write the offset into config space
*/
virtual Tick writeConfig(Packet *pkt);
/**
* Read from 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
* for normal operations that it does not need to override.
* @param pkt packet containing the write the offset into config space
*/
virtual Tick readConfig(Packet *pkt);
public: public:
Addr pciToDma(Addr pciAddr) const Addr pciToDma(Addr pciAddr) const
@ -171,21 +208,25 @@ class PciDev : public DmaDevice
void void
intrPost() intrPost()
{ plat->postPciInt(configData->config.interruptLine); } { plat->postPciInt(letoh(configData->config.interruptLine)); }
void void
intrClear() intrClear()
{ plat->clearPciInt(configData->config.interruptLine); } { plat->clearPciInt(letoh(configData->config.interruptLine)); }
uint8_t uint8_t
interruptLine() interruptLine()
{ return configData->config.interruptLine; } { return letoh(configData->config.interruptLine); }
/** return the address ranges that this device responds to. /** return the address ranges that this device responds to.
* @params range_list range list to populate with ranges * @params range_list range list to populate with ranges
*/ */
void addressRanges(AddrRangeList &range_list); void addressRanges(AddrRangeList &range_list);
/** Do a PCI Configspace memory access. */
Tick recvConfig(Packet *pkt)
{ return pkt->isRead() ? readConfig(pkt) : writeConfig(pkt); }
/** /**
* Constructor for PCI Dev. This function copies data from the * Constructor for PCI Dev. This function copies data from the
* config file object PCIConfigData and registers the device with * config file object PCIConfigData and registers the device with
@ -193,30 +234,7 @@ class PciDev : public DmaDevice
*/ */
PciDev(Params *params); PciDev(Params *params);
/** virtual void init();
* 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
* for normal operations that it does not need to override.
* @param offset the offset into config space
* @param size the size of the write
* @param data the data to write
*/
virtual void writeConfig(int offset, const uint8_t data);
virtual void writeConfig(int offset, const uint16_t data);
virtual void writeConfig(int offset, const uint32_t data);
/**
* Read from 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
* for normal operations that it does not need to override.
* @param offset the offset into config space
* @param size the size of the read
* @param data pointer to the location where the read value should be stored
*/
virtual void readConfig(int offset, uint8_t *data);
virtual void readConfig(int offset, uint16_t *data);
virtual void readConfig(int offset, uint32_t *data);
/** /**
* Serialize this object to the given output stream. * Serialize this object to the given output stream.
@ -230,5 +248,19 @@ class PciDev : public DmaDevice
* @param section The section name of this object * @param section The section name of this object
*/ */
virtual void unserialize(Checkpoint *cp, const std::string &section); virtual void unserialize(Checkpoint *cp, const std::string &section);
virtual Port *getPort(const std::string &if_name, int idx = -1)
{
if (if_name == "config") {
if (configPort != NULL)
panic("pciconfig port already connected to.");
configPort = new PciConfigPort(this, params()->busNum,
params()->deviceNum, params()->functionNum,
params()->platform);
return configPort;
}
return DmaDevice::getPort(if_name, idx);
}
}; };
#endif // __DEV_PCIDEV_HH__ #endif // __DEV_PCIDEV_HH__

View file

@ -142,6 +142,7 @@ union PCIConfig {
// Device specific offsets // Device specific offsets
#define PCI_DEVICE_SPECIFIC 0x40 // 192 bytes #define PCI_DEVICE_SPECIFIC 0x40 // 192 bytes
#define PCI_CONFIG_SIZE 0xFF
// Some Vendor IDs // Some Vendor IDs
#define PCI_VENDOR_DEC 0x1011 #define PCI_VENDOR_DEC 0x1011

View file

@ -63,5 +63,21 @@ Platform::pciToDma(Addr pciAddr) const
panic("No PCI dma support in platform."); panic("No PCI dma support in platform.");
} }
void
Platform::registerPciDevice(uint8_t bus, uint8_t dev, uint8_t func, uint8_t intr)
{
uint32_t bdf = bus << 16 | dev << 8 | func << 0;
if (pciDevices.find(bdf) != pciDevices.end())
fatal("Two PCI devices have same bus:device:function\n");
if (intLines.test(intr))
fatal("Two PCI devices have same interrupt line: %d\n", intr);
pciDevices.insert(bdf);
intLines.set(intr);
}
DEFINE_SIM_OBJECT_CLASS_NAME("Platform", Platform) DEFINE_SIM_OBJECT_CLASS_NAME("Platform", Platform)

View file

@ -37,6 +37,9 @@
#ifndef __DEV_PLATFORM_HH__ #ifndef __DEV_PLATFORM_HH__
#define __DEV_PLATFORM_HH__ #define __DEV_PLATFORM_HH__
#include <bitset>
#include <set>
#include "sim/sim_object.hh" #include "sim/sim_object.hh"
#include "arch/isa_traits.hh" #include "arch/isa_traits.hh"
@ -52,9 +55,6 @@ class Platform : public SimObject
/** Pointer to the interrupt controller */ /** Pointer to the interrupt controller */
IntrControl *intrctrl; IntrControl *intrctrl;
/** Pointer to the PCI configuration space */
PciConfigAll *pciconfig;
/** Pointer to the UART, set by the uart */ /** Pointer to the UART, set by the uart */
Uart *uart; Uart *uart;
@ -64,13 +64,20 @@ class Platform : public SimObject
public: public:
Platform(const std::string &name, IntrControl *intctrl); Platform(const std::string &name, IntrControl *intctrl);
virtual ~Platform(); virtual ~Platform();
virtual void init() { if (pciconfig == NULL) panic("PCI Config not set"); }
virtual void postConsoleInt() = 0; virtual void postConsoleInt() = 0;
virtual void clearConsoleInt() = 0; virtual void clearConsoleInt() = 0;
virtual Tick intrFrequency() = 0; virtual Tick intrFrequency() = 0;
virtual void postPciInt(int line); virtual void postPciInt(int line);
virtual void clearPciInt(int line); virtual void clearPciInt(int line);
virtual Addr pciToDma(Addr pciAddr) const; virtual Addr pciToDma(Addr pciAddr) const;
virtual Addr calcConfigAddr(int bus, int dev, int func) = 0;
virtual void registerPciDevice(uint8_t bus, uint8_t dev, uint8_t func,
uint8_t intr);
private:
std::bitset<256> intLines;
std::set<uint32_t> pciDevices;
}; };
#endif // __DEV_PLATFORM_HH__ #endif // __DEV_PLATFORM_HH__

View file

@ -37,7 +37,6 @@
#include "cpu/intr_control.hh" #include "cpu/intr_control.hh"
#include "dev/etherlink.hh" #include "dev/etherlink.hh"
#include "dev/sinic.hh" #include "dev/sinic.hh"
#include "dev/pciconfigall.hh"
#include "mem/packet.hh" #include "mem/packet.hh"
#include "sim/builder.hh" #include "sim/builder.hh"
#include "sim/debug.hh" #include "sim/debug.hh"
@ -1623,7 +1622,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
SimObjectParam<System *> system; SimObjectParam<System *> system;
SimObjectParam<Platform *> platform; SimObjectParam<Platform *> platform;
SimObjectParam<PciConfigAll *> configspace;
SimObjectParam<PciConfigData *> configdata; SimObjectParam<PciConfigData *> configdata;
Param<uint32_t> pci_bus; Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev; Param<uint32_t> pci_dev;
@ -1666,7 +1664,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Device)
INIT_PARAM(system, "System pointer"), INIT_PARAM(system, "System pointer"),
INIT_PARAM(platform, "Platform pointer"), INIT_PARAM(platform, "Platform pointer"),
INIT_PARAM(configspace, "PCI Configspace"),
INIT_PARAM(configdata, "PCI Config data"), INIT_PARAM(configdata, "PCI Config data"),
INIT_PARAM(pci_bus, "PCI bus ID"), INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"), INIT_PARAM(pci_dev, "PCI device number"),
@ -1711,7 +1708,6 @@ CREATE_SIM_OBJECT(Device)
params->name = getInstanceName(); params->name = getInstanceName();
params->platform = platform; params->platform = platform;
params->system = system; params->system = system;
params->configSpace = configspace;
params->configData = configdata; params->configData = configdata;
params->busNum = pci_bus; params->busNum = pci_bus;
params->deviceNum = pci_dev; params->deviceNum = pci_dev;

View file

@ -95,6 +95,13 @@ Tsunami::pciToDma(Addr pciAddr) const
return pchip->translatePciToDma(pciAddr); return pchip->translatePciToDma(pciAddr);
} }
Addr
Tsunami::calcConfigAddr(int bus, int dev, int func)
{
return pchip->calcConfigAddr(bus, dev, func);
}
void void
Tsunami::serialize(std::ostream &os) Tsunami::serialize(std::ostream &os)
{ {

View file

@ -113,8 +113,14 @@ class Tsunami : public Platform
*/ */
virtual void clearPciInt(int line); virtual void clearPciInt(int line);
virtual Addr pciToDma(Addr pciAddr) const; virtual Addr pciToDma(Addr pciAddr) const;
/**
* Calculate the configuration address given a bus/dev/func.
*/
virtual Addr calcConfigAddr(int bus, int dev, int func);
/** /**
* Serialize this object to the given output stream. * Serialize this object to the given output stream.
* @param os The stream to serialize to. * @param os The stream to serialize to.

View file

@ -302,6 +302,17 @@ TsunamiPChip::translatePciToDma(Addr busAddr)
// if no match was found, then return the original address // if no match was found, then return the original address
return busAddr; return busAddr;
} }
Addr
TsunamiPChip::calcConfigAddr(int bus, int dev, int func)
{
assert(func < 8);
assert(dev < 32);
assert(bus == 0);
return TsunamiPciBus0Config | (func << 8) | (dev << 11);
}
void void
TsunamiPChip::serialize(std::ostream &os) TsunamiPChip::serialize(std::ostream &os)

View file

@ -45,6 +45,9 @@
class TsunamiPChip : public BasicPioDevice class TsunamiPChip : public BasicPioDevice
{ {
protected: protected:
static const Addr TsunamiPciBus0Config = 0x801fe000000;
/** Pchip control register */ /** Pchip control register */
uint64_t pctl; uint64_t pctl;
@ -80,6 +83,8 @@ class TsunamiPChip : public BasicPioDevice
*/ */
Addr translatePciToDma(Addr busAddr); Addr translatePciToDma(Addr busAddr);
Addr calcConfigAddr(int bus, int dev, int func);
virtual Tick read(Packet *pkt); virtual Tick read(Packet *pkt);
virtual Tick write(Packet *pkt); virtual Tick write(Packet *pkt);

View file

@ -33,6 +33,7 @@
*/ */
#include "base/misc.hh"
#include "base/trace.hh" #include "base/trace.hh"
#include "mem/bus.hh" #include "mem/bus.hh"
#include "sim/builder.hh" #include "sim/builder.hh"
@ -40,6 +41,14 @@
Port * Port *
Bus::getPort(const std::string &if_name, int idx) Bus::getPort(const std::string &if_name, int idx)
{ {
if (if_name == "default")
if (defaultPort == NULL) {
defaultPort = new BusPort(csprintf("%s-default",name()), this,
defaultId);
return defaultPort;
} else
fatal("Default port already set\n");
// if_name ignored? forced to be empty? // if_name ignored? forced to be empty?
int id = interfaces.size(); int id = interfaces.size();
BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id); BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id);
@ -47,11 +56,12 @@ Bus::getPort(const std::string &if_name, int idx)
return bp; return bp;
} }
/** Get the ranges of anyone that we are connected to. */ /** Get the ranges of anyone other buses that we are connected to. */
void void
Bus::init() Bus::init()
{ {
std::vector<Port*>::iterator intIter; std::vector<Port*>::iterator intIter;
for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
(*intIter)->sendStatusChange(Port::RangeChange); (*intIter)->sendStatusChange(Port::RangeChange);
} }
@ -110,6 +120,7 @@ Bus::findPort(Addr addr, int id)
int dest_id = -1; int dest_id = -1;
int i = 0; int i = 0;
bool found = false; bool found = false;
AddrRangeIter iter;
while (i < portList.size() && !found) while (i < portList.size() && !found)
{ {
@ -120,8 +131,18 @@ Bus::findPort(Addr addr, int id)
} }
i++; i++;
} }
if (dest_id == -1)
// Check if this matches the default range
if (dest_id == -1) {
for (iter = defaultRange.begin(); iter != defaultRange.end(); iter++) {
if (*iter == addr) {
DPRINTF(Bus, " found addr 0x%llx on default\n", addr);
return defaultPort;
}
}
panic("Unable to find destination for addr: %llx", addr); panic("Unable to find destination for addr: %llx", addr);
}
// we shouldn't be sending this back to where it came from // we shouldn't be sending this back to where it came from
assert(dest_id != id); assert(dest_id != id);
@ -155,39 +176,52 @@ Bus::recvFunctional(Packet *pkt)
void void
Bus::recvStatusChange(Port::Status status, int id) Bus::recvStatusChange(Port::Status status, int id)
{ {
AddrRangeList ranges;
AddrRangeList snoops;
int x;
AddrRangeIter iter;
assert(status == Port::RangeChange && assert(status == Port::RangeChange &&
"The other statuses need to be implemented."); "The other statuses need to be implemented.");
DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id); DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id);
assert(id < interfaces.size() && id >= 0); if (id == defaultId) {
int x; defaultRange.clear();
Port *port = interfaces[id]; defaultPort->getPeerAddressRanges(ranges, snoops);
AddrRangeList ranges; assert(snoops.size() == 0);
AddrRangeList snoops; for(iter = ranges.begin(); iter != ranges.end(); iter++) {
AddrRangeIter iter; defaultRange.push_back(*iter);
std::vector<DevMap>::iterator portIter; DPRINTF(BusAddrRanges, "Adding range %llx - %llx for default\n",
iter->start, iter->end);
}
} else {
// Clean out any previously existent ids assert((id < interfaces.size() && id >= 0) || id == -1);
for (portIter = portList.begin(); portIter != portList.end(); ) { Port *port = interfaces[id];
if (portIter->portId == id) std::vector<DevMap>::iterator portIter;
portIter = portList.erase(portIter);
else
portIter++;
}
port->getPeerAddressRanges(ranges, snoops); // Clean out any previously existent ids
for (portIter = portList.begin(); portIter != portList.end(); ) {
if (portIter->portId == id)
portIter = portList.erase(portIter);
else
portIter++;
}
// not dealing with snooping yet either port->getPeerAddressRanges(ranges, snoops);
assert(snoops.size() == 0);
for(iter = ranges.begin(); iter != ranges.end(); iter++) {
DevMap dm;
dm.portId = id;
dm.range = *iter;
DPRINTF(BusAddrRanges, "Adding range %llx - %llx for id %d\n", // not dealing with snooping yet either
dm.range.start, dm.range.end, id); assert(snoops.size() == 0);
portList.push_back(dm); for(iter = ranges.begin(); iter != ranges.end(); iter++) {
DevMap dm;
dm.portId = id;
dm.range = *iter;
DPRINTF(BusAddrRanges, "Adding range %llx - %llx for id %d\n",
dm.range.start, dm.range.end, id);
portList.push_back(dm);
}
} }
DPRINTF(MMU, "port list has %d entries\n", portList.size()); DPRINTF(MMU, "port list has %d entries\n", portList.size());
@ -196,19 +230,47 @@ Bus::recvStatusChange(Port::Status status, int id)
for (x = 0; x < interfaces.size(); x++) for (x = 0; x < interfaces.size(); x++)
if (x != id) if (x != id)
interfaces[x]->sendStatusChange(Port::RangeChange); interfaces[x]->sendStatusChange(Port::RangeChange);
if (id != defaultId && defaultPort)
defaultPort->sendStatusChange(Port::RangeChange);
} }
void void
Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id) Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id)
{ {
std::vector<DevMap>::iterator portIter; std::vector<DevMap>::iterator portIter;
AddrRangeIter dflt_iter;
bool subset;
resp.clear(); resp.clear();
snoop.clear(); snoop.clear();
DPRINTF(BusAddrRanges, "received address range request, returning:\n"); DPRINTF(BusAddrRanges, "received address range request, returning:\n");
for (dflt_iter = defaultRange.begin(); dflt_iter != defaultRange.end();
dflt_iter++) {
resp.push_back(*dflt_iter);
DPRINTF(BusAddrRanges, " -- %#llX : %#llX\n",dflt_iter->start,
dflt_iter->end);
}
for (portIter = portList.begin(); portIter != portList.end(); portIter++) { for (portIter = portList.begin(); portIter != portList.end(); portIter++) {
if (portIter->portId != id) { subset = false;
for (dflt_iter = defaultRange.begin(); dflt_iter != defaultRange.end();
dflt_iter++) {
if ((portIter->range.start < dflt_iter->start &&
portIter->range.end >= dflt_iter->start) ||
(portIter->range.start < dflt_iter->end &&
portIter->range.end >= dflt_iter->end))
fatal("Devices can not set ranges that itersect the default set\
but are not a subset of the default set.\n");
if (portIter->range.start >= dflt_iter->start &&
portIter->range.end <= dflt_iter->end) {
subset = true;
DPRINTF(BusAddrRanges, " -- %#llX : %#llX is a SUBSET\n",
portIter->range.start, portIter->range.end);
}
}
if (portIter->portId != id && !subset) {
resp.push_back(portIter->range); resp.push_back(portIter->range);
DPRINTF(BusAddrRanges, " -- %#llX : %#llX\n", DPRINTF(BusAddrRanges, " -- %#llX : %#llX\n",
portIter->range.start, portIter->range.end); portIter->range.start, portIter->range.end);

View file

@ -51,19 +51,22 @@ class Bus : public MemObject
/** a globally unique id for this bus. */ /** a globally unique id for this bus. */
int busId; int busId;
static const int defaultId = -1;
struct DevMap { struct DevMap {
int portId; int portId;
Range<Addr> range; Range<Addr> range;
}; };
std::vector<DevMap> portList; std::vector<DevMap> portList;
AddrRangeList defaultRange;
/** Function called by the port when the bus is recieving a Timing /** Function called by the port when the bus is recieving a Timing
transaction.*/ transaction.*/
bool recvTiming(Packet *pkt); bool recvTiming(Packet *pkt);
/** Function called by the port when the bus is recieving a Atomic /** Function called by the port when the bus is recieving a Atomic
transaction.*/ transaction.*/
Tick recvAtomic(Packet *pkt); Tick recvAtomic(Packet *pkt);
/** Function called by the port when the bus is recieving a Functional /** Function called by the port when the bus is recieving a Functional
@ -159,6 +162,9 @@ class Bus : public MemObject
* original send failed for whatever reason.*/ * original send failed for whatever reason.*/
std::list<Port*> retryList; std::list<Port*> retryList;
/** Port that handles requests that don't match any of the interfaces.*/
Port *defaultPort;
public: public:
/** A function used to return the port associated with this bus object. */ /** A function used to return the port associated with this bus object. */
@ -167,7 +173,7 @@ class Bus : public MemObject
virtual void init(); virtual void init();
Bus(const std::string &n, int bus_id) Bus(const std::string &n, int bus_id)
: MemObject(n), busId(bus_id) {} : MemObject(n), busId(bus_id), defaultPort(NULL) {}
}; };

View file

@ -4,4 +4,5 @@ from MemObject import MemObject
class Bus(MemObject): class Bus(MemObject):
type = 'Bus' type = 'Bus'
port = VectorPort("vector port for connecting devices") port = VectorPort("vector port for connecting devices")
default = Port("Default port for requests that aren't handeled by a device.")
bus_id = Param.Int(0, "blah") bus_id = Param.Int(0, "blah")

View file

@ -1,5 +1,5 @@
from m5.config import * from m5.config import *
from Device import BasicPioDevice, DmaDevice from Device import BasicPioDevice, DmaDevice, PioDevice
class PciConfigData(SimObject): class PciConfigData(SimObject):
type = 'PciConfigData' type = 'PciConfigData'
@ -38,18 +38,22 @@ class PciConfigData(SimObject):
MaximumLatency = Param.UInt8(0x00, "Maximum Latency") MaximumLatency = Param.UInt8(0x00, "Maximum Latency")
MinimumGrant = Param.UInt8(0x00, "Minimum Grant") MinimumGrant = Param.UInt8(0x00, "Minimum Grant")
class PciConfigAll(BasicPioDevice): class PciConfigAll(PioDevice):
type = 'PciConfigAll' type = 'PciConfigAll'
pio_latency = Param.Tick(1, "Programmed IO latency in simticks")
bus = Param.UInt8(0x00, "PCI bus to act as config space for")
size = Param.MemorySize32('16MB', "Size of config space")
class PciDevice(DmaDevice): class PciDevice(DmaDevice):
type = 'PciDevice' type = 'PciDevice'
abstract = True abstract = True
config = Port("PCI configuration space port")
pci_bus = Param.Int("PCI bus") pci_bus = Param.Int("PCI bus")
pci_dev = Param.Int("PCI device number") pci_dev = Param.Int("PCI device number")
pci_func = Param.Int("PCI function code") pci_func = Param.Int("PCI function code")
pio_latency = Param.Tick(1, "Programmed IO latency in simticks") pio_latency = Param.Tick(1, "Programmed IO latency in simticks")
configdata = Param.PciConfigData(Parent.any, "PCI Config data") configdata = Param.PciConfigData(Parent.any, "PCI Config data")
configspace = Param.PciConfigAll(Parent.any, "PCI Configspace")
class PciFake(PciDevice): class PciFake(PciDevice):
type = 'PciFake' type = 'PciFake'