summaryrefslogtreecommitdiff
path: root/dev
diff options
context:
space:
mode:
Diffstat (limited to 'dev')
-rw-r--r--dev/alpha_console.cc8
-rw-r--r--dev/baddev.cc4
-rw-r--r--dev/etherdump.cc39
-rw-r--r--dev/etherdump.hh6
-rw-r--r--dev/etherint.hh16
-rw-r--r--dev/etherlink.cc28
-rw-r--r--dev/etherlink.hh6
-rw-r--r--dev/etherpkt.cc16
-rw-r--r--dev/etherpkt.hh62
-rw-r--r--dev/ethertap.cc5
-rw-r--r--dev/ethertap.hh4
-rw-r--r--dev/ide_ctrl.cc123
-rw-r--r--dev/ide_ctrl.hh50
-rw-r--r--dev/ide_disk.cc18
-rw-r--r--dev/io_device.hh2
-rw-r--r--dev/ns_gige.cc827
-rw-r--r--dev/ns_gige.hh111
-rw-r--r--dev/pciconfigall.cc37
-rw-r--r--dev/pciconfigall.hh7
-rw-r--r--dev/pcidev.cc101
-rw-r--r--dev/pcidev.hh95
-rw-r--r--dev/pktfifo.cc70
-rw-r--r--dev/pktfifo.hh107
-rw-r--r--dev/platform.cc18
-rw-r--r--dev/platform.hh4
-rw-r--r--dev/simconsole.cc36
-rw-r--r--dev/simconsole.hh2
-rw-r--r--dev/sinic.cc1433
-rw-r--r--dev/sinic.hh340
-rw-r--r--dev/sinicreg.hh187
-rw-r--r--dev/tsunami.cc18
-rw-r--r--dev/tsunami.hh19
-rw-r--r--dev/tsunami_cchip.cc292
-rw-r--r--dev/tsunami_cchip.hh36
-rw-r--r--dev/tsunami_io.cc8
-rw-r--r--dev/tsunami_pchip.cc8
-rw-r--r--dev/tsunamireg.h7
-rw-r--r--dev/uart.cc11
38 files changed, 3272 insertions, 889 deletions
diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc
index 680704b30..7deabe2fc 100644
--- a/dev/alpha_console.cc
+++ b/dev/alpha_console.cc
@@ -61,12 +61,12 @@ AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d,
HierParams *hier, Bus *bus)
: PioDevice(name), disk(d), console(cons), addr(a)
{
- mmu->add_child(this, Range<Addr>(addr, addr + size));
+ mmu->add_child(this, RangeSize(addr, size));
if (bus) {
pioInterface = newPioInterface(name, hier, bus, this,
&AlphaConsole::cacheAccess);
- pioInterface->addAddrRange(addr, addr + size);
+ pioInterface->addAddrRange(RangeSize(addr, size));
}
alphaAccess = new AlphaAccess;
@@ -98,7 +98,7 @@ AlphaConsole::read(MemReqPtr &req, uint8_t *data)
{
memset(data, 0, req->size);
- Addr daddr = req->paddr - (addr & PA_IMPL_MASK);
+ Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
switch (req->size)
{
@@ -198,7 +198,7 @@ AlphaConsole::write(MemReqPtr &req, const uint8_t *data)
return Machine_Check_Fault;
}
- Addr daddr = req->paddr - (addr & PA_IMPL_MASK);
+ Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
ExecContext *other_xc;
switch (daddr) {
diff --git a/dev/baddev.cc b/dev/baddev.cc
index 7c563e80a..73b082d47 100644
--- a/dev/baddev.cc
+++ b/dev/baddev.cc
@@ -50,12 +50,12 @@ BadDevice::BadDevice(const string &name, Addr a, MemoryController *mmu,
HierParams *hier, Bus *bus, const string &devicename)
: PioDevice(name), addr(a), devname(devicename)
{
- mmu->add_child(this, Range<Addr>(addr, addr + size));
+ mmu->add_child(this, RangeSize(addr, size));
if (bus) {
pioInterface = newPioInterface(name, hier, bus, this,
&BadDevice::cacheAccess);
- pioInterface->addAddrRange(addr, addr + size - 1);
+ pioInterface->addAddrRange(RangeSize(addr, size));
}
}
diff --git a/dev/etherdump.cc b/dev/etherdump.cc
index 27817d456..485d5599c 100644
--- a/dev/etherdump.cc
+++ b/dev/etherdump.cc
@@ -42,11 +42,9 @@
using std::string;
-EtherDump::EtherDump(const string &name, const string &file, int max)
- : SimObject(name), maxlen(max)
+EtherDump::EtherDump(const string &name, std::ostream *_stream, int max)
+ : SimObject(name), stream(_stream), maxlen(max)
{
- if (!file.empty())
- stream.open(file.c_str());
}
#define DLT_EN10MB 1 // Ethernet (10Mb)
@@ -74,9 +72,6 @@ struct pcap_pkthdr {
void
EtherDump::init()
{
- if (!stream.is_open())
- return;
-
curtime = time(NULL);
s_freq = ticksPerSecond;
us_freq = ticksPerSecond / ULL(1000000);
@@ -91,7 +86,7 @@ EtherDump::init()
hdr.sigfigs = 0;
hdr.linktype = DLT_EN10MB;
- stream.write(reinterpret_cast<char *>(&hdr), sizeof(hdr));
+ stream->write(reinterpret_cast<char *>(&hdr), sizeof(hdr));
/*
* output an empty packet with the current time so that we know
@@ -103,9 +98,9 @@ EtherDump::init()
pkthdr.microseconds = 0;
pkthdr.caplen = 0;
pkthdr.len = 0;
- stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
+ stream->write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
- stream.flush();
+ stream->flush();
}
void
@@ -116,9 +111,9 @@ EtherDump::dumpPacket(PacketPtr &packet)
pkthdr.microseconds = (curTick / us_freq) % ULL(1000000);
pkthdr.caplen = std::min(packet->length, maxlen);
pkthdr.len = packet->length;
- stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
- stream.write(reinterpret_cast<char *>(packet->data), pkthdr.caplen);
- stream.flush();
+ stream->write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
+ stream->write(reinterpret_cast<char *>(packet->data), pkthdr.caplen);
+ stream->flush();
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDump)
@@ -130,28 +125,14 @@ END_DECLARE_SIM_OBJECT_PARAMS(EtherDump)
BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDump)
- INIT_PARAM(file, "file to dump packets to"),
+ INIT_PARAM_DFLT(file, "file to dump packets to", "etherdump"),
INIT_PARAM_DFLT(maxlen, "max portion of packet data to dump", 96)
END_INIT_SIM_OBJECT_PARAMS(EtherDump)
CREATE_SIM_OBJECT(EtherDump)
{
- string filename;
- if (file.isValid()) {
- filename = file;
-
- if (filename[0] != '/' && !outputDirectory.empty())
- filename = outputDirectory + filename;
- } else {
- if (outputDirectory.empty()) {
- filename = "etherdump";
- } else {
- filename = outputDirectory + "etherdump";
- }
- }
-
- return new EtherDump(getInstanceName(), filename, maxlen);
+ return new EtherDump(getInstanceName(), makeOutputStream(file), maxlen);
}
REGISTER_SIM_OBJECT("EtherDump", EtherDump)
diff --git a/dev/etherdump.hh b/dev/etherdump.hh
index 62364359e..b127d05e2 100644
--- a/dev/etherdump.hh
+++ b/dev/etherdump.hh
@@ -43,7 +43,7 @@
class EtherDump : public SimObject
{
private:
- std::ofstream stream;
+ std::ostream *stream;
const int maxlen;
void dumpPacket(PacketPtr &packet);
void init();
@@ -53,9 +53,9 @@ class EtherDump : public SimObject
Tick us_freq;
public:
- EtherDump(const std::string &name, const std::string &file, int max);
+ EtherDump(const std::string &name, std::ostream *_stream, int max);
- inline void dump(PacketPtr &pkt) { if (stream.is_open()) dumpPacket(pkt); }
+ inline void dump(PacketPtr &pkt) { dumpPacket(pkt); }
};
#endif // __ETHERDUMP_H__
diff --git a/dev/etherint.hh b/dev/etherint.hh
index ddfe16d88..bcdf0ae06 100644
--- a/dev/etherint.hh
+++ b/dev/etherint.hh
@@ -31,8 +31,8 @@
* components.
*/
-#ifndef __ETHERINT_HH__
-#define __ETHERINT_HH__
+#ifndef __DEV_ETHERINT_HH__
+#define __DEV_ETHERINT_HH__
#include <string>
@@ -54,13 +54,13 @@ class EtherInt : public SimObject
virtual ~EtherInt() {}
void setPeer(EtherInt *p);
- virtual bool recvPacket(PacketPtr &packet) = 0;
+
void recvDone() { peer->sendDone(); }
- bool sendPacket(PacketPtr &packet)
- {
- return peer ? peer->recvPacket(packet) : true;
- }
virtual void sendDone() = 0;
+
+ bool sendPacket(PacketPtr packet)
+ { return peer ? peer->recvPacket(packet) : true; }
+ virtual bool recvPacket(PacketPtr packet) = 0;
};
-#endif // __ETHERINT_HH__
+#endif // __DEV_ETHERINT_HH__
diff --git a/dev/etherlink.cc b/dev/etherlink.cc
index 3cc4f75ea..d637e152a 100644
--- a/dev/etherlink.cc
+++ b/dev/etherlink.cc
@@ -41,8 +41,9 @@
#include "dev/etherlink.hh"
#include "dev/etherpkt.hh"
#include "sim/builder.hh"
-#include "sim/universe.hh"
+#include "sim/serialize.hh"
#include "sim/system.hh"
+#include "sim/universe.hh"
using namespace std;
@@ -104,7 +105,7 @@ EtherLink::unserialize(Checkpoint *cp, const string &section)
}
void
-EtherLink::Link::txComplete(PacketPtr &packet)
+EtherLink::Link::txComplete(PacketPtr packet)
{
DPRINTF(Ethernet, "packet received: len=%d\n", packet->length);
DDUMP(EthernetData, packet->data, packet->length);
@@ -121,7 +122,7 @@ class LinkDelayEvent : public Event
LinkDelayEvent(EtherLink::Link *link);
public:
- LinkDelayEvent(EtherLink::Link *link, PacketPtr &pkt, Tick when);
+ LinkDelayEvent(EtherLink::Link *link, PacketPtr pkt, Tick when);
void process();
@@ -152,7 +153,7 @@ EtherLink::Link::txDone()
}
bool
-EtherLink::Link::transmit(PacketPtr &pkt)
+EtherLink::Link::transmit(PacketPtr pkt)
{
if (busy()) {
DPRINTF(Ethernet, "packet not sent, link busy\n");
@@ -184,10 +185,8 @@ EtherLink::Link::serialize(ostream &os)
SERIALIZE_SCALAR(event_time);
}
- if (packet_exists) {
- nameOut(os, csprintf("%s.packet", name()));
- packet->serialize(os);
- }
+ if (packet_exists)
+ packet->serialize("packet", os);
}
void
@@ -196,8 +195,8 @@ EtherLink::Link::unserialize(Checkpoint *cp, const string &section)
bool packet_exists;
UNSERIALIZE_SCALAR(packet_exists);
if (packet_exists) {
- packet = new EtherPacket;
- packet->unserialize(cp, csprintf("%s.packet", section));
+ packet = new PacketData(16384);
+ packet->unserialize("packet", cp, section);
}
bool event_scheduled;
@@ -216,7 +215,7 @@ LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l)
setFlags(AutoDelete);
}
-LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr &p, Tick when)
+LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr p, Tick when)
: Event(&mainEventQueue), link(l), packet(p)
{
setFlags(AutoSerialize);
@@ -237,8 +236,7 @@ LinkDelayEvent::serialize(ostream &os)
Event::serialize(os);
SERIALIZE_OBJPTR(link);
- nameOut(os, csprintf("%s.packet", name()));
- packet->serialize(os);
+ packet->serialize("packet", os);
}
@@ -246,8 +244,8 @@ void
LinkDelayEvent::unserialize(Checkpoint *cp, const string &section)
{
Event::unserialize(cp, section);
- packet = new EtherPacket;
- packet->unserialize(cp, csprintf("%s.packet", section));
+ packet = new PacketData(16384);
+ packet->unserialize("packet", cp, section);
}
diff --git a/dev/etherlink.hh b/dev/etherlink.hh
index 204348c6d..e998a006f 100644
--- a/dev/etherlink.hh
+++ b/dev/etherlink.hh
@@ -75,7 +75,7 @@ class EtherLink : public SimObject
DoneEvent doneEvent;
friend class LinkDelayEvent;
- void txComplete(PacketPtr &packet);
+ void txComplete(PacketPtr packet);
public:
Link(const std::string &name, double rate, Tick delay,
@@ -85,7 +85,7 @@ class EtherLink : public SimObject
virtual const std::string name() const { return objName; }
bool busy() const { return (bool)packet; }
- bool transmit(PacketPtr &packet);
+ bool transmit(PacketPtr packet);
void setTxInt(Interface *i) { assert(!txint); txint = i; }
void setRxInt(Interface *i) { assert(!rxint); rxint = i; }
@@ -104,7 +104,7 @@ class EtherLink : public SimObject
public:
Interface(const std::string &name, Link *txlink, Link *rxlink);
- bool recvPacket(PacketPtr &packet) { return txlink->transmit(packet); }
+ bool recvPacket(PacketPtr packet) { return txlink->transmit(packet); }
void sendDone() { peer->sendDone(); }
};
diff --git a/dev/etherpkt.cc b/dev/etherpkt.cc
index 9eda89e9d..bf60bc150 100644
--- a/dev/etherpkt.cc
+++ b/dev/etherpkt.cc
@@ -28,23 +28,23 @@
#include <iostream>
+#include "base/misc.hh"
#include "dev/etherpkt.hh"
#include "sim/serialize.hh"
using namespace std;
void
-EtherPacket::serialize(ostream &os)
+PacketData::serialize(const string &base, ostream &os)
{
- SERIALIZE_SCALAR(length);
- SERIALIZE_ARRAY(data, length);
+ paramOut(os, base + ".length", length);
+ arrayParamOut(os, base + ".data", data, length);
}
void
-EtherPacket::unserialize(Checkpoint *cp, const string &section)
+PacketData::unserialize(const string &base, Checkpoint *cp,
+ const string &section)
{
- UNSERIALIZE_SCALAR(length);
- data = new uint8_t[length];
- UNSERIALIZE_ARRAY(data, length);
+ paramIn(cp, section, base + ".length", length);
+ arrayParamIn(cp, section, base + ".data", data, length);
}
-
diff --git a/dev/etherpkt.hh b/dev/etherpkt.hh
index abdf30166..7a7809f0a 100644
--- a/dev/etherpkt.hh
+++ b/dev/etherpkt.hh
@@ -37,70 +37,32 @@
#include <memory>
#include <assert.h>
-#include "sim/host.hh"
#include "base/refcnt.hh"
-#include "base/inet_hdrs.hh"
+#include "sim/host.hh"
-class Checkpoint;
/*
* Reference counted class containing ethernet packet data
*/
-class EtherPacket : public RefCounted
+class Checkpoint;
+class PacketData : public RefCounted
{
public:
uint8_t *data;
int length;
public:
- EtherPacket() : data(NULL), length(0) {}
- EtherPacket(std::auto_ptr<uint8_t> d, int l)
- : data(d.release()), length(l) {}
- ~EtherPacket() { if (data) delete [] data; }
+ PacketData() : data(NULL), length(0) { }
+ explicit PacketData(size_t size) : data(new uint8_t[size]), length(0) { }
+ PacketData(std::auto_ptr<uint8_t> d, int l)
+ : data(d.release()), length(l) { }
+ ~PacketData() { if (data) delete [] data; }
public:
- bool IsUnicast() { return data[0] == 0x00; }
- bool IsMulticast() { return data[0] == 0x01; }
- bool IsBroadcast() { return data[0] == 0xff; }
-
- bool isIpPkt() {
- eth_header *eth = (eth_header *) data;
- return (eth->type == 0x8);
- }
- bool isTcpPkt(ip_header *ip) {
- return (ip->protocol == 0x6);
- }
- bool isTcpPkt() {
- ip_header *ip = getIpHdr();
- return (ip->protocol == 0x6);
- }
- bool isUdpPkt(ip_header *ip) {
- return (ip->protocol == 17);
- }
- bool isUdpPkt() {
- ip_header *ip = getIpHdr();
- return (ip->protocol == 17);
- }
-
- ip_header *getIpHdr() {
- assert(isIpPkt());
- return (ip_header *) (data + sizeof(eth_header));
- }
-
- tcp_header *getTcpHdr(ip_header *ip) {
- assert(isTcpPkt(ip));
- return (tcp_header *) ((uint8_t *) ip + (ip->vers_len & 0xf)*4);
- }
-
- udp_header *getUdpHdr(ip_header *ip) {
- assert(isUdpPkt(ip));
- return (udp_header *) ((uint8_t *) ip + (ip->vers_len & 0xf)*4);
- }
- typedef RefCountingPtr<EtherPacket> PacketPtr;
-
- void serialize(std::ostream &os);
- void unserialize(Checkpoint *cp, const std::string &section);
+ void serialize(const std::string &base, std::ostream &os);
+ void unserialize(const std::string &base, Checkpoint *cp,
+ const std::string &section);
};
-typedef RefCountingPtr<EtherPacket> PacketPtr;
+typedef RefCountingPtr<PacketData> PacketPtr;
#endif // __ETHERPKT_HH__
diff --git a/dev/ethertap.cc b/dev/ethertap.cc
index edc400760..1603a9bd3 100644
--- a/dev/ethertap.cc
+++ b/dev/ethertap.cc
@@ -169,7 +169,7 @@ EtherTap::detach()
}
bool
-EtherTap::recvPacket(PacketPtr &packet)
+EtherTap::recvPacket(PacketPtr packet)
{
if (dump)
dump->dump(packet);
@@ -219,8 +219,7 @@ EtherTap::process(int revent)
while (data_len != 0 && buffer_offset >= data_len + sizeof(u_int32_t)) {
PacketPtr packet;
- packet = new EtherPacket;
- packet->data = new uint8_t[data_len];
+ packet = new PacketData(data_len);
packet->length = data_len;
memcpy(packet->data, data, data_len);
diff --git a/dev/ethertap.hh b/dev/ethertap.hh
index 1fe368085..5f760ed34 100644
--- a/dev/ethertap.hh
+++ b/dev/ethertap.hh
@@ -70,7 +70,7 @@ class EtherTap : public EtherInt
std::queue<PacketPtr> packetBuffer;
void process(int revent);
- void enqueue(EtherPacket *packet);
+ void enqueue(PacketData *packet);
void retransmit();
/*
@@ -94,7 +94,7 @@ class EtherTap : public EtherInt
EtherTap(const std::string &name, EtherDump *dump, int port, int bufsz);
virtual ~EtherTap();
- virtual bool recvPacket(PacketPtr &packet);
+ virtual bool recvPacket(PacketPtr packet);
virtual void sendDone();
virtual void serialize(std::ostream &os);
diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc
index e40248461..109908ead 100644
--- a/dev/ide_ctrl.cc
+++ b/dev/ide_ctrl.cc
@@ -34,16 +34,15 @@
#include "base/trace.hh"
#include "cpu/intr_control.hh"
#include "dev/dma.hh"
-#include "dev/pcireg.h"
-#include "dev/pciconfigall.hh"
-#include "dev/ide_disk.hh"
#include "dev/ide_ctrl.hh"
-#include "dev/tsunami_cchip.hh"
+#include "dev/ide_disk.hh"
+#include "dev/pciconfigall.hh"
+#include "dev/pcireg.h"
+#include "dev/platform.hh"
#include "mem/bus/bus.hh"
+#include "mem/bus/dma_interface.hh"
#include "mem/bus/pio_interface.hh"
#include "mem/bus/pio_interface_impl.hh"
-#include "mem/bus/dma_interface.hh"
-#include "dev/tsunami.hh"
#include "mem/functional_mem/memory_control.hh"
#include "mem/functional_mem/physical_memory.hh"
#include "sim/builder.hh"
@@ -55,17 +54,9 @@ using namespace std;
// Initialization and destruction
////
-IdeController::IdeController(const string &name, IntrControl *ic,
- const vector<IdeDisk *> &new_disks,
- MemoryController *mmu, PciConfigAll *cf,
- PciConfigData *cd, Tsunami *t, uint32_t bus_num,
- uint32_t dev_num, uint32_t func_num,
- Bus *host_bus, Tick pio_latency, HierParams *hier)
- : PciDev(name, mmu, cf, cd, bus_num, dev_num, func_num), tsunami(t)
+IdeController::IdeController(Params *p)
+ : PciDev(p)
{
- // put back pointer into Tsunami
- tsunami->disk_controller = this;
-
// initialize the PIO interface addresses
pri_cmd_addr = 0;
pri_cmd_size = BARSize[0];
@@ -99,23 +90,25 @@ IdeController::IdeController(const string &name, IntrControl *ic,
memset(cmd_in_progress, 0, sizeof(cmd_in_progress));
// create the PIO and DMA interfaces
- if (host_bus) {
- pioInterface = newPioInterface(name, hier, host_bus, this,
+ if (params()->host_bus) {
+ pioInterface = newPioInterface(name(), params()->hier,
+ params()->host_bus, this,
&IdeController::cacheAccess);
- dmaInterface = new DMAInterface<Bus>(name + ".dma", host_bus,
- host_bus, 1);
- pioLatency = pio_latency * host_bus->clockRatio;
+ dmaInterface = new DMAInterface<Bus>(name() + ".dma",
+ params()->host_bus,
+ params()->host_bus, 1);
+ pioLatency = params()->pio_latency * params()->host_bus->clockRatio;
}
// setup the disks attached to controller
memset(disks, 0, sizeof(IdeDisk *) * 4);
- if (new_disks.size() > 3)
+ if (params()->disks.size() > 3)
panic("IDE controllers support a maximum of 4 devices attached!\n");
- for (int i = 0; i < new_disks.size(); i++) {
- disks[i] = new_disks[i];
+ for (int i = 0; i < params()->disks.size(); i++) {
+ disks[i] = params()->disks[i];
disks[i]->setController(this, dmaInterface);
}
}
@@ -239,22 +232,6 @@ IdeController::setDmaComplete(IdeDisk *disk)
}
////
-// Interrupt handling
-////
-
-void
-IdeController::intrPost()
-{
- tsunami->cchip->postDRIR(configData->config.hdr.pci0.interruptLine);
-}
-
-void
-IdeController::intrClear()
-{
- tsunami->cchip->clearDRIR(configData->config.hdr.pci0.interruptLine);
-}
-
-////
// Bus timing and bus access functions
////
@@ -377,10 +354,10 @@ IdeController::WriteConfig(int offset, int size, uint32_t data)
if (BARAddrs[0] != 0) {
pri_cmd_addr = BARAddrs[0];
if (pioInterface)
- pioInterface->addAddrRange(pri_cmd_addr,
- pri_cmd_addr + pri_cmd_size - 1);
+ pioInterface->addAddrRange(RangeSize(pri_cmd_addr,
+ pri_cmd_size));
- pri_cmd_addr &= PA_UNCACHED_MASK;
+ pri_cmd_addr &= EV5::PAddrUncachedMask;
}
break;
@@ -388,10 +365,10 @@ IdeController::WriteConfig(int offset, int size, uint32_t data)
if (BARAddrs[1] != 0) {
pri_ctrl_addr = BARAddrs[1];
if (pioInterface)
- pioInterface->addAddrRange(pri_ctrl_addr,
- pri_ctrl_addr + pri_ctrl_size - 1);
+ pioInterface->addAddrRange(RangeSize(pri_ctrl_addr,
+ pri_ctrl_size));
- pri_ctrl_addr &= PA_UNCACHED_MASK;
+ pri_ctrl_addr &= EV5::PAddrUncachedMask;
}
break;
@@ -399,10 +376,10 @@ IdeController::WriteConfig(int offset, int size, uint32_t data)
if (BARAddrs[2] != 0) {
sec_cmd_addr = BARAddrs[2];
if (pioInterface)
- pioInterface->addAddrRange(sec_cmd_addr,
- sec_cmd_addr + sec_cmd_size - 1);
+ pioInterface->addAddrRange(RangeSize(sec_cmd_addr,
+ sec_cmd_size));
- sec_cmd_addr &= PA_UNCACHED_MASK;
+ sec_cmd_addr &= EV5::PAddrUncachedMask;
}
break;
@@ -410,10 +387,10 @@ IdeController::WriteConfig(int offset, int size, uint32_t data)
if (BARAddrs[3] != 0) {
sec_ctrl_addr = BARAddrs[3];
if (pioInterface)
- pioInterface->addAddrRange(sec_ctrl_addr,
- sec_ctrl_addr + sec_ctrl_size - 1);
+ pioInterface->addAddrRange(RangeSize(sec_ctrl_addr,
+ sec_ctrl_size));
- sec_ctrl_addr &= PA_UNCACHED_MASK;
+ sec_ctrl_addr &= EV5::PAddrUncachedMask;
}
break;
@@ -421,9 +398,9 @@ IdeController::WriteConfig(int offset, int size, uint32_t data)
if (BARAddrs[4] != 0) {
bmi_addr = BARAddrs[4];
if (pioInterface)
- pioInterface->addAddrRange(bmi_addr, bmi_addr + bmi_size - 1);
+ pioInterface->addAddrRange(RangeSize(bmi_addr, bmi_size));
- bmi_addr &= PA_UNCACHED_MASK;
+ bmi_addr &= EV5::PAddrUncachedMask;
}
break;
}
@@ -675,15 +652,11 @@ IdeController::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_ARRAY(cmd_in_progress, 4);
if (pioInterface) {
- pioInterface->addAddrRange(pri_cmd_addr, pri_cmd_addr +
- pri_cmd_size - 1);
- pioInterface->addAddrRange(pri_ctrl_addr, pri_ctrl_addr +
- pri_ctrl_size - 1);
- pioInterface->addAddrRange(sec_cmd_addr, sec_cmd_addr +
- sec_cmd_size - 1);
- pioInterface->addAddrRange(sec_ctrl_addr, sec_ctrl_addr +
- sec_ctrl_size - 1);
- pioInterface->addAddrRange(bmi_addr, bmi_addr + bmi_size - 1);
+ pioInterface->addAddrRange(RangeSize(pri_cmd_addr, pri_cmd_size));
+ pioInterface->addAddrRange(RangeSize(pri_ctrl_addr, pri_ctrl_size));
+ pioInterface->addAddrRange(RangeSize(sec_cmd_addr, sec_cmd_size));
+ pioInterface->addAddrRange(RangeSize(sec_ctrl_addr, sec_ctrl_size));
+ pioInterface->addAddrRange(RangeSize(bmi_addr, bmi_size));
}
}
@@ -691,12 +664,11 @@ IdeController::unserialize(Checkpoint *cp, const std::string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
- SimObjectParam<IntrControl *> intr_ctrl;
SimObjectVectorParam<IdeDisk *> disks;
SimObjectParam<MemoryController *> mmu;
SimObjectParam<PciConfigAll *> configspace;
SimObjectParam<PciConfigData *> configdata;
- SimObjectParam<Tsunami *> tsunami;
+ SimObjectParam<Platform *> platform;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
Param<uint32_t> pci_func;
@@ -708,12 +680,11 @@ END_DECLARE_SIM_OBJECT_PARAMS(IdeController)
BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController)
- INIT_PARAM(intr_ctrl, "Interrupt Controller"),
INIT_PARAM(disks, "IDE disks attached to this controller"),
INIT_PARAM(mmu, "Memory controller"),
INIT_PARAM(configspace, "PCI Configspace"),
INIT_PARAM(configdata, "PCI Config data"),
- INIT_PARAM(tsunami, "Tsunami chipset pointer"),
+ INIT_PARAM(platform, "Platform pointer"),
INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"),
INIT_PARAM(pci_func, "PCI function code"),
@@ -725,9 +696,21 @@ END_INIT_SIM_OBJECT_PARAMS(IdeController)
CREATE_SIM_OBJECT(IdeController)
{
- return new IdeController(getInstanceName(), intr_ctrl, disks, mmu,
- configspace, configdata, tsunami, pci_bus,
- pci_dev, pci_func, io_bus, pio_latency, hier);
+ IdeController::Params *params = new IdeController::Params;
+ params->name = getInstanceName();
+ params->mmu = mmu;
+ params->configSpace = configspace;
+ params->configData = configdata;
+ params->plat = platform;
+ params->busNum = pci_bus;
+ params->deviceNum = pci_dev;
+ params->functionNum = pci_func;
+
+ params->disks = disks;
+ params->host_bus = io_bus;
+ params->pio_latency = pio_latency;
+ params->hier = hier;
+ return new IdeController(params);
}
REGISTER_SIM_OBJECT("IdeController", IdeController)
diff --git a/dev/ide_ctrl.hh b/dev/ide_ctrl.hh
index b29e5ae9a..f1082d094 100644
--- a/dev/ide_ctrl.hh
+++ b/dev/ide_ctrl.hh
@@ -80,14 +80,14 @@ typedef enum RegType {
BMI_BLOCK
} RegType_t;
+class BaseInterface;
+class Bus;
+class HierParams;
class IdeDisk;
class IntrControl;
class PciConfigAll;
-class Tsunami;
class PhysicalMemory;
-class BaseInterface;
-class HierParams;
-class Bus;
+class Platform;
/**
* Device model for an Intel PIIX4 IDE controller
@@ -95,6 +95,8 @@ class Bus;
class IdeController : public PciDev
{
+ friend class IdeDisk;
+
private:
/** Primary command block registers */
Addr pri_cmd_addr;
@@ -125,10 +127,6 @@ class IdeController : public PciDev
bool bm_enabled;
bool cmd_in_progress[4];
- public:
- /** Pointer to the chipset */
- Tsunami *tsunami;
-
private:
/** IDE disks connected to controller */
IdeDisk *disks[4];
@@ -149,37 +147,23 @@ class IdeController : public PciDev
bool isDiskSelected(IdeDisk *diskPtr);
public:
- /**
- * Constructs and initializes this controller.
- * @param name The name of this controller.
- * @param ic The interrupt controller.
- * @param mmu The memory controller
- * @param cf PCI config space
- * @param cd PCI config data
- * @param bus_num The PCI bus number
- * @param dev_num The PCI device number
- * @param func_num The PCI function number
- * @param host_bus The host bus to connect to
- * @param hier The hierarchy parameters
- */
- IdeController(const std::string &name, IntrControl *ic,
- const std::vector<IdeDisk *> &new_disks,
- MemoryController *mmu, PciConfigAll *cf,
- PciConfigData *cd, Tsunami *t,
- uint32_t bus_num, uint32_t dev_num, uint32_t func_num,
- Bus *host_bus, Tick pio_latency, HierParams *hier);
+ struct Params : public PciDev::Params
+ {
+ /** Array of disk objects */
+ std::vector<IdeDisk *> disks;
+ Bus *host_bus;
+ Tick pio_latency;
+ HierParams *hier;
+ };
+ const Params *params() const { return (const Params *)_params; }
- /**
- * Deletes the connected devices.
- */
+ public:
+ IdeController(Params *p);
~IdeController();
virtual void WriteConfig(int offset, int size, uint32_t data);
virtual void ReadConfig(int offset, int size, uint8_t *data);
- void intrPost();
- void intrClear();
-
void setDmaComplete(IdeDisk *disk);
/**
diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc
index 99724f077..073c10436 100644
--- a/dev/ide_disk.cc
+++ b/dev/ide_disk.cc
@@ -35,7 +35,6 @@
#include <deque>
#include <string>
-#include "arch/alpha/pmap.h"
#include "base/cprintf.hh" // csprintf
#include "base/trace.hh"
#include "dev/disk_image.hh"
@@ -51,6 +50,7 @@
#include "sim/builder.hh"
#include "sim/sim_object.hh"
#include "sim/universe.hh"
+#include "targetarch/isa_traits.hh"
using namespace std;
@@ -177,7 +177,7 @@ Addr
IdeDisk::pciToDma(Addr pciAddr)
{
if (ctrl)
- return ctrl->tsunami->pchip->translatePciToDma(pciAddr);
+ return ctrl->plat->pciToDma(pciAddr);
else
panic("Access to unset controller!\n");
}
@@ -188,14 +188,14 @@ IdeDisk::bytesInDmaPage(Addr curAddr, uint32_t bytesLeft)
uint32_t bytesInPage = 0;
// First calculate how many bytes could be in the page
- if (bytesLeft > ALPHA_PGBYTES)
- bytesInPage = ALPHA_PGBYTES;
+ if (bytesLeft > TheISA::PageBytes)
+ bytesInPage = TheISA::PageBytes;
else
bytesInPage = bytesLeft;
// Next, see if we have crossed a page boundary, and adjust
Addr upperBound = curAddr + bytesInPage;
- Addr pageBound = alpha_trunc_page(curAddr) + ALPHA_PGBYTES;
+ Addr pageBound = TheISA::TruncPage(curAddr) + TheISA::PageBytes;
assert(upperBound >= curAddr && "DMA read wraps around address space!\n");
@@ -510,7 +510,7 @@ IdeDisk::dmaWriteDone()
// setup the initial page and DMA address
curAddr = curPrd.getBaseAddr();
- pageAddr = alpha_trunc_page(curAddr);
+ pageAddr = TheISA::TruncPage(curAddr);
dmaAddr = pciToDma(curAddr);
// clear out the data buffer
@@ -518,14 +518,14 @@ IdeDisk::dmaWriteDone()
while (bytesRead < curPrd.getByteCount()) {
// see if we have crossed into a new page
- if (pageAddr != alpha_trunc_page(curAddr)) {
+ if (pageAddr != TheISA::TruncPage(curAddr)) {
// write the data to memory
memcpy(physmem->dma_addr(dmaAddr, bytesInPage),
(void *)(dataBuffer + (bytesRead - bytesInPage)),
bytesInPage);
// update the DMA address and page address
- pageAddr = alpha_trunc_page(curAddr);
+ pageAddr = TheISA::TruncPage(curAddr);
dmaAddr = pciToDma(curAddr);
bytesInPage = 0;
@@ -732,6 +732,7 @@ IdeDisk::startCommand()
void
IdeDisk::intrPost()
{
+ DPRINTF(IdeDisk, "IDE Disk Posting Interrupt\n");
if (intrPending)
panic("Attempt to post an interrupt with one pending\n");
@@ -745,6 +746,7 @@ IdeDisk::intrPost()
void
IdeDisk::intrClear()
{
+ DPRINTF(IdeDisk, "IDE Disk Clearing Interrupt\n");
if (!intrPending)
panic("Attempt to clear a non-pending interrupt\n");
diff --git a/dev/io_device.hh b/dev/io_device.hh
index f49afc0a6..8c9dc4a35 100644
--- a/dev/io_device.hh
+++ b/dev/io_device.hh
@@ -34,7 +34,7 @@
class BaseInterface;
class Bus;
class HierParams;
-template <class Bus> class DMAInterface;
+template <class BusType> class DMAInterface;
class PioDevice : public FunctionalMemory
{
diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc
index f7f56d39b..eee8fbbce 100644
--- a/dev/ns_gige.cc
+++ b/dev/ns_gige.cc
@@ -41,7 +41,6 @@
#include "dev/etherlink.hh"
#include "dev/ns_gige.hh"
#include "dev/pciconfigall.hh"
-#include "dev/tsunami_cchip.hh"
#include "mem/bus/bus.hh"
#include "mem/bus/dma_interface.hh"
#include "mem/bus/pio_interface.hh"
@@ -51,7 +50,7 @@
#include "sim/builder.hh"
#include "sim/debug.hh"
#include "sim/host.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
#include "targetarch/vtophys.hh"
const char *NsRxStateStrings[] =
@@ -86,82 +85,68 @@ const char *NsDmaState[] =
};
using namespace std;
-
-// helper function declarations
-// These functions reverse Endianness so we can evaluate network data
-// correctly
-uint16_t reverseEnd16(uint16_t);
-uint32_t reverseEnd32(uint32_t);
+using namespace Net;
///////////////////////////////////////////////////////////////////////
//
// NSGigE PCI Device
//
-NSGigE::NSGigE(const std::string &name, IntrControl *i, Tick intr_delay,
- PhysicalMemory *pmem, Tick tx_delay, Tick rx_delay,
- MemoryController *mmu, HierParams *hier, Bus *header_bus,
- Bus *payload_bus, Tick pio_latency, bool dma_desc_free,
- bool dma_data_free, Tick dma_read_delay, Tick dma_write_delay,
- Tick dma_read_factor, Tick dma_write_factor, PciConfigAll *cf,
- PciConfigData *cd, Tsunami *t, uint32_t bus, uint32_t dev,
- uint32_t func, bool rx_filter, const int eaddr[6],
- uint32_t tx_fifo_size, uint32_t rx_fifo_size)
- : PciDev(name, mmu, cf, cd, bus, dev, func), tsunami(t), ioEnable(false),
- maxTxFifoSize(tx_fifo_size), maxRxFifoSize(rx_fifo_size),
+NSGigE::NSGigE(Params *p)
+ : PciDev(p), ioEnable(false),
+ txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size),
txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
txXferLen(0), rxXferLen(0), txState(txIdle), txEnable(false),
- CTDD(false), txFifoAvail(tx_fifo_size),
+ CTDD(false),
txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
- rxEnable(false), CRDD(false), rxPktBytes(0), rxFifoCnt(0),
+ rxEnable(false), CRDD(false), rxPktBytes(0),
rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false),
rxDmaReadEvent(this), rxDmaWriteEvent(this),
txDmaReadEvent(this), txDmaWriteEvent(this),
- dmaDescFree(dma_desc_free), dmaDataFree(dma_data_free),
- txDelay(tx_delay), rxDelay(rx_delay), rxKickTick(0), txKickTick(0),
- txEvent(this), rxFilterEnable(rx_filter), acceptBroadcast(false),
+ dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free),
+ txDelay(p->tx_delay), rxDelay(p->rx_delay),
+ rxKickTick(0), txKickTick(0),
+ txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false),
acceptMulticast(false), acceptUnicast(false),
acceptPerfect(false), acceptArp(false),
- physmem(pmem), intctrl(i), intrTick(0), cpuPendingIntr(false),
+ physmem(p->pmem), intrTick(0), cpuPendingIntr(false),
intrEvent(0), interface(0)
{
- tsunami->ethernet = this;
-
- if (header_bus) {
- pioInterface = newPioInterface(name, hier, header_bus, this,
+ if (p->header_bus) {
+ pioInterface = newPioInterface(name(), p->hier,
+ p->header_bus, this,
&NSGigE::cacheAccess);
- pioLatency = pio_latency * header_bus->clockRatio;
+ pioLatency = p->pio_latency * p->header_bus->clockRatio;
- if (payload_bus)
- dmaInterface = new DMAInterface<Bus>(name + ".dma",
- header_bus, payload_bus, 1);
+ if (p->payload_bus)
+ dmaInterface = new DMAInterface<Bus>(name() + ".dma",
+ p->header_bus,
+ p->payload_bus, 1);
else
- dmaInterface = new DMAInterface<Bus>(name + ".dma",
- header_bus, header_bus, 1);
- } else if (payload_bus) {
- pioInterface = newPioInterface(name, hier, payload_bus, this,
+ dmaInterface = new DMAInterface<Bus>(name() + ".dma",
+ p->header_bus,
+ p->header_bus, 1);
+ } else if (p->payload_bus) {
+ pioInterface = newPioInterface(name(), p->hier,
+ p->payload_bus, this,
&NSGigE::cacheAccess);
- pioLatency = pio_latency * payload_bus->clockRatio;
+ pioLatency = p->pio_latency * p->payload_bus->clockRatio;
- dmaInterface = new DMAInterface<Bus>(name + ".dma", payload_bus,
- payload_bus, 1);
+ dmaInterface = new DMAInterface<Bus>(name() + ".dma",
+ p->payload_bus,
+ p->payload_bus, 1);
}
- intrDelay = US2Ticks(intr_delay);
- dmaReadDelay = dma_read_delay;
- dmaWriteDelay = dma_write_delay;
- dmaReadFactor = dma_read_factor;
- dmaWriteFactor = dma_write_factor;
+ intrDelay = US2Ticks(p->intr_delay);
+ dmaReadDelay = p->dma_read_delay;
+ dmaWriteDelay = p->dma_write_delay;
+ dmaReadFactor = p->dma_read_factor;
+ dmaWriteFactor = p->dma_write_factor;
regsReset();
- rom.perfectMatch[0] = eaddr[0];
- rom.perfectMatch[1] = eaddr[1];
- rom.perfectMatch[2] = eaddr[2];
- rom.perfectMatch[3] = eaddr[3];
- rom.perfectMatch[4] = eaddr[4];
- rom.perfectMatch[5] = eaddr[5];
+ memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN);
}
NSGigE::~NSGigE()
@@ -194,34 +179,48 @@ NSGigE::regStats()
.prereq(rxBytes)
;
- txIPChecksums
- .name(name() + ".txIPChecksums")
+ txIpChecksums
+ .name(name() + ".txIpChecksums")
.desc("Number of tx IP Checksums done by device")
.precision(0)
.prereq(txBytes)
;
- rxIPChecksums
- .name(name() + ".rxIPChecksums")
+ rxIpChecksums
+ .name(name() + ".rxIpChecksums")
.desc("Number of rx IP Checksums done by device")
.precision(0)
.prereq(rxBytes)
;
- txTCPChecksums
- .name(name() + ".txTCPChecksums")
+ txTcpChecksums
+ .name(name() + ".txTcpChecksums")
.desc("Number of tx TCP Checksums done by device")
.precision(0)
.prereq(txBytes)
;
- rxTCPChecksums
- .name(name() + ".rxTCPChecksums")
+ rxTcpChecksums
+ .name(name() + ".rxTcpChecksums")
.desc("Number of rx TCP Checksums done by device")
.precision(0)
.prereq(rxBytes)
;
+ txUdpChecksums
+ .name(name() + ".txUdpChecksums")
+ .desc("Number of tx UDP Checksums done by device")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ rxUdpChecksums
+ .name(name() + ".rxUdpChecksums")
+ .desc("Number of rx UDP Checksums done by device")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
descDmaReads
.name(name() + ".descDMAReads")
.desc("Number of descriptors the device read w/ DMA")
@@ -275,6 +274,180 @@ NSGigE::regStats()
.prereq(rxBytes)
;
+ postedSwi
+ .name(name() + ".postedSwi")
+ .desc("number of software interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalSwi
+ .name(name() + ".totalSwi")
+ .desc("number of total Swi written to ISR")
+ .precision(0)
+ ;
+
+ coalescedSwi
+ .name(name() + ".coalescedSwi")
+ .desc("average number of Swi's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedRxIdle
+ .name(name() + ".postedRxIdle")
+ .desc("number of rxIdle interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalRxIdle
+ .name(name() + ".totalRxIdle")
+ .desc("number of total RxIdle written to ISR")
+ .precision(0)
+ ;
+
+ coalescedRxIdle
+ .name(name() + ".coalescedRxIdle")
+ .desc("average number of RxIdle's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedRxOk
+ .name(name() + ".postedRxOk")
+ .desc("number of RxOk interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalRxOk
+ .name(name() + ".totalRxOk")
+ .desc("number of total RxOk written to ISR")
+ .precision(0)
+ ;
+
+ coalescedRxOk
+ .name(name() + ".coalescedRxOk")
+ .desc("average number of RxOk's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedRxDesc
+ .name(name() + ".postedRxDesc")
+ .desc("number of RxDesc interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalRxDesc
+ .name(name() + ".totalRxDesc")
+ .desc("number of total RxDesc written to ISR")
+ .precision(0)
+ ;
+
+ coalescedRxDesc
+ .name(name() + ".coalescedRxDesc")
+ .desc("average number of RxDesc's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedTxOk
+ .name(name() + ".postedTxOk")
+ .desc("number of TxOk interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalTxOk
+ .name(name() + ".totalTxOk")
+ .desc("number of total TxOk written to ISR")
+ .precision(0)
+ ;
+
+ coalescedTxOk
+ .name(name() + ".coalescedTxOk")
+ .desc("average number of TxOk's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedTxIdle
+ .name(name() + ".postedTxIdle")
+ .desc("number of TxIdle interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalTxIdle
+ .name(name() + ".totalTxIdle")
+ .desc("number of total TxIdle written to ISR")
+ .precision(0)
+ ;
+
+ coalescedTxIdle
+ .name(name() + ".coalescedTxIdle")
+ .desc("average number of TxIdle's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedTxDesc
+ .name(name() + ".postedTxDesc")
+ .desc("number of TxDesc interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalTxDesc
+ .name(name() + ".totalTxDesc")
+ .desc("number of total TxDesc written to ISR")
+ .precision(0)
+ ;
+
+ coalescedTxDesc
+ .name(name() + ".coalescedTxDesc")
+ .desc("average number of TxDesc's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedRxOrn
+ .name(name() + ".postedRxOrn")
+ .desc("number of RxOrn posted to CPU")
+ .precision(0)
+ ;
+
+ totalRxOrn
+ .name(name() + ".totalRxOrn")
+ .desc("number of total RxOrn written to ISR")
+ .precision(0)
+ ;
+
+ coalescedRxOrn
+ .name(name() + ".coalescedRxOrn")
+ .desc("average number of RxOrn's coalesced into each post")
+ .precision(0)
+ ;
+
+ coalescedTotal
+ .name(name() + ".coalescedTotal")
+ .desc("average number of interrupts coalesced into each post")
+ .precision(0)
+ ;
+
+ postedInterrupts
+ .name(name() + ".postedInterrupts")
+ .desc("number of posts to CPU")
+ .precision(0)
+ ;
+
+ droppedPackets
+ .name(name() + ".droppedPackets")
+ .desc("number of packets dropped")
+ .precision(0)
+ ;
+
+ coalescedSwi = totalSwi / postedInterrupts;
+ coalescedRxIdle = totalRxIdle / postedInterrupts;
+ coalescedRxOk = totalRxOk / postedInterrupts;
+ coalescedRxDesc = totalRxDesc / postedInterrupts;
+ coalescedTxOk = totalTxOk / postedInterrupts;
+ coalescedTxIdle = totalTxIdle / postedInterrupts;
+ coalescedTxDesc = totalTxDesc / postedInterrupts;
+ coalescedRxOrn = totalRxOrn / postedInterrupts;
+
+ coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc + totalTxOk
+ + totalTxIdle + totalTxDesc + totalRxOrn) / postedInterrupts;
+
txBandwidth = txBytes * Stats::constant(8) / simSeconds;
rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
txPacketRate = txPackets / simSeconds;
@@ -335,19 +508,17 @@ NSGigE::WriteConfig(int offset, int size, uint32_t data)
case PCI0_BASE_ADDR0:
if (BARAddrs[0] != 0) {
if (pioInterface)
- pioInterface->addAddrRange(BARAddrs[0],
- BARAddrs[0] + BARSize[0] - 1);
+ pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
- BARAddrs[0] &= PA_UNCACHED_MASK;
+ BARAddrs[0] &= EV5::PAddrUncachedMask;
}
break;
case PCI0_BASE_ADDR1:
if (BARAddrs[1] != 0) {
if (pioInterface)
- pioInterface->addAddrRange(BARAddrs[1],
- BARAddrs[1] + BARSize[1] - 1);
+ pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1]));
- BARAddrs[1] &= PA_UNCACHED_MASK;
+ BARAddrs[1] &= EV5::PAddrUncachedMask;
}
break;
}
@@ -934,6 +1105,33 @@ NSGigE::devIntrPost(uint32_t interrupts)
interrupts &= ~ISR_NOIMPL;
regs.isr |= interrupts;
+ if (interrupts & regs.imr) {
+ if (interrupts & ISR_SWI) {
+ totalSwi++;
+ }
+ if (interrupts & ISR_RXIDLE) {
+ totalRxIdle++;
+ }
+ if (interrupts & ISR_RXOK) {
+ totalRxOk++;
+ }
+ if (interrupts & ISR_RXDESC) {
+ totalRxDesc++;
+ }
+ if (interrupts & ISR_TXOK) {
+ totalTxOk++;
+ }
+ if (interrupts & ISR_TXIDLE) {
+ totalTxIdle++;
+ }
+ if (interrupts & ISR_TXDESC) {
+ totalTxDesc++;
+ }
+ if (interrupts & ISR_RXORN) {
+ totalRxOrn++;
+ }
+ }
+
DPRINTF(EthernetIntr,
"interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
interrupts, regs.isr, regs.imr);
@@ -946,12 +1144,46 @@ NSGigE::devIntrPost(uint32_t interrupts)
}
}
+/* writing this interrupt counting stats inside this means that this function
+ is now limited to being used to clear all interrupts upon the kernel
+ reading isr and servicing. just telling you in case you were thinking
+ of expanding use.
+*/
void
NSGigE::devIntrClear(uint32_t interrupts)
{
if (interrupts & ISR_RESERVE)
panic("Cannot clear a reserved interrupt");
+ if (regs.isr & regs.imr & ISR_SWI) {
+ postedSwi++;
+ }
+ if (regs.isr & regs.imr & ISR_RXIDLE) {
+ postedRxIdle++;
+ }
+ if (regs.isr & regs.imr & ISR_RXOK) {
+ postedRxOk++;
+ }
+ if (regs.isr & regs.imr & ISR_RXDESC) {
+ postedRxDesc++;
+ }
+ if (regs.isr & regs.imr & ISR_TXOK) {
+ postedTxOk++;
+ }
+ if (regs.isr & regs.imr & ISR_TXIDLE) {
+ postedTxIdle++;
+ }
+ if (regs.isr & regs.imr & ISR_TXDESC) {
+ postedTxDesc++;
+ }
+ if (regs.isr & regs.imr & ISR_RXORN) {
+ postedRxOrn++;
+ }
+
+ if (regs.isr & regs.imr & (ISR_SWI | ISR_RXIDLE | ISR_RXOK | ISR_RXDESC |
+ ISR_TXOK | ISR_TXIDLE | ISR_TXDESC | ISR_RXORN) )
+ postedInterrupts++;
+
interrupts &= ~ISR_NOIMPL;
regs.isr &= ~interrupts;
@@ -987,61 +1219,50 @@ NSGigE::cpuIntrPost(Tick when)
* @todo this warning should be removed and the intrTick code should
* be fixed.
*/
- if (intrTick < curTick && intrTick != 0) {
- warn("intrTick < curTick !!! intrTick=%d curTick=%d\n",
- intrTick, curTick);
- intrTick = 0;
- }
- assert((intrTick >= curTick) || (intrTick == 0));
- if (when > intrTick && intrTick != 0)
+ assert(when >= curTick);
+ assert(intrTick >= curTick || intrTick == 0);
+ if (when > intrTick && intrTick != 0) {
+ DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
+ intrTick);
return;
+ }
intrTick = when;
-
- if (intrEvent) {
- intrEvent->squash();
- intrEvent = 0;
+ if (intrTick < curTick) {
+ debug_break();
+ intrTick = curTick;
}
- if (when < curTick) {
- cpuInterrupt();
- } else {
- DPRINTF(EthernetIntr,
- "going to schedule an interrupt for intrTick=%d\n",
- intrTick);
- intrEvent = new IntrEvent(this, true);
- intrEvent->schedule(intrTick);
- }
+ DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
+ intrTick);
+
+ if (intrEvent)
+ intrEvent->squash();
+ intrEvent = new IntrEvent(this, true);
+ intrEvent->schedule(intrTick);
}
void
NSGigE::cpuInterrupt()
{
- // Don't send an interrupt if there's already one
- if (cpuPendingIntr) {
- DPRINTF(EthernetIntr,
- "would send an interrupt now, but there's already pending\n");
- intrTick = 0;
- return;
- }
- // Don't send an interrupt if it's supposed to be delayed
- if (intrTick > curTick) {
- DPRINTF(EthernetIntr,
- "an interrupt is scheduled for %d, wait til then\n",
- intrTick);
- return;
- }
+ assert(intrTick == curTick);
// Whether or not there's a pending interrupt, we don't care about
// it anymore
intrEvent = 0;
intrTick = 0;
- // Send interrupt
- cpuPendingIntr = true;
+ // Don't send an interrupt if there's already one
+ if (cpuPendingIntr) {
+ DPRINTF(EthernetIntr,
+ "would send an interrupt now, but there's already pending\n");
+ } else {
+ // Send interrupt
+ cpuPendingIntr = true;
- DPRINTF(EthernetIntr, "posting cchip interrupt\n");
- tsunami->cchip->postDRIR(configData->config.hdr.pci0.interruptLine);
+ DPRINTF(EthernetIntr, "posting interrupt\n");
+ intrPost();
+ }
}
void
@@ -1050,10 +1271,17 @@ NSGigE::cpuIntrClear()
if (!cpuPendingIntr)
return;
+ if (intrEvent) {
+ intrEvent->squash();
+ intrEvent = 0;
+ }
+
+ intrTick = 0;
+
cpuPendingIntr = false;
- DPRINTF(EthernetIntr, "clearing cchip interrupt\n");
- tsunami->cchip->clearDRIR(configData->config.hdr.pci0.interruptLine);
+ DPRINTF(EthernetIntr, "clearing interrupt\n");
+ intrClear();
}
bool
@@ -1067,7 +1295,6 @@ NSGigE::txReset()
DPRINTF(Ethernet, "transmit reset\n");
CTDD = false;
- txFifoAvail = maxTxFifoSize;
txEnable = false;;
txFragPtr = 0;
assert(txDescCnt == 0);
@@ -1083,7 +1310,6 @@ NSGigE::rxReset()
CRDD = false;
assert(rxPktBytes == 0);
- rxFifoCnt = 0;
rxEnable = false;
rxFragPtr = 0;
assert(rxDescCnt == 0);
@@ -1336,14 +1562,13 @@ NSGigE::rxKick()
#if TRACING_ON
if (DTRACE(Ethernet)) {
- if (rxPacket->isIpPkt()) {
- ip_header *ip = rxPacket->getIpHdr();
- DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID));
- if (rxPacket->isTcpPkt()) {
- tcp_header *tcp = rxPacket->getTcpHdr(ip);
+ IpPtr ip(rxPacket);
+ if (ip) {
+ DPRINTF(Ethernet, "ID is %d\n", ip->id());
+ TcpPtr tcp(ip);
+ if (tcp) {
DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n",
- reverseEnd16(tcp->src_port_num),
- reverseEnd16(tcp->dest_port_num));
+ tcp->sport(), tcp->dport());
}
}
}
@@ -1351,12 +1576,7 @@ NSGigE::rxKick()
// sanity check - i think the driver behaves like this
assert(rxDescCnt >= rxPktBytes);
-
- // Must clear the value before popping to decrement the
- // reference count
- rxFifo.front() = NULL;
- rxFifo.pop_front();
- rxFifoCnt -= rxPacket->length;
+ rxFifo.pop();
}
@@ -1399,33 +1619,38 @@ NSGigE::rxKick()
*/
if (rxFilterEnable) {
rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK;
- if (rxFifo.front()->IsUnicast())
+ const EthAddr &dst = rxFifoFront()->dst();
+ if (dst->unicast())
rxDescCache.cmdsts |= CMDSTS_DEST_SELF;
- if (rxFifo.front()->IsMulticast())
+ if (dst->multicast())
rxDescCache.cmdsts |= CMDSTS_DEST_MULTI;
- if (rxFifo.front()->IsBroadcast())
+ if (dst->broadcast())
rxDescCache.cmdsts |= CMDSTS_DEST_MASK;
}
#endif
- if (rxPacket->isIpPkt() && extstsEnable) {
+ IpPtr ip(rxPacket);
+ if (extstsEnable && ip) {
rxDescCache.extsts |= EXTSTS_IPPKT;
- rxIPChecksums++;
- if (!ipChecksum(rxPacket, false)) {
+ rxIpChecksums++;
+ if (cksum(ip) != 0) {
DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
rxDescCache.extsts |= EXTSTS_IPERR;
}
- if (rxPacket->isTcpPkt()) {
+ TcpPtr tcp(ip);
+ UdpPtr udp(ip);
+ if (tcp) {
rxDescCache.extsts |= EXTSTS_TCPPKT;
- rxTCPChecksums++;
- if (!tcpChecksum(rxPacket, false)) {
+ rxTcpChecksums++;
+ if (cksum(tcp) != 0) {
DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
rxDescCache.extsts |= EXTSTS_TCPERR;
}
- } else if (rxPacket->isUdpPkt()) {
+ } else if (udp) {
rxDescCache.extsts |= EXTSTS_UDPPKT;
- if (!udpChecksum(rxPacket, false)) {
+ rxUdpChecksums++;
+ if (cksum(udp) != 0) {
DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
rxDescCache.extsts |= EXTSTS_UDPERR;
}
@@ -1539,18 +1764,17 @@ NSGigE::transmit()
}
DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n",
- maxTxFifoSize - txFifoAvail);
+ txFifo.size());
if (interface->sendPacket(txFifo.front())) {
#if TRACING_ON
if (DTRACE(Ethernet)) {
- if (txFifo.front()->isIpPkt()) {
- ip_header *ip = txFifo.front()->getIpHdr();
- DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID));
- if (txFifo.front()->isTcpPkt()) {
- tcp_header *tcp = txFifo.front()->getTcpHdr(ip);
+ IpPtr ip(txFifo.front());
+ if (ip) {
+ DPRINTF(Ethernet, "ID is %d\n", ip->id());
+ TcpPtr tcp(ip);
+ if (tcp) {
DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n",
- reverseEnd16(tcp->src_port_num),
- reverseEnd16(tcp->dest_port_num));
+ tcp->sport(), tcp->dport());
}
}
}
@@ -1560,12 +1784,9 @@ NSGigE::transmit()
txBytes += txFifo.front()->length;
txPackets++;
- txFifoAvail += txFifo.front()->length;
-
DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",
- txFifoAvail);
- txFifo.front() = NULL;
- txFifo.pop_front();
+ txFifo.avail());
+ txFifo.pop();
/*
* normally do a writeback of the descriptor here, and ONLY
@@ -1575,9 +1796,6 @@ NSGigE::transmit()
* besides, it's functionally the same.
*/
devIntrPost(ISR_TXOK);
- } else {
- DPRINTF(Ethernet,
- "May need to rethink always sending the descriptors back?\n");
}
if (!txFifo.empty() && !txEvent.scheduled()) {
@@ -1784,8 +2002,7 @@ NSGigE::txKick()
case txFifoBlock:
if (!txPacket) {
DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
- txPacket = new EtherPacket;
- txPacket->data = new uint8_t[16384];
+ txPacket = new PacketData(16384);
txPacketBufPtr = txPacket->data;
}
@@ -1810,15 +2027,22 @@ NSGigE::txKick()
DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
/* deal with the the packet that just finished */
if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
+ IpPtr ip(txPacket);
if (txDescCache.extsts & EXTSTS_UDPPKT) {
- udpChecksum(txPacket, true);
+ UdpPtr udp(ip);
+ udp->sum(0);
+ udp->sum(cksum(udp));
+ txUdpChecksums++;
} else if (txDescCache.extsts & EXTSTS_TCPPKT) {
- tcpChecksum(txPacket, true);
- txTCPChecksums++;
+ TcpPtr tcp(ip);
+ tcp->sum(0);
+ tcp->sum(cksum(tcp));
+ txTcpChecksums++;
}
if (txDescCache.extsts & EXTSTS_IPPKT) {
- ipChecksum(txPacket, true);
- txIPChecksums++;
+ ip->sum(0);
+ ip->sum(cksum(ip));
+ txIpChecksums++;
}
}
@@ -1826,7 +2050,11 @@ NSGigE::txKick()
// this is just because the receive can't handle a
// packet bigger want to make sure
assert(txPacket->length <= 1514);
- txFifo.push_back(txPacket);
+#ifndef NDEBUG
+ bool success =
+#endif
+ txFifo.push(txPacket);
+ assert(success);
/*
* this following section is not tqo spec, but
@@ -1872,7 +2100,7 @@ NSGigE::txKick()
}
} else {
DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
- if (txFifoAvail) {
+ if (!txFifo.full()) {
txState = txFragRead;
/*
@@ -1881,7 +2109,7 @@ NSGigE::txKick()
* is not enough room in the fifo, just whatever room
* is left in the fifo
*/
- txXferLen = min<uint32_t>(txDescCnt, txFifoAvail);
+ txXferLen = min<uint32_t>(txDescCnt, txFifo.avail());
txDmaAddr = txFragPtr & 0x3fffffff;
txDmaData = txPacketBufPtr;
@@ -1907,7 +2135,7 @@ NSGigE::txKick()
txPacketBufPtr += txXferLen;
txFragPtr += txXferLen;
txDescCnt -= txXferLen;
- txFifoAvail -= txXferLen;
+ txFifo.reserve(txXferLen);
txState = txFifoBlock;
break;
@@ -1976,45 +2204,35 @@ NSGigE::transferDone()
}
bool
-NSGigE::rxFilter(PacketPtr packet)
+NSGigE::rxFilter(const PacketPtr &packet)
{
+ EthPtr eth = packet;
bool drop = true;
string type;
- if (packet->IsUnicast()) {
- type = "unicast";
-
+ const EthAddr &dst = eth->dst();
+ if (dst.unicast()) {
// If we're accepting all unicast addresses
if (acceptUnicast)
drop = false;
// If we make a perfect match
- if (acceptPerfect &&
- memcmp(rom.perfectMatch, packet->data, EADDR_LEN) == 0)
+ if (acceptPerfect && dst == rom.perfectMatch)
drop = false;
- eth_header *eth = (eth_header *) packet->data;
- if ((acceptArp) && (eth->type == 0x608))
+ if (acceptArp && eth->type() == ETH_TYPE_ARP)
drop = false;
- } else if (packet->IsBroadcast()) {
- type = "broadcast";
-
+ } else if (dst.broadcast()) {
// if we're accepting broadcasts
if (acceptBroadcast)
drop = false;
- } else if (packet->IsMulticast()) {
- type = "multicast";
-
+ } else if (dst.multicast()) {
// if we're accepting all multicasts
if (acceptMulticast)
drop = false;
- } else {
- type = "unknown";
-
- // oh well, punt on this one
}
if (drop) {
@@ -2032,7 +2250,7 @@ NSGigE::recvPacket(PacketPtr packet)
rxPackets++;
DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n",
- maxRxFifoSize - rxFifoCnt);
+ rxFifo.avail());
if (!rxEnable) {
DPRINTF(Ethernet, "receive disabled...packet dropped\n");
@@ -2047,136 +2265,21 @@ NSGigE::recvPacket(PacketPtr packet)
return true;
}
- if ((rxFifoCnt + packet->length) >= maxRxFifoSize) {
+ if (rxFifo.avail() < packet->length) {
DPRINTF(Ethernet,
"packet will not fit in receive buffer...packet dropped\n");
+ droppedPackets++;
devIntrPost(ISR_RXORN);
return false;
}
- rxFifo.push_back(packet);
- rxFifoCnt += packet->length;
+ rxFifo.push(packet);
interface->recvDone();
rxKick();
return true;
}
-/**
- * does a udp checksum. if gen is true, then it generates it and puts
- * it in the right place else, it just checks what it calculates
- * against the value in the header in packet
- */
-bool
-NSGigE::udpChecksum(PacketPtr packet, bool gen)
-{
- ip_header *ip = packet->getIpHdr();
- udp_header *hdr = packet->getUdpHdr(ip);
-
- pseudo_header *pseudo = new pseudo_header;
-
- pseudo->src_ip_addr = ip->src_ip_addr;
- pseudo->dest_ip_addr = ip->dest_ip_addr;
- pseudo->protocol = ip->protocol;
- pseudo->len = hdr->len;
-
- uint16_t cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr,
- (uint32_t) hdr->len);
-
- delete pseudo;
- if (gen)
- hdr->chksum = cksum;
- else
- if (cksum != 0)
- return false;
-
- return true;
-}
-
-bool
-NSGigE::tcpChecksum(PacketPtr packet, bool gen)
-{
- ip_header *ip = packet->getIpHdr();
- tcp_header *hdr = packet->getTcpHdr(ip);
-
- uint16_t cksum;
- pseudo_header *pseudo = new pseudo_header;
- if (!gen) {
- pseudo->src_ip_addr = ip->src_ip_addr;
- pseudo->dest_ip_addr = ip->dest_ip_addr;
- pseudo->protocol = reverseEnd16(ip->protocol);
- pseudo->len = reverseEnd16(reverseEnd16(ip->dgram_len) -
- (ip->vers_len & 0xf)*4);
-
- cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr,
- (uint32_t) reverseEnd16(pseudo->len));
- } else {
- pseudo->src_ip_addr = 0;
- pseudo->dest_ip_addr = 0;
- pseudo->protocol = hdr->chksum;
- pseudo->len = 0;
- hdr->chksum = 0;
- cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr,
- (uint32_t) (reverseEnd16(ip->dgram_len) -
- (ip->vers_len & 0xf)*4));
- }
-
- delete pseudo;
- if (gen)
- hdr->chksum = cksum;
- else
- if (cksum != 0)
- return false;
-
- return true;
-}
-
-bool
-NSGigE::ipChecksum(PacketPtr packet, bool gen)
-{
- ip_header *hdr = packet->getIpHdr();
-
- uint16_t cksum = checksumCalc(NULL, (uint16_t *) hdr,
- (hdr->vers_len & 0xf)*4);
-
- if (gen) {
- DPRINTF(EthernetCksum, "generated checksum: %#x\n", cksum);
- hdr->hdr_chksum = cksum;
- }
- else
- if (cksum != 0)
- return false;
-
- return true;
-}
-
-uint16_t
-NSGigE::checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len)
-{
- uint32_t sum = 0;
-
- uint16_t last_pad = 0;
- if (len & 1) {
- last_pad = buf[len/2] & 0xff;
- len--;
- sum += last_pad;
- }
-
- if (pseudo) {
- sum = pseudo[0] + pseudo[1] + pseudo[2] +
- pseudo[3] + pseudo[4] + pseudo[5];
- }
-
- for (int i=0; i < (len/2); ++i) {
- sum += buf[i];
- }
-
- while (sum >> 16)
- sum = (sum >> 16) + (sum & 0xffff);
-
- return ~sum;
-}
-
//=====================================================================
//
//
@@ -2234,30 +2337,15 @@ NSGigE::serialize(ostream &os)
SERIALIZE_SCALAR(regs.taner);
SERIALIZE_SCALAR(regs.tesr);
- SERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN);
+ SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
SERIALIZE_SCALAR(ioEnable);
/*
* Serialize the data Fifos
*/
- int txNumPkts = txFifo.size();
- SERIALIZE_SCALAR(txNumPkts);
- int i = 0;
- pktiter_t end = txFifo.end();
- for (pktiter_t p = txFifo.begin(); p != end; ++p) {
- nameOut(os, csprintf("%s.txFifo%d", name(), i++));
- (*p)->serialize(os);
- }
-
- int rxNumPkts = rxFifo.size();
- SERIALIZE_SCALAR(rxNumPkts);
- i = 0;
- end = rxFifo.end();
- for (pktiter_t p = rxFifo.begin(); p != end; ++p) {
- nameOut(os, csprintf("%s.rxFifo%d", name(), i++));
- (*p)->serialize(os);
- }
+ rxFifo.serialize("rxFifo", os);
+ txFifo.serialize("txFifo", os);
/*
* Serialize the various helper variables
@@ -2265,8 +2353,7 @@ NSGigE::serialize(ostream &os)
bool txPacketExists = txPacket;
SERIALIZE_SCALAR(txPacketExists);
if (txPacketExists) {
- nameOut(os, csprintf("%s.txPacket", name()));
- txPacket->serialize(os);
+ txPacket->serialize("txPacket", os);
uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
SERIALIZE_SCALAR(txPktBufPtr);
}
@@ -2274,8 +2361,7 @@ NSGigE::serialize(ostream &os)
bool rxPacketExists = rxPacket;
SERIALIZE_SCALAR(rxPacketExists);
if (rxPacketExists) {
- nameOut(os, csprintf("%s.rxPacket", name()));
- rxPacket->serialize(os);
+ rxPacket->serialize("rxPacket", os);
uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
SERIALIZE_SCALAR(rxPktBufPtr);
}
@@ -2302,7 +2388,6 @@ NSGigE::serialize(ostream &os)
SERIALIZE_SCALAR(txState);
SERIALIZE_SCALAR(txEnable);
SERIALIZE_SCALAR(CTDD);
- SERIALIZE_SCALAR(txFifoAvail);
SERIALIZE_SCALAR(txFragPtr);
SERIALIZE_SCALAR(txDescCnt);
int txDmaState = this->txDmaState;
@@ -2316,7 +2401,7 @@ NSGigE::serialize(ostream &os)
SERIALIZE_SCALAR(rxEnable);
SERIALIZE_SCALAR(CRDD);
SERIALIZE_SCALAR(rxPktBytes);
- SERIALIZE_SCALAR(rxFifoCnt);
+ SERIALIZE_SCALAR(rxFragPtr);
SERIALIZE_SCALAR(rxDescCnt);
int rxDmaState = this->rxDmaState;
SERIALIZE_SCALAR(rxDmaState);
@@ -2391,29 +2476,15 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(regs.taner);
UNSERIALIZE_SCALAR(regs.tesr);
- UNSERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN);
+ UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
UNSERIALIZE_SCALAR(ioEnable);
/*
* unserialize the data fifos
*/
- int txNumPkts;
- UNSERIALIZE_SCALAR(txNumPkts);
- int i;
- for (i = 0; i < txNumPkts; ++i) {
- PacketPtr p = new EtherPacket;
- p->unserialize(cp, csprintf("%s.rxFifo%d", section, i));
- txFifo.push_back(p);
- }
-
- int rxNumPkts;
- UNSERIALIZE_SCALAR(rxNumPkts);
- for (i = 0; i < rxNumPkts; ++i) {
- PacketPtr p = new EtherPacket;
- p->unserialize(cp, csprintf("%s.rxFifo%d", section, i));
- rxFifo.push_back(p);
- }
+ rxFifo.unserialize("rxFifo", cp, section);
+ txFifo.unserialize("txFifo", cp, section);
/*
* unserialize the various helper variables
@@ -2421,8 +2492,8 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
bool txPacketExists;
UNSERIALIZE_SCALAR(txPacketExists);
if (txPacketExists) {
- txPacket = new EtherPacket;
- txPacket->unserialize(cp, csprintf("%s.txPacket", section));
+ txPacket = new PacketData(16384);
+ txPacket->unserialize("txPacket", cp, section);
uint32_t txPktBufPtr;
UNSERIALIZE_SCALAR(txPktBufPtr);
txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
@@ -2433,8 +2504,8 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(rxPacketExists);
rxPacket = 0;
if (rxPacketExists) {
- rxPacket = new EtherPacket;
- rxPacket->unserialize(cp, csprintf("%s.rxPacket", section));
+ rxPacket = new PacketData(16384);
+ rxPacket->unserialize("rxPacket", cp, section);
uint32_t rxPktBufPtr;
UNSERIALIZE_SCALAR(rxPktBufPtr);
rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
@@ -2464,7 +2535,6 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
this->txState = (TxState) txState;
UNSERIALIZE_SCALAR(txEnable);
UNSERIALIZE_SCALAR(CTDD);
- UNSERIALIZE_SCALAR(txFifoAvail);
UNSERIALIZE_SCALAR(txFragPtr);
UNSERIALIZE_SCALAR(txDescCnt);
int txDmaState;
@@ -2480,7 +2550,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(rxEnable);
UNSERIALIZE_SCALAR(CRDD);
UNSERIALIZE_SCALAR(rxPktBytes);
- UNSERIALIZE_SCALAR(rxFifoCnt);
+ UNSERIALIZE_SCALAR(rxFragPtr);
UNSERIALIZE_SCALAR(rxDescCnt);
int rxDmaState;
UNSERIALIZE_SCALAR(rxDmaState);
@@ -2522,8 +2592,8 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
* re-add addrRanges to bus bridges
*/
if (pioInterface) {
- pioInterface->addAddrRange(BARAddrs[0], BARAddrs[0] + BARSize[0] - 1);
- pioInterface->addAddrRange(BARAddrs[1], BARAddrs[1] + BARSize[1] - 1);
+ pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
+ pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1]));
}
}
@@ -2534,28 +2604,6 @@ NSGigE::cacheAccess(MemReqPtr &req)
req->paddr, req->paddr - addr);
return curTick + pioLatency;
}
-//=====================================================================
-
-
-//********** helper functions******************************************
-
-uint16_t reverseEnd16(uint16_t num)
-{
- uint16_t reverse = (num & 0xff)<<8;
- reverse += ((num & 0xff00) >> 8);
- return reverse;
-}
-
-uint32_t reverseEnd32(uint32_t num)
-{
- uint32_t reverse = (reverseEnd16(num & 0xffff)) << 16;
- reverse += reverseEnd16((uint16_t) ((num & 0xffff0000) >> 8));
- return reverse;
-}
-
-
-
-//=====================================================================
BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
@@ -2591,7 +2639,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
Param<Tick> tx_delay;
Param<Tick> rx_delay;
- SimObjectParam<IntrControl *> intr_ctrl;
Param<Tick> intr_delay;
SimObjectParam<MemoryController *> mmu;
SimObjectParam<PhysicalMemory *> physmem;
@@ -2609,7 +2656,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
Param<Tick> dma_write_factor;
SimObjectParam<PciConfigAll *> configspace;
SimObjectParam<PciConfigData *> configdata;
- SimObjectParam<Tsunami *> tsunami;
+ SimObjectParam<Platform *> platform;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
Param<uint32_t> pci_func;
@@ -2622,7 +2669,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000),
INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000),
- INIT_PARAM(intr_ctrl, "Interrupt Controller"),
INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0),
INIT_PARAM(mmu, "Memory Controller"),
INIT_PARAM(physmem, "Physical Memory"),
@@ -2641,7 +2687,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0),
INIT_PARAM(configspace, "PCI Configspace"),
INIT_PARAM(configdata, "PCI Config data"),
- INIT_PARAM(tsunami, "Tsunami"),
+ INIT_PARAM(platform, "Platform"),
INIT_PARAM(pci_bus, "PCI bus"),
INIT_PARAM(pci_dev, "PCI device number"),
INIT_PARAM(pci_func, "PCI function code"),
@@ -2653,17 +2699,36 @@ END_INIT_SIM_OBJECT_PARAMS(NSGigE)
CREATE_SIM_OBJECT(NSGigE)
{
- int eaddr[6];
- sscanf(((string)hardware_address).c_str(), "%x:%x:%x:%x:%x:%x",
- &eaddr[0], &eaddr[1], &eaddr[2], &eaddr[3], &eaddr[4], &eaddr[5]);
-
- return new NSGigE(getInstanceName(), intr_ctrl, intr_delay,
- physmem, tx_delay, rx_delay, mmu, hier, header_bus,
- payload_bus, pio_latency, dma_desc_free, dma_data_free,
- dma_read_delay, dma_write_delay, dma_read_factor,
- dma_write_factor, configspace, configdata,
- tsunami, pci_bus, pci_dev, pci_func, rx_filter, eaddr,
- tx_fifo_size, rx_fifo_size);
+ NSGigE::Params *params = new NSGigE::Params;
+
+ params->name = getInstanceName();
+ params->mmu = mmu;
+ params->configSpace = configspace;
+ params->configData = configdata;
+ params->plat = platform;
+ params->busNum = pci_bus;
+ params->deviceNum = pci_dev;
+ params->functionNum = pci_func;
+
+ params->intr_delay = intr_delay;
+ params->pmem = physmem;
+ params->tx_delay = tx_delay;
+ params->rx_delay = rx_delay;
+ params->hier = hier;
+ params->header_bus = header_bus;
+ params->payload_bus = payload_bus;
+ params->pio_latency = pio_latency;
+ params->dma_desc_free = dma_desc_free;
+ params->dma_data_free = dma_data_free;
+ params->dma_read_delay = dma_read_delay;
+ params->dma_write_delay = dma_write_delay;
+ params->dma_read_factor = dma_read_factor;
+ params->dma_write_factor = dma_write_factor;
+ params->rx_filter = rx_filter;
+ params->eaddr = hardware_address;
+ params->tx_fifo_size = tx_fifo_size;
+ params->rx_fifo_size = rx_fifo_size;
+ return new NSGigE(params);
}
REGISTER_SIM_OBJECT("NSGigE", NSGigE)
diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh
index 82f640db1..8d6016126 100644
--- a/dev/ns_gige.hh
+++ b/dev/ns_gige.hh
@@ -31,22 +31,20 @@
* DP83820 ethernet controller
*/
-#ifndef __NS_GIGE_HH__
-#define __NS_GIGE_HH__
+#ifndef __DEV_NS_GIGE_HH__
+#define __DEV_NS_GIGE_HH__
+#include "base/inet.hh"
#include "base/statistics.hh"
#include "dev/etherint.hh"
#include "dev/etherpkt.hh"
#include "dev/io_device.hh"
#include "dev/ns_gige_reg.h"
#include "dev/pcidev.hh"
-#include "dev/tsunami.hh"
+#include "dev/pktfifo.hh"
#include "mem/bus/bus.hh"
#include "sim/eventq.hh"
-/** length of ethernet address in bytes */
-#define EADDR_LEN 6
-
/**
* Ethernet device registers
*/
@@ -90,7 +88,7 @@ struct dp_rom {
* for perfect match memory.
* the linux driver doesn't use any other ROM
*/
- uint8_t perfectMatch[EADDR_LEN];
+ uint8_t perfectMatch[ETH_ADDR_LEN];
};
class IntrControl;
@@ -141,10 +139,6 @@ class NSGigE : public PciDev
};
private:
- /** pointer to the chipset */
- Tsunami *tsunami;
-
- private:
Addr addr;
static const Addr size = sizeof(dp_regs);
@@ -165,10 +159,8 @@ class NSGigE : public PciDev
/*** BASIC STRUCTURES FOR TX/RX ***/
/* Data FIFOs */
- pktbuf_t txFifo;
- uint32_t maxTxFifoSize;
- pktbuf_t rxFifo;
- uint32_t maxRxFifoSize;
+ PacketFifo txFifo;
+ PacketFifo rxFifo;
/** various helper vars */
PacketPtr txPacket;
@@ -190,8 +182,6 @@ class NSGigE : public PciDev
/** Current Transmit Descriptor Done */
bool CTDD;
- /** current amt of free space in txDataFifo in bytes */
- uint32_t txFifoAvail;
/** halt the tx state machine after next packet */
bool txHalt;
/** ptr to the next byte in the current fragment */
@@ -208,8 +198,6 @@ class NSGigE : public PciDev
bool CRDD;
/** num of bytes in the current packet being drained from rxDataFifo */
uint32_t rxPktBytes;
- /** number of bytes in the rxFifo */
- uint32_t rxFifoCnt;
/** halt the rx state machine after current packet */
bool rxHalt;
/** ptr to the next byte in current fragment */
@@ -302,7 +290,7 @@ class NSGigE : public PciDev
* receive address filter
*/
bool rxFilterEnable;
- bool rxFilter(PacketPtr packet);
+ bool rxFilter(const PacketPtr &packet);
bool acceptBroadcast;
bool acceptMulticast;
bool acceptUnicast;
@@ -329,28 +317,34 @@ class NSGigE : public PciDev
typedef EventWrapper<NSGigE, &NSGigE::cpuInterrupt> IntrEvent;
friend class IntrEvent;
IntrEvent *intrEvent;
-
- /**
- * Hardware checksum support
- */
- bool udpChecksum(PacketPtr packet, bool gen);
- bool tcpChecksum(PacketPtr packet, bool gen);
- bool ipChecksum(PacketPtr packet, bool gen);
- uint16_t checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len);
-
NSGigEInt *interface;
public:
- NSGigE(const std::string &name, IntrControl *i, Tick intr_delay,
- PhysicalMemory *pmem, Tick tx_delay, Tick rx_delay,
- MemoryController *mmu, HierParams *hier, Bus *header_bus,
- Bus *payload_bus, Tick pio_latency, bool dma_desc_free,
- bool dma_data_free, Tick dma_read_delay, Tick dma_write_delay,
- Tick dma_read_factor, Tick dma_write_factor, PciConfigAll *cf,
- PciConfigData *cd, Tsunami *t, uint32_t bus, uint32_t dev,
- uint32_t func, bool rx_filter, const int eaddr[6],
- uint32_t tx_fifo_size, uint32_t rx_fifo_size);
+ struct Params : public PciDev::Params
+ {
+ PhysicalMemory *pmem;
+ HierParams *hier;
+ Bus *header_bus;
+ Bus *payload_bus;
+ Tick intr_delay;
+ Tick tx_delay;
+ Tick rx_delay;
+ Tick pio_latency;
+ bool dma_desc_free;
+ bool dma_data_free;
+ Tick dma_read_delay;
+ Tick dma_write_delay;
+ Tick dma_read_factor;
+ Tick dma_write_factor;
+ bool rx_filter;
+ Net::EthAddr eaddr;
+ uint32_t tx_fifo_size;
+ uint32_t rx_fifo_size;
+ };
+
+ NSGigE(Params *params);
~NSGigE();
+ const Params *params() const { return (const Params *)_params; }
virtual void WriteConfig(int offset, int size, uint32_t data);
virtual void ReadConfig(int offset, int size, uint8_t *data);
@@ -377,10 +371,12 @@ class NSGigE : public PciDev
Stats::Scalar<> rxBytes;
Stats::Scalar<> txPackets;
Stats::Scalar<> rxPackets;
- Stats::Scalar<> txIPChecksums;
- Stats::Scalar<> rxIPChecksums;
- Stats::Scalar<> txTCPChecksums;
- Stats::Scalar<> rxTCPChecksums;
+ Stats::Scalar<> txIpChecksums;
+ Stats::Scalar<> rxIpChecksums;
+ Stats::Scalar<> txTcpChecksums;
+ Stats::Scalar<> rxTcpChecksums;
+ Stats::Scalar<> txUdpChecksums;
+ Stats::Scalar<> rxUdpChecksums;
Stats::Scalar<> descDmaReads;
Stats::Scalar<> descDmaWrites;
Stats::Scalar<> descDmaRdBytes;
@@ -389,6 +385,33 @@ class NSGigE : public PciDev
Stats::Formula rxBandwidth;
Stats::Formula txPacketRate;
Stats::Formula rxPacketRate;
+ Stats::Scalar<> postedSwi;
+ Stats::Formula coalescedSwi;
+ Stats::Scalar<> totalSwi;
+ Stats::Scalar<> postedRxIdle;
+ Stats::Formula coalescedRxIdle;
+ Stats::Scalar<> totalRxIdle;
+ Stats::Scalar<> postedRxOk;
+ Stats::Formula coalescedRxOk;
+ Stats::Scalar<> totalRxOk;
+ Stats::Scalar<> postedRxDesc;
+ Stats::Formula coalescedRxDesc;
+ Stats::Scalar<> totalRxDesc;
+ Stats::Scalar<> postedTxOk;
+ Stats::Formula coalescedTxOk;
+ Stats::Scalar<> totalTxOk;
+ Stats::Scalar<> postedTxIdle;
+ Stats::Formula coalescedTxIdle;
+ Stats::Scalar<> totalTxIdle;
+ Stats::Scalar<> postedTxDesc;
+ Stats::Formula coalescedTxDesc;
+ Stats::Scalar<> totalTxDesc;
+ Stats::Scalar<> postedRxOrn;
+ Stats::Formula coalescedRxOrn;
+ Stats::Scalar<> totalRxOrn;
+ Stats::Formula coalescedTotal;
+ Stats::Scalar<> postedInterrupts;
+ Stats::Scalar<> droppedPackets;
public:
Tick cacheAccess(MemReqPtr &req);
@@ -406,8 +429,8 @@ class NSGigEInt : public EtherInt
NSGigEInt(const std::string &name, NSGigE *d)
: EtherInt(name), dev(d) { dev->setInterface(this); }
- virtual bool recvPacket(PacketPtr &pkt) { return dev->recvPacket(pkt); }
+ virtual bool recvPacket(PacketPtr pkt) { return dev->recvPacket(pkt); }
virtual void sendDone() { dev->transferDone(); }
};
-#endif // __NS_GIGE_HH__
+#endif // __DEV_NS_GIGE_HH__
diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc
index 740a9b4ac..609763e92 100644
--- a/dev/pciconfigall.cc
+++ b/dev/pciconfigall.cc
@@ -33,10 +33,12 @@
#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 "mem/bus/bus.hh"
#include "mem/bus/pio_interface.hh"
#include "mem/bus/pio_interface_impl.hh"
@@ -50,12 +52,12 @@ PciConfigAll::PciConfigAll(const string &name, Addr a, MemoryController *mmu,
HierParams *hier, Bus *bus, Tick pio_latency)
: PioDevice(name), addr(a)
{
- mmu->add_child(this, Range<Addr>(addr, addr + size));
+ mmu->add_child(this, RangeSize(addr, size));
if (bus) {
pioInterface = newPioInterface(name, hier, bus, this,
&PciConfigAll::cacheAccess);
- pioInterface->addAddrRange(addr, addr + size - 1);
+ pioInterface->addAddrRange(RangeSize(addr, size));
pioLatency = pio_latency * bus->clockRatio;
}
@@ -65,13 +67,40 @@ PciConfigAll::PciConfigAll(const string &name, Addr a, MemoryController *mmu,
devices[x][y] = NULL;
}
+// If two interrupts share the same line largely bad things will happen.
+// Since we don't track how many times an interrupt was set and correspondingly
+// cleared two devices on the same interrupt line and assert and deassert each
+// others interrupt "line". Interrupts will not work correctly.
+void
+PciConfigAll::startup()
+{
+ bitset<256> intLines;
+ PciDev *tempDev;
+ uint8_t intline;
+
+ for (int x = 0; x < MAX_PCI_DEV; x++) {
+ for (int y = 0; y < MAX_PCI_FUNC; y++) {
+ if (devices[x][y] != NULL) {
+ tempDev = devices[x][y];
+ intline = tempDev->interruptLine();
+ if (intLines.test(intline))
+ warn("Interrupt line %#X is used multiple times"
+ "(You probably want to fix this).\n", (uint32_t)intline);
+ else
+ intLines.set(intline);
+ } // devices != NULL
+ } // PCI_FUNC
+ } // PCI_DEV
+
+}
+
Fault
PciConfigAll::read(MemReqPtr &req, uint8_t *data)
{
DPRINTF(PciConfigAll, "read va=%#x size=%d\n",
req->vaddr, req->size);
- Addr daddr = (req->paddr - (addr & PA_IMPL_MASK));
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
int device = (daddr >> 11) & 0x1F;
int func = (daddr >> 8) & 0x7;
@@ -115,7 +144,7 @@ PciConfigAll::read(MemReqPtr &req, uint8_t *data)
Fault
PciConfigAll::write(MemReqPtr &req, const uint8_t *data)
{
- Addr daddr = (req->paddr - (addr & PA_IMPL_MASK));
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
int device = (daddr >> 11) & 0x1F;
int func = (daddr >> 8) & 0x7;
diff --git a/dev/pciconfigall.hh b/dev/pciconfigall.hh
index d6b37b9b1..9cf2cf972 100644
--- a/dev/pciconfigall.hh
+++ b/dev/pciconfigall.hh
@@ -116,6 +116,12 @@ class PciConfigAll : public PioDevice
virtual Fault write(MemReqPtr &req, const uint8_t *data);
/**
+ * 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();
+
+ /**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
*/
@@ -134,6 +140,7 @@ class PciConfigAll : public PioDevice
* @return Tick when the request is done
*/
Tick cacheAccess(MemReqPtr &req);
+
};
#endif // __PCICONFIGALL_HH__
diff --git a/dev/pcidev.cc b/dev/pcidev.cc
index 7b13aac80..d156b6a02 100644
--- a/dev/pcidev.cc
+++ b/dev/pcidev.cc
@@ -50,36 +50,38 @@
using namespace std;
-PciDev::PciDev(const string &name, MemoryController *mmu, PciConfigAll *cf,
- PciConfigData *cd, uint32_t bus, uint32_t dev, uint32_t func)
- : DmaDevice(name), mmu(mmu), configSpace(cf), configData(cd), busNum(bus),
- deviceNum(dev), functionNum(func)
+PciDev::PciDev(Params *p)
+ : DmaDevice(p->name), _params(p), plat(p->plat), configData(p->configData)
{
// copy the config data from the PciConfigData object
- if (cd) {
- memcpy(config.data, cd->config.data, sizeof(config.data));
- memcpy(BARSize, cd->BARSize, sizeof(BARSize));
- memcpy(BARAddrs, cd->BARAddrs, sizeof(BARAddrs));
+ if (configData) {
+ memcpy(config.data, configData->config.data, sizeof(config.data));
+ memcpy(BARSize, configData->BARSize, sizeof(BARSize));
+ memcpy(BARAddrs, configData->BARAddrs, sizeof(BARAddrs));
} else
panic("NULL pointer to configuration data");
// Setup pointer in config space to point to this entry
- if (cf->deviceExists(dev,func))
- panic("Two PCI devices occuping same dev: %#x func: %#x", dev, func);
+ if (p->configSpace->deviceExists(p->deviceNum, p->functionNum))
+ panic("Two PCI devices occuping same dev: %#x func: %#x",
+ p->deviceNum, p->functionNum);
else
- cf->registerDevice(dev, func, this);
+ p->configSpace->registerDevice(p->deviceNum, p->functionNum, this);
}
void
PciDev::ReadConfig(int offset, int size, uint8_t *data)
{
+ if (offset >= PCI_DEVICE_SPECIFIC)
+ panic("Device specific PCI config space not implemented!\n");
+
switch(size) {
case sizeof(uint32_t):
memcpy((uint8_t*)data, config.data + offset, sizeof(uint32_t));
*(uint32_t*)data = htoa(*(uint32_t*)data);
DPRINTF(PCIDEV,
"read device: %#x function: %#x register: %#x %d bytes: data: %#x\n",
- deviceNum, functionNum, offset, size,
+ params()->deviceNum, params()->functionNum, offset, size,
*(uint32_t*)(config.data + offset));
break;
@@ -88,7 +90,7 @@ PciDev::ReadConfig(int offset, int size, uint8_t *data)
*(uint16_t*)data = htoa(*(uint16_t*)data);
DPRINTF(PCIDEV,
"read device: %#x function: %#x register: %#x %d bytes: data: %#x\n",
- deviceNum, functionNum, offset, size,
+ params()->deviceNum, params()->functionNum, offset, size,
*(uint16_t*)(config.data + offset));
break;
@@ -96,7 +98,7 @@ PciDev::ReadConfig(int offset, int size, uint8_t *data)
memcpy((uint8_t*)data, config.data + offset, sizeof(uint8_t));
DPRINTF(PCIDEV,
"read device: %#x function: %#x register: %#x %d bytes: data: %#x\n",
- deviceNum, functionNum, offset, size,
+ params()->deviceNum, params()->functionNum, offset, size,
(uint16_t)(*(uint8_t*)(config.data + offset)));
break;
@@ -108,6 +110,9 @@ PciDev::ReadConfig(int offset, int size, uint8_t *data)
void
PciDev::WriteConfig(int offset, int size, uint32_t data)
{
+ if (offset >= PCI_DEVICE_SPECIFIC)
+ panic("Device specific PCI config space not implemented!\n");
+
uint32_t barnum;
union {
@@ -119,7 +124,8 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
DPRINTF(PCIDEV,
"write device: %#x function: %#x reg: %#x size: %d data: %#x\n",
- deviceNum, functionNum, offset, size, word_value);
+ params()->deviceNum, params()->functionNum, offset, size,
+ word_value);
barnum = (offset - PCI0_BASE_ADDR0) >> 2;
@@ -129,7 +135,7 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
case PCI0_INTERRUPT_LINE:
case PCI_CACHE_LINE_SIZE:
case PCI_LATENCY_TIMER:
- *(uint8_t *)&config.data[offset] = byte_value;
+ *(uint8_t *)&config.data[offset] = htoa(byte_value);
break;
default:
@@ -142,7 +148,7 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
case PCI_COMMAND:
case PCI_STATUS:
case PCI_CACHE_LINE_SIZE:
- *(uint16_t *)&config.data[offset] = half_value;
+ *(uint16_t *)&config.data[offset] = htoa(half_value);
break;
default:
@@ -166,67 +172,63 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
// to size of memory it needs
if (word_value == 0xffffffff) {
// This is I/O Space, bottom two bits are read only
- if (config.data[offset] & 0x1) {
- *(uint32_t *)&config.data[offset] =
+ if (htoa(config.data[offset]) & 0x1) {
+ *(uint32_t *)&config.data[offset] = htoa(
~(BARSize[barnum] - 1) |
- (config.data[offset] & 0x3);
+ (htoa(config.data[offset]) & 0x3));
} else {
// This is memory space, bottom four bits are read only
- *(uint32_t *)&config.data[offset] =
+ *(uint32_t *)&config.data[offset] = htoa(
~(BARSize[barnum] - 1) |
- (config.data[offset] & 0xF);
+ (htoa(config.data[offset]) & 0xF));
}
} else {
+ MemoryController *mmu = params()->mmu;
+
// This is I/O Space, bottom two bits are read only
- if(config.data[offset] & 0x1) {
- *(uint32_t *)&config.data[offset] = (word_value & ~0x3) |
- (config.data[offset] & 0x3);
+ if(htoa(config.data[offset]) & 0x1) {
+ *(uint32_t *)&config.data[offset] =
+ htoa((word_value & ~0x3) |
+ (htoa(config.data[offset]) & 0x3));
if (word_value & ~0x1) {
Addr base_addr = (word_value & ~0x1) + TSUNAMI_PCI0_IO;
- Addr base_size = BARSize[barnum]-1;
+ Addr base_size = BARSize[barnum];
// It's never been set
if (BARAddrs[barnum] == 0)
mmu->add_child((FunctionalMemory *)this,
- Range<Addr>(base_addr,
- base_addr + base_size));
+ RangeSize(base_addr, base_size));
else
mmu->update_child((FunctionalMemory *)this,
- Range<Addr>(BARAddrs[barnum],
- BARAddrs[barnum] +
- base_size),
- Range<Addr>(base_addr,
- base_addr +
- base_size));
+ RangeSize(BARAddrs[barnum],
+ base_size),
+ RangeSize(base_addr, base_size));
BARAddrs[barnum] = base_addr;
}
} else {
// This is memory space, bottom four bits are read only
- *(uint32_t *)&config.data[offset] = (word_value & ~0xF) |
- (config.data[offset] & 0xF);
+ *(uint32_t *)&config.data[offset] =
+ htoa((word_value & ~0xF) |
+ (htoa(config.data[offset]) & 0xF));
if (word_value & ~0x3) {
Addr base_addr = (word_value & ~0x3) +
TSUNAMI_PCI0_MEMORY;
- Addr base_size = BARSize[barnum]-1;
+ Addr base_size = BARSize[barnum];
// It's never been set
if (BARAddrs[barnum] == 0)
mmu->add_child((FunctionalMemory *)this,
- Range<Addr>(base_addr,
- base_addr + base_size));
+ RangeSize(base_addr, base_size));
else
mmu->update_child((FunctionalMemory *)this,
- Range<Addr>(BARAddrs[barnum],
- BARAddrs[barnum] +
- base_size),
- Range<Addr>(base_addr,
- base_addr +
- base_size));
+ RangeSize(BARAddrs[barnum],
+ base_size),
+ RangeSize(base_addr, base_size));
BARAddrs[barnum] = base_addr;
}
@@ -238,14 +240,14 @@ PciDev::WriteConfig(int offset, int size, uint32_t data)
if (word_value == 0xfffffffe)
*(uint32_t *)&config.data[offset] = 0xffffffff;
else
- *(uint32_t *)&config.data[offset] = word_value;
+ *(uint32_t *)&config.data[offset] = htoa(word_value);
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
- *(uint16_t *)&config.data[offset] = half_value;
+ *(uint16_t *)&config.data[offset] = htoa(half_value);
break;
default:
@@ -273,10 +275,7 @@ PciDev::unserialize(Checkpoint *cp, const std::string &section)
// Add the MMU mappings for the BARs
for (int i=0; i < 6; i++) {
if (BARAddrs[i] != 0)
- mmu->add_child((FunctionalMemory *)this,
- Range<Addr>(BARAddrs[i],
- BARAddrs[i] +
- BARSize[i] - 1));
+ params()->mmu->add_child(this, RangeSize(BARAddrs[i], BARSize[i]));
}
}
diff --git a/dev/pcidev.hh b/dev/pcidev.hh
index c0fe47ac4..4b947b560 100644
--- a/dev/pcidev.hh
+++ b/dev/pcidev.hh
@@ -30,11 +30,12 @@
* Interface for devices using PCI configuration
*/
-#ifndef __PCI_DEV_HH__
-#define __PCI_DEV_HH__
+#ifndef __DEV_PCIDEV_HH__
+#define __DEV_PCIDEV_HH__
-#include "dev/pcireg.h"
#include "dev/io_device.hh"
+#include "dev/pcireg.h"
+#include "dev/platform.hh"
class PciConfigAll;
class MemoryController;
@@ -78,29 +79,43 @@ class PciConfigData : public SimObject
class PciDev : public DmaDevice
{
protected:
- MemoryController *mmu;
- /** A pointer to the configspace all object that calls
- * us when a read comes to this particular device/function.
- */
- PciConfigAll *configSpace;
+ struct Params;
+ Params *_params;
- /**
- * A pointer to the object that contains the first 64 bytes of
- * config space
- */
- PciConfigData *configData;
+ public:
+ struct Params
+ {
+ std::string name;
+ Platform *plat;
+ MemoryController *mmu;
+
+ /**
+ * A pointer to the configspace all object that calls us when
+ * a read comes to this particular device/function.
+ */
+ PciConfigAll *configSpace;
+
+ /**
+ * A pointer to the object that contains the first 64 bytes of
+ * config space
+ */
+ PciConfigData *configData;
- /** The bus number we are on */
- uint32_t busNum;
+ /** The bus number we are on */
+ uint32_t busNum;
- /** The device number we have */
- uint32_t deviceNum;
+ /** The device number we have */
+ uint32_t deviceNum;
- /** The function number */
- uint32_t functionNum;
+ /** The function number */
+ uint32_t functionNum;
+ };
+ const Params *params() const { return _params; }
- /** The current config space. Unlike the PciConfigData this is updated
- * during simulation while continues to refelect what was in the config file.
+ protected:
+ /** The current config space. Unlike the PciConfigData this is
+ * updated during simulation while continues to refelect what was
+ * in the config file.
*/
PCIConfig config;
@@ -110,21 +125,33 @@ class PciDev : public DmaDevice
/** The current address mapping of the BARs */
Addr BARAddrs[6];
+ protected:
+ Platform *plat;
+ PciConfigData *configData;
+
+ public:
+ Addr pciToDma(Addr pciAddr) const
+ { return plat->pciToDma(pciAddr); }
+
+ void
+ intrPost()
+ { plat->postPciInt(configData->config.hdr.pci0.interruptLine); }
+
+ void
+ intrClear()
+ { plat->clearPciInt(configData->config.hdr.pci0.interruptLine); }
+
+ uint8_t
+ interruptLine()
+ { return configData->config.hdr.pci0.interruptLine; }
+
public:
/**
- * Constructor for PCI Dev. This function copies data from the config file
- * object PCIConfigData and registers the device with a PciConfigAll object.
- * @param name name of the object
- * @param mmu a pointer to the memory controller
- * @param cf a pointer to the config space object that this device need to
- * register with
- * @param cd A pointer to the config space values specified in the conig file
- * @param bus the bus this device is on
- * @param dev the device id of this device
- * @param func the function number of this device
+ * Constructor for PCI Dev. This function copies data from the
+ * config file object PCIConfigData and registers the device with
+ * a PciConfigAll object.
*/
- PciDev(const std::string &name, MemoryController *mmu, PciConfigAll *cf,
- PciConfigData *cd, uint32_t bus, uint32_t dev, uint32_t func);
+ PciDev(Params *params);
virtual Fault read(MemReqPtr &req, uint8_t *data) {
return No_Fault;
@@ -168,4 +195,4 @@ class PciDev : public DmaDevice
virtual void unserialize(Checkpoint *cp, const std::string &section);
};
-#endif // __PCI_DEV_HH__
+#endif // __DEV_PCIDEV_HH__
diff --git a/dev/pktfifo.cc b/dev/pktfifo.cc
new file mode 100644
index 000000000..ae82123cf
--- /dev/null
+++ b/dev/pktfifo.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2002-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "base/misc.hh"
+#include "dev/pktfifo.hh"
+
+using namespace std;
+
+void
+PacketFifo::serialize(const string &base, ostream &os)
+{
+ paramOut(os, base + ".size", _size);
+ paramOut(os, base + ".maxsize", _maxsize);
+ paramOut(os, base + ".reserved", _reserved);
+ paramOut(os, base + ".packets", fifo.size());
+
+ int i = 0;
+ std::list<PacketPtr>::iterator p = fifo.begin();
+ std::list<PacketPtr>::iterator end = fifo.end();
+ while (p != end) {
+ (*p)->serialize(csprintf("%s.packet%d", base, i), os);
+ ++p;
+ ++i;
+ }
+}
+
+void
+PacketFifo::unserialize(const string &base, Checkpoint *cp,
+ const string &section)
+{
+ paramIn(cp, section, base + ".size", _size);
+ paramIn(cp, section, base + ".maxsize", _maxsize);
+ paramIn(cp, section, base + ".reserved", _reserved);
+ int fifosize;
+ paramIn(cp, section, base + ".packets", fifosize);
+
+ fifo.clear();
+ fifo.resize(fifosize);
+
+ for (int i = 0; i < fifosize; ++i) {
+ PacketPtr p = new PacketData(16384);
+ p->unserialize(csprintf("%s.packet%d", base, i), cp, section);
+ fifo.push_back(p);
+ }
+}
diff --git a/dev/pktfifo.hh b/dev/pktfifo.hh
new file mode 100644
index 000000000..0c237949c
--- /dev/null
+++ b/dev/pktfifo.hh
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2002-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DEV_PKTFIFO_HH__
+#define __DEV_PKTFIFO_HH__
+
+#include <iosfwd>
+#include <list>
+#include <string>
+
+#include "dev/etherpkt.hh"
+#include "sim/serialize.hh"
+
+class Checkpoint;
+class PacketFifo
+{
+ protected:
+ std::list<PacketPtr> fifo;
+ int _maxsize;
+ int _size;
+ int _reserved;
+
+ public:
+ explicit PacketFifo(int max) : _maxsize(max), _size(0), _reserved(0) {}
+ virtual ~PacketFifo() {}
+
+ int packets() const { return fifo.size(); }
+ int maxsize() const { return _maxsize; }
+ int size() const { return _size; }
+ int reserved() const { return _reserved; }
+ int avail() const { return _maxsize - _size - _reserved; }
+ bool empty() const { return size() <= 0; }
+ bool full() const { return avail() <= 0; }
+
+ int reserve(int len = 0)
+ {
+ _reserved += len;
+ assert(avail() >= 0);
+ return _reserved;
+ }
+
+ bool push(PacketPtr ptr)
+ {
+ assert(_reserved <= ptr->length);
+ if (avail() < ptr->length - _reserved)
+ return false;
+
+ _size += ptr->length;
+ fifo.push_back(ptr);
+ _reserved = 0;
+ return true;
+ }
+
+ PacketPtr front() { return fifo.front(); }
+
+ void pop()
+ {
+ if (empty())
+ return;
+
+ _size -= fifo.front()->length;
+ fifo.front() = NULL;
+ fifo.pop_front();
+ }
+
+ void clear()
+ {
+ fifo.clear();
+ _size = 0;
+ _reserved = 0;
+ }
+
+/**
+ * Serialization stuff
+ */
+ public:
+ void serialize(const std::string &base, std::ostream &os);
+ void unserialize(const std::string &base,
+ Checkpoint *cp, const std::string &section);
+};
+
+#endif // __DEV_PKTFIFO_HH__
diff --git a/dev/platform.cc b/dev/platform.cc
index 8515d543a..cf012352b 100644
--- a/dev/platform.cc
+++ b/dev/platform.cc
@@ -32,5 +32,23 @@
using namespace std;
+void
+Platform::postPciInt(int line)
+{
+ panic("No PCI interrupt support in platform.");
+}
+
+void
+Platform::clearPciInt(int line)
+{
+ panic("No PCI interrupt support in platform.");
+}
+
+Addr
+Platform::pciToDma(Addr pciAddr) const
+{
+ panic("No PCI dma support in platform.");
+}
+
DEFINE_SIM_OBJECT_CLASS_NAME("Platform", Platform)
diff --git a/dev/platform.hh b/dev/platform.hh
index 7920480bc..717e49411 100644
--- a/dev/platform.hh
+++ b/dev/platform.hh
@@ -35,6 +35,7 @@
#define __PLATFORM_HH_
#include "sim/sim_object.hh"
+#include "targetarch/isa_traits.hh"
class PciConfigAll;
class IntrControl;
@@ -65,6 +66,9 @@ class Platform : public SimObject
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;
};
#endif // __PLATFORM_HH_
diff --git a/dev/simconsole.cc b/dev/simconsole.cc
index a15057402..d8d890e15 100644
--- a/dev/simconsole.cc
+++ b/dev/simconsole.cc
@@ -45,12 +45,11 @@
#include "base/misc.hh"
#include "base/socket.hh"
#include "base/trace.hh"
+#include "dev/platform.hh"
#include "dev/simconsole.hh"
+#include "dev/uart.hh"
#include "mem/functional_mem/memory_control.hh"
#include "sim/builder.hh"
-#include "targetarch/ev5.hh"
-#include "dev/uart.hh"
-#include "dev/platform.hh"
using namespace std;
@@ -72,27 +71,22 @@ SimConsole::Event::process(int revent)
cons->detach();
}
-SimConsole::SimConsole(const string &name, const string &file, int num)
+SimConsole::SimConsole(const string &name, std::ostream *os, int num)
: SimObject(name), event(NULL), number(num), in_fd(-1), out_fd(-1),
- listener(NULL), txbuf(16384), rxbuf(16384), outfile(NULL)
+ listener(NULL), txbuf(16384), rxbuf(16384), outfile(os)
#if TRACING_ON == 1
, linebuf(16384)
#endif
{
- if (!file.empty())
- outfile = new ofstream(file.c_str());
-
if (outfile)
outfile->setf(ios::unitbuf);
-
}
SimConsole::~SimConsole()
{
close();
-
if (outfile)
- delete outfile;
+ closeOutputStream(outfile);
}
void
@@ -311,7 +305,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SimConsole)
INIT_PARAM(listener, "console listener"),
INIT_PARAM(intr_control, "interrupt controller"),
- INIT_PARAM_DFLT(output, "file to dump output to", ""),
+ INIT_PARAM(output, "file to dump output to"),
INIT_PARAM_DFLT(append_name, "append name() to filename", true),
INIT_PARAM_DFLT(number, "console number", 0)
@@ -319,18 +313,18 @@ END_INIT_SIM_OBJECT_PARAMS(SimConsole)
CREATE_SIM_OBJECT(SimConsole)
{
- string filename = output;
- if (filename.empty()) {
- if (!outputDirectory.empty())
- filename = outputDirectory + getInstanceName();
+ string filename;
+
+ if (!output.isValid()) {
+ filename = getInstanceName();
+ } else if (append_name) {
+ filename = (string)output + "." + getInstanceName();
} else {
- if (append_name)
- filename += "." + getInstanceName();
- if (!outputDirectory.empty())
- filename = outputDirectory + filename;
+ filename = output;
}
- SimConsole *console = new SimConsole(getInstanceName(), filename, number);
+ SimConsole *console = new SimConsole(getInstanceName(),
+ makeOutputStream(filename), number);
((ConsoleListener *)listener)->add(console);
return console;
diff --git a/dev/simconsole.hh b/dev/simconsole.hh
index 138e2e36a..c5a281834 100644
--- a/dev/simconsole.hh
+++ b/dev/simconsole.hh
@@ -70,7 +70,7 @@ class SimConsole : public SimObject
ConsoleListener *listener;
public:
- SimConsole(const std::string &name, const std::string &file, int num);
+ SimConsole(const std::string &name, std::ostream *os, int num);
~SimConsole();
protected:
diff --git a/dev/sinic.cc b/dev/sinic.cc
new file mode 100644
index 000000000..56782b589
--- /dev/null
+++ b/dev/sinic.cc
@@ -0,0 +1,1433 @@
+/*
+ * Copyright (c) 2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cstdio>
+#include <deque>
+#include <string>
+
+#include "base/inet.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/intr_control.hh"
+#include "dev/dma.hh"
+#include "dev/etherlink.hh"
+#include "dev/sinic.hh"
+#include "dev/pciconfigall.hh"
+#include "mem/bus/bus.hh"
+#include "mem/bus/dma_interface.hh"
+#include "mem/bus/pio_interface.hh"
+#include "mem/bus/pio_interface_impl.hh"
+#include "mem/functional_mem/memory_control.hh"
+#include "mem/functional_mem/physical_memory.hh"
+#include "sim/builder.hh"
+#include "sim/debug.hh"
+#include "sim/eventq.hh"
+#include "sim/host.hh"
+#include "sim/stats.hh"
+#include "targetarch/vtophys.hh"
+
+using namespace Net;
+
+namespace Sinic {
+
+const char *RxStateStrings[] =
+{
+ "rxIdle",
+ "rxFifoBlock",
+ "rxBeginCopy",
+ "rxCopy",
+ "rxCopyDone"
+};
+
+const char *TxStateStrings[] =
+{
+ "txIdle",
+ "txFifoBlock",
+ "txBeginCopy",
+ "txCopy",
+ "txCopyDone"
+};
+
+
+///////////////////////////////////////////////////////////////////////
+//
+// Sinic PCI Device
+//
+Base::Base(Params *p)
+ : PciDev(p), rxEnable(false), txEnable(false),
+ intrDelay(US2Ticks(p->intr_delay)),
+ intrTick(0), cpuIntrEnable(false), cpuPendingIntr(false), intrEvent(0),
+ interface(NULL)
+{
+}
+
+Device::Device(Params *p)
+ : Base(p), plat(p->plat), physmem(p->physmem),
+ rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size),
+ rxKickTick(0), txKickTick(0),
+ txEvent(this), rxDmaEvent(this), txDmaEvent(this),
+ dmaReadDelay(p->dma_read_delay), dmaReadFactor(p->dma_read_factor),
+ dmaWriteDelay(p->dma_write_delay), dmaWriteFactor(p->dma_write_factor)
+{
+ reset();
+
+ if (p->header_bus) {
+ pioInterface = newPioInterface(p->name, p->hier, p->header_bus, this,
+ &Device::cacheAccess);
+
+ pioLatency = p->pio_latency * p->header_bus->clockRatio;
+
+ if (p->payload_bus)
+ dmaInterface = new DMAInterface<Bus>(p->name + ".dma",
+ p->header_bus, p->payload_bus,
+ 1);
+ else
+ dmaInterface = new DMAInterface<Bus>(p->name + ".dma",
+ p->header_bus, p->header_bus,
+ 1);
+ } else if (p->payload_bus) {
+ pioInterface = newPioInterface(p->name, p->hier, p->payload_bus, this,
+ &Device::cacheAccess);
+
+ pioLatency = p->pio_latency * p->payload_bus->clockRatio;
+
+ dmaInterface = new DMAInterface<Bus>(p->name + ".dma", p->payload_bus,
+ p->payload_bus, 1);
+ }
+}
+
+Device::~Device()
+{}
+
+void
+Device::regStats()
+{
+ rxBytes
+ .name(name() + ".rxBytes")
+ .desc("Bytes Received")
+ .prereq(rxBytes)
+ ;
+
+ rxBandwidth
+ .name(name() + ".rxBandwidth")
+ .desc("Receive Bandwidth (bits/s)")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ rxPackets
+ .name(name() + ".rxPackets")
+ .desc("Number of Packets Received")
+ .prereq(rxBytes)
+ ;
+
+ rxPacketRate
+ .name(name() + ".rxPPS")
+ .desc("Packet Reception Rate (packets/s)")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ rxIpPackets
+ .name(name() + ".rxIpPackets")
+ .desc("Number of IP Packets Received")
+ .prereq(rxBytes)
+ ;
+
+ rxTcpPackets
+ .name(name() + ".rxTcpPackets")
+ .desc("Number of Packets Received")
+ .prereq(rxBytes)
+ ;
+
+ rxUdpPackets
+ .name(name() + ".rxUdpPackets")
+ .desc("Number of UDP Packets Received")
+ .prereq(rxBytes)
+ ;
+
+ rxIpChecksums
+ .name(name() + ".rxIpChecksums")
+ .desc("Number of rx IP Checksums done by device")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ rxTcpChecksums
+ .name(name() + ".rxTcpChecksums")
+ .desc("Number of rx TCP Checksums done by device")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ rxUdpChecksums
+ .name(name() + ".rxUdpChecksums")
+ .desc("Number of rx UDP Checksums done by device")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ txBytes
+ .name(name() + ".txBytes")
+ .desc("Bytes Transmitted")
+ .prereq(txBytes)
+ ;
+
+ txBandwidth
+ .name(name() + ".txBandwidth")
+ .desc("Transmit Bandwidth (bits/s)")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ txPackets
+ .name(name() + ".txPackets")
+ .desc("Number of Packets Transmitted")
+ .prereq(txBytes)
+ ;
+
+ txPacketRate
+ .name(name() + ".txPPS")
+ .desc("Packet Tranmission Rate (packets/s)")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ txIpPackets
+ .name(name() + ".txIpPackets")
+ .desc("Number of IP Packets Transmitted")
+ .prereq(txBytes)
+ ;
+
+ txTcpPackets
+ .name(name() + ".txTcpPackets")
+ .desc("Number of TCP Packets Transmitted")
+ .prereq(txBytes)
+ ;
+
+ txUdpPackets
+ .name(name() + ".txUdpPackets")
+ .desc("Number of Packets Transmitted")
+ .prereq(txBytes)
+ ;
+
+ txIpChecksums
+ .name(name() + ".txIpChecksums")
+ .desc("Number of tx IP Checksums done by device")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ txTcpChecksums
+ .name(name() + ".txTcpChecksums")
+ .desc("Number of tx TCP Checksums done by device")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ txUdpChecksums
+ .name(name() + ".txUdpChecksums")
+ .desc("Number of tx UDP Checksums done by device")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ txBandwidth = txBytes * Stats::constant(8) / simSeconds;
+ rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
+ txPacketRate = txPackets / simSeconds;
+ rxPacketRate = rxPackets / simSeconds;
+}
+
+/**
+ * This is to write to the PCI general configuration registers
+ */
+void
+Device::WriteConfig(int offset, int size, uint32_t data)
+{
+ switch (offset) {
+ case PCI0_BASE_ADDR0:
+ // Need to catch writes to BARs to update the PIO interface
+ PciDev::WriteConfig(offset, size, data);
+ if (BARAddrs[0] != 0) {
+ if (pioInterface)
+ pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
+
+ BARAddrs[0] &= EV5::PAddrUncachedMask;
+ }
+ break;
+
+ default:
+ PciDev::WriteConfig(offset, size, data);
+ }
+}
+
+/**
+ * This reads the device registers, which are detailed in the NS83820
+ * spec sheet
+ */
+Fault
+Device::read(MemReqPtr &req, uint8_t *data)
+{
+ assert(config.hdr.command & PCI_CMD_MSE);
+
+ //The mask is to give you only the offset into the device register file
+ Addr daddr = req->paddr & 0xfff;
+
+ if (Regs::regSize(daddr) == 0)
+ panic("invalid address: da=%#x pa=%#x va=%#x size=%d",
+ daddr, req->paddr, req->vaddr, req->size);
+
+ if (req->size != Regs::regSize(daddr))
+ panic("invalid size for reg %s: da=%#x pa=%#x va=%#x size=%d",
+ Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
+
+ DPRINTF(EthernetPIO, "read reg=%s da=%#x pa=%#x va=%#x size=%d\n",
+ Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
+
+ uint32_t &reg32 = *(uint32_t *)data;
+ uint64_t &reg64 = *(uint64_t *)data;
+
+ switch (daddr) {
+ case Regs::Config:
+ reg32 = regs.Config;
+ break;
+
+ case Regs::RxMaxCopy:
+ reg32 = regs.RxMaxCopy;
+ break;
+
+ case Regs::TxMaxCopy:
+ reg32 = regs.TxMaxCopy;
+ break;
+
+ case Regs::RxThreshold:
+ reg32 = regs.RxThreshold;
+ break;
+
+ case Regs::TxThreshold:
+ reg32 = regs.TxThreshold;
+ break;
+
+ case Regs::IntrStatus:
+ reg32 = regs.IntrStatus;
+ devIntrClear();
+ break;
+
+ case Regs::IntrMask:
+ reg32 = regs.IntrMask;
+ break;
+
+ case Regs::RxData:
+ reg64 = regs.RxData;
+ break;
+
+ case Regs::RxDone:
+ case Regs::RxWait:
+ reg64 = Regs::set_RxDone_FifoLen(regs.RxDone,
+ min(rxFifo.packets(), 255));
+ break;
+
+ case Regs::TxData:
+ reg64 = regs.TxData;
+ break;
+
+ case Regs::TxDone:
+ case Regs::TxWait:
+ reg64 = Regs::set_TxDone_FifoLen(regs.TxDone,
+ min(txFifo.packets(), 255));
+ break;
+
+ case Regs::HwAddr:
+ reg64 = params()->eaddr;
+ break;
+
+ default:
+ panic("reading write only register %s: da=%#x pa=%#x va=%#x size=%d",
+ Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
+ }
+
+ DPRINTF(EthernetPIO, "read reg=%s done val=%#x\n", Regs::regName(daddr),
+ Regs::regSize(daddr) == 4 ? reg32 : reg64);
+
+ return No_Fault;
+}
+
+Fault
+Device::write(MemReqPtr &req, const uint8_t *data)
+{
+ assert(config.hdr.command & PCI_CMD_MSE);
+ Addr daddr = req->paddr & 0xfff;
+
+ if (Regs::regSize(daddr) == 0)
+ panic("invalid address: da=%#x pa=%#x va=%#x size=%d",
+ daddr, req->paddr, req->vaddr, req->size);
+
+ if (req->size != Regs::regSize(daddr))
+ panic("invalid size: reg=%s da=%#x pa=%#x va=%#x size=%d",
+ Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
+
+ uint32_t reg32 = *(uint32_t *)data;
+ uint64_t reg64 = *(uint64_t *)data;
+
+ DPRINTF(EthernetPIO, "write reg=%s val=%#x da=%#x pa=%#x va=%#x size=%d\n",
+ Regs::regName(daddr), Regs::regSize(daddr) == 4 ? reg32 : reg64,
+ daddr, req->paddr, req->vaddr, req->size);
+
+
+ switch (daddr) {
+ case Regs::Config:
+ changeConfig(reg32);
+ break;
+
+ case Regs::RxThreshold:
+ regs.RxThreshold = reg32;
+ break;
+
+ case Regs::TxThreshold:
+ regs.TxThreshold = reg32;
+ break;
+
+ case Regs::IntrMask:
+ devIntrChangeMask(reg32);
+ break;
+
+ case Regs::RxData:
+ if (rxState != rxIdle)
+ panic("receive machine busy with another request!");
+
+ regs.RxDone = 0;
+ regs.RxData = reg64;
+ if (rxEnable) {
+ rxState = rxFifoBlock;
+ rxKick();
+ }
+ break;
+
+ case Regs::TxData:
+ if (txState != txIdle)
+ panic("transmit machine busy with another request!");
+
+ regs.TxDone = 0;
+ regs.TxData = reg64;
+ if (txEnable) {
+ txState = txFifoBlock;
+ txKick();
+ }
+ break;
+
+ default:
+ panic("writing read only register %s: da=%#x pa=%#x va=%#x size=%d",
+ Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
+ }
+
+ return No_Fault;
+}
+
+void
+Device::devIntrPost(uint32_t interrupts)
+{
+ if ((interrupts & Regs::Intr_Res))
+ panic("Cannot set a reserved interrupt");
+
+ regs.IntrStatus |= interrupts;
+
+ DPRINTF(EthernetIntr,
+ "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n",
+ interrupts, regs.IntrStatus, regs.IntrMask);
+
+ if ((regs.IntrStatus & regs.IntrMask)) {
+ Tick when = curTick;
+ if ((regs.IntrStatus & regs.IntrMask & Regs::Intr_NoDelay) == 0)
+ when += intrDelay;
+ cpuIntrPost(when);
+ }
+}
+
+void
+Device::devIntrClear(uint32_t interrupts)
+{
+ if ((interrupts & Regs::Intr_Res))
+ panic("Cannot clear a reserved interrupt");
+
+ regs.IntrStatus &= ~interrupts;
+
+ DPRINTF(EthernetIntr,
+ "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n",
+ interrupts, regs.IntrStatus, regs.IntrMask);
+
+ if (!(regs.IntrStatus & regs.IntrMask))
+ cpuIntrClear();
+}
+
+void
+Device::devIntrChangeMask(uint32_t newmask)
+{
+ if (regs.IntrMask == newmask)
+ return;
+
+ regs.IntrMask = newmask;
+
+ DPRINTF(EthernetIntr,
+ "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n",
+ regs.IntrStatus, regs.IntrMask, regs.IntrStatus & regs.IntrMask);
+
+ if (regs.IntrStatus & regs.IntrMask)
+ cpuIntrPost(curTick);
+ else
+ cpuIntrClear();
+}
+
+void
+Base::cpuIntrPost(Tick when)
+{
+ // If the interrupt you want to post is later than an interrupt
+ // already scheduled, just let it post in the coming one and don't
+ // schedule another.
+ // HOWEVER, must be sure that the scheduled intrTick is in the
+ // future (this was formerly the source of a bug)
+ /**
+ * @todo this warning should be removed and the intrTick code should
+ * be fixed.
+ */
+ assert(when >= curTick);
+ assert(intrTick >= curTick || intrTick == 0);
+ if (!cpuIntrEnable) {
+ DPRINTF(EthernetIntr, "interrupts not enabled.\n",
+ intrTick);
+ return;
+ }
+
+ if (when > intrTick && intrTick != 0) {
+ DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
+ intrTick);
+ return;
+ }
+
+ intrTick = when;
+ if (intrTick < curTick) {
+ debug_break();
+ intrTick = curTick;
+ }
+
+ DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
+ intrTick);
+
+ if (intrEvent)
+ intrEvent->squash();
+ intrEvent = new IntrEvent(this, true);
+ intrEvent->schedule(intrTick);
+}
+
+void
+Base::cpuInterrupt()
+{
+ assert(intrTick == curTick);
+
+ // Whether or not there's a pending interrupt, we don't care about
+ // it anymore
+ intrEvent = 0;
+ intrTick = 0;
+
+ // Don't send an interrupt if there's already one
+ if (cpuPendingIntr) {
+ DPRINTF(EthernetIntr,
+ "would send an interrupt now, but there's already pending\n");
+ } else {
+ // Send interrupt
+ cpuPendingIntr = true;
+
+ DPRINTF(EthernetIntr, "posting interrupt\n");
+ intrPost();
+ }
+}
+
+void
+Base::cpuIntrClear()
+{
+ if (!cpuPendingIntr)
+ return;
+
+ if (intrEvent) {
+ intrEvent->squash();
+ intrEvent = 0;
+ }
+
+ intrTick = 0;
+
+ cpuPendingIntr = false;
+
+ DPRINTF(EthernetIntr, "clearing cchip interrupt\n");
+ intrClear();
+}
+
+bool
+Base::cpuIntrPending() const
+{ return cpuPendingIntr; }
+
+void
+Device::changeConfig(uint32_t newconf)
+{
+ uint32_t changed = regs.Config ^ newconf;
+ if (!changed)
+ return;
+
+ regs.Config = newconf;
+
+ if ((changed & Regs::Config_Reset)) {
+ assert(regs.Config & Regs::Config_Reset);
+ reset();
+ regs.Config &= ~Regs::Config_Reset;
+ }
+
+ if ((changed & Regs::Config_IntEn)) {
+ cpuIntrEnable = regs.Config & Regs::Config_IntEn;
+ if (cpuIntrEnable) {
+ if (regs.IntrStatus & regs.IntrMask)
+ cpuIntrPost(curTick);
+ } else {
+ cpuIntrClear();
+ }
+ }
+
+ if ((changed & Regs::Config_TxEn)) {
+ txEnable = regs.Config & Regs::Config_TxEn;
+ if (txEnable)
+ txKick();
+ }
+
+ if ((changed & Regs::Config_RxEn)) {
+ rxEnable = regs.Config & Regs::Config_RxEn;
+ if (rxEnable)
+ rxKick();
+ }
+}
+
+void
+Device::reset()
+{
+ using namespace Regs;
+ memset(&regs, 0, sizeof(regs));
+ regs.RxMaxCopy = params()->rx_max_copy;
+ regs.TxMaxCopy = params()->tx_max_copy;
+ regs.IntrMask = Intr_TxFifo | Intr_RxFifo | Intr_RxData;
+
+ rxState = rxIdle;
+ txState = txIdle;
+
+ rxFifo.clear();
+ txFifo.clear();
+}
+
+void
+Device::rxDmaCopy()
+{
+ assert(rxState == rxCopy);
+ rxState = rxCopyDone;
+ physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen);
+ DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
+ rxDmaAddr, rxDmaLen);
+ DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
+}
+
+void
+Device::rxDmaDone()
+{
+ rxDmaCopy();
+ rxKick();
+}
+
+void
+Device::rxKick()
+{
+ DPRINTF(EthernetSM, "receive kick rxState=%s (rxFifo.size=%d)\n",
+ RxStateStrings[rxState], rxFifo.size());
+
+ if (rxKickTick > curTick) {
+ DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
+ rxKickTick);
+ return;
+ }
+
+ next:
+ switch (rxState) {
+ case rxIdle:
+ if (rxPioRequest) {
+ pioInterface->respond(rxPioRequest, curTick);
+ rxPioRequest = 0;
+ }
+ goto exit;
+
+ case rxFifoBlock:
+ if (rxPacket) {
+ rxState = rxBeginCopy;
+ break;
+ }
+
+ if (rxFifo.empty()) {
+ DPRINTF(EthernetSM, "receive waiting for data. Nothing to do.\n");
+ goto exit;
+ }
+
+ // Grab a new packet from the fifo.
+ rxPacket = rxFifo.front();
+ rxPacketBufPtr = rxPacket->data;
+ rxPktBytes = rxPacket->length;
+ assert(rxPktBytes);
+
+ rxDoneData = 0;
+ /* scope for variables */ {
+ IpPtr ip(rxPacket);
+ if (ip) {
+ rxDoneData |= Regs::RxDone_IpPacket;
+ rxIpChecksums++;
+ if (cksum(ip) != 0) {
+ DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
+ rxDoneData |= Regs::RxDone_IpError;
+ }
+ TcpPtr tcp(ip);
+ UdpPtr udp(ip);
+ if (tcp) {
+ rxDoneData |= Regs::RxDone_TcpPacket;
+ rxTcpChecksums++;
+ if (cksum(tcp) != 0) {
+ DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
+ rxDoneData |= Regs::RxDone_TcpError;
+ }
+ } else if (udp) {
+ rxDoneData |= Regs::RxDone_UdpPacket;
+ rxUdpChecksums++;
+ if (cksum(udp) != 0) {
+ DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
+ rxDoneData |= Regs::RxDone_UdpError;
+ }
+ }
+ }
+ }
+ rxState = rxBeginCopy;
+ break;
+
+ case rxBeginCopy:
+ rxDmaAddr = plat->pciToDma(Regs::get_RxData_Addr(regs.RxData));
+ rxDmaLen = min<int>(Regs::get_RxData_Len(regs.RxData), rxPktBytes);
+ rxDmaData = rxPacketBufPtr;
+
+ if (dmaInterface) {
+ if (!dmaInterface->busy()) {
+ dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen,
+ curTick, &rxDmaEvent, true);
+ rxState = rxCopy;
+ }
+ goto exit;
+ }
+
+ rxState = rxCopy;
+ if (dmaWriteDelay != 0 || dmaWriteFactor != 0) {
+ Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor;
+ Tick start = curTick + dmaWriteDelay + factor;
+ rxDmaEvent.schedule(start);
+ goto exit;
+ }
+
+ rxDmaCopy();
+ break;
+
+ case rxCopy:
+ DPRINTF(EthernetSM, "receive machine still copying\n");
+ goto exit;
+
+ case rxCopyDone:
+ regs.RxDone = rxDoneData | rxDmaLen;
+
+ if (rxPktBytes == rxDmaLen) {
+ rxPacket = NULL;
+ rxFifo.pop();
+ } else {
+ regs.RxDone |= Regs::RxDone_More;
+ rxPktBytes -= rxDmaLen;
+ rxPacketBufPtr += rxDmaLen;
+ }
+
+ regs.RxDone |= Regs::RxDone_Complete;
+ devIntrPost(Regs::Intr_RxData);
+ rxState = rxIdle;
+ break;
+
+ default:
+ panic("Invalid rxState!");
+ }
+
+ DPRINTF(EthernetSM, "entering next rxState=%s\n",
+ RxStateStrings[rxState]);
+
+ goto next;
+
+ exit:
+ /**
+ * @todo do we want to schedule a future kick?
+ */
+ DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
+ RxStateStrings[rxState]);
+}
+
+void
+Device::txDmaCopy()
+{
+ assert(txState == txCopy);
+ txState = txCopyDone;
+ physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen);
+ DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n",
+ txDmaAddr, txDmaLen);
+ DDUMP(EthernetDMA, txDmaData, txDmaLen);
+}
+
+void
+Device::txDmaDone()
+{
+ txDmaCopy();
+ txKick();
+}
+
+void
+Device::transmit()
+{
+ if (txFifo.empty()) {
+ DPRINTF(Ethernet, "nothing to transmit\n");
+ return;
+ }
+
+ PacketPtr packet = txFifo.front();
+ if (!interface->sendPacket(packet)) {
+ DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n",
+ txFifo.avail());
+ goto reschedule;
+ }
+
+ txFifo.pop();
+
+#if TRACING_ON
+ if (DTRACE(Ethernet)) {
+ IpPtr ip(packet);
+ if (ip) {
+ DPRINTF(Ethernet, "ID is %d\n", ip->id());
+ TcpPtr tcp(ip);
+ if (tcp) {
+ DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n",
+ tcp->sport(), tcp->dport());
+ }
+ }
+ }
+#endif
+
+ DDUMP(Ethernet, packet->data, packet->length);
+ txBytes += packet->length;
+ txPackets++;
+
+ DPRINTF(Ethernet, "Packet Transmit: successful txFifo Available %d\n",
+ txFifo.avail());
+
+ if (txFifo.size() <= params()->tx_fifo_threshold)
+ devIntrPost(Regs::Intr_TxFifo);
+
+ devIntrPost(Regs::Intr_TxDone);
+
+ reschedule:
+ if (!txFifo.empty() && !txEvent.scheduled()) {
+ DPRINTF(Ethernet, "reschedule transmit\n");
+ txEvent.schedule(curTick + 1000);
+ }
+}
+
+void
+Device::txKick()
+{
+ DPRINTF(EthernetSM, "transmit kick txState=%s (txFifo.size=%d)\n",
+ TxStateStrings[txState], txFifo.size());
+
+ if (txKickTick > curTick) {
+ DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
+ txKickTick);
+ return;
+ }
+
+ next:
+ switch (txState) {
+ case txIdle:
+ if (txPioRequest) {
+ pioInterface->respond(txPioRequest, curTick + pioLatency);
+ txPioRequest = 0;
+ }
+ goto exit;
+
+ case txFifoBlock:
+ if (!txPacket) {
+ // Grab a new packet from the fifo.
+ txPacket = new PacketData(16384);
+ txPacketBufPtr = txPacket->data;
+ }
+
+ if (txFifo.avail() - txPacket->length <
+ Regs::get_TxData_Len(regs.TxData)) {
+ DPRINTF(EthernetSM, "transmit fifo full. Nothing to do.\n");
+ goto exit;
+ }
+
+ txState = txBeginCopy;
+ break;
+
+ case txBeginCopy:
+ txDmaAddr = plat->pciToDma(Regs::get_TxData_Addr(regs.TxData));
+ txDmaLen = Regs::get_TxData_Len(regs.TxData);
+ txDmaData = txPacketBufPtr;
+
+ if (dmaInterface) {
+ if (!dmaInterface->busy()) {
+ dmaInterface->doDMA(Read, txDmaAddr, txDmaLen,
+ curTick, &txDmaEvent, true);
+ txState = txCopy;
+ }
+
+ goto exit;
+ }
+
+ txState = txCopy;
+ if (dmaReadDelay != 0 || dmaReadFactor != 0) {
+ Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor;
+ Tick start = curTick + dmaReadDelay + factor;
+ txDmaEvent.schedule(start);
+ goto exit;
+ }
+
+ txDmaCopy();
+ break;
+
+ case txCopy:
+ DPRINTF(EthernetSM, "transmit machine still copying\n");
+ goto exit;
+
+ case txCopyDone:
+ txPacket->length += txDmaLen;
+ if ((regs.TxData & Regs::TxData_More)) {
+ txPacketBufPtr += txDmaLen;
+ } else {
+ assert(txPacket->length <= txFifo.avail());
+ if ((regs.TxData & Regs::TxData_Checksum)) {
+ IpPtr ip(txPacket);
+ if (ip) {
+ TcpPtr tcp(ip);
+ if (tcp) {
+ tcp->sum(0);
+ tcp->sum(cksum(tcp));
+ txTcpChecksums++;
+ }
+
+ UdpPtr udp(ip);
+ if (udp) {
+ udp->sum(0);
+ udp->sum(cksum(udp));
+ txUdpChecksums++;
+ }
+
+ ip->sum(0);
+ ip->sum(cksum(ip));
+ txIpChecksums++;
+ }
+ }
+ txFifo.push(txPacket);
+ txPacket = 0;
+ transmit();
+ }
+
+ regs.TxDone = txDmaLen | Regs::TxDone_Complete;
+ devIntrPost(Regs::Intr_TxData);
+ txState = txIdle;
+ break;
+
+ default:
+ panic("Invalid txState!");
+ }
+
+ DPRINTF(EthernetSM, "entering next txState=%s\n",
+ TxStateStrings[txState]);
+
+ goto next;
+
+ exit:
+ /**
+ * @todo do we want to schedule a future kick?
+ */
+ DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
+ TxStateStrings[txState]);
+}
+
+void
+Device::transferDone()
+{
+ if (txFifo.empty()) {
+ DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
+ return;
+ }
+
+ DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
+
+ if (txEvent.scheduled())
+ txEvent.reschedule(curTick + 1);
+ else
+ txEvent.schedule(curTick + 1);
+}
+
+bool
+Device::rxFilter(const PacketPtr &packet)
+{
+ if (!Regs::get_Config_Filter(regs.Config))
+ return false;
+
+ panic("receive filter not implemented\n");
+ bool drop = true;
+
+#if 0
+ string type;
+
+ EthHdr *eth = packet->eth();
+ if (eth->unicast()) {
+ // If we're accepting all unicast addresses
+ if (acceptUnicast)
+ drop = false;
+
+ // If we make a perfect match
+ if (acceptPerfect && params->eaddr == eth.dst())
+ drop = false;
+
+ if (acceptArp && eth->type() == ETH_TYPE_ARP)
+ drop = false;
+
+ } else if (eth->broadcast()) {
+ // if we're accepting broadcasts
+ if (acceptBroadcast)
+ drop = false;
+
+ } else if (eth->multicast()) {
+ // if we're accepting all multicasts
+ if (acceptMulticast)
+ drop = false;
+
+ }
+
+ if (drop) {
+ DPRINTF(Ethernet, "rxFilter drop\n");
+ DDUMP(EthernetData, packet->data, packet->length);
+ }
+#endif
+ return drop;
+}
+
+bool
+Device::recvPacket(PacketPtr packet)
+{
+ rxBytes += packet->length;
+ rxPackets++;
+
+ DPRINTF(Ethernet, "Receiving packet from wire, rxFifo Available is %d\n",
+ rxFifo.avail());
+
+ if (!rxEnable) {
+ DPRINTF(Ethernet, "receive disabled...packet dropped\n");
+ interface->recvDone();
+ return true;
+ }
+
+ if (rxFilter(packet)) {
+ DPRINTF(Ethernet, "packet filtered...dropped\n");
+ interface->recvDone();
+ return true;
+ }
+
+ if (rxFifo.size() >= params()->rx_fifo_threshold)
+ devIntrPost(Regs::Intr_RxFifo);
+
+ if (!rxFifo.push(packet)) {
+ DPRINTF(Ethernet,
+ "packet will not fit in receive buffer...packet dropped\n");
+ return false;
+ }
+
+ interface->recvDone();
+ devIntrPost(Regs::Intr_RxDone);
+ rxKick();
+ return true;
+}
+
+//=====================================================================
+//
+//
+void
+Base::serialize(ostream &os)
+{
+ // Serialize the PciDev base class
+ PciDev::serialize(os);
+
+ SERIALIZE_SCALAR(rxEnable);
+ SERIALIZE_SCALAR(txEnable);
+ SERIALIZE_SCALAR(cpuIntrEnable);
+
+ /*
+ * Keep track of pending interrupt status.
+ */
+ SERIALIZE_SCALAR(intrTick);
+ SERIALIZE_SCALAR(cpuPendingIntr);
+ Tick intrEventTick = 0;
+ if (intrEvent)
+ intrEventTick = intrEvent->when();
+ SERIALIZE_SCALAR(intrEventTick);
+}
+
+void
+Base::unserialize(Checkpoint *cp, const std::string &section)
+{
+ // Unserialize the PciDev base class
+ PciDev::unserialize(cp, section);
+
+ UNSERIALIZE_SCALAR(rxEnable);
+ UNSERIALIZE_SCALAR(txEnable);
+ UNSERIALIZE_SCALAR(cpuIntrEnable);
+
+ /*
+ * Keep track of pending interrupt status.
+ */
+ UNSERIALIZE_SCALAR(intrTick);
+ UNSERIALIZE_SCALAR(cpuPendingIntr);
+ Tick intrEventTick;
+ UNSERIALIZE_SCALAR(intrEventTick);
+ if (intrEventTick) {
+ intrEvent = new IntrEvent(this, true);
+ intrEvent->schedule(intrEventTick);
+ }
+}
+
+void
+Device::serialize(ostream &os)
+{
+ // Serialize the PciDev base class
+ Base::serialize(os);
+
+ if (rxDmaEvent.scheduled())
+ rxDmaCopy();
+
+ if (txDmaEvent.scheduled())
+ txDmaCopy();
+
+ /*
+ * Serialize the device registers
+ */
+ SERIALIZE_SCALAR(regs.Config);
+ SERIALIZE_SCALAR(regs.RxMaxCopy);
+ SERIALIZE_SCALAR(regs.TxMaxCopy);
+ SERIALIZE_SCALAR(regs.RxThreshold);
+ SERIALIZE_SCALAR(regs.TxThreshold);
+ SERIALIZE_SCALAR(regs.IntrStatus);
+ SERIALIZE_SCALAR(regs.IntrMask);
+ SERIALIZE_SCALAR(regs.RxData);
+ SERIALIZE_SCALAR(regs.RxDone);
+ SERIALIZE_SCALAR(regs.TxData);
+ SERIALIZE_SCALAR(regs.TxDone);
+
+ /*
+ * Serialize rx state machine
+ */
+ int rxState = this->rxState;
+ SERIALIZE_SCALAR(rxState);
+ rxFifo.serialize("rxFifo", os);
+ bool rxPacketExists = rxPacket;
+ SERIALIZE_SCALAR(rxPacketExists);
+ if (rxPacketExists) {
+ rxPacket->serialize("rxPacket", os);
+ uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
+ SERIALIZE_SCALAR(rxPktBufPtr);
+ SERIALIZE_SCALAR(rxPktBytes);
+ }
+ SERIALIZE_SCALAR(rxDoneData);
+
+ /*
+ * Serialize tx state machine
+ */
+ int txState = this->txState;
+ SERIALIZE_SCALAR(txState);
+ txFifo.serialize("txFifo", os);
+ bool txPacketExists = txPacket;
+ SERIALIZE_SCALAR(txPacketExists);
+ if (txPacketExists) {
+ txPacket->serialize("txPacket", os);
+ uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
+ SERIALIZE_SCALAR(txPktBufPtr);
+ SERIALIZE_SCALAR(txPktBytes);
+ }
+
+ /*
+ * If there's a pending transmit, store the time so we can
+ * reschedule it later
+ */
+ Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0;
+ SERIALIZE_SCALAR(transmitTick);
+}
+
+void
+Device::unserialize(Checkpoint *cp, const std::string &section)
+{
+ // Unserialize the PciDev base class
+ Base::unserialize(cp, section);
+
+ /*
+ * Unserialize the device registers
+ */
+ UNSERIALIZE_SCALAR(regs.Config);
+ UNSERIALIZE_SCALAR(regs.RxMaxCopy);
+ UNSERIALIZE_SCALAR(regs.TxMaxCopy);
+ UNSERIALIZE_SCALAR(regs.RxThreshold);
+ UNSERIALIZE_SCALAR(regs.TxThreshold);
+ UNSERIALIZE_SCALAR(regs.IntrStatus);
+ UNSERIALIZE_SCALAR(regs.IntrMask);
+ UNSERIALIZE_SCALAR(regs.RxData);
+ UNSERIALIZE_SCALAR(regs.RxDone);
+ UNSERIALIZE_SCALAR(regs.TxData);
+ UNSERIALIZE_SCALAR(regs.TxDone);
+
+ /*
+ * Unserialize rx state machine
+ */
+ int rxState;
+ UNSERIALIZE_SCALAR(rxState);
+ this->rxState = (RxState) rxState;
+ rxFifo.unserialize("rxFifo", cp, section);
+ bool rxPacketExists;
+ UNSERIALIZE_SCALAR(rxPacketExists);
+ rxPacket = 0;
+ if (rxPacketExists) {
+ rxPacket = new PacketData(16384);
+ rxPacket->unserialize("rxPacket", cp, section);
+ uint32_t rxPktBufPtr;
+ UNSERIALIZE_SCALAR(rxPktBufPtr);
+ this->rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
+ UNSERIALIZE_SCALAR(rxPktBytes);
+ }
+ UNSERIALIZE_SCALAR(rxDoneData);
+
+ /*
+ * Unserialize tx state machine
+ */
+ int txState;
+ UNSERIALIZE_SCALAR(txState);
+ this->txState = (TxState) txState;
+ txFifo.unserialize("txFifo", cp, section);
+ bool txPacketExists;
+ UNSERIALIZE_SCALAR(txPacketExists);
+ txPacket = 0;
+ if (txPacketExists) {
+ txPacket = new PacketData(16384);
+ txPacket->unserialize("txPacket", cp, section);
+ uint32_t txPktBufPtr;
+ UNSERIALIZE_SCALAR(txPktBufPtr);
+ this->txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
+ UNSERIALIZE_SCALAR(txPktBytes);
+ }
+
+ /*
+ * If there's a pending transmit, reschedule it now
+ */
+ Tick transmitTick;
+ UNSERIALIZE_SCALAR(transmitTick);
+ if (transmitTick)
+ txEvent.schedule(curTick + transmitTick);
+
+ /*
+ * re-add addrRanges to bus bridges
+ */
+ if (pioInterface)
+ pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
+}
+
+Tick
+Device::cacheAccess(MemReqPtr &req)
+{
+ //The mask is to give you only the offset into the device register file
+ Addr daddr = req->paddr - addr;
+
+ DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n",
+ req->paddr, daddr);
+
+ Tick when = curTick + pioLatency;
+
+ switch (daddr) {
+ case Regs::RxDone:
+ if (rxState != rxIdle) {
+ rxPioRequest = req;
+ when = 0;
+ }
+ break;
+
+ case Regs::TxDone:
+ if (txState != txIdle) {
+ txPioRequest = req;
+ when = 0;
+ }
+ break;
+ }
+
+ return when;
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface)
+
+ SimObjectParam<EtherInt *> peer;
+ SimObjectParam<Device *> device;
+
+END_DECLARE_SIM_OBJECT_PARAMS(Interface)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(Interface)
+
+ INIT_PARAM_DFLT(peer, "peer interface", NULL),
+ INIT_PARAM(device, "Ethernet device of this interface")
+
+END_INIT_SIM_OBJECT_PARAMS(Interface)
+
+CREATE_SIM_OBJECT(Interface)
+{
+ Interface *dev_int = new Interface(getInstanceName(), device);
+
+ EtherInt *p = (EtherInt *)peer;
+ if (p) {
+ dev_int->setPeer(p);
+ p->setPeer(dev_int);
+ }
+
+ return dev_int;
+}
+
+REGISTER_SIM_OBJECT("SinicInt", Interface)
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
+
+ Param<Tick> tx_delay;
+ Param<Tick> rx_delay;
+ Param<Tick> intr_delay;
+ SimObjectParam<MemoryController *> mmu;
+ SimObjectParam<PhysicalMemory *> physmem;
+ Param<bool> rx_filter;
+ Param<string> hardware_address;
+ SimObjectParam<Bus*> header_bus;
+ SimObjectParam<Bus*> payload_bus;
+ SimObjectParam<HierParams *> hier;
+ Param<Tick> pio_latency;
+ SimObjectParam<PciConfigAll *> configspace;
+ SimObjectParam<PciConfigData *> configdata;
+ SimObjectParam<Platform *> platform;
+ Param<uint32_t> pci_bus;
+ Param<uint32_t> pci_dev;
+ Param<uint32_t> pci_func;
+ Param<uint32_t> rx_max_copy;
+ Param<uint32_t> tx_max_copy;
+ Param<uint32_t> rx_fifo_size;
+ Param<uint32_t> tx_fifo_size;
+ Param<uint32_t> rx_fifo_threshold;
+ Param<uint32_t> tx_fifo_threshold;
+ Param<Tick> dma_read_delay;
+ Param<Tick> dma_read_factor;
+ Param<Tick> dma_write_delay;
+ Param<Tick> dma_write_factor;
+
+END_DECLARE_SIM_OBJECT_PARAMS(Device)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(Device)
+
+ INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000),
+ INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000),
+ INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0),
+ INIT_PARAM(mmu, "Memory Controller"),
+ INIT_PARAM(physmem, "Physical Memory"),
+ INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true),
+ INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address",
+ "00:99:00:00:00:01"),
+ INIT_PARAM_DFLT(header_bus, "The IO Bus to attach to for headers", NULL),
+ INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL),
+ INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams),
+ INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
+ INIT_PARAM(configspace, "PCI Configspace"),
+ INIT_PARAM(configdata, "PCI Config data"),
+ INIT_PARAM(platform, "Platform"),
+ INIT_PARAM(pci_bus, "PCI bus"),
+ INIT_PARAM(pci_dev, "PCI device number"),
+ INIT_PARAM(pci_func, "PCI function code"),
+ INIT_PARAM_DFLT(rx_max_copy, "rx max copy", 16*1024),
+ INIT_PARAM_DFLT(tx_max_copy, "rx max copy", 16*1024),
+ INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 64*1024),
+ INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 64*1024),
+ INIT_PARAM_DFLT(rx_fifo_threshold, "max size in bytes of rxFifo", 48*1024),
+ INIT_PARAM_DFLT(tx_fifo_threshold, "max size in bytes of txFifo", 16*1024),
+ INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0),
+ INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0),
+ INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0),
+ INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0)
+
+END_INIT_SIM_OBJECT_PARAMS(Device)
+
+
+CREATE_SIM_OBJECT(Device)
+{
+ Device::Params *params = new Device::Params;
+ params->name = getInstanceName();
+ params->intr_delay = intr_delay;
+ params->physmem = physmem;
+ params->tx_delay = tx_delay;
+ params->rx_delay = rx_delay;
+ params->mmu = mmu;
+ params->hier = hier;
+ params->header_bus = header_bus;
+ params->payload_bus = payload_bus;
+ params->pio_latency = pio_latency;
+ params->configSpace = configspace;
+ params->configData = configdata;
+ params->plat = platform;
+ params->busNum = pci_bus;
+ params->deviceNum = pci_dev;
+ params->functionNum = pci_func;
+ params->rx_filter = rx_filter;
+ params->eaddr = hardware_address;
+ params->rx_max_copy = rx_max_copy;
+ params->tx_max_copy = tx_max_copy;
+ params->rx_fifo_size = rx_fifo_size;
+ params->tx_fifo_size = tx_fifo_size;
+ params->rx_fifo_threshold = rx_fifo_threshold;
+ params->tx_fifo_threshold = tx_fifo_threshold;
+ params->dma_read_delay = dma_read_delay;
+ params->dma_read_factor = dma_read_factor;
+ params->dma_write_delay = dma_write_delay;
+ params->dma_write_factor = dma_write_factor;
+ return new Device(params);
+}
+
+REGISTER_SIM_OBJECT("Sinic", Device)
+
+/* namespace Sinic */ }
diff --git a/dev/sinic.hh b/dev/sinic.hh
new file mode 100644
index 000000000..ef515ffad
--- /dev/null
+++ b/dev/sinic.hh
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DEV_SINIC_HH__
+#define __DEV_SINIC_HH__
+
+#include "base/inet.hh"
+#include "base/statistics.hh"
+#include "dev/etherint.hh"
+#include "dev/etherpkt.hh"
+#include "dev/io_device.hh"
+#include "dev/pcidev.hh"
+#include "dev/pktfifo.hh"
+#include "dev/sinicreg.hh"
+#include "mem/bus/bus.hh"
+#include "sim/eventq.hh"
+
+namespace Sinic {
+
+class Interface;
+class Base : public PciDev
+{
+ protected:
+ bool rxEnable;
+ bool txEnable;
+
+ protected:
+ Tick intrDelay;
+ Tick intrTick;
+ bool cpuIntrEnable;
+ bool cpuPendingIntr;
+ void cpuIntrPost(Tick when);
+ void cpuInterrupt();
+ void cpuIntrClear();
+
+ typedef EventWrapper<Base, &Base::cpuInterrupt> IntrEvent;
+ friend class IntrEvent;
+ IntrEvent *intrEvent;
+ Interface *interface;
+
+ bool cpuIntrPending() const;
+ void cpuIntrAck() { cpuIntrClear(); }
+
+/**
+ * Serialization stuff
+ */
+ public:
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+/**
+ * Construction/Destruction/Parameters
+ */
+ public:
+ struct Params : public PciDev::Params
+ {
+ Tick intr_delay;
+ };
+
+ Base(Params *p);
+};
+
+class Device : public Base
+{
+ protected:
+ Platform *plat;
+ PhysicalMemory *physmem;
+
+ protected:
+ /** Receive State Machine States */
+ enum RxState {
+ rxIdle,
+ rxFifoBlock,
+ rxBeginCopy,
+ rxCopy,
+ rxCopyDone
+ };
+
+ /** Transmit State Machine states */
+ enum TxState {
+ txIdle,
+ txFifoBlock,
+ txBeginCopy,
+ txCopy,
+ txCopyDone
+ };
+
+ /** device register file */
+ struct {
+ uint32_t Config;
+ uint32_t RxMaxCopy;
+ uint32_t TxMaxCopy;
+ uint32_t RxThreshold;
+ uint32_t TxThreshold;
+ uint32_t IntrStatus;
+ uint32_t IntrMask;
+ uint64_t RxData;
+ uint64_t RxDone;
+ uint64_t TxData;
+ uint64_t TxDone;
+ } regs;
+
+ private:
+ Addr addr;
+ static const Addr size = Regs::Size;
+
+ protected:
+ RxState rxState;
+ PacketFifo rxFifo;
+ PacketPtr rxPacket;
+ uint8_t *rxPacketBufPtr;
+ int rxPktBytes;
+ uint64_t rxDoneData;
+ Addr rxDmaAddr;
+ uint8_t *rxDmaData;
+ int rxDmaLen;
+
+ TxState txState;
+ PacketFifo txFifo;
+ PacketPtr txPacket;
+ uint8_t *txPacketBufPtr;
+ int txPktBytes;
+ Addr txDmaAddr;
+ uint8_t *txDmaData;
+ int txDmaLen;
+
+ protected:
+ void reset();
+
+ void rxKick();
+ Tick rxKickTick;
+ typedef EventWrapper<Device, &Device::rxKick> RxKickEvent;
+ friend class RxKickEvent;
+
+ void txKick();
+ Tick txKickTick;
+ typedef EventWrapper<Device, &Device::txKick> TxKickEvent;
+ friend class TxKickEvent;
+
+ /**
+ * Retransmit event
+ */
+ void transmit();
+ void txEventTransmit()
+ {
+ transmit();
+ if (txState == txFifoBlock)
+ txKick();
+ }
+ typedef EventWrapper<Device, &Device::txEventTransmit> TxEvent;
+ friend class TxEvent;
+ TxEvent txEvent;
+
+ void txDump() const;
+ void rxDump() const;
+
+ /**
+ * receive address filter
+ */
+ bool rxFilter(const PacketPtr &packet);
+
+/**
+ * device configuration
+ */
+ void changeConfig(uint32_t newconfig);
+
+/**
+ * device ethernet interface
+ */
+ public:
+ bool recvPacket(PacketPtr packet);
+ void transferDone();
+ void setInterface(Interface *i) { assert(!interface); interface = i; }
+
+/**
+ * DMA parameters
+ */
+ protected:
+ void rxDmaCopy();
+ void rxDmaDone();
+ friend class EventWrapper<Device, &Device::rxDmaDone>;
+ EventWrapper<Device, &Device::rxDmaDone> rxDmaEvent;
+
+ void txDmaCopy();
+ void txDmaDone();
+ friend class EventWrapper<Device, &Device::txDmaDone>;
+ EventWrapper<Device, &Device::rxDmaDone> txDmaEvent;
+
+ Tick dmaReadDelay;
+ Tick dmaReadFactor;
+ Tick dmaWriteDelay;
+ Tick dmaWriteFactor;
+
+/**
+ * PIO parameters
+ */
+ protected:
+ MemReqPtr rxPioRequest;
+ MemReqPtr txPioRequest;
+
+/**
+ * Interrupt management
+ */
+ protected:
+ void devIntrPost(uint32_t interrupts);
+ void devIntrClear(uint32_t interrupts = Regs::Intr_All);
+ void devIntrChangeMask(uint32_t newmask);
+
+/**
+ * PCI Configuration interface
+ */
+ public:
+ virtual void WriteConfig(int offset, int size, uint32_t data);
+
+/**
+ * Memory Interface
+ */
+ public:
+ virtual Fault read(MemReqPtr &req, uint8_t *data);
+ virtual Fault write(MemReqPtr &req, const uint8_t *data);
+ Tick cacheAccess(MemReqPtr &req);
+
+/**
+ * Statistics
+ */
+ private:
+ Stats::Scalar<> rxBytes;
+ Stats::Formula rxBandwidth;
+ Stats::Scalar<> rxPackets;
+ Stats::Formula rxPacketRate;
+ Stats::Scalar<> rxIpPackets;
+ Stats::Scalar<> rxTcpPackets;
+ Stats::Scalar<> rxUdpPackets;
+ Stats::Scalar<> rxIpChecksums;
+ Stats::Scalar<> rxTcpChecksums;
+ Stats::Scalar<> rxUdpChecksums;
+
+ Stats::Scalar<> txBytes;
+ Stats::Formula txBandwidth;
+ Stats::Scalar<> txPackets;
+ Stats::Formula txPacketRate;
+ Stats::Scalar<> txIpPackets;
+ Stats::Scalar<> txTcpPackets;
+ Stats::Scalar<> txUdpPackets;
+ Stats::Scalar<> txIpChecksums;
+ Stats::Scalar<> txTcpChecksums;
+ Stats::Scalar<> txUdpChecksums;
+
+ public:
+ virtual void regStats();
+
+/**
+ * Serialization stuff
+ */
+ public:
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+/**
+ * Construction/Destruction/Parameters
+ */
+ public:
+ struct Params : public Base::Params
+ {
+ IntrControl *i;
+ PhysicalMemory *pmem;
+ Tick tx_delay;
+ Tick rx_delay;
+ HierParams *hier;
+ Bus *header_bus;
+ Bus *payload_bus;
+ Tick pio_latency;
+ PhysicalMemory *physmem;
+ IntrControl *intctrl;
+ bool rx_filter;
+ Net::EthAddr eaddr;
+ uint32_t rx_max_copy;
+ uint32_t tx_max_copy;
+ uint32_t rx_fifo_size;
+ uint32_t tx_fifo_size;
+ uint32_t rx_fifo_threshold;
+ uint32_t tx_fifo_threshold;
+ Tick dma_read_delay;
+ Tick dma_read_factor;
+ Tick dma_write_delay;
+ Tick dma_write_factor;
+ };
+
+ protected:
+ const Params *params() const { return (const Params *)_params; }
+
+ public:
+ Device(Params *params);
+ ~Device();
+};
+
+/*
+ * Ethernet Interface for an Ethernet Device
+ */
+class Interface : public EtherInt
+{
+ private:
+ Device *dev;
+
+ public:
+ Interface(const std::string &name, Device *d)
+ : EtherInt(name), dev(d) { dev->setInterface(this); }
+
+ virtual bool recvPacket(PacketPtr pkt) { return dev->recvPacket(pkt); }
+ virtual void sendDone() { dev->transferDone(); }
+};
+
+/* namespace Sinic */ }
+
+#endif // __DEV_SINIC_HH__
diff --git a/dev/sinicreg.hh b/dev/sinicreg.hh
new file mode 100644
index 000000000..9f3412a31
--- /dev/null
+++ b/dev/sinicreg.hh
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DEV_SINICREG_HH__
+#define __DEV_SINICREG_HH__
+
+#define __SINIC_REG32(NAME, VAL) static const uint32_t NAME = (VAL)
+#define __SINIC_REG64(NAME, VAL) static const uint64_t NAME = (VAL)
+
+#define __SINIC_VAL32(NAME, OFFSET, WIDTH) \
+ static const uint32_t NAME##_width = WIDTH; \
+ static const uint32_t NAME##_offset = OFFSET; \
+ static const uint32_t NAME##_mask = (1 << WIDTH) - 1; \
+ static const uint32_t NAME = ((1 << WIDTH) - 1) << OFFSET; \
+ static inline uint32_t get_##NAME(uint32_t reg) \
+ { return (reg & NAME) >> OFFSET; } \
+ static inline uint32_t set_##NAME(uint32_t reg, uint32_t val) \
+ { return (reg & ~NAME) | ((val << OFFSET) & NAME); }
+
+#define __SINIC_VAL64(NAME, OFFSET, WIDTH) \
+ static const uint64_t NAME##_width = WIDTH; \
+ static const uint64_t NAME##_offset = OFFSET; \
+ static const uint64_t NAME##_mask = (ULL(1) << WIDTH) - 1; \
+ static const uint64_t NAME = ((ULL(1) << WIDTH) - 1) << OFFSET; \
+ static inline uint64_t get_##NAME(uint64_t reg) \
+ { return (reg & NAME) >> OFFSET; } \
+ static inline uint64_t set_##NAME(uint64_t reg, uint64_t val) \
+ { return (reg & ~NAME) | ((val << OFFSET) & NAME); }
+
+namespace Sinic {
+namespace Regs {
+
+// Registers
+__SINIC_REG32(Config, 0x00); // 32: configuration register
+__SINIC_REG32(RxMaxCopy, 0x04); // 32: max rx copy
+__SINIC_REG32(TxMaxCopy, 0x08); // 32: max tx copy
+__SINIC_REG32(RxThreshold, 0x0c); // 32: receive fifo threshold
+__SINIC_REG32(TxThreshold, 0x10); // 32: transmit fifo threshold
+__SINIC_REG32(IntrStatus, 0x14); // 32: interrupt status
+__SINIC_REG32(IntrMask, 0x18); // 32: interrupt mask
+__SINIC_REG32(RxData, 0x20); // 64: receive data
+__SINIC_REG32(RxDone, 0x28); // 64: receive done
+__SINIC_REG32(RxWait, 0x30); // 64: receive done (busy wait)
+__SINIC_REG32(TxData, 0x38); // 64: transmit data
+__SINIC_REG32(TxDone, 0x40); // 64: transmit done
+__SINIC_REG32(TxWait, 0x48); // 64: transmit done (busy wait)
+__SINIC_REG32(HwAddr, 0x50); // 64: mac address
+__SINIC_REG32(Size, 0x58);
+
+// Config register bits
+__SINIC_VAL32(Config_Reset, 31, 1); // reset chip
+__SINIC_VAL32(Config_Filter, 7, 1); // enable receive filter
+__SINIC_VAL32(Config_Vlan, 6, 1); // enable vlan tagging
+__SINIC_VAL32(Config_Virtual, 5, 1); // enable virtual addressing
+__SINIC_VAL32(Config_Desc, 4, 1); // enable tx/rx descriptors
+__SINIC_VAL32(Config_Poll, 3, 1); // enable polling
+__SINIC_VAL32(Config_IntEn, 2, 1); // enable interrupts
+__SINIC_VAL32(Config_TxEn, 1, 1); // enable transmit
+__SINIC_VAL32(Config_RxEn, 0, 1); // enable receive
+
+// Interrupt register bits
+__SINIC_VAL32(Intr_TxFifo, 5, 1); // Fifo oflow/uflow/threshold
+__SINIC_VAL32(Intr_TxData, 4, 1); // DMA Completed w/ interrupt
+__SINIC_VAL32(Intr_TxDone, 3, 1); // Packet transmitted
+__SINIC_VAL32(Intr_RxFifo, 2, 1); // Fifo oflow/uflow/threshold
+__SINIC_VAL32(Intr_RxData, 1, 1); // DMA Completed w/ interrupt
+__SINIC_VAL32(Intr_RxDone, 0, 1); // Packet received
+__SINIC_REG32(Intr_All, 0x3f);
+__SINIC_REG32(Intr_NoDelay, 0x24);
+__SINIC_REG32(Intr_Res, ~0x3f);
+
+// RX Data Description
+__SINIC_VAL64(RxData_Len, 40, 20); // 0 - 1M
+__SINIC_VAL64(RxData_Addr, 0, 40); // Address 1TB
+
+// TX Data Description
+__SINIC_VAL64(TxData_More, 63, 1);
+__SINIC_VAL64(TxData_Checksum, 62, 1);
+__SINIC_VAL64(TxData_Len, 40, 20); // 0 - 1M
+__SINIC_VAL64(TxData_Addr, 0, 40); // Address 1TB
+
+// RX Done/Busy Information
+__SINIC_VAL64(RxDone_Complete, 63, 1);
+__SINIC_VAL64(RxDone_IpPacket, 45, 1);
+__SINIC_VAL64(RxDone_TcpPacket, 44, 1);
+__SINIC_VAL64(RxDone_UdpPacket, 43, 1);
+__SINIC_VAL64(RxDone_IpError, 42, 1);
+__SINIC_VAL64(RxDone_TcpError, 41, 1);
+__SINIC_VAL64(RxDone_UdpError, 40, 1);
+__SINIC_VAL64(RxDone_More, 32, 1);
+__SINIC_VAL64(RxDone_FifoLen, 20, 8); // up to 255 packets
+__SINIC_VAL64(RxDone_CopyLen, 0, 20); // up to 256k
+
+// TX Done/Busy Information
+__SINIC_VAL64(TxDone_Complete, 63, 1);
+__SINIC_VAL64(TxDone_FifoLen, 20, 8); // up to 255 packets
+__SINIC_VAL64(TxDone_CopyLen, 0, 20); // up to 256k
+
+inline int
+regSize(int offset)
+{
+ static const char sizes[] = {
+ 4,
+ 4,
+ 4,
+ 4,
+ 4,
+ 4,
+ 4,
+ 0,
+ 8, 0,
+ 8, 0,
+ 8, 0,
+ 8, 0,
+ 8, 0,
+ 8, 0,
+ 8, 0
+ };
+
+ if (offset & 0x3)
+ return 0;
+
+ if (offset >= Size)
+ return 0;
+
+ return sizes[offset / 4];
+}
+
+inline const char *
+regName(int offset)
+{
+ static const char *names[] = {
+ "Config",
+ "RxMaxCopy",
+ "TxMaxCopy",
+ "RxThreshold",
+ "TxThreshold",
+ "IntrStatus",
+ "IntrMask",
+ "invalid",
+ "RxData", "invalid",
+ "RxDone", "invalid",
+ "RxWait", "invalid",
+ "TxData", "invalid",
+ "TxDone", "invalid",
+ "TxWait", "invalid",
+ "HwAddr", "invalid"
+ };
+
+ if (offset & 0x3)
+ return "invalid";
+
+ if (offset >= Size)
+ return "invalid";
+
+ return names[offset / 4];
+}
+
+/* namespace Regs */ }
+/* namespace Sinic */ }
+
+#endif // __DEV_SINICREG_HH__
diff --git a/dev/tsunami.cc b/dev/tsunami.cc
index c44da69b7..f98254354 100644
--- a/dev/tsunami.cc
+++ b/dev/tsunami.cc
@@ -75,6 +75,24 @@ Tsunami::clearConsoleInt()
}
void
+Tsunami::postPciInt(int line)
+{
+ cchip->postDRIR(line);
+}
+
+void
+Tsunami::clearPciInt(int line)
+{
+ cchip->clearDRIR(line);
+}
+
+Addr
+Tsunami::pciToDma(Addr pciAddr) const
+{
+ return pchip->translatePciToDma(pciAddr);
+}
+
+void
Tsunami::serialize(std::ostream &os)
{
SERIALIZE_ARRAY(intr_sum_type, Tsunami::Max_CPUs);
diff --git a/dev/tsunami.hh b/dev/tsunami.hh
index db266d62d..d7c549e90 100644
--- a/dev/tsunami.hh
+++ b/dev/tsunami.hh
@@ -58,16 +58,13 @@ class Tsunami : public Platform
public:
/** Max number of CPUs in a Tsunami */
- static const int Max_CPUs = 4;
+ static const int Max_CPUs = 64;
/** Pointer to the system */
System *system;
+
/** Pointer to the TsunamiIO device which has the RTC */
TsunamiIO *io;
- /** Pointer to the disk controller device */
- IdeController *disk_controller;
- /** Pointer to the ethernet controller device */
- NSGigE *ethernet;
/** Pointer to the Tsunami CChip.
* The chip contains some configuration information and
@@ -112,6 +109,18 @@ class Tsunami : public Platform
virtual void clearConsoleInt();
/**
+ * Cause the chipset to post a cpi interrupt to the CPU.
+ */
+ virtual void postPciInt(int line);
+
+ /**
+ * Clear a posted PCI->CPU interrupt
+ */
+ virtual void clearPciInt(int line);
+
+ virtual Addr pciToDma(Addr pciAddr) const;
+
+ /**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
*/
diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc
index 870924a2f..a1f900153 100644
--- a/dev/tsunami_cchip.cc
+++ b/dev/tsunami_cchip.cc
@@ -53,25 +53,24 @@ TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
Tick pio_latency)
: PioDevice(name), addr(a), tsunami(t)
{
- mmu->add_child(this, Range<Addr>(addr, addr + size));
-
- for(int i=0; i < Tsunami::Max_CPUs; i++) {
- dim[i] = 0;
- dir[i] = 0;
- dirInterrupting[i] = false;
- ipiInterrupting[i] = false;
- RTCInterrupting[i] = false;
- }
+ mmu->add_child(this, RangeSize(addr, size));
if (bus) {
pioInterface = newPioInterface(name, hier, bus, this,
&TsunamiCChip::cacheAccess);
- pioInterface->addAddrRange(addr, addr + size - 1);
+ pioInterface->addAddrRange(RangeSize(addr, size));
pioLatency = pio_latency * bus->clockRatio;
}
drir = 0;
- misc = 0;
+ ipint = 0;
+ itint = 0;
+
+ for (int x = 0; x < Tsunami::Max_CPUs; x++)
+ {
+ dim[x] = 0;
+ dir[x] = 0;
+ }
//Put back pointer in tsunami
tsunami->cchip = this;
@@ -80,16 +79,29 @@ TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
Fault
TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
{
- DPRINTF(Tsunami, "read va=%#x size=%d\n",
- req->vaddr, req->size);
+ DPRINTF(Tsunami, "read va=%#x size=%d\n", req->vaddr, req->size);
+
+ Addr regnum = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
- Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
ExecContext *xc = req->xc;
switch (req->size) {
case sizeof(uint64_t):
- switch(daddr) {
+ if (daddr & TSDEV_CC_BDIMS)
+ {
+ *(uint64_t*)data = dim[(daddr >> 4) & 0x3F];
+ return No_Fault;
+ }
+
+ if (daddr & TSDEV_CC_BDIRS)
+ {
+ *(uint64_t*)data = dir[(daddr >> 4) & 0x3F];
+ return No_Fault;
+ }
+
+ switch(regnum) {
case TSDEV_CC_CSR:
*(uint64_t*)data = 0x0;
return No_Fault;
@@ -97,7 +109,9 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
panic("TSDEV_CC_MTR not implemeted\n");
return No_Fault;
case TSDEV_CC_MISC:
- *(uint64_t*)data = misc | (xc->cpu_id & 0x3);
+ *(uint64_t*)data = (ipint << 8) & 0xF |
+ (itint << 4) & 0xF |
+ (xc->cpu_id & 0x3);
return No_Fault;
case TSDEV_CC_AAR0:
case TSDEV_CC_AAR1:
@@ -147,6 +161,12 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
case TSDEV_CC_MPR3:
panic("TSDEV_CC_MPRx not implemented\n");
return No_Fault;
+ case TSDEV_CC_IPIR:
+ *(uint64_t*)data = ipint;
+ return No_Fault;
+ case TSDEV_CC_ITIR:
+ *(uint64_t*)data = itint;
+ return No_Fault;
default:
panic("default in cchip read reached, accessing 0x%x\n");
} // uint64_t
@@ -158,7 +178,7 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
default:
panic("invalid access size(?) for tsunami register!\n");
}
- DPRINTFN("Tsunami CChip ERROR: read daddr=%#x size=%d\n", daddr, req->size);
+ DPRINTFN("Tsunami CChip ERROR: read regnum=%#x size=%d\n", regnum, req->size);
return No_Fault;
}
@@ -169,73 +189,95 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
DPRINTF(Tsunami, "write - va=%#x value=%#x size=%d \n",
req->vaddr, *(uint64_t*)data, req->size);
- Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
+ Addr regnum = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
bool supportedWrite = false;
- uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
switch (req->size) {
case sizeof(uint64_t):
- switch(daddr) {
- case TSDEV_CC_CSR:
+ if (daddr & TSDEV_CC_BDIMS)
+ {
+ int number = (daddr >> 4) & 0x3F;
+
+ uint64_t bitvector;
+ uint64_t olddim;
+ uint64_t olddir;
+
+ olddim = dim[number];
+ olddir = dir[number];
+ dim[number] = *(uint64_t*)data;
+ dir[number] = dim[number] & drir;
+ for(int x = 0; x < Tsunami::Max_CPUs; x++)
+ {
+ bitvector = ULL(1) << x;
+ // Figure out which bits have changed
+ if ((dim[number] & bitvector) != (olddim & bitvector))
+ {
+ // The bit is now set and it wasn't before (set)
+ if((dim[number] & bitvector) && (dir[number] & bitvector))
+ {
+ tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x);
+ DPRINTF(Tsunami, "dim write resulting in posting dir"
+ " interrupt to cpu %d\n", number);
+ }
+ else if ((olddir & bitvector) &&
+ !(dir[number] & bitvector))
+ {
+ // The bit was set and now its now clear and
+ // we were interrupting on that bit before
+ tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x);
+ DPRINTF(Tsunami, "dim write resulting in clear"
+ " dir interrupt to cpu %d\n", number);
+
+ }
+
+
+ }
+ }
+ return No_Fault;
+ }
+
+ switch(regnum) {
+ case TSDEV_CC_CSR:
panic("TSDEV_CC_CSR write\n");
return No_Fault;
case TSDEV_CC_MTR:
panic("TSDEV_CC_MTR write not implemented\n");
return No_Fault;
case TSDEV_CC_MISC:
- //If it is the 4-7th bit, clear the RTC interrupt
- uint64_t itintr;
- if ((itintr = (*(uint64_t*) data) & (0xf<<4))) {
- //Clear the bits in ITINTR
- misc &= ~(itintr);
- for (int i=0; i < size; i++) {
- if ((itintr & (1 << (i+4))) && RTCInterrupting[i]) {
- tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ2, 0);
- RTCInterrupting[i] = false;
- DPRINTF(Tsunami, "clearing rtc interrupt to cpu=%d\n", i);
- }
- }
- supportedWrite = true;
- }
- //If it is 12th-15th bit, IPI sent to Processor 1
uint64_t ipreq;
- if ((ipreq = (*(uint64_t*) data) & (0xf << 12))) {
- //Set the bits in IPINTR
- misc |= (ipreq >> 4);
- for (int i=0; i < size; i++) {
- if ((ipreq & (1 << (i + 12)))) {
- if (!ipiInterrupting[i])
- tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ3, 0);
- ipiInterrupting[i]++;
- DPRINTF(IPI, "send cpu=%d pending=%d from=%d\n", i,
- ipiInterrupting[i], req->cpu_num);
- }
- }
+ ipreq = (*(uint64_t*)data >> 12) & 0xF;
+ //If it is bit 12-15, this is an IPI post
+ if (ipreq) {
+ reqIPI(ipreq);
supportedWrite = true;
}
- //If it is bits 8-11, then clearing IPI's
+
+ //If it is bit 8-11, this is an IPI clear
uint64_t ipintr;
- if ((ipintr = (*(uint64_t*) data) & (0xf << 8))) {
- //Clear the bits in IPINTR
- misc &= ~(ipintr);
- for (int i=0; i < size; i++) {
- if ((ipintr & (1 << (i + 8))) && ipiInterrupting[i]) {
- if (!(--ipiInterrupting[i]))
- tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ3, 0);
- DPRINTF(IPI, "clearing cpu=%d pending=%d from=%d\n", i,
- ipiInterrupting[i] + 1, req->cpu_num);
- }
- }
+ ipintr = (*(uint64_t*)data >> 8) & 0xF;
+ if (ipintr) {
+ clearIPI(ipintr);
+ supportedWrite = true;
+ }
+
+ //If it is the 4-7th bit, clear the RTC interrupt
+ uint64_t itintr;
+ itintr = (*(uint64_t*)data >> 4) & 0xF;
+ if (itintr) {
+ clearITI(itintr);
supportedWrite = true;
}
- // ignore NXMs
- if (*(uint64_t*)data & 0x10000000)
- supportedWrite = true;
+ // ignore NXMs
+ if (*(uint64_t*)data & 0x10000000)
+ supportedWrite = true;
+
+ if(!supportedWrite)
+ panic("TSDEV_CC_MISC write not implemented\n");
- if(!supportedWrite) panic("TSDEV_CC_MISC write not implemented\n");
return No_Fault;
case TSDEV_CC_AAR0:
case TSDEV_CC_AAR1:
@@ -248,11 +290,11 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
case TSDEV_CC_DIM2:
case TSDEV_CC_DIM3:
int number;
- if(daddr == TSDEV_CC_DIM0)
+ if(regnum == TSDEV_CC_DIM0)
number = 0;
- else if(daddr == TSDEV_CC_DIM1)
+ else if(regnum == TSDEV_CC_DIM1)
number = 1;
- else if(daddr == TSDEV_CC_DIM2)
+ else if(regnum == TSDEV_CC_DIM2)
number = 2;
else
number = 3;
@@ -267,7 +309,7 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
dir[number] = dim[number] & drir;
for(int x = 0; x < 64; x++)
{
- bitvector = (uint64_t)1 << x;
+ bitvector = ULL(1) << x;
// Figure out which bits have changed
if ((dim[number] & bitvector) != (olddim & bitvector))
{
@@ -284,7 +326,8 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
// we were interrupting on that bit before
tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x);
DPRINTF(Tsunami, "dim write resulting in clear"
- "dir interrupt to cpu 0\n");
+ " dir interrupt to cpu %d\n",
+ x);
}
@@ -311,6 +354,15 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
case TSDEV_CC_MPR2:
case TSDEV_CC_MPR3:
panic("TSDEV_CC_MPRx write not implemented\n");
+ case TSDEV_CC_IPIR:
+ clearIPI(*(uint64_t*)data);
+ return No_Fault;
+ case TSDEV_CC_ITIR:
+ clearITI(*(uint64_t*)data);
+ return No_Fault;
+ case TSDEV_CC_IPIQ:
+ reqIPI(*(uint64_t*)data);
+ return No_Fault;
default:
panic("default in cchip read reached, accessing 0x%x\n");
}
@@ -329,14 +381,88 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
}
void
+TsunamiCChip::clearIPI(uint64_t ipintr)
+{
+ int numcpus = tsunami->intrctrl->cpu->system->execContexts.size();
+ assert(numcpus <= Tsunami::Max_CPUs);
+
+ if (ipintr) {
+ for (int cpunum=0; cpunum < numcpus; cpunum++) {
+ // Check each cpu bit
+ uint64_t cpumask = ULL(1) << cpunum;
+ if (ipintr & cpumask) {
+ // Check if there is a pending ipi
+ if (ipint & cpumask) {
+ ipint &= ~cpumask;
+ tsunami->intrctrl->clear(cpunum, TheISA::INTLEVEL_IRQ3, 0);
+ DPRINTF(IPI, "clear IPI IPI cpu=%d\n", cpunum);
+ }
+ else
+ warn("clear IPI for CPU=%d, but NO IPI\n", cpunum);
+ }
+ }
+ }
+ else
+ panic("Big IPI Clear, but not processors indicated\n");
+}
+
+void
+TsunamiCChip::clearITI(uint64_t itintr)
+{
+ int numcpus = tsunami->intrctrl->cpu->system->execContexts.size();
+ assert(numcpus <= Tsunami::Max_CPUs);
+
+ if (itintr) {
+ for (int i=0; i < numcpus; i++) {
+ uint64_t cpumask = ULL(1) << i;
+ if (itintr & cpumask & itint) {
+ tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ2, 0);
+ itint &= ~cpumask;
+ DPRINTF(Tsunami, "clearing rtc interrupt to cpu=%d\n", i);
+ }
+ }
+ }
+ else
+ panic("Big ITI Clear, but not processors indicated\n");
+}
+
+void
+TsunamiCChip::reqIPI(uint64_t ipreq)
+{
+ int numcpus = tsunami->intrctrl->cpu->system->execContexts.size();
+ assert(numcpus <= Tsunami::Max_CPUs);
+
+ if (ipreq) {
+ for (int cpunum=0; cpunum < numcpus; cpunum++) {
+ // Check each cpu bit
+ uint64_t cpumask = ULL(1) << cpunum;
+ if (ipreq & cpumask) {
+ // Check if there is already an ipi (bits 8:11)
+ if (!(ipint & cpumask)) {
+ ipint |= cpumask;
+ tsunami->intrctrl->post(cpunum, TheISA::INTLEVEL_IRQ3, 0);
+ DPRINTF(IPI, "send IPI cpu=%d\n", cpunum);
+ }
+ else
+ warn("post IPI for CPU=%d, but IPI already\n", cpunum);
+ }
+ }
+ }
+ else
+ panic("Big IPI Request, but not processors indicated\n");
+}
+
+
+void
TsunamiCChip::postRTC()
{
int size = tsunami->intrctrl->cpu->system->execContexts.size();
+ assert(size <= Tsunami::Max_CPUs);
for (int i = 0; i < size; i++) {
- if (!RTCInterrupting[i]) {
- misc |= 16 << i;
- RTCInterrupting[i] = true;
+ uint64_t cpumask = ULL(1) << i;
+ if (!(cpumask & itint)) {
+ itint |= cpumask;
tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ2, 0);
DPRINTF(Tsunami, "Posting RTC interrupt to cpu=%d", i);
}
@@ -347,9 +473,11 @@ TsunamiCChip::postRTC()
void
TsunamiCChip::postDRIR(uint32_t interrupt)
{
- uint64_t bitvector = (uint64_t)0x1 << interrupt;
- drir |= bitvector;
+ uint64_t bitvector = ULL(1) << interrupt;
uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
+ assert(size <= Tsunami::Max_CPUs);
+ drir |= bitvector;
+
for(int i=0; i < size; i++) {
dir[i] = dim[i] & drir;
if (dim[i] & bitvector) {
@@ -363,8 +491,10 @@ TsunamiCChip::postDRIR(uint32_t interrupt)
void
TsunamiCChip::clearDRIR(uint32_t interrupt)
{
- uint64_t bitvector = (uint64_t)0x1 << interrupt;
+ uint64_t bitvector = ULL(1) << interrupt;
uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
+ assert(size <= Tsunami::Max_CPUs);
+
if (drir & bitvector)
{
drir &= ~bitvector;
@@ -394,11 +524,9 @@ TsunamiCChip::serialize(std::ostream &os)
{
SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
- SERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs);
- SERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs);
+ SERIALIZE_SCALAR(ipint);
+ SERIALIZE_SCALAR(itint);
SERIALIZE_SCALAR(drir);
- SERIALIZE_SCALAR(misc);
- SERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs);
}
void
@@ -406,11 +534,9 @@ TsunamiCChip::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
- UNSERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs);
- UNSERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs);
+ UNSERIALIZE_SCALAR(ipint);
+ UNSERIALIZE_SCALAR(itint);
UNSERIALIZE_SCALAR(drir);
- UNSERIALIZE_SCALAR(misc);
- UNSERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs);
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
diff --git a/dev/tsunami_cchip.hh b/dev/tsunami_cchip.hh
index 3269cf53a..05fafa782 100644
--- a/dev/tsunami_cchip.hh
+++ b/dev/tsunami_cchip.hh
@@ -47,7 +47,7 @@ class TsunamiCChip : public PioDevice
Addr addr;
/** The size of mappad from the above address */
- static const Addr size = 0xfff;
+ static const Addr size = 0xfffffff;
protected:
/**
@@ -68,7 +68,6 @@ class TsunamiCChip : public PioDevice
* One exists for each CPU, the DRIR X DIM = DIR
*/
uint64_t dir[Tsunami::Max_CPUs];
- bool dirInterrupting[Tsunami::Max_CPUs];
/**
* This register contains bits for each PCI interrupt
@@ -76,17 +75,11 @@ class TsunamiCChip : public PioDevice
*/
uint64_t drir;
- /**
- * The MISC register contains the CPU we are currently on
- * as well as bits to ack RTC and IPI interrupts.
- */
- uint64_t misc;
+ /** Indicator of which CPUs have an IPI interrupt */
+ uint64_t ipint;
- /** Count of the number of pending IPIs on a CPU */
- uint64_t ipiInterrupting[Tsunami::Max_CPUs];
-
- /** Indicator of which CPUs have had an RTC interrupt */
- bool RTCInterrupting[Tsunami::Max_CPUs];
+ /** Indicator of which CPUs have an RTC interrupt */
+ uint64_t itint;
public:
/**
@@ -138,6 +131,25 @@ class TsunamiCChip : public PioDevice
void clearDRIR(uint32_t interrupt);
/**
+ * post an ipi interrupt to the CPU.
+ * @param ipintr the cpu number to clear(bitvector)
+ */
+ void clearIPI(uint64_t ipintr);
+
+ /**
+ * clear a timer interrupt previously posted to the CPU.
+ * @param interrupt the cpu number to clear(bitvector)
+ */
+ void clearITI(uint64_t itintr);
+
+ /**
+ * request an interrupt be posted to the CPU.
+ * @param ipreq the cpu number to interrupt(bitvector)
+ */
+ void reqIPI(uint64_t ipreq);
+
+
+ /**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
*/
diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc
index 105e3b5b7..51ff8b81c 100644
--- a/dev/tsunami_io.cc
+++ b/dev/tsunami_io.cc
@@ -164,12 +164,12 @@ TsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time,
Tick pio_latency)
: PioDevice(name), addr(a), tsunami(t), rtc(t)
{
- mmu->add_child(this, Range<Addr>(addr, addr + size));
+ mmu->add_child(this, RangeSize(addr, size));
if (bus) {
pioInterface = newPioInterface(name, hier, bus, this,
&TsunamiIO::cacheAccess);
- pioInterface->addAddrRange(addr, addr + size - 1);
+ pioInterface->addAddrRange(RangeSize(addr, size));
pioLatency = pio_latency * bus->clockRatio;
}
@@ -196,7 +196,7 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n",
req->vaddr, req->size, req->vaddr & 0xfff);
- Addr daddr = (req->paddr - (addr & PA_IMPL_MASK));
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
switch(req->size) {
@@ -298,7 +298,7 @@ TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
req->vaddr, req->size, req->vaddr & 0xfff, dt64);
- Addr daddr = (req->paddr - (addr & PA_IMPL_MASK));
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
switch(req->size) {
case sizeof(uint8_t):
diff --git a/dev/tsunami_pchip.cc b/dev/tsunami_pchip.cc
index 89940fb5a..9af19d930 100644
--- a/dev/tsunami_pchip.cc
+++ b/dev/tsunami_pchip.cc
@@ -53,7 +53,7 @@ TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
Bus *bus, Tick pio_latency)
: PioDevice(name), addr(a), tsunami(t)
{
- mmu->add_child(this, Range<Addr>(addr, addr + size));
+ mmu->add_child(this, RangeSize(addr, size));
for (int i = 0; i < 4; i++) {
wsba[i] = 0;
@@ -64,7 +64,7 @@ TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
if (bus) {
pioInterface = newPioInterface(name, hier, bus, this,
&TsunamiPChip::cacheAccess);
- pioInterface->addAddrRange(addr, addr + size - 1);
+ pioInterface->addAddrRange(RangeSize(addr, size));
pioLatency = pio_latency * bus->clockRatio;
}
@@ -82,7 +82,7 @@ TsunamiPChip::read(MemReqPtr &req, uint8_t *data)
DPRINTF(Tsunami, "read va=%#x size=%d\n",
req->vaddr, req->size);
- Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
switch (req->size) {
@@ -171,7 +171,7 @@ TsunamiPChip::write(MemReqPtr &req, const uint8_t *data)
DPRINTF(Tsunami, "write - va=%#x size=%d \n",
req->vaddr, req->size);
- Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
+ Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
switch (req->size) {
diff --git a/dev/tsunamireg.h b/dev/tsunamireg.h
index 876c6bf18..3304082a5 100644
--- a/dev/tsunamireg.h
+++ b/dev/tsunamireg.h
@@ -60,6 +60,13 @@
#define TSDEV_CC_IIC2 0x1C
#define TSDEV_CC_IIC3 0x1D
+// BigTsunami Registers
+#define TSDEV_CC_BDIMS 0x1000000
+#define TSDEV_CC_BDIRS 0x2000000
+#define TSDEV_CC_IPIQ 0x20 //0xf01a000800
+#define TSDEV_CC_IPIR 0x21 //0xf01a000840
+#define TSDEV_CC_ITIR 0x22 //0xf01a000880
+
// PChip Registers
#define TSDEV_PC_WSBA0 0x00
diff --git a/dev/uart.cc b/dev/uart.cc
index fca856d5d..2ff94dda5 100644
--- a/dev/uart.cc
+++ b/dev/uart.cc
@@ -44,7 +44,6 @@
#include "mem/bus/pio_interface_impl.hh"
#include "mem/functional_mem/memory_control.hh"
#include "sim/builder.hh"
-#include "targetarch/ev5.hh"
using namespace std;
@@ -92,13 +91,13 @@ Uart::Uart(const string &name, SimConsole *c, MemoryController *mmu, Addr a,
: PioDevice(name), addr(a), size(s), cons(c), txIntrEvent(this, TX_INT),
rxIntrEvent(this, RX_INT), platform(p)
{
- mmu->add_child(this, Range<Addr>(addr, addr + size));
+ mmu->add_child(this, RangeSize(addr, size));
if (bus) {
pioInterface = newPioInterface(name, hier, bus, this,
&Uart::cacheAccess);
- pioInterface->addAddrRange(addr, addr + size - 1);
+ pioInterface->addAddrRange(RangeSize(addr, size));
pioLatency = pio_latency * bus->clockRatio;
}
@@ -118,7 +117,7 @@ Uart::Uart(const string &name, SimConsole *c, MemoryController *mmu, Addr a,
Fault
Uart::read(MemReqPtr &req, uint8_t *data)
{
- Addr daddr = req->paddr - (addr & PA_IMPL_MASK);
+ Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
DPRINTF(Uart, " read register %#x\n", daddr);
@@ -246,7 +245,7 @@ Uart::read(MemReqPtr &req, uint8_t *data)
Fault
Uart::write(MemReqPtr &req, const uint8_t *data)
{
- Addr daddr = req->paddr - (addr & PA_IMPL_MASK);
+ Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
DPRINTF(Uart, " write register %#x value %#x\n", daddr, *(uint8_t*)data);
@@ -287,7 +286,7 @@ Uart::write(MemReqPtr &req, const uint8_t *data)
switch (daddr) {
case 0x0:
if (!(LCR & 0x80)) { // write byte
- cons->out(*(uint64_t *)data);
+ cons->out(*(uint8_t *)data);
platform->clearConsoleInt();
status &= ~TX_INT;
if (UART_IER_THRI & IER)