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:
Kevin Lim
2006-07-06 14:54:09 -04:00
23 changed files with 615 additions and 568 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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;

View File

@@ -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);

View File

@@ -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 &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
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);
}

View File

@@ -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 &section);
};
#endif // __PCICONFIGALL_HH__

View File

@@ -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

View File

@@ -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 &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__

View File

@@ -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

View File

@@ -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)

View File

@@ -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__

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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.

View File

@@ -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)

View File

@@ -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);

View File

@@ -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);

View File

@@ -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) {}
};

View File

@@ -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")

View File

@@ -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'