Merge ktlim@zizzer:/bk/newmem
into zamp.eecs.umich.edu:/z/ktlim2/clean/newmem-merge --HG-- extra : convert_revision : 0c4fbbe0826358a6a58f844bec34ce830ffd4ced
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import m5
|
||||
from m5.objects import *
|
||||
import os
|
||||
import os,optparse,sys
|
||||
from SysPaths import *
|
||||
|
||||
parser = optparse.OptionParser(option_list=m5.standardOptions)
|
||||
@@ -98,7 +98,7 @@ class SpecwebFilesetDisk(IdeDisk):
|
||||
class BaseTsunami(Tsunami):
|
||||
cchip = TsunamiCChip(pio_addr=0x801a0000000)
|
||||
pchip = TsunamiPChip(pio_addr=0x80180000000)
|
||||
pciconfig = PciConfigAll(pio_addr=0x801fe000000)
|
||||
pciconfig = PciConfigAll()
|
||||
fake_sm_chip = IsaFake(pio_addr=0x801fc000370)
|
||||
|
||||
fake_uart1 = IsaFake(pio_addr=0x801fc0002f8)
|
||||
@@ -151,16 +151,18 @@ class MyLinuxAlphaSystem(LinuxAlphaSystem):
|
||||
tsunami = LinuxTsunami()
|
||||
tsunami.cchip.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.ethernet.pio = magicbus.port
|
||||
tsunami.ethernet.dma = magicbus.port
|
||||
tsunami.ethernet.config = magicbus.port
|
||||
tsunami.fake_uart1.pio = magicbus.port
|
||||
tsunami.fake_uart2.pio = magicbus.port
|
||||
tsunami.fake_uart3.pio = magicbus.port
|
||||
tsunami.fake_uart4.pio = magicbus.port
|
||||
tsunami.ide.pio = magicbus.port
|
||||
tsunami.ide.dma = magicbus.port
|
||||
tsunami.ide.config = magicbus.port
|
||||
tsunami.fake_ppc.pio = magicbus.port
|
||||
tsunami.fake_OROM.pio = magicbus.port
|
||||
tsunami.fake_pnp_addr.pio = magicbus.port
|
||||
|
||||
@@ -227,177 +227,143 @@ IdeController::setDmaComplete(IdeDisk *disk)
|
||||
// Read and write handling
|
||||
////
|
||||
|
||||
void
|
||||
IdeController::readConfig(int offset, uint8_t *data)
|
||||
Tick
|
||||
IdeController::readConfig(Packet *pkt)
|
||||
{
|
||||
if (offset < PCI_DEVICE_SPECIFIC) {
|
||||
PciDev::readConfig(offset, data);
|
||||
} else if (offset >= IDE_CTRL_CONF_START &&
|
||||
(offset + 1) <= IDE_CTRL_CONF_END) {
|
||||
int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
|
||||
if (offset < PCI_DEVICE_SPECIFIC)
|
||||
return PciDev::readConfig(pkt);
|
||||
assert(offset >= IDE_CTRL_CONF_START && (offset + 1) <= IDE_CTRL_CONF_END);
|
||||
|
||||
pkt->allocate();
|
||||
|
||||
switch (pkt->getSize()) {
|
||||
case sizeof(uint8_t):
|
||||
switch (offset) {
|
||||
case IDE_CTRL_CONF_DEV_TIMING:
|
||||
*data = config_regs.sidetim;
|
||||
pkt->set<uint8_t>(config_regs.sidetim);
|
||||
break;
|
||||
case IDE_CTRL_CONF_UDMA_CNTRL:
|
||||
*data = config_regs.udmactl;
|
||||
pkt->set<uint8_t>(config_regs.udmactl);
|
||||
break;
|
||||
case IDE_CTRL_CONF_PRIM_TIMING+1:
|
||||
*data = htole(config_regs.idetim0) >> 8;
|
||||
pkt->set<uint8_t>(htole(config_regs.idetim0) >> 8);
|
||||
break;
|
||||
case IDE_CTRL_CONF_SEC_TIMING+1:
|
||||
*data = htole(config_regs.idetim1) >> 8;
|
||||
pkt->set<uint8_t>(htole(config_regs.idetim1) >> 8);
|
||||
break;
|
||||
case IDE_CTRL_CONF_IDE_CONFIG:
|
||||
*data = htole(config_regs.ideconfig) & 0xFF;
|
||||
pkt->set<uint8_t>(htole(config_regs.ideconfig) & 0xFF);
|
||||
break;
|
||||
case IDE_CTRL_CONF_IDE_CONFIG+1:
|
||||
*data = htole(config_regs.ideconfig) >> 8;
|
||||
pkt->set<uint8_t>(htole(config_regs.ideconfig) >> 8);
|
||||
break;
|
||||
default:
|
||||
panic("Invalid PCI configuration read for size 1 at offset: %#x!\n",
|
||||
offset);
|
||||
}
|
||||
|
||||
} else {
|
||||
panic("Read of unimplemented PCI config. register: %x\n", offset);
|
||||
}
|
||||
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) {
|
||||
|
||||
DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n", offset,
|
||||
(uint32_t)pkt->get<uint8_t>());
|
||||
break;
|
||||
case sizeof(uint16_t):
|
||||
switch (offset) {
|
||||
case IDE_CTRL_CONF_PRIM_TIMING:
|
||||
*data = config_regs.idetim0;
|
||||
pkt->set<uint16_t>(config_regs.idetim0);
|
||||
break;
|
||||
case IDE_CTRL_CONF_SEC_TIMING:
|
||||
*data = config_regs.idetim1;
|
||||
pkt->set<uint16_t>(config_regs.idetim1);
|
||||
break;
|
||||
case IDE_CTRL_CONF_UDMA_TIMING:
|
||||
*data = config_regs.udmatim;
|
||||
pkt->set<uint16_t>(config_regs.udmatim);
|
||||
break;
|
||||
case IDE_CTRL_CONF_IDE_CONFIG:
|
||||
*data = config_regs.ideconfig;
|
||||
pkt->set<uint16_t>(config_regs.ideconfig);
|
||||
break;
|
||||
default:
|
||||
panic("Invalid PCI configuration read for size 2 offset: %#x!\n",
|
||||
offset);
|
||||
}
|
||||
|
||||
} else {
|
||||
panic("Read of unimplemented PCI config. register: %x\n", offset);
|
||||
DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset,
|
||||
(uint32_t)pkt->get<uint16_t>());
|
||||
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) {
|
||||
case IDE_CTRL_CONF_DEV_TIMING:
|
||||
config_regs.sidetim = data;
|
||||
Tick
|
||||
IdeController::writeConfig(Packet *pkt)
|
||||
{
|
||||
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;
|
||||
case IDE_CTRL_CONF_UDMA_CNTRL:
|
||||
config_regs.udmactl = data;
|
||||
case sizeof(uint16_t):
|
||||
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;
|
||||
case IDE_CTRL_CONF_IDE_CONFIG:
|
||||
config_regs.ideconfig = (config_regs.ideconfig & 0xFF00) | (data);
|
||||
break;
|
||||
case IDE_CTRL_CONF_IDE_CONFIG+1:
|
||||
config_regs.ideconfig = (config_regs.ideconfig & 0x00FF) | data << 8;
|
||||
case sizeof(uint32_t):
|
||||
panic("Write of unimplemented PCI config. register: %x\n", offset);
|
||||
break;
|
||||
default:
|
||||
panic("Invalid PCI configuration write for size 1 offset: %#x!\n",
|
||||
offset);
|
||||
panic("invalid access size(?) for PCI configspace!\n");
|
||||
}
|
||||
|
||||
} 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* Trap command register writes and enable IO/BM as appropriate as well as
|
||||
* BARs. */
|
||||
switch(offset) {
|
||||
case PCI0_BASE_ADDR0:
|
||||
if (BARAddrs[0] != 0)
|
||||
@@ -423,9 +389,24 @@ IdeController::writeConfig(int offset, const uint32_t data)
|
||||
if (BARAddrs[4] != 0)
|
||||
bmi_addr = BARAddrs[4];
|
||||
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
|
||||
IdeController::read(Packet *pkt)
|
||||
{
|
||||
@@ -770,7 +751,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
|
||||
|
||||
SimObjectParam<System *> system;
|
||||
SimObjectParam<Platform *> platform;
|
||||
SimObjectParam<PciConfigAll *> configspace;
|
||||
SimObjectParam<PciConfigData *> configdata;
|
||||
Param<uint32_t> pci_bus;
|
||||
Param<uint32_t> pci_dev;
|
||||
@@ -784,7 +764,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController)
|
||||
|
||||
INIT_PARAM(system, "System pointer"),
|
||||
INIT_PARAM(platform, "Platform pointer"),
|
||||
INIT_PARAM(configspace, "PCI Configspace"),
|
||||
INIT_PARAM(configdata, "PCI Config data"),
|
||||
INIT_PARAM(pci_bus, "PCI bus ID"),
|
||||
INIT_PARAM(pci_dev, "PCI device number"),
|
||||
@@ -800,7 +779,6 @@ CREATE_SIM_OBJECT(IdeController)
|
||||
params->name = getInstanceName();
|
||||
params->platform = platform;
|
||||
params->system = system;
|
||||
params->configSpace = configspace;
|
||||
params->configData = configdata;
|
||||
params->busNum = pci_bus;
|
||||
params->deviceNum = pci_dev;
|
||||
|
||||
@@ -204,12 +204,8 @@ class IdeController : public PciDev
|
||||
IdeController(Params *p);
|
||||
~IdeController();
|
||||
|
||||
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);
|
||||
virtual void readConfig(int offset, uint8_t *data);
|
||||
virtual void readConfig(int offset, uint16_t *data);
|
||||
virtual void readConfig(int offset, uint32_t *data);
|
||||
virtual Tick writeConfig(Packet *pkt);
|
||||
virtual Tick readConfig(Packet *pkt);
|
||||
|
||||
void setDmaComplete(IdeDisk *disk);
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
#include "sim/builder.hh"
|
||||
|
||||
|
||||
PioPort::PioPort(PioDevice *dev, Platform *p)
|
||||
: Port(dev->name() + "-pioport"), device(dev), platform(p)
|
||||
PioPort::PioPort(PioDevice *dev, Platform *p, std::string pname)
|
||||
: Port(dev->name() + pname), device(dev), platform(p)
|
||||
{ }
|
||||
|
||||
|
||||
@@ -79,19 +79,23 @@ PioPort::SendEvent::process()
|
||||
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
|
||||
PioPort::recvTiming(Packet *pkt)
|
||||
{
|
||||
if (pkt->result == Packet::Nacked) {
|
||||
pkt->reinitNacked();
|
||||
if (transmitList.size()) {
|
||||
transmitList.push_front(pkt);
|
||||
} else {
|
||||
if (!Port::sendTiming(pkt))
|
||||
transmitList.push_front(pkt);
|
||||
}
|
||||
resendNacked(pkt);
|
||||
} else {
|
||||
Tick latency = device->recvAtomic(pkt);
|
||||
// turn packet around to go back to requester
|
||||
|
||||
@@ -82,6 +82,8 @@ class PioPort : public Port
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
|
||||
|
||||
void resendNacked(Packet *pkt);
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -113,7 +115,7 @@ class PioPort : public Port
|
||||
virtual void recvRetry();
|
||||
|
||||
public:
|
||||
PioPort(PioDevice *dev, Platform *p);
|
||||
PioPort(PioDevice *dev, Platform *p, std::string pname = "-pioport");
|
||||
|
||||
friend class PioPort::SendEvent;
|
||||
};
|
||||
|
||||
@@ -465,11 +465,12 @@ NSGigE::regStats()
|
||||
/**
|
||||
* This is to write to the PCI general configuration registers
|
||||
*/
|
||||
void
|
||||
NSGigE::writeConfig(int offset, const uint16_t data)
|
||||
Tick
|
||||
NSGigE::writeConfig(Packet *pkt)
|
||||
{
|
||||
int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
|
||||
if (offset < PCI_DEVICE_SPECIFIC)
|
||||
PciDev::writeConfig(offset, data);
|
||||
PciDev::writeConfig(pkt);
|
||||
else
|
||||
panic("Device specific PCI config space not implemented!\n");
|
||||
|
||||
@@ -484,6 +485,8 @@ NSGigE::writeConfig(int offset, const uint16_t data)
|
||||
ioEnable = false;
|
||||
break;
|
||||
}
|
||||
pkt->result = Packet::Success;
|
||||
return configDelay;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -508,14 +511,7 @@ NSGigE::read(Packet *pkt)
|
||||
if (daddr > LAST && daddr <= RESERVED) {
|
||||
panic("Accessing reserved register");
|
||||
} else if (daddr > RESERVED && daddr <= 0x3FC) {
|
||||
if (pkt->getSize() == sizeof(uint8_t))
|
||||
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;
|
||||
return readConfig(pkt);
|
||||
} else if (daddr >= MIB_START && daddr <= MIB_END) {
|
||||
// don't implement all the MIB's. hopefully the kernel
|
||||
// doesn't actually DEPEND upon their values
|
||||
@@ -733,14 +729,7 @@ NSGigE::write(Packet *pkt)
|
||||
if (daddr > LAST && daddr <= RESERVED) {
|
||||
panic("Accessing reserved register");
|
||||
} else if (daddr > RESERVED && daddr <= 0x3FC) {
|
||||
if (pkt->getSize() == sizeof(uint8_t))
|
||||
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;
|
||||
return writeConfig(pkt);
|
||||
} else if (daddr > 0x3FC)
|
||||
panic("Something is messed up!\n");
|
||||
|
||||
@@ -2807,7 +2796,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
|
||||
|
||||
SimObjectParam<System *> system;
|
||||
SimObjectParam<Platform *> platform;
|
||||
SimObjectParam<PciConfigAll *> configspace;
|
||||
SimObjectParam<PciConfigData *> configdata;
|
||||
Param<uint32_t> pci_bus;
|
||||
Param<uint32_t> pci_dev;
|
||||
@@ -2841,7 +2829,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
|
||||
|
||||
INIT_PARAM(system, "System pointer"),
|
||||
INIT_PARAM(platform, "Platform pointer"),
|
||||
INIT_PARAM(configspace, "PCI Configspace"),
|
||||
INIT_PARAM(configdata, "PCI Config data"),
|
||||
INIT_PARAM(pci_bus, "PCI bus ID"),
|
||||
INIT_PARAM(pci_dev, "PCI device number"),
|
||||
@@ -2879,7 +2866,6 @@ CREATE_SIM_OBJECT(NSGigE)
|
||||
params->name = getInstanceName();
|
||||
params->platform = platform;
|
||||
params->system = system;
|
||||
params->configSpace = configspace;
|
||||
params->configData = configdata;
|
||||
params->busNum = pci_bus;
|
||||
params->deviceNum = pci_dev;
|
||||
|
||||
@@ -114,7 +114,6 @@ struct dp_rom {
|
||||
|
||||
class NSGigEInt;
|
||||
class Packet;
|
||||
class PciConfigAll;
|
||||
|
||||
/**
|
||||
* NS DP83820 Ethernet device model
|
||||
@@ -376,7 +375,7 @@ class NSGigE : public PciDev
|
||||
~NSGigE();
|
||||
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 write(Packet *pkt);
|
||||
|
||||
@@ -33,14 +33,8 @@
|
||||
* PCI Configspace implementation
|
||||
*/
|
||||
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "dev/pciconfigall.hh"
|
||||
#include "dev/pcidev.hh"
|
||||
#include "dev/pcireg.h"
|
||||
#include "dev/platform.hh"
|
||||
#include "mem/packet.hh"
|
||||
@@ -50,151 +44,61 @@
|
||||
using namespace std;
|
||||
|
||||
PciConfigAll::PciConfigAll(Params *p)
|
||||
: BasicPioDevice(p)
|
||||
: PioDevice(p)
|
||||
{
|
||||
pioSize = 0xffffff;
|
||||
|
||||
// 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;
|
||||
pioAddr = p->platform->calcConfigAddr(params()->bus,0,0);
|
||||
}
|
||||
|
||||
// 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
|
||||
PciConfigAll::read(Packet *pkt)
|
||||
{
|
||||
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();
|
||||
|
||||
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());
|
||||
|
||||
switch (pkt->getSize()) {
|
||||
case sizeof(uint32_t):
|
||||
if (devices[device][func] == NULL)
|
||||
pkt->set<uint32_t>(0xFFFFFFFF);
|
||||
else
|
||||
devices[device][func]->readConfig(reg, pkt->getPtr<uint32_t>());
|
||||
pkt->set<uint32_t>(0xFFFFFFFF);
|
||||
break;
|
||||
case sizeof(uint16_t):
|
||||
if (devices[device][func] == NULL)
|
||||
pkt->set<uint16_t>(0xFFFF);
|
||||
else
|
||||
devices[device][func]->readConfig(reg, pkt->getPtr<uint16_t>());
|
||||
pkt->set<uint16_t>(0xFFFF);
|
||||
break;
|
||||
case sizeof(uint8_t):
|
||||
if (devices[device][func] == NULL)
|
||||
pkt->set<uint8_t>(0xFF);
|
||||
else
|
||||
devices[device][func]->readConfig(reg, pkt->getPtr<uint8_t>());
|
||||
pkt->set<uint8_t>(0xFF);
|
||||
break;
|
||||
default:
|
||||
panic("invalid access size(?) for PCI configspace!\n");
|
||||
}
|
||||
pkt->result = Packet::Success;
|
||||
return pioDelay;
|
||||
return params()->pio_delay;
|
||||
}
|
||||
|
||||
Tick
|
||||
PciConfigAll::write(Packet *pkt)
|
||||
{
|
||||
assert(pkt->result == Packet::Unknown);
|
||||
assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
|
||||
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;
|
||||
panic("Attempting to write to config space on non-existant device\n");
|
||||
}
|
||||
|
||||
void
|
||||
PciConfigAll::serialize(std::ostream &os)
|
||||
PciConfigAll::addressRanges(AddrRangeList &range_list)
|
||||
{
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
range_list.clear();
|
||||
range_list.push_back(RangeSize(pioAddr, params()->size));
|
||||
}
|
||||
|
||||
void
|
||||
PciConfigAll::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
/*
|
||||
* 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
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll)
|
||||
|
||||
Param<Addr> pio_addr;
|
||||
Param<Tick> pio_latency;
|
||||
Param<int> bus;
|
||||
Param<Addr> size;
|
||||
SimObjectParam<Platform *> platform;
|
||||
SimObjectParam<System *> system;
|
||||
|
||||
@@ -202,8 +106,9 @@ END_DECLARE_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(bus, "Bus that this object handles config space for"),
|
||||
INIT_PARAM(size, "The size of config space"),
|
||||
INIT_PARAM(platform, "platform"),
|
||||
INIT_PARAM(system, "system object")
|
||||
|
||||
@@ -211,11 +116,13 @@ END_INIT_SIM_OBJECT_PARAMS(PciConfigAll)
|
||||
|
||||
CREATE_SIM_OBJECT(PciConfigAll)
|
||||
{
|
||||
BasicPioDevice::Params *p = new BasicPioDevice::Params;
|
||||
p->pio_addr = pio_addr;
|
||||
PciConfigAll::Params *p = new PciConfigAll::Params;
|
||||
p->pio_delay = pio_latency;
|
||||
p->platform = platform;
|
||||
p->system = system;
|
||||
p->bus = bus;
|
||||
p->size = size;
|
||||
|
||||
return new PciConfigAll(p);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,11 +42,6 @@
|
||||
#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
|
||||
* 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
|
||||
* 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:
|
||||
struct Params : public PioDevice::Params
|
||||
{
|
||||
Tick pio_delay;
|
||||
Addr size;
|
||||
int bus;
|
||||
};
|
||||
const Params *params() const { return (const Params *)_params; }
|
||||
|
||||
/**
|
||||
* Constructor for PCIConfigAll
|
||||
* @param p parameters structure
|
||||
*/
|
||||
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
|
||||
* -1 is returned, if the device does exist its PciDev::ReadConfig (or the
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
* panics. If it does it is passed on the PciDev::WriteConfig (or the virtual
|
||||
* function that overrides it).
|
||||
* @param req Contains the address to write to.
|
||||
* @param data The data to write.
|
||||
* @return The fault condition of the access.
|
||||
* @param pkt Contains information about the write operation
|
||||
* @return Amount of time to do the read
|
||||
*/
|
||||
|
||||
virtual Tick write(Packet *pkt);
|
||||
|
||||
/**
|
||||
* 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();
|
||||
void addressRanges(AddrRangeList &range_list);
|
||||
|
||||
/**
|
||||
* Serialize this object to the given output stream.
|
||||
* @param os The stream to serialize to.
|
||||
*/
|
||||
virtual void serialize(std::ostream &os);
|
||||
private:
|
||||
Addr pioAddr;
|
||||
|
||||
/**
|
||||
* 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 §ion);
|
||||
};
|
||||
|
||||
#endif // __PCICONFIGALL_HH__
|
||||
|
||||
@@ -53,9 +53,63 @@
|
||||
|
||||
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)
|
||||
: 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
|
||||
if (configData) {
|
||||
@@ -65,25 +119,56 @@ PciDev::PciDev(Params *p)
|
||||
} else
|
||||
panic("NULL pointer to configuration data");
|
||||
|
||||
// Setup pointer in config space to point to this entry
|
||||
if (p->configSpace->deviceExists(p->deviceNum, p->functionNum))
|
||||
panic("Two PCI devices occuping same dev: %#x func: %#x",
|
||||
p->deviceNum, p->functionNum);
|
||||
else
|
||||
p->configSpace->registerDevice(p->deviceNum, p->functionNum, this);
|
||||
plat->registerPciDevice(0, p->deviceNum, p->functionNum,
|
||||
letoh(configData->config.interruptLine));
|
||||
}
|
||||
|
||||
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)
|
||||
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",
|
||||
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
|
||||
@@ -96,158 +181,128 @@ PciDev::addressRanges(AddrRangeList &range_list)
|
||||
range_list.push_back(RangeSize(BARAddrs[x],BARSize[x]));
|
||||
}
|
||||
|
||||
void
|
||||
PciDev::readConfig(int offset, uint16_t *data)
|
||||
Tick
|
||||
PciDev::writeConfig(Packet *pkt)
|
||||
{
|
||||
int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
|
||||
if (offset >= PCI_DEVICE_SPECIFIC)
|
||||
panic("Device specific PCI config space not implemented!\n");
|
||||
|
||||
*data = *(uint16_t*)&config.data[offset];
|
||||
|
||||
DPRINTF(PCIDEV,
|
||||
"read device: %#x function: %#x register: %#x 2 bytes: data: %#x\n",
|
||||
params()->deviceNum, params()->functionNum, offset, *data);
|
||||
}
|
||||
|
||||
void
|
||||
PciDev::readConfig(int offset, uint32_t *data)
|
||||
{
|
||||
if (offset >= PCI_DEVICE_SPECIFIC)
|
||||
panic("Device specific PCI config space not implemented!\n");
|
||||
|
||||
*data = *(uint32_t*)&config.data[offset];
|
||||
|
||||
DPRINTF(PCIDEV,
|
||||
"read device: %#x function: %#x register: %#x 4 bytes: data: %#x\n",
|
||||
params()->deviceNum, params()->functionNum, offset, *data);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
switch (pkt->getSize()) {
|
||||
case sizeof(uint8_t):
|
||||
switch (offset) {
|
||||
case PCI0_INTERRUPT_LINE:
|
||||
config.interruptLine = pkt->get<uint8_t>();
|
||||
case PCI_CACHE_LINE_SIZE:
|
||||
config.cacheLineSize = pkt->get<uint8_t>();
|
||||
case PCI_LATENCY_TIMER:
|
||||
config.latencyTimer = pkt->get<uint8_t>();
|
||||
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");
|
||||
}
|
||||
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
|
||||
// value of the bar to size of memory it needs
|
||||
if (letoh(data) == 0xffffffff) {
|
||||
// This is I/O Space, bottom two bits are read only
|
||||
uint32_t barnum, bar_mask;
|
||||
Addr base_addr, base_size, space_base;
|
||||
|
||||
config.baseAddr[barnum] = letoh(
|
||||
(~(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));
|
||||
barnum = BAR_NUMBER(offset);
|
||||
|
||||
if (letoh(config.baseAddr[barnum]) & ~bar_mask) {
|
||||
base_addr = (letoh(data) & ~bar_mask) + space_base;
|
||||
base_size = BARSize[barnum];
|
||||
BARAddrs[barnum] = base_addr;
|
||||
|
||||
pioPort->sendStatusChange(Port::RangeChange);
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
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:
|
||||
DPRINTF(PCIDEV, "Writing to a read only register");
|
||||
panic("invalid access size(?) for PCI configspace!\n");
|
||||
}
|
||||
pkt->result = Packet::Success;
|
||||
return configDelay;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -47,8 +47,6 @@
|
||||
#define BAR_IO_SPACE(x) ((x) & BAR_IO_SPACE_BIT)
|
||||
#define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2);
|
||||
|
||||
class PciConfigAll;
|
||||
|
||||
|
||||
/**
|
||||
* This class encapulates the first 64 bytes of a singles PCI
|
||||
@@ -78,24 +76,41 @@ class PciConfigData : public SimObject
|
||||
Addr BARAddrs[6];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
public:
|
||||
struct Params : public ::PioDevice::Params
|
||||
class PciConfigPort : public PioPort
|
||||
{
|
||||
/**
|
||||
* A pointer to the configspace all object that calls us when
|
||||
* a read comes to this particular device/function.
|
||||
*/
|
||||
PciConfigAll *configSpace;
|
||||
protected:
|
||||
PciDev *device;
|
||||
|
||||
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
|
||||
* config space
|
||||
@@ -113,6 +128,9 @@ class PciDev : public DmaDevice
|
||||
|
||||
/** The latency for pio accesses. */
|
||||
Tick pio_delay;
|
||||
|
||||
/** The latency for a config access. */
|
||||
Tick config_delay;
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -164,6 +182,25 @@ class PciDev : public DmaDevice
|
||||
Platform *plat;
|
||||
PciConfigData *configData;
|
||||
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:
|
||||
Addr pciToDma(Addr pciAddr) const
|
||||
@@ -171,21 +208,25 @@ class PciDev : public DmaDevice
|
||||
|
||||
void
|
||||
intrPost()
|
||||
{ plat->postPciInt(configData->config.interruptLine); }
|
||||
{ plat->postPciInt(letoh(configData->config.interruptLine)); }
|
||||
|
||||
void
|
||||
intrClear()
|
||||
{ plat->clearPciInt(configData->config.interruptLine); }
|
||||
{ plat->clearPciInt(letoh(configData->config.interruptLine)); }
|
||||
|
||||
uint8_t
|
||||
interruptLine()
|
||||
{ return configData->config.interruptLine; }
|
||||
{ return letoh(configData->config.interruptLine); }
|
||||
|
||||
/** return the address ranges that this device responds to.
|
||||
* @params range_list range list to populate with ranges
|
||||
*/
|
||||
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
|
||||
* config file object PCIConfigData and registers the device with
|
||||
@@ -193,30 +234,7 @@ class PciDev : public DmaDevice
|
||||
*/
|
||||
PciDev(Params *params);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
virtual void init();
|
||||
|
||||
/**
|
||||
* Serialize this object to the given output stream.
|
||||
@@ -230,5 +248,19 @@ class PciDev : public DmaDevice
|
||||
* @param section The section name of this object
|
||||
*/
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
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__
|
||||
|
||||
@@ -142,6 +142,7 @@ union PCIConfig {
|
||||
|
||||
// Device specific offsets
|
||||
#define PCI_DEVICE_SPECIFIC 0x40 // 192 bytes
|
||||
#define PCI_CONFIG_SIZE 0xFF
|
||||
|
||||
// Some Vendor IDs
|
||||
#define PCI_VENDOR_DEC 0x1011
|
||||
|
||||
@@ -63,5 +63,21 @@ Platform::pciToDma(Addr pciAddr) const
|
||||
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)
|
||||
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
#ifndef __DEV_PLATFORM_HH__
|
||||
#define __DEV_PLATFORM_HH__
|
||||
|
||||
#include <bitset>
|
||||
#include <set>
|
||||
|
||||
#include "sim/sim_object.hh"
|
||||
#include "arch/isa_traits.hh"
|
||||
|
||||
@@ -52,9 +55,6 @@ class Platform : public SimObject
|
||||
/** Pointer to the interrupt controller */
|
||||
IntrControl *intrctrl;
|
||||
|
||||
/** Pointer to the PCI configuration space */
|
||||
PciConfigAll *pciconfig;
|
||||
|
||||
/** Pointer to the UART, set by the uart */
|
||||
Uart *uart;
|
||||
|
||||
@@ -64,13 +64,20 @@ class Platform : public SimObject
|
||||
public:
|
||||
Platform(const std::string &name, IntrControl *intctrl);
|
||||
virtual ~Platform();
|
||||
virtual void init() { if (pciconfig == NULL) panic("PCI Config not set"); }
|
||||
virtual void postConsoleInt() = 0;
|
||||
virtual void clearConsoleInt() = 0;
|
||||
virtual Tick intrFrequency() = 0;
|
||||
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 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__
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
#include "cpu/intr_control.hh"
|
||||
#include "dev/etherlink.hh"
|
||||
#include "dev/sinic.hh"
|
||||
#include "dev/pciconfigall.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "sim/builder.hh"
|
||||
#include "sim/debug.hh"
|
||||
@@ -1623,7 +1622,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
|
||||
|
||||
SimObjectParam<System *> system;
|
||||
SimObjectParam<Platform *> platform;
|
||||
SimObjectParam<PciConfigAll *> configspace;
|
||||
SimObjectParam<PciConfigData *> configdata;
|
||||
Param<uint32_t> pci_bus;
|
||||
Param<uint32_t> pci_dev;
|
||||
@@ -1666,7 +1664,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Device)
|
||||
|
||||
INIT_PARAM(system, "System pointer"),
|
||||
INIT_PARAM(platform, "Platform pointer"),
|
||||
INIT_PARAM(configspace, "PCI Configspace"),
|
||||
INIT_PARAM(configdata, "PCI Config data"),
|
||||
INIT_PARAM(pci_bus, "PCI bus ID"),
|
||||
INIT_PARAM(pci_dev, "PCI device number"),
|
||||
@@ -1711,7 +1708,6 @@ CREATE_SIM_OBJECT(Device)
|
||||
params->name = getInstanceName();
|
||||
params->platform = platform;
|
||||
params->system = system;
|
||||
params->configSpace = configspace;
|
||||
params->configData = configdata;
|
||||
params->busNum = pci_bus;
|
||||
params->deviceNum = pci_dev;
|
||||
|
||||
@@ -95,6 +95,13 @@ Tsunami::pciToDma(Addr pciAddr) const
|
||||
return pchip->translatePciToDma(pciAddr);
|
||||
}
|
||||
|
||||
|
||||
Addr
|
||||
Tsunami::calcConfigAddr(int bus, int dev, int func)
|
||||
{
|
||||
return pchip->calcConfigAddr(bus, dev, func);
|
||||
}
|
||||
|
||||
void
|
||||
Tsunami::serialize(std::ostream &os)
|
||||
{
|
||||
|
||||
@@ -113,8 +113,14 @@ class Tsunami : public Platform
|
||||
*/
|
||||
virtual void clearPciInt(int line);
|
||||
|
||||
|
||||
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.
|
||||
* @param os The stream to serialize to.
|
||||
|
||||
@@ -302,6 +302,17 @@ 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)
|
||||
{
|
||||
assert(func < 8);
|
||||
assert(dev < 32);
|
||||
assert(bus == 0);
|
||||
|
||||
return TsunamiPciBus0Config | (func << 8) | (dev << 11);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
TsunamiPChip::serialize(std::ostream &os)
|
||||
|
||||
@@ -45,6 +45,9 @@
|
||||
class TsunamiPChip : public BasicPioDevice
|
||||
{
|
||||
protected:
|
||||
|
||||
static const Addr TsunamiPciBus0Config = 0x801fe000000;
|
||||
|
||||
/** Pchip control register */
|
||||
uint64_t pctl;
|
||||
|
||||
@@ -80,6 +83,8 @@ class TsunamiPChip : public BasicPioDevice
|
||||
*/
|
||||
Addr translatePciToDma(Addr busAddr);
|
||||
|
||||
Addr calcConfigAddr(int bus, int dev, int func);
|
||||
|
||||
virtual Tick read(Packet *pkt);
|
||||
virtual Tick write(Packet *pkt);
|
||||
|
||||
|
||||
116
src/mem/bus.cc
116
src/mem/bus.cc
@@ -33,6 +33,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "base/misc.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "mem/bus.hh"
|
||||
#include "sim/builder.hh"
|
||||
@@ -40,6 +41,14 @@
|
||||
Port *
|
||||
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?
|
||||
int id = interfaces.size();
|
||||
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;
|
||||
}
|
||||
|
||||
/** Get the ranges of anyone that we are connected to. */
|
||||
/** Get the ranges of anyone other buses that we are connected to. */
|
||||
void
|
||||
Bus::init()
|
||||
{
|
||||
std::vector<Port*>::iterator intIter;
|
||||
|
||||
for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
|
||||
(*intIter)->sendStatusChange(Port::RangeChange);
|
||||
}
|
||||
@@ -110,6 +120,7 @@ Bus::findPort(Addr addr, int id)
|
||||
int dest_id = -1;
|
||||
int i = 0;
|
||||
bool found = false;
|
||||
AddrRangeIter iter;
|
||||
|
||||
while (i < portList.size() && !found)
|
||||
{
|
||||
@@ -120,8 +131,18 @@ Bus::findPort(Addr addr, int id)
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
// we shouldn't be sending this back to where it came from
|
||||
assert(dest_id != id);
|
||||
@@ -155,39 +176,52 @@ Bus::recvFunctional(Packet *pkt)
|
||||
void
|
||||
Bus::recvStatusChange(Port::Status status, int id)
|
||||
{
|
||||
AddrRangeList ranges;
|
||||
AddrRangeList snoops;
|
||||
int x;
|
||||
AddrRangeIter iter;
|
||||
|
||||
assert(status == Port::RangeChange &&
|
||||
"The other statuses need to be implemented.");
|
||||
|
||||
DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id);
|
||||
|
||||
assert(id < interfaces.size() && id >= 0);
|
||||
int x;
|
||||
Port *port = interfaces[id];
|
||||
AddrRangeList ranges;
|
||||
AddrRangeList snoops;
|
||||
AddrRangeIter iter;
|
||||
std::vector<DevMap>::iterator portIter;
|
||||
if (id == defaultId) {
|
||||
defaultRange.clear();
|
||||
defaultPort->getPeerAddressRanges(ranges, snoops);
|
||||
assert(snoops.size() == 0);
|
||||
for(iter = ranges.begin(); iter != ranges.end(); iter++) {
|
||||
defaultRange.push_back(*iter);
|
||||
DPRINTF(BusAddrRanges, "Adding range %llx - %llx for default\n",
|
||||
iter->start, iter->end);
|
||||
}
|
||||
} else {
|
||||
|
||||
// Clean out any previously existent ids
|
||||
for (portIter = portList.begin(); portIter != portList.end(); ) {
|
||||
if (portIter->portId == id)
|
||||
portIter = portList.erase(portIter);
|
||||
else
|
||||
portIter++;
|
||||
}
|
||||
assert((id < interfaces.size() && id >= 0) || id == -1);
|
||||
Port *port = interfaces[id];
|
||||
std::vector<DevMap>::iterator 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
|
||||
assert(snoops.size() == 0);
|
||||
for(iter = ranges.begin(); iter != ranges.end(); iter++) {
|
||||
DevMap dm;
|
||||
dm.portId = id;
|
||||
dm.range = *iter;
|
||||
port->getPeerAddressRanges(ranges, snoops);
|
||||
|
||||
DPRINTF(BusAddrRanges, "Adding range %llx - %llx for id %d\n",
|
||||
dm.range.start, dm.range.end, id);
|
||||
portList.push_back(dm);
|
||||
// not dealing with snooping yet either
|
||||
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",
|
||||
dm.range.start, dm.range.end, id);
|
||||
portList.push_back(dm);
|
||||
}
|
||||
}
|
||||
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++)
|
||||
if (x != id)
|
||||
interfaces[x]->sendStatusChange(Port::RangeChange);
|
||||
|
||||
if (id != defaultId && defaultPort)
|
||||
defaultPort->sendStatusChange(Port::RangeChange);
|
||||
}
|
||||
|
||||
void
|
||||
Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id)
|
||||
{
|
||||
std::vector<DevMap>::iterator portIter;
|
||||
AddrRangeIter dflt_iter;
|
||||
bool subset;
|
||||
|
||||
resp.clear();
|
||||
snoop.clear();
|
||||
|
||||
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++) {
|
||||
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);
|
||||
DPRINTF(BusAddrRanges, " -- %#llX : %#llX\n",
|
||||
portIter->range.start, portIter->range.end);
|
||||
|
||||
@@ -51,19 +51,22 @@ class Bus : public MemObject
|
||||
/** a globally unique id for this bus. */
|
||||
int busId;
|
||||
|
||||
static const int defaultId = -1;
|
||||
|
||||
struct DevMap {
|
||||
int portId;
|
||||
Range<Addr> range;
|
||||
};
|
||||
std::vector<DevMap> portList;
|
||||
AddrRangeList defaultRange;
|
||||
|
||||
|
||||
/** Function called by the port when the bus is recieving a Timing
|
||||
transaction.*/
|
||||
transaction.*/
|
||||
bool recvTiming(Packet *pkt);
|
||||
|
||||
/** Function called by the port when the bus is recieving a Atomic
|
||||
transaction.*/
|
||||
transaction.*/
|
||||
Tick recvAtomic(Packet *pkt);
|
||||
|
||||
/** 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.*/
|
||||
std::list<Port*> retryList;
|
||||
|
||||
/** Port that handles requests that don't match any of the interfaces.*/
|
||||
Port *defaultPort;
|
||||
|
||||
public:
|
||||
|
||||
/** A function used to return the port associated with this bus object. */
|
||||
@@ -167,7 +173,7 @@ class Bus : public MemObject
|
||||
virtual void init();
|
||||
|
||||
Bus(const std::string &n, int bus_id)
|
||||
: MemObject(n), busId(bus_id) {}
|
||||
: MemObject(n), busId(bus_id), defaultPort(NULL) {}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -4,4 +4,5 @@ from MemObject import MemObject
|
||||
class Bus(MemObject):
|
||||
type = 'Bus'
|
||||
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")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from m5.config import *
|
||||
from Device import BasicPioDevice, DmaDevice
|
||||
from Device import BasicPioDevice, DmaDevice, PioDevice
|
||||
|
||||
class PciConfigData(SimObject):
|
||||
type = 'PciConfigData'
|
||||
@@ -38,18 +38,22 @@ class PciConfigData(SimObject):
|
||||
MaximumLatency = Param.UInt8(0x00, "Maximum Latency")
|
||||
MinimumGrant = Param.UInt8(0x00, "Minimum Grant")
|
||||
|
||||
class PciConfigAll(BasicPioDevice):
|
||||
class PciConfigAll(PioDevice):
|
||||
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):
|
||||
type = 'PciDevice'
|
||||
abstract = True
|
||||
config = Port("PCI configuration space port")
|
||||
pci_bus = Param.Int("PCI bus")
|
||||
pci_dev = Param.Int("PCI device number")
|
||||
pci_func = Param.Int("PCI function code")
|
||||
pio_latency = Param.Tick(1, "Programmed IO latency in simticks")
|
||||
configdata = Param.PciConfigData(Parent.any, "PCI Config data")
|
||||
configspace = Param.PciConfigAll(Parent.any, "PCI Configspace")
|
||||
|
||||
class PciFake(PciDevice):
|
||||
type = 'PciFake'
|
||||
|
||||
Reference in New Issue
Block a user