summaryrefslogtreecommitdiff
path: root/dev
diff options
context:
space:
mode:
Diffstat (limited to 'dev')
-rw-r--r--dev/alpha_console.cc11
-rw-r--r--dev/alpha_console.hh7
-rw-r--r--dev/console.cc63
-rw-r--r--dev/console.hh8
-rw-r--r--dev/etherbus.cc2
-rw-r--r--dev/etherbus.hh2
-rw-r--r--dev/etherdump.cc20
-rw-r--r--dev/etherdump.hh4
-rw-r--r--dev/etherint.hh4
-rw-r--r--dev/etherlink.cc2
-rw-r--r--dev/etherlink.hh4
-rw-r--r--dev/ethertap.cc2
-rw-r--r--dev/ethertap.hh2
-rw-r--r--dev/tsunami.cc95
-rw-r--r--dev/tsunami.hh110
-rw-r--r--dev/tsunami_cchip.cc312
-rw-r--r--dev/tsunami_cchip.hh70
-rw-r--r--dev/tsunami_io.cc356
-rw-r--r--dev/tsunami_io.hh134
-rw-r--r--dev/tsunami_pchip.cc260
-rw-r--r--dev/tsunami_pchip.hh74
-rw-r--r--dev/tsunami_uart.cc206
-rw-r--r--dev/tsunami_uart.hh63
-rw-r--r--dev/tsunamireg.h103
24 files changed, 1871 insertions, 43 deletions
diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc
index ccf6c33fd..9411c6470 100644
--- a/dev/alpha_console.cc
+++ b/dev/alpha_console.cc
@@ -46,12 +46,13 @@
#include "mem/functional_mem/memory_control.hh"
#include "sim/builder.hh"
#include "sim/system.hh"
+#include "dev/tsunami_io.hh"
using namespace std;
AlphaConsole::AlphaConsole(const string &name, SimConsole *cons,
SimpleDisk *d, int size, System *system,
- BaseCPU *cpu, TlaserClock *clock, int num_cpus,
+ BaseCPU *cpu, TsunamiIO *clock, int num_cpus,
Addr addr, Addr mask, MemoryController *mmu)
: MmapDevice(name, addr, mask, mmu), disk(d), console(cons)
{
@@ -73,7 +74,7 @@ AlphaConsole::AlphaConsole(const string &name, SimConsole *cons,
}
Fault
-AlphaConsole::read(MemReqPtr req, uint8_t *data)
+AlphaConsole::read(MemReqPtr &req, uint8_t *data)
{
memset(data, 0, req->size);
uint64_t val;
@@ -81,7 +82,7 @@ AlphaConsole::read(MemReqPtr req, uint8_t *data)
Addr daddr = req->paddr & addr_mask;
switch (daddr) {
case offsetof(AlphaAccess, inputChar):
- val = console->in();
+ val = console->console_in();
break;
default:
@@ -109,7 +110,7 @@ AlphaConsole::read(MemReqPtr req, uint8_t *data)
}
Fault
-AlphaConsole::write(MemReqPtr req, const uint8_t *data)
+AlphaConsole::write(MemReqPtr &req, const uint8_t *data)
{
uint64_t val;
@@ -250,7 +251,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
Param<Addr> mask;
SimObjectParam<System *> system;
SimObjectParam<BaseCPU *> cpu;
- SimObjectParam<TlaserClock *> clock;
+ SimObjectParam<TsunamiIO *> clock;
END_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
diff --git a/dev/alpha_console.hh b/dev/alpha_console.hh
index 9e774773e..4647be538 100644
--- a/dev/alpha_console.hh
+++ b/dev/alpha_console.hh
@@ -36,6 +36,7 @@
#include "sim/host.hh"
#include "dev/alpha_access.h"
#include "mem/functional_mem/mmap_device.hh"
+#include "dev/tsunami_io.hh"
class BaseCPU;
class SimConsole;
@@ -87,15 +88,15 @@ class AlphaConsole : public MmapDevice
AlphaConsole(const std::string &name, SimConsole *cons,
SimpleDisk *d, int size,
System *system, BaseCPU *cpu,
- TlaserClock *clock, int num_cpus,
+ TsunamiIO *clock, int num_cpus,
Addr addr, Addr mask, MemoryController *mmu);
public:
/**
* memory mapped reads and writes
*/
- virtual Fault read(MemReqPtr req, uint8_t *data);
- virtual Fault write(MemReqPtr req, const uint8_t *data);
+ virtual Fault read(MemReqPtr &req, uint8_t *data);
+ virtual Fault write(MemReqPtr &req, const uint8_t *data);
/**
* standard serialization routines for checkpointing
diff --git a/dev/console.cc b/dev/console.cc
index f4156207d..fb74c388a 100644
--- a/dev/console.cc
+++ b/dev/console.cc
@@ -228,27 +228,44 @@ SimConsole::configTerm()
#define RECEIVE_NONE (ULL(2) << 62)
#define RECEIVE_ERROR (ULL(3) << 62)
-uint64_t
-SimConsole::in()
+bool
+SimConsole::in(uint8_t &c)
{
- char c = 0;
- uint64_t val = 0;
- if (rxbuf.empty()) {
+ bool empty, ret;
+
+ empty = rxbuf.empty();
+ ret = !empty;
+ if (!empty) {
+ rxbuf.read((char *)&c, 1);
+ empty = rxbuf.empty();
+ }
+
+ if (empty)
clearInt(ReceiveInterrupt);
- val |= RECEIVE_NONE;
- return 0x8;
- } else {
- uint64_t val;
- rxbuf.read(&c, 1);
- val |= RECEIVE_SUCCESS | c;
+
+ DPRINTF(ConsoleVerbose, "in: \'%c\' %#02x more: %d, return: %d\n",
+ isprint(c) ? c : ' ', c, !empty, ret);
+
+ return ret;
+}
+
+uint64_t
+SimConsole::console_in()
+{
+ uint8_t c;
+ uint64_t value;
+
+ if (in(c)) {
+ value = RECEIVE_SUCCESS | c;
if (!rxbuf.empty())
- val |= MORE_PENDING;
+ value |= MORE_PENDING;
+ } else {
+ value = RECEIVE_NONE;
}
- DPRINTF(ConsoleVerbose, "in: \'%c\' %#02x retval: %#x\n",
- isprint(c) ? c : ' ', c, val);
+ DPRINTF(ConsoleVerbose, "console_in: return: %#x\n", value);
- return val;
+ return value;
}
void
@@ -383,13 +400,21 @@ END_INIT_SIM_OBJECT_PARAMS(SimConsole)
CREATE_SIM_OBJECT(SimConsole)
{
string filename = output;
- if (!filename.empty() && append_name)
- filename += "." + getInstanceName();
+ if (filename.empty()) {
+ if (!outputDirectory.empty())
+ filename = outputDirectory + getInstanceName();
+ } else {
+ if (append_name)
+ filename += "." + getInstanceName();
+ if (!outputDirectory.empty())
+ filename = outputDirectory + filename;
+ }
+
SimConsole *console = new SimConsole(getInstanceName(), filename, number);
((ConsoleListener *)listener)->add(console);
((SimConsole *)console)->initInt(intr_control);
- ((SimConsole *)console)->setInt(SimConsole::TransmitInterrupt |
- SimConsole::ReceiveInterrupt);
+// ((SimConsole *)console)->setInt(SimConsole::TransmitInterrupt |
+// SimConsole::ReceiveInterrupt);
return console;
}
diff --git a/dev/console.hh b/dev/console.hh
index 9913fe379..d2bba4612 100644
--- a/dev/console.hh
+++ b/dev/console.hh
@@ -109,7 +109,10 @@ class SimConsole : public SimObject
// OS interface
// Get a character from the console.
- // the return value corresponds to the console GETC return value:
+ bool in(uint8_t &value);
+
+ // get a character from the console in the console specific format
+ // corresponds to GETC:
// retval<63:61>
// 000: success: character received
// 001: success: character received, more pending
@@ -118,8 +121,9 @@ class SimConsole : public SimObject
// 111: failure: character received with error, more pending
// retval<31:0>
// character read from console
+ //
// Interrupts are cleared when the buffer is empty.
- uint64_t in();
+ uint64_t console_in();
// Send a character to the console
void out(char c, bool raise_int = true);
diff --git a/dev/etherbus.cc b/dev/etherbus.cc
index 3f6036f72..76697dd3e 100644
--- a/dev/etherbus.cc
+++ b/dev/etherbus.cc
@@ -81,7 +81,7 @@ EtherBus::reg(EtherInt *dev)
{ devlist.push_back(dev); }
bool
-EtherBus::send(EtherInt *sndr, PacketPtr pkt)
+EtherBus::send(EtherInt *sndr, PacketPtr &pkt)
{
if (busy()) {
DPRINTF(Ethernet, "ethernet packet not sent, bus busy\n", curTick);
diff --git a/dev/etherbus.hh b/dev/etherbus.hh
index f7f633303..9ef477808 100644
--- a/dev/etherbus.hh
+++ b/dev/etherbus.hh
@@ -73,7 +73,7 @@ class EtherBus : public SimObject
void txDone();
void reg(EtherInt *dev);
bool busy() const { return (bool)packet; }
- bool send(EtherInt *sender, PacketPtr packet);
+ bool send(EtherInt *sender, PacketPtr &packet);
};
#endif // __ETHERBUS_H__
diff --git a/dev/etherdump.cc b/dev/etherdump.cc
index 60dc1559d..6d86adc32 100644
--- a/dev/etherdump.cc
+++ b/dev/etherdump.cc
@@ -106,7 +106,7 @@ EtherDump::init()
}
void
-EtherDump::dumpPacket(PacketPtr packet)
+EtherDump::dumpPacket(PacketPtr &packet)
{
pcap_pkthdr pkthdr;
pkthdr.ts.tv_sec = curtime + (curTick / s_freq);
@@ -126,13 +126,27 @@ END_DECLARE_SIM_OBJECT_PARAMS(EtherDump)
BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDump)
- INIT_PARAM_DFLT(file, "file to dump packets to", "")
+ INIT_PARAM(file, "file to dump packets to")
END_INIT_SIM_OBJECT_PARAMS(EtherDump)
CREATE_SIM_OBJECT(EtherDump)
{
- return new EtherDump(getInstanceName(), file);
+ 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);
}
REGISTER_SIM_OBJECT("EtherDump", EtherDump)
diff --git a/dev/etherdump.hh b/dev/etherdump.hh
index b3aefeb74..e22b66166 100644
--- a/dev/etherdump.hh
+++ b/dev/etherdump.hh
@@ -44,7 +44,7 @@ class EtherDump : public SimObject
{
private:
std::ofstream stream;
- void dumpPacket(PacketPtr packet);
+ void dumpPacket(PacketPtr &packet);
void init();
Tick curtime;
@@ -54,7 +54,7 @@ class EtherDump : public SimObject
public:
EtherDump(const std::string &name, const std::string &file);
- inline void dump(PacketPtr pkt) { if (stream.is_open()) dumpPacket(pkt); }
+ inline void dump(PacketPtr &pkt) { if (stream.is_open()) dumpPacket(pkt); }
};
#endif // __ETHERDUMP_H__
diff --git a/dev/etherint.hh b/dev/etherint.hh
index dfc9f6fd6..70e29eb7c 100644
--- a/dev/etherint.hh
+++ b/dev/etherint.hh
@@ -54,9 +54,9 @@ class EtherInt : public SimObject
virtual ~EtherInt() {}
void setPeer(EtherInt *p);
- virtual bool recvPacket(PacketPtr packet) = 0;
+ virtual bool recvPacket(PacketPtr &packet) = 0;
void recvDone() { peer->sendDone(); }
- bool sendPacket(PacketPtr packet)
+ bool sendPacket(PacketPtr &packet)
{
return peer ? peer->recvPacket(packet) : true;
}
diff --git a/dev/etherlink.cc b/dev/etherlink.cc
index c042cac34..676b1da1c 100644
--- a/dev/etherlink.cc
+++ b/dev/etherlink.cc
@@ -102,7 +102,7 @@ EtherLink::Link::txDone()
}
bool
-EtherLink::Link::transmit(PacketPtr pkt)
+EtherLink::Link::transmit(PacketPtr &pkt)
{
if (busy()) {
DPRINTF(Ethernet, "EtherLink packet not sent, link busy\n");
diff --git a/dev/etherlink.hh b/dev/etherlink.hh
index ef587faf7..895bac2e1 100644
--- a/dev/etherlink.hh
+++ b/dev/etherlink.hh
@@ -92,7 +92,7 @@ class EtherLink : public SimObject
virtual 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; }
@@ -108,7 +108,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() { }
};
diff --git a/dev/ethertap.cc b/dev/ethertap.cc
index 339e7ac78..960d21d73 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);
diff --git a/dev/ethertap.hh b/dev/ethertap.hh
index e2b1f640f..0b853a11d 100644
--- a/dev/ethertap.hh
+++ b/dev/ethertap.hh
@@ -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/tsunami.cc b/dev/tsunami.cc
new file mode 100644
index 000000000..a8cf551d3
--- /dev/null
+++ b/dev/tsunami.cc
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2003 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 <deque>
+#include <string>
+#include <vector>
+
+#include "cpu/intr_control.hh"
+#include "dev/console.hh"
+#include "dev/etherdev.hh"
+#include "dev/scsi_ctrl.hh"
+#include "dev/tlaser_clock.hh"
+#include "dev/tsunami_cchip.hh"
+#include "dev/tsunami_pchip.hh"
+#include "dev/tsunami.hh"
+#include "sim/builder.hh"
+#include "sim/system.hh"
+
+using namespace std;
+
+Tsunami::Tsunami(const string &name, ScsiController *s, EtherDev *e,
+ SimConsole *con, IntrControl *ic, int intr_freq)
+ : SimObject(name), intrctrl(ic), cons(con), scsi(s), ethernet(e),
+ interrupt_frequency(intr_freq)
+{
+ for (int i = 0; i < Tsunami::Max_CPUs; i++)
+ intr_sum_type[i] = 0;
+}
+
+void
+Tsunami::serialize(std::ostream &os)
+{
+ SERIALIZE_ARRAY(intr_sum_type, Tsunami::Max_CPUs);
+}
+
+void
+Tsunami::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_ARRAY(intr_sum_type, Tsunami::Max_CPUs);
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tsunami)
+
+ SimObjectParam<ScsiController *> scsi;
+ SimObjectParam<EtherDev *> ethernet;
+ SimObjectParam<SimConsole *> cons;
+ SimObjectParam<IntrControl *> intrctrl;
+ Param<int> interrupt_frequency;
+
+END_DECLARE_SIM_OBJECT_PARAMS(Tsunami)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(Tsunami)
+
+ INIT_PARAM(scsi, "scsi controller"),
+ INIT_PARAM(ethernet, "ethernet controller"),
+ INIT_PARAM(cons, "system console"),
+ INIT_PARAM(intrctrl, "interrupt controller"),
+ INIT_PARAM_DFLT(interrupt_frequency, "frequency of interrupts", 1200)
+
+END_INIT_SIM_OBJECT_PARAMS(Tsunami)
+
+
+CREATE_SIM_OBJECT(Tsunami)
+{
+ return new Tsunami(getInstanceName(), scsi, ethernet,
+ cons, intrctrl, interrupt_frequency);
+}
+
+REGISTER_SIM_OBJECT("Tsunami", Tsunami)
+
diff --git a/dev/tsunami.hh b/dev/tsunami.hh
new file mode 100644
index 000000000..e6623899d
--- /dev/null
+++ b/dev/tsunami.hh
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2003 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.
+ */
+
+/**
+ * @file
+ * Declaration of top level class for the Tsunami chipset. This class just retains pointers
+ * to all its children so the children can communicate
+ */
+
+#ifndef __TSUNAMI_HH__
+#define __TSUNAMI_HH__
+
+#include "sim/sim_object.hh"
+
+class IntrControl;
+class ConsoleListener;
+class SimConsole;
+class ScsiController;
+class TlaserClock;
+class EtherDev;
+class TsunamiCChip;
+class TsunamiPChip;
+class TsunamiPCIConfig;
+
+/**
+ * Top level class for Tsunami Chipset emulation.
+ * This structure just contains pointers to all the
+ * children so the children can commnicate to do the
+ * read work
+ */
+
+class Tsunami : public SimObject
+{
+ public:
+
+ /** Max number of CPUs in a Tsunami */
+ static const int Max_CPUs = 4;
+
+ /** Pointer to the interrupt controller (used to post and ack interrupts on the CPU) */
+ IntrControl *intrctrl;
+ /** Pointer to the UART emulation code */
+ SimConsole *cons;
+
+ /** Pointer to the SCSI controller device */
+ ScsiController *scsi;
+ /** Pointer to the ethernet controller device */
+ EtherDev *ethernet;
+
+ /** Pointer to the Tsunami CChip.
+ * The chip contains some configuration information and
+ * all the interrupt mask and status registers
+ */
+ TsunamiCChip *cchip;
+
+ /** Pointer to the Tsunami PChip.
+ * The pchip is the interface to the PCI bus, in our case
+ * it does not have to do much.
+ */
+ TsunamiPChip *pchip;
+
+ /** Pointer to the Tsunami PCI Config Space
+ * The config space in tsunami all needs to return
+ * -1 if a device is not there.
+ */
+ TsunamiPCIConfig *pciconfig;
+
+ int intr_sum_type[Tsunami::Max_CPUs];
+ int ipi_pending[Tsunami::Max_CPUs];
+
+ int interrupt_frequency;
+
+ public:
+ /**
+ * Constructor for the Tsunami Class.
+ * @param
+ */
+ Tsunami(const std::string &name, ScsiController *scsi,
+ EtherDev *ethernet,
+ SimConsole *, IntrControl *intctrl, int intrFreq);
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+};
+
+#endif // __TSUNAMI_HH__
diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc
new file mode 100644
index 000000000..9bb9be13f
--- /dev/null
+++ b/dev/tsunami_cchip.cc
@@ -0,0 +1,312 @@
+/* $Id$ */
+
+/* @file
+ * Tsunami CChip (processor, memory, or IO)
+ */
+
+#include <deque>
+#include <string>
+#include <vector>
+
+#include "base/trace.hh"
+#include "cpu/exec_context.hh"
+#include "dev/console.hh"
+#include "dev/tsunami_cchip.hh"
+#include "dev/tsunamireg.h"
+#include "dev/tsunami.hh"
+#include "cpu/intr_control.hh"
+#include "mem/functional_mem/memory_control.hh"
+#include "sim/builder.hh"
+#include "sim/system.hh"
+
+using namespace std;
+
+TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t,
+ Addr addr, Addr mask, MemoryController *mmu)
+ : MmapDevice(name, addr, mask, mmu), tsunami(t)
+{
+ for(int i=0; i < Tsunami::Max_CPUs; i++) {
+ dim[i] = 0;
+ dir[i] = 0;
+ dirInterrupting[i] = false;
+ }
+
+ drir = 0;
+ misc = 0;
+ RTCInterrupting = false;
+
+ //Put back pointer in tsunami
+ tsunami->cchip = this;
+}
+
+Fault
+TsunamiCChip::read(MemReqPtr req, uint8_t *data)
+{
+ DPRINTF(Tsunami, "read va=%#x size=%d\n",
+ req->vaddr, req->size);
+
+ Addr daddr = (req->paddr & addr_mask) >> 6;
+ ExecContext *xc = req->xc;
+
+ switch (req->size) {
+
+ case sizeof(uint64_t):
+ switch(daddr) {
+ case TSDEV_CC_CSR:
+ *(uint64_t*)data = 0x0;
+ return No_Fault;
+ case TSDEV_CC_MTR:
+ panic("TSDEV_CC_MTR not implemeted\n");
+ return No_Fault;
+ case TSDEV_CC_MISC:
+ *(uint64_t*)data = misc | (xc->cpu_id & 0x3);
+ return No_Fault;
+ case TSDEV_CC_AAR0:
+ case TSDEV_CC_AAR1:
+ case TSDEV_CC_AAR2:
+ case TSDEV_CC_AAR3:
+ panic("TSDEV_CC_AARx not implemeted\n");
+ return No_Fault;
+ case TSDEV_CC_DIM0:
+ *(uint64_t*)data = dim[0];
+ return No_Fault;
+ case TSDEV_CC_DIM1:
+ *(uint64_t*)data = dim[1];
+ return No_Fault;
+ case TSDEV_CC_DIM2:
+ *(uint64_t*)data = dim[2];
+ return No_Fault;
+ case TSDEV_CC_DIM3:
+ *(uint64_t*)data = dim[3];
+ return No_Fault;
+ case TSDEV_CC_DIR0:
+ *(uint64_t*)data = dir[0];
+ return No_Fault;
+ case TSDEV_CC_DIR1:
+ *(uint64_t*)data = dir[1];
+ return No_Fault;
+ case TSDEV_CC_DIR2:
+ *(uint64_t*)data = dir[2];
+ return No_Fault;
+ case TSDEV_CC_DIR3:
+ *(uint64_t*)data = dir[3];
+ return No_Fault;
+ case TSDEV_CC_DRIR:
+ *(uint64_t*)data = drir;
+ return No_Fault;
+ case TSDEV_CC_PRBEN:
+ panic("TSDEV_CC_PRBEN not implemented\n");
+ return No_Fault;
+ case TSDEV_CC_IIC0:
+ case TSDEV_CC_IIC1:
+ case TSDEV_CC_IIC2:
+ case TSDEV_CC_IIC3:
+ panic("TSDEV_CC_IICx not implemented\n");
+ return No_Fault;
+ case TSDEV_CC_MPR0:
+ case TSDEV_CC_MPR1:
+ case TSDEV_CC_MPR2:
+ case TSDEV_CC_MPR3:
+ panic("TSDEV_CC_MPRx not implemented\n");
+ return No_Fault;
+ default:
+ panic("default in cchip read reached, accessing 0x%x\n");
+ } // uint64_t
+
+ break;
+ case sizeof(uint32_t):
+ case sizeof(uint16_t):
+ case sizeof(uint8_t):
+ default:
+ panic("invalid access size(?) for tsunami register!\n");
+ }
+ DPRINTFN("Tsunami CChip ERROR: read daddr=%#x size=%d\n", daddr, req->size);
+
+ return No_Fault;
+}
+
+Fault
+TsunamiCChip::write(MemReqPtr req, const uint8_t *data)
+{
+ DPRINTF(Tsunami, "write - va=%#x size=%d \n",
+ req->vaddr, req->size);
+
+ Addr daddr = (req->paddr & addr_mask) >> 6;
+
+ switch (req->size) {
+
+ case sizeof(uint64_t):
+ switch(daddr) {
+ 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 seventh bit, clear the RTC interrupt
+ if ((*(uint64_t*) data) & (1<<4)) {
+ RTCInterrupting = false;
+ tsunami->intrctrl->clear(0, TheISA::INTLEVEL_IRQ2, 0);
+ DPRINTF(Tsunami, "clearing rtc interrupt\n");
+ misc &= ~(1<<4);
+ } else panic("TSDEV_CC_MISC write not implemented\n");
+ return No_Fault;
+ case TSDEV_CC_AAR0:
+ case TSDEV_CC_AAR1:
+ case TSDEV_CC_AAR2:
+ case TSDEV_CC_AAR3:
+ panic("TSDEV_CC_AARx write not implemeted\n");
+ return No_Fault;
+ case TSDEV_CC_DIM0:
+ dim[0] = *(uint64_t*)data;
+ if (dim[0] & drir) {
+ dir[0] = dim[0] & drir;
+ if (!dirInterrupting[0]) {
+ dirInterrupting[0] = true;
+ tsunami->intrctrl->post(0, TheISA::INTLEVEL_IRQ1, 0);
+ DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n");
+ }
+ }
+ return No_Fault;
+ case TSDEV_CC_DIM1:
+ dim[1] = *(uint64_t*)data;
+ if (dim[1] & drir) {
+ dir[1] = dim[1] & drir;
+ if (!dirInterrupting[1]) {
+ dirInterrupting[1] = true;
+ tsunami->intrctrl->post(1, TheISA::INTLEVEL_IRQ1, 0);
+ DPRINTF(Tsunami, "posting dir interrupt to cpu 1\n");
+ }
+ }
+ return No_Fault;
+ case TSDEV_CC_DIM2:
+ dim[2] = *(uint64_t*)data;
+ if (dim[2] & drir) {
+ dir[2] = dim[2] & drir;
+ if (!dirInterrupting[2]) {
+ dirInterrupting[2] = true;
+ tsunami->intrctrl->post(2, TheISA::INTLEVEL_IRQ1, 0);
+ DPRINTF(Tsunami, "posting dir interrupt to cpu 2\n");
+ }
+ }
+ return No_Fault;
+ case TSDEV_CC_DIM3:
+ dim[3] = *(uint64_t*)data;
+ if ((dim[3] & drir) /*And Not Already Int*/) {
+ dir[3] = dim[3] & drir;
+ if (!dirInterrupting[3]) {
+ dirInterrupting[3] = true;
+ tsunami->intrctrl->post(3, TheISA::INTLEVEL_IRQ1, 0);
+ DPRINTF(Tsunami, "posting dir interrupt to cpu 3\n");
+ }
+ }
+ return No_Fault;
+ case TSDEV_CC_DIR0:
+ case TSDEV_CC_DIR1:
+ case TSDEV_CC_DIR2:
+ case TSDEV_CC_DIR3:
+ panic("TSDEV_CC_DIR write not implemented\n");
+ return No_Fault;
+ case TSDEV_CC_DRIR:
+ panic("TSDEV_CC_DRIR write not implemented\n");
+ return No_Fault;
+ case TSDEV_CC_PRBEN:
+ panic("TSDEV_CC_PRBEN write not implemented\n");
+ return No_Fault;
+ case TSDEV_CC_IIC0:
+ case TSDEV_CC_IIC1:
+ case TSDEV_CC_IIC2:
+ case TSDEV_CC_IIC3:
+ panic("TSDEV_CC_IICx write not implemented\n");
+ return No_Fault;
+ case TSDEV_CC_MPR0:
+ case TSDEV_CC_MPR1:
+ case TSDEV_CC_MPR2:
+ case TSDEV_CC_MPR3:
+ panic("TSDEV_CC_MPRx write not implemented\n");
+ return No_Fault;
+ default:
+ panic("default in cchip read reached, accessing 0x%x\n");
+ }
+
+ break;
+ case sizeof(uint32_t):
+ case sizeof(uint16_t):
+ case sizeof(uint8_t):
+ default:
+ panic("invalid access size(?) for tsunami register!\n");
+ }
+
+ DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size);
+
+ return No_Fault;
+}
+
+void
+TsunamiCChip::postDRIR(uint64_t bitvector)
+{
+ drir |= bitvector;
+ for(int i=0; i < Tsunami::Max_CPUs; i++) {
+ if (bitvector & dim[i]) {
+ dir[i] |= bitvector;
+ if (!dirInterrupting[i]) {
+ dirInterrupting[i] = true;
+ tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, 0);
+ DPRINTF(Tsunami, "posting dir interrupt to cpu %d\n",i);
+ }
+ }
+ }
+}
+
+void
+TsunamiCChip::clearDRIR(uint64_t bitvector)
+{
+ drir &= ~bitvector;
+ for(int i=0; i < Tsunami::Max_CPUs; i++) {
+ dir[i] &= ~bitvector;
+ if (!dir[i]) {
+ dirInterrupting[i] = false;
+ tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, 0);
+ DPRINTF(Tsunami, "clearing dir interrupt to cpu %d\n", i);
+
+ }
+ }
+}
+
+void
+TsunamiCChip::serialize(std::ostream &os)
+{
+ // code should be written
+}
+
+void
+TsunamiCChip::unserialize(Checkpoint *cp, const std::string &section)
+{
+ //code should be written
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
+
+ SimObjectParam<Tsunami *> tsunami;
+ SimObjectParam<MemoryController *> mmu;
+ Param<Addr> addr;
+ Param<Addr> mask;
+
+END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
+
+ INIT_PARAM(tsunami, "Tsunami"),
+ INIT_PARAM(mmu, "Memory Controller"),
+ INIT_PARAM(addr, "Device Address"),
+ INIT_PARAM(mask, "Address Mask")
+
+END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
+
+CREATE_SIM_OBJECT(TsunamiCChip)
+{
+ return new TsunamiCChip(getInstanceName(), tsunami, addr, mask, mmu);
+}
+
+REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip)
diff --git a/dev/tsunami_cchip.hh b/dev/tsunami_cchip.hh
new file mode 100644
index 000000000..c1c196d18
--- /dev/null
+++ b/dev/tsunami_cchip.hh
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2003 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.
+ */
+
+/* @file
+ * Turbolaser system bus node (processor, memory, or IO)
+ */
+
+#ifndef __TSUNAMI_CCHIP_HH__
+#define __TSUNAMI_CCHIP_HH__
+
+#include "mem/functional_mem/mmap_device.hh"
+#include "dev/tsunami.hh"
+
+/*
+ * Tsunami CChip
+ */
+class TsunamiCChip : public MmapDevice
+{
+ public:
+
+ protected:
+ Tsunami *tsunami;
+ uint64_t dim[Tsunami::Max_CPUs];
+ uint64_t dir[Tsunami::Max_CPUs];
+ bool dirInterrupting[Tsunami::Max_CPUs];
+ uint64_t drir;
+
+ public:
+ TsunamiCChip(const std::string &name, Tsunami *t,
+ Addr addr, Addr mask, MemoryController *mmu);
+
+ virtual Fault read(MemReqPtr req, uint8_t *data);
+ virtual Fault write(MemReqPtr req, const uint8_t *data);
+
+ void postDRIR(uint64_t bitvector);
+ void clearDRIR(uint64_t bitvector);
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+ uint64_t misc;
+ bool RTCInterrupting;
+};
+
+#endif // __TSUNAMI_CCHIP_HH__
diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc
new file mode 100644
index 000000000..c6447cf64
--- /dev/null
+++ b/dev/tsunami_io.cc
@@ -0,0 +1,356 @@
+/* $Id$ */
+
+/* @file
+ * Tsunami I/O including PIC, PIT, RTC, DMA
+ */
+
+#include <sys/time.h>
+
+#include <deque>
+#include <string>
+#include <vector>
+
+#include "base/trace.hh"
+#include "cpu/exec_context.hh"
+#include "dev/console.hh"
+#include "dev/tlaser_clock.hh"
+#include "dev/tsunami_io.hh"
+#include "dev/tsunamireg.h"
+#include "dev/tsunami.hh"
+#include "mem/functional_mem/memory_control.hh"
+#include "sim/builder.hh"
+#include "dev/tsunami_cchip.hh"
+
+using namespace std;
+
+#define UNIX_YEAR_OFFSET 52
+
+
+// Timer Event for Periodic interrupt of RTC
+TsunamiIO::RTCEvent::RTCEvent(Tsunami* t)
+ : Event(&mainEventQueue), tsunami(t)
+{
+ DPRINTF(MC146818, "RTC Event Initilizing\n");
+ schedule(curTick + ticksPerSecond/RTC_RATE);
+}
+
+void
+TsunamiIO::RTCEvent::process()
+{
+ DPRINTF(MC146818, "RTC Timer Interrupt\n");
+ schedule(curTick + ticksPerSecond/RTC_RATE);
+ //Actually interrupt the processor here
+ if (!tsunami->cchip->RTCInterrupting) {
+ tsunami->cchip->misc |= 1 << 7;
+ tsunami->cchip->RTCInterrupting = true;
+ tsunami->intrctrl->post(0, TheISA::INTLEVEL_IRQ2, 0);
+ }
+}
+
+const char *
+TsunamiIO::RTCEvent::description()
+{
+ return "tsunami RTC 1024Hz interrupt";
+}
+
+// Timer Event for PIT Timers
+TsunamiIO::ClockEvent::ClockEvent()
+ : Event(&mainEventQueue)
+{
+ DPRINTF(Tsunami, "Clock Event Initilizing\n");
+ mode = 0;
+}
+
+void
+TsunamiIO::ClockEvent::process()
+{
+ DPRINTF(Tsunami, "Timer Interrupt\n");
+ if (mode == 0)
+ status = 0x20; // set bit that linux is looking for
+ else
+ schedule(curTick + interval);
+}
+
+void
+TsunamiIO::ClockEvent::Program(int count)
+{
+ DPRINTF(Tsunami, "Timer set to curTick + %d\n", count);
+ // should be count * (cpufreq/pitfreq)
+ interval = count * ticksPerSecond/1193180UL;
+ schedule(curTick + interval);
+ status = 0;
+}
+
+const char *
+TsunamiIO::ClockEvent::description()
+{
+ return "tsunami 8254 Interval timer";
+}
+
+void
+TsunamiIO::ClockEvent::ChangeMode(uint8_t md)
+{
+ mode = md;
+}
+
+uint8_t
+TsunamiIO::ClockEvent::Status()
+{
+ return status;
+}
+
+
+
+
+TsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time,
+ Addr addr, Addr mask, MemoryController *mmu)
+ : MmapDevice(name, addr, mask, mmu), tsunami(t), rtc(t)
+{
+ timerData = 0;
+ set_time(init_time == 0 ? time(NULL) : init_time);
+ uip = 1;
+ picr = 0;
+ picInterrupting = false;
+}
+
+void
+TsunamiIO::set_time(time_t t)
+{
+ gmtime_r(&t, &tm);
+ DPRINTFN("Real-time clock set to %s", asctime(&tm));
+}
+
+Fault
+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_mask);
+// ExecContext *xc = req->xc;
+// int cpuid = xc->cpu_id;
+
+ switch(req->size) {
+ case sizeof(uint8_t):
+ switch(daddr) {
+ case TSDEV_TMR_CTL:
+ *(uint8_t*)data = timer2.Status();
+ return No_Fault;
+ case TSDEV_RTC_DATA:
+ switch(RTCAddress) {
+ case RTC_CONTROL_REGISTERA:
+ *(uint8_t*)data = uip << 7 | 0x26;
+ uip = !uip;
+ return No_Fault;
+ case RTC_CONTROL_REGISTERB:
+ // DM and 24/12 and UIE
+ *(uint8_t*)data = 0x46;
+ return No_Fault;
+ case RTC_CONTROL_REGISTERC:
+ // If we want to support RTC user access in linux
+ // This won't work, but for now it's fine
+ *(uint8_t*)data = 0x00;
+ return No_Fault;
+ case RTC_CONTROL_REGISTERD:
+ panic("RTC Control Register D not implemented");
+ case RTC_SECOND:
+ *(uint8_t *)data = tm.tm_sec;
+ return No_Fault;
+ case RTC_MINUTE:
+ *(uint8_t *)data = tm.tm_min;
+ return No_Fault;
+ case RTC_HOUR:
+ *(uint8_t *)data = tm.tm_hour;
+ return No_Fault;
+ case RTC_DAY_OF_WEEK:
+ *(uint8_t *)data = tm.tm_wday;
+ return No_Fault;
+ case RTC_DAY_OF_MONTH:
+ *(uint8_t *)data = tm.tm_mday;
+ case RTC_MONTH:
+ *(uint8_t *)data = tm.tm_mon + 1;
+ return No_Fault;
+ case RTC_YEAR:
+ *(uint8_t *)data = tm.tm_year - UNIX_YEAR_OFFSET;
+ return No_Fault;
+ default:
+ panic("Unknown RTC Address\n");
+ }
+
+ default:
+ panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
+ }
+ case sizeof(uint16_t):
+ case sizeof(uint32_t):
+ case sizeof(uint64_t):
+ default:
+ panic("I/O Read - invalid size - va %#x size %d\n", req->vaddr, req->size);
+ }
+ panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
+
+ return No_Fault;
+}
+
+Fault
+TsunamiIO::write(MemReqPtr req, const uint8_t *data)
+{
+ uint8_t dt = *(uint8_t*)data;
+ uint64_t dt64 = dt;
+
+ 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_mask);
+
+ switch(req->size) {
+ case sizeof(uint8_t):
+ switch(daddr) {
+ case TSDEV_PIC1_MASK:
+ mask1 = *(uint8_t*)data;
+ if ((picr & mask1) && !picInterrupting) {
+ picInterrupting = true;
+ tsunami->cchip->postDRIR(uint64_t(1) << 55);
+ DPRINTF(Tsunami, "posting pic interrupt to cchip\n");
+ }
+ return No_Fault;
+ case TSDEV_PIC2_MASK:
+ mask2 = *(uint8_t*)data;
+ //PIC2 Not implemented to interrupt
+ return No_Fault;
+ case TSDEV_DMA1_RESET:
+ return No_Fault;
+ case TSDEV_DMA2_RESET:
+ return No_Fault;
+ case TSDEV_DMA1_MODE:
+ mode1 = *(uint8_t*)data;
+ return No_Fault;
+ case TSDEV_DMA2_MODE:
+ mode2 = *(uint8_t*)data;
+ return No_Fault;
+ case TSDEV_DMA1_MASK:
+ case TSDEV_DMA2_MASK:
+ return No_Fault;
+ case TSDEV_TMR_CTL:
+ return No_Fault;
+ case TSDEV_TMR2_CTL:
+ if ((*(uint8_t*)data & 0x30) != 0x30)
+ panic("Only L/M write supported\n");
+
+ switch(*(uint8_t*)data >> 6) {
+ case 0:
+ timer0.ChangeMode((*(uint8_t*)data & 0xF) >> 1);
+ break;
+ case 2:
+ timer2.ChangeMode((*(uint8_t*)data & 0xF) >> 1);
+ break;
+ default:
+ panic("Read Back Command not implemented\n");
+ }
+ return No_Fault;
+ case TSDEV_TMR2_DATA:
+ /* two writes before we actually start the Timer
+ so I set a flag in the timerData */
+ if(timerData & 0x1000) {
+ timerData &= 0x1000;
+ timerData += *(uint8_t*)data << 8;
+ timer2.Program(timerData);
+ } else {
+ timerData = *(uint8_t*)data;
+ timerData |= 0x1000;
+ }
+ return No_Fault;
+ case TSDEV_TMR0_DATA:
+ /* two writes before we actually start the Timer
+ so I set a flag in the timerData */
+ if(timerData & 0x1000) {
+ timerData &= 0x1000;
+ timerData += *(uint8_t*)data << 8;
+ timer0.Program(timerData);
+ } else {
+ timerData = *(uint8_t*)data;
+ timerData |= 0x1000;
+ }
+ return No_Fault;
+ case TSDEV_RTC_ADDR:
+ RTCAddress = *(uint8_t*)data;
+ return No_Fault;
+ case TSDEV_RTC_DATA:
+ panic("RTC Write not implmented (rtc.o won't work)\n");
+ default:
+ panic("I/O Write - va%#x size %d\n", req->vaddr, req->size);
+ }
+ case sizeof(uint16_t):
+ case sizeof(uint32_t):
+ case sizeof(uint64_t):
+ default:
+ panic("I/O Write - invalid size - va %#x size %d\n", req->vaddr, req->size);
+ }
+
+
+ return No_Fault;
+}
+
+void
+TsunamiIO::postPIC(uint8_t bitvector)
+{
+ //PIC2 Is not implemented, because nothing of interest there
+ picr |= bitvector;
+ if ((picr & mask1) && !picInterrupting) {
+ picInterrupting = true;
+ tsunami->cchip->postDRIR(uint64_t(1) << 55);
+ DPRINTF(Tsunami, "posting pic interrupt to cchip\n");
+ }
+}
+
+void
+TsunamiIO::clearPIC(uint8_t bitvector)
+{
+ //PIC2 Is not implemented, because nothing of interest there
+ picr &= ~bitvector;
+ if (!(picr & mask1)) {
+ picInterrupting = false;
+ tsunami->cchip->clearDRIR(uint64_t(1) << 55);
+ DPRINTF(Tsunami, "clearing pic interrupt to cchip\n");
+ }
+}
+
+void
+TsunamiIO::serialize(std::ostream &os)
+{
+ // code should be written
+}
+
+void
+TsunamiIO::unserialize(Checkpoint *cp, const std::string &section)
+{
+ //code should be written
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
+
+ SimObjectParam<Tsunami *> tsunami;
+ Param<time_t> time;
+ SimObjectParam<MemoryController *> mmu;
+ Param<Addr> addr;
+ Param<Addr> mask;
+
+END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
+
+ INIT_PARAM(tsunami, "Tsunami"),
+ INIT_PARAM_DFLT(time, "System time to use "
+ "(0 for actual time, default is 1/1/06", ULL(1136073600)),
+ INIT_PARAM(mmu, "Memory Controller"),
+ INIT_PARAM(addr, "Device Address"),
+ INIT_PARAM(mask, "Address Mask")
+
+END_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
+
+CREATE_SIM_OBJECT(TsunamiIO)
+{
+ return new TsunamiIO(getInstanceName(), tsunami, time, addr,
+ mask, mmu);
+}
+
+REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO)
diff --git a/dev/tsunami_io.hh b/dev/tsunami_io.hh
new file mode 100644
index 000000000..97589e5f0
--- /dev/null
+++ b/dev/tsunami_io.hh
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2003 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.
+ */
+
+/* @file
+ * Tsunami Fake I/O Space mapping including RTC/timer interrupts
+ */
+
+#ifndef __TSUNAMI_DMA_HH__
+#define __TSUNAMI_DMA_HH__
+
+#define RTC_RATE 1024
+
+#include "mem/functional_mem/mmap_device.hh"
+#include "dev/tsunami.hh"
+
+/*
+ * Tsunami I/O device
+ */
+class TsunamiIO : public MmapDevice
+{
+
+ private:
+ struct tm tm;
+
+ // In Tsunami RTC only has two i/o ports
+ // one for data and one for address, so you
+ // write the address and then read/write the data
+ uint8_t RTCAddress;
+
+ protected:
+
+ class ClockEvent : public Event
+ {
+ protected:
+ Tick interval;
+ uint8_t mode;
+ uint8_t status;
+
+ public:
+ ClockEvent();
+
+ virtual void process();
+ virtual const char *description();
+ void Program(int count);
+ void ChangeMode(uint8_t mode);
+ uint8_t Status();
+
+ };
+
+ class RTCEvent : public Event
+ {
+ protected:
+ Tsunami* tsunami;
+ public:
+ RTCEvent(Tsunami* t);
+
+ virtual void process();
+ virtual const char *description();
+ };
+
+ uint8_t uip;
+
+ uint8_t mask1;
+ uint8_t mask2;
+ uint8_t mode1;
+ uint8_t mode2;
+
+ uint8_t picr; //Raw PIC interrput register, before masking
+ bool picInterrupting;
+
+ Tsunami *tsunami;
+
+ /* This timer is initilized, but after I wrote the code
+ it doesn't seem to be used again, and best I can tell
+ it too is not connected to any interrupt port */
+ ClockEvent timer0;
+
+ /* This timer is used to control the speaker, which
+ we normally could care less about, however it is
+ also used to calculated the clockspeed and hense
+ bogomips which is kinda important to the scheduler
+ so we need to implemnt it although after boot I can't
+ imagine we would be playing with the PC speaker much */
+ ClockEvent timer2;
+
+ RTCEvent rtc;
+
+ uint32_t timerData;
+
+
+ public:
+ uint32_t frequency() const { return RTC_RATE; }
+
+ TsunamiIO(const std::string &name, Tsunami *t, time_t init_time,
+ Addr addr, Addr mask, MemoryController *mmu);
+
+ void set_time(time_t t);
+
+ virtual Fault read(MemReqPtr req, uint8_t *data);
+ virtual Fault write(MemReqPtr req, const uint8_t *data);
+
+ void postPIC(uint8_t bitvector);
+ void clearPIC(uint8_t bitvector);
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+};
+
+#endif // __TSUNAMI_IO_HH__
diff --git a/dev/tsunami_pchip.cc b/dev/tsunami_pchip.cc
new file mode 100644
index 000000000..aadcf998f
--- /dev/null
+++ b/dev/tsunami_pchip.cc
@@ -0,0 +1,260 @@
+/* $Id$ */
+
+/* @file
+ * Tsunami PChip (pci)
+ */
+
+#include <deque>
+#include <string>
+#include <vector>
+
+#include "base/trace.hh"
+#include "cpu/exec_context.hh"
+#include "dev/console.hh"
+#include "dev/etherdev.hh"
+#include "dev/scsi_ctrl.hh"
+#include "dev/tlaser_clock.hh"
+#include "dev/tsunami_pchip.hh"
+#include "dev/tsunamireg.h"
+#include "dev/tsunami.hh"
+#include "mem/functional_mem/memory_control.hh"
+#include "sim/builder.hh"
+#include "sim/system.hh"
+
+using namespace std;
+
+TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t,
+ Addr addr, Addr mask, MemoryController *mmu)
+ : MmapDevice(name, addr, mask, mmu), tsunami(t)
+{
+ wsba0 = 0;
+ wsba1 = 0;
+ wsba2 = 0;
+ wsba3 = 0;
+ wsm0 = 0;
+ wsm1 = 0;
+ wsm2 = 0;
+ wsm3 = 0;
+ tba0 = 0;
+ tba1 = 0;
+ tba2 = 0;
+ tba3 = 0;
+
+ //Set back pointer in tsunami
+ tsunami->pchip = this;
+}
+
+Fault
+TsunamiPChip::read(MemReqPtr req, uint8_t *data)
+{
+ DPRINTF(Tsunami, "read va=%#x size=%d\n",
+ req->vaddr, req->size);
+
+ Addr daddr = (req->paddr & addr_mask) >> 6;
+// ExecContext *xc = req->xc;
+// int cpuid = xc->cpu_id;
+
+ switch (req->size) {
+
+ case sizeof(uint64_t):
+ switch(daddr) {
+ case TSDEV_PC_WSBA0:
+ *(uint64_t*)data = wsba0;
+ return No_Fault;
+ case TSDEV_PC_WSBA1:
+ *(uint64_t*)data = wsba1;
+ return No_Fault;
+ case TSDEV_PC_WSBA2:
+ *(uint64_t*)data = wsba2;
+ return No_Fault;
+ case TSDEV_PC_WSBA3:
+ *(uint64_t*)data = wsba3;
+ return No_Fault;
+ case TSDEV_PC_WSM0:
+ *(uint64_t*)data = wsm0;
+ return No_Fault;
+ case TSDEV_PC_WSM1:
+ *(uint64_t*)data = wsm1;
+ return No_Fault;
+ case TSDEV_PC_WSM2:
+ *(uint64_t*)data = wsm2;
+ return No_Fault;
+ case TSDEV_PC_WSM3:
+ *(uint64_t*)data = wsm3;
+ return No_Fault;
+ case TSDEV_PC_TBA0:
+ *(uint64_t*)data = tba0;
+ return No_Fault;
+ case TSDEV_PC_TBA1:
+ *(uint64_t*)data = tba1;
+ return No_Fault;
+ case TSDEV_PC_TBA2:
+ *(uint64_t*)data = tba2;
+ return No_Fault;
+ case TSDEV_PC_TBA3:
+ *(uint64_t*)data = tba3;
+ return No_Fault;
+ case TSDEV_PC_PCTL:
+ // might want to change the clock??
+ *(uint64_t*)data = 0x00; // try this
+ return No_Fault;
+ case TSDEV_PC_PLAT:
+ panic("PC_PLAT not implemented\n");
+ case TSDEV_PC_RES:
+ panic("PC_RES not implemented\n");
+ case TSDEV_PC_PERROR:
+ panic("PC_PERROR not implemented\n");
+ case TSDEV_PC_PERRMASK:
+ panic("PC_PERRMASK not implemented\n");
+ case TSDEV_PC_PERRSET:
+ panic("PC_PERRSET not implemented\n");
+ case TSDEV_PC_TLBIV:
+ panic("PC_TLBIV not implemented\n");
+ case TSDEV_PC_TLBIA:
+ *(uint64_t*)data = 0x00; // shouldn't be readable, but linux
+ return No_Fault;
+ case TSDEV_PC_PMONCTL:
+ panic("PC_PMONCTL not implemented\n");
+ case TSDEV_PC_PMONCNT:
+ panic("PC_PMONCTN not implemented\n");
+ default:
+ panic("Default in PChip Read reached reading 0x%x\n", daddr);
+
+ } // uint64_t
+
+ break;
+ case sizeof(uint32_t):
+ case sizeof(uint16_t):
+ case sizeof(uint8_t):
+ default:
+ panic("invalid access size(?) for tsunami register!\n\n");
+ }
+ DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size);
+
+ return No_Fault;
+}
+
+Fault
+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_mask) >> 6;
+
+ switch (req->size) {
+
+ case sizeof(uint64_t):
+ switch(daddr) {
+ case TSDEV_PC_WSBA0:
+ wsba0 = *(uint64_t*)data;
+ return No_Fault;
+ case TSDEV_PC_WSBA1:
+ wsba1 = *(uint64_t*)data;
+ return No_Fault;
+ case TSDEV_PC_WSBA2:
+ wsba2 = *(uint64_t*)data;
+ return No_Fault;
+ case TSDEV_PC_WSBA3:
+ wsba3 = *(uint64_t*)data;
+ return No_Fault;
+ case TSDEV_PC_WSM0:
+ wsm0 = *(uint64_t*)data;
+ return No_Fault;
+ case TSDEV_PC_WSM1:
+ wsm1 = *(uint64_t*)data;
+ return No_Fault;
+ case TSDEV_PC_WSM2:
+ wsm2 = *(uint64_t*)data;
+ return No_Fault;
+ case TSDEV_PC_WSM3:
+ wsm3 = *(uint64_t*)data;
+ return No_Fault;
+ case TSDEV_PC_TBA0:
+ tba0 = *(uint64_t*)data;
+ return No_Fault;
+ case TSDEV_PC_TBA1:
+ tba1 = *(uint64_t*)data;
+ return No_Fault;
+ case TSDEV_PC_TBA2:
+ tba2 = *(uint64_t*)data;
+ return No_Fault;
+ case TSDEV_PC_TBA3:
+ tba3 = *(uint64_t*)data;
+ return No_Fault;
+ case TSDEV_PC_PCTL:
+ // might want to change the clock??
+ //*(uint64_t*)data; // try this
+ return No_Fault;
+ case TSDEV_PC_PLAT:
+ panic("PC_PLAT not implemented\n");
+ case TSDEV_PC_RES:
+ panic("PC_RES not implemented\n");
+ case TSDEV_PC_PERROR:
+ panic("PC_PERROR not implemented\n");
+ case TSDEV_PC_PERRMASK:
+ panic("PC_PERRMASK not implemented\n");
+ case TSDEV_PC_PERRSET:
+ panic("PC_PERRSET not implemented\n");
+ case TSDEV_PC_TLBIV:
+ panic("PC_TLBIV not implemented\n");
+ case TSDEV_PC_TLBIA:
+ return No_Fault; // value ignored, supposted to invalidate SG TLB
+ case TSDEV_PC_PMONCTL:
+ panic("PC_PMONCTL not implemented\n");
+ case TSDEV_PC_PMONCNT:
+ panic("PC_PMONCTN not implemented\n");
+ default:
+ panic("Default in PChip Read reached reading 0x%x\n", daddr);
+
+ } // uint64_t
+
+ break;
+ case sizeof(uint32_t):
+ case sizeof(uint16_t):
+ case sizeof(uint8_t):
+ default:
+ panic("invalid access size(?) for tsunami register!\n\n");
+ }
+
+ DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size);
+
+ return No_Fault;
+}
+
+void
+TsunamiPChip::serialize(std::ostream &os)
+{
+ // code should be written
+}
+
+void
+TsunamiPChip::unserialize(Checkpoint *cp, const std::string &section)
+{
+ //code should be written
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
+
+ SimObjectParam<Tsunami *> tsunami;
+ SimObjectParam<MemoryController *> mmu;
+ Param<Addr> addr;
+ Param<Addr> mask;
+
+END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
+
+ INIT_PARAM(tsunami, "Tsunami"),
+ INIT_PARAM(mmu, "Memory Controller"),
+ INIT_PARAM(addr, "Device Address"),
+ INIT_PARAM(mask, "Address Mask")
+
+END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
+
+CREATE_SIM_OBJECT(TsunamiPChip)
+{
+ return new TsunamiPChip(getInstanceName(), tsunami, addr, mask, mmu);
+}
+
+REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip)
diff --git a/dev/tsunami_pchip.hh b/dev/tsunami_pchip.hh
new file mode 100644
index 000000000..6a7f24e95
--- /dev/null
+++ b/dev/tsunami_pchip.hh
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2003 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.
+ */
+
+/* @file
+ * Tsunami PChip
+ */
+
+#ifndef __TSUNAMI_PCHIP_HH__
+#define __TSUNAMI_PCHIP_HH__
+
+#include "mem/functional_mem/mmap_device.hh"
+#include "dev/tsunami.hh"
+
+/*
+ * Tsunami PChip
+ */
+class TsunamiPChip : public MmapDevice
+{
+ public:
+
+ protected:
+ Tsunami *tsunami;
+
+ uint64_t wsba0;
+ uint64_t wsba1;
+ uint64_t wsba2;
+ uint64_t wsba3;
+ uint64_t wsm0;
+ uint64_t wsm1;
+ uint64_t wsm2;
+ uint64_t wsm3;
+ uint64_t tba0;
+ uint64_t tba1;
+ uint64_t tba2;
+ uint64_t tba3;
+
+
+ public:
+ TsunamiPChip(const std::string &name, Tsunami *t,
+ Addr addr, Addr mask, MemoryController *mmu);
+
+ virtual Fault read(MemReqPtr req, uint8_t *data);
+ virtual Fault write(MemReqPtr req, const uint8_t *data);
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+};
+
+#endif // __TSUNAMI_PCHIP_HH__
diff --git a/dev/tsunami_uart.cc b/dev/tsunami_uart.cc
new file mode 100644
index 000000000..d2056e65b
--- /dev/null
+++ b/dev/tsunami_uart.cc
@@ -0,0 +1,206 @@
+/* $Id$ */
+
+/* @file
+ * Tsunami UART
+ */
+
+/*
+ * Copyright (C) 1998 by the Board of Trustees
+ * of Leland Stanford Junior University.
+ * Copyright (C) 1998 Digital Equipment Corporation
+ *
+ * This file is part of the SimOS distribution.
+ * See LICENSE file for terms of the license.
+ *
+ */
+
+#include <string>
+#include <vector>
+
+#include "base/inifile.hh"
+#include "base/str.hh" // for to_number
+#include "base/trace.hh"
+#include "dev/console.hh"
+#include "dev/tsunami_uart.hh"
+#include "mem/functional_mem/memory_control.hh"
+#include "sim/builder.hh"
+#include "targetarch/ev5.hh"
+
+using namespace std;
+
+#define CONS_INT_TX 0x01 // interrupt enable / state bits
+#define CONS_INT_RX 0x02
+
+TsunamiUart::TsunamiUart(const string &name, SimConsole *c,
+ Addr addr, Addr mask, MemoryController *mmu)
+ : MmapDevice(name, addr, mask, mmu),
+ cons(c), status_store(0), valid_char(false)
+{
+}
+
+Fault
+TsunamiUart::read(MemReqPtr req, uint8_t *data)
+{
+ Addr daddr = req->paddr & addr_mask;
+ DPRINTF(TsunamiUart, " read register %#x\n", daddr);
+
+ switch (req->size) {
+ case sizeof(uint64_t):
+ *(uint64_t *)data = 0;
+ break;
+ case sizeof(uint32_t):
+ *(uint32_t *)data = 0;
+ break;
+ case sizeof(uint16_t):
+ *(uint16_t *)data = 0;
+ break;
+ case sizeof(uint8_t):
+ *(uint8_t *)data = 0;
+ break;
+ }
+
+ switch (daddr) {
+ case 0xD: // Status Register
+ {
+ int status = cons->intStatus();
+ if (!valid_char) {
+ valid_char = cons->in(next_char);
+ if (!valid_char)
+ status &= ~CONS_INT_RX;
+ } else {
+ status |= CONS_INT_RX;
+ }
+
+ if (status_store == 3) {
+ // RR3 stuff? Don't really understand it, btw
+ status_store = 0;
+ if (status & CONS_INT_TX) {
+ *data = (1 << 4);
+ return No_Fault;
+ } else if (status & CONS_INT_RX) {
+ *data = (1 << 5);
+ return No_Fault;
+ } else {
+ DPRINTF(TsunamiUart, "spurious read\n");
+ return No_Fault;
+ }
+ } else {
+ int reg = (1 << 2) | (1 << 5) | (1 << 6);
+ if (status & CONS_INT_RX)
+ reg |= (1 << 0);
+ *data = reg;
+ return No_Fault;
+ }
+ break;
+ }
+
+ case 0x8: // Data register (RX)
+ if (!valid_char)
+ panic("Invalid character");
+
+ DPRINTF(TsunamiUart, "read data register \'%c\' %#02x\n",
+ isprint(next_char) ? next_char : ' ', next_char);
+
+ *data = next_char;
+ valid_char = false;
+ return No_Fault;
+
+ case 0x9: // Interrupt Enable Register
+ *data = 0;
+ return No_Fault;
+ }
+ *data = 0;
+ // panic("%s: read daddr=%#x type=read *data=%#x\n", name(), daddr, *data);
+
+ return No_Fault;
+}
+
+Fault
+TsunamiUart::write(MemReqPtr req, const uint8_t *data)
+{
+ Addr daddr = req->paddr & addr_mask;
+
+ DPRINTF(TsunamiUart, " write register %#x value %#x\n", daddr, *(uint8_t*)data);
+ switch (daddr) {
+ case 0xb:
+ status_store = *data;
+ switch (*data) {
+ case 0x03: // going to read RR3
+ return No_Fault;
+
+ case 0x28: // Ack of TX
+ {
+ if ((cons->intStatus() & CONS_INT_TX) == 0)
+ panic("Ack of transmit, though there was no interrupt");
+
+ cons->clearInt(CONS_INT_TX);
+ return No_Fault;
+ }
+
+ case 0x00:
+ case 0x01:
+ case 0x12:
+ // going to write data???
+ return No_Fault;
+
+ default:
+ DPRINTF(TsunamiUart, "writing status register %#x \n",
+ *(uint64_t *)data);
+ return No_Fault;
+ }
+
+ case 0x8: // Data register (TX)
+ cons->out(*(uint64_t *)data);
+ return No_Fault;
+ case 0x9: // DLM
+ DPRINTF(TsunamiUart, "writing to DLM/IER %#x\n", *(uint8_t*)data);
+ return No_Fault;
+ case 0xc: // MCR
+ DPRINTF(TsunamiUart, "writing to MCR %#x\n", *(uint8_t*)data);
+ return No_Fault;
+
+ }
+
+ return No_Fault;
+}
+
+void
+TsunamiUart::serialize(ostream &os)
+{
+ SERIALIZE_SCALAR(status_store);
+ SERIALIZE_SCALAR(next_char);
+ SERIALIZE_SCALAR(valid_char);
+}
+
+void
+TsunamiUart::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_SCALAR(status_store);
+ UNSERIALIZE_SCALAR(next_char);
+ UNSERIALIZE_SCALAR(valid_char);
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiUart)
+
+ SimObjectParam<SimConsole *> console;
+ SimObjectParam<MemoryController *> mmu;
+ Param<Addr> addr;
+ Param<Addr> mask;
+
+END_DECLARE_SIM_OBJECT_PARAMS(TsunamiUart)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiUart)
+
+ INIT_PARAM(console, "The console"),
+ INIT_PARAM(mmu, "Memory Controller"),
+ INIT_PARAM(addr, "Device Address"),
+ INIT_PARAM(mask, "Address Mask")
+
+END_INIT_SIM_OBJECT_PARAMS(TsunamiUart)
+
+CREATE_SIM_OBJECT(TsunamiUart)
+{
+ return new TsunamiUart(getInstanceName(), console, addr, mask, mmu);
+}
+
+REGISTER_SIM_OBJECT("TsunamiUart", TsunamiUart)
diff --git a/dev/tsunami_uart.hh b/dev/tsunami_uart.hh
new file mode 100644
index 000000000..f32b1ff4c
--- /dev/null
+++ b/dev/tsunami_uart.hh
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2003 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.
+ */
+
+/* @file
+ * Tsunami UART
+ */
+
+#ifndef __TSUNAMI_UART_HH__
+#define __TSUNAMI_UART_HH__
+
+#include "mem/functional_mem/mmap_device.hh"
+
+class SimConsole;
+
+/*
+ * Tsunami UART
+ */
+class TsunamiUart : public MmapDevice
+{
+ protected:
+ SimConsole *cons;
+ int status_store;
+ uint8_t next_char;
+ bool valid_char;
+
+ public:
+ TsunamiUart(const std::string &name, SimConsole *c,
+ Addr addr, Addr mask, MemoryController *mmu);
+
+ Fault read(MemReqPtr req, uint8_t *data);
+ Fault write(MemReqPtr req, const uint8_t *data);
+
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+};
+
+#endif // __TSUNAMI_UART_HH__
diff --git a/dev/tsunamireg.h b/dev/tsunamireg.h
new file mode 100644
index 000000000..7201edf94
--- /dev/null
+++ b/dev/tsunamireg.h
@@ -0,0 +1,103 @@
+
+#ifndef __TSUNAMIREG_H__
+#define __TSUNAMIREG_H__
+
+// CChip Registers
+#define TSDEV_CC_CSR 0x00
+#define TSDEV_CC_MTR 0x01
+#define TSDEV_CC_MISC 0x02
+
+#define TSDEV_CC_AAR0 0x04
+#define TSDEV_CC_AAR1 0x05
+#define TSDEV_CC_AAR2 0x06
+#define TSDEV_CC_AAR3 0x07
+#define TSDEV_CC_DIM0 0x08
+#define TSDEV_CC_DIM1 0x09
+#define TSDEV_CC_DIR0 0x0A
+#define TSDEV_CC_DIR1 0x0B
+#define TSDEV_CC_DRIR 0x0C
+#define TSDEV_CC_PRBEN 0x0D
+#define TSDEV_CC_IIC0 0x0E
+#define TSDEV_CC_IIC1 0x0F
+#define TSDEV_CC_MPR0 0x10
+#define TSDEV_CC_MPR1 0x11
+#define TSDEV_CC_MPR2 0x12
+#define TSDEV_CC_MPR3 0x13
+
+#define TSDEV_CC_DIM2 0x18
+#define TSDEV_CC_DIM3 0x19
+#define TSDEV_CC_DIR2 0x1A
+#define TSDEV_CC_DIR3 0x1B
+#define TSDEV_CC_IIC2 0x1C
+#define TSDEV_CC_IIC3 0x1D
+
+
+// PChip Registers
+#define TSDEV_PC_WSBA0 0x00
+#define TSDEV_PC_WSBA1 0x01
+#define TSDEV_PC_WSBA2 0x02
+#define TSDEV_PC_WSBA3 0x03
+#define TSDEV_PC_WSM0 0x04
+#define TSDEV_PC_WSM1 0x05
+#define TSDEV_PC_WSM2 0x06
+#define TSDEV_PC_WSM3 0x07
+#define TSDEV_PC_TBA0 0x08
+#define TSDEV_PC_TBA1 0x09
+#define TSDEV_PC_TBA2 0x0A
+#define TSDEV_PC_TBA3 0x0B
+#define TSDEV_PC_PCTL 0x0C
+#define TSDEV_PC_PLAT 0x0D
+#define TSDEV_PC_RES 0x0E
+#define TSDEV_PC_PERROR 0x0F
+#define TSDEV_PC_PERRMASK 0x10
+#define TSDEV_PC_PERRSET 0x11
+#define TSDEV_PC_TLBIV 0x12
+#define TSDEV_PC_TLBIA 0x13
+#define TSDEV_PC_PMONCTL 0x14
+#define TSDEV_PC_PMONCNT 0x15
+
+#define TSDEV_PC_SPST 0x20
+
+
+// DChip Registers
+#define TSDEV_DC_DSC 0x20
+#define TSDEV_DC_STR 0x21
+#define TSDEV_DC_DREV 0x22
+#define TSDEV_DC_DSC2 0x23
+
+// I/O Ports
+#define TSDEV_PIC1_MASK 0x21
+#define TSDEV_PIC2_MASK 0xA1
+#define TSDEV_DMA1_RESET 0x0D
+#define TSDEV_DMA2_RESET 0xDA
+#define TSDEV_DMA1_MODE 0x0B
+#define TSDEV_DMA2_MODE 0xD6
+#define TSDEV_DMA1_MASK 0x0A
+#define TSDEV_DMA2_MASK 0xD4
+#define TSDEV_TMR_CTL 0x61
+#define TSDEV_TMR2_CTL 0x43
+#define TSDEV_TMR2_DATA 0x42
+#define TSDEV_TMR0_DATA 0x40
+
+#define TSDEV_RTC_ADDR 0x70
+#define TSDEV_RTC_DATA 0x71
+
+// RTC defines
+#define RTC_SECOND 0 // second of minute [0..59]
+#define RTC_SECOND_ALARM 1 // seconds to alarm
+#define RTC_MINUTE 2 // minute of hour [0..59]
+#define RTC_MINUTE_ALARM 3 // minutes to alarm
+#define RTC_HOUR 4 // hour of day [0..23]
+#define RTC_HOUR_ALARM 5 // hours to alarm
+#define RTC_DAY_OF_WEEK 6 // day of week [1..7]
+#define RTC_DAY_OF_MONTH 7 // day of month [1..31]
+#define RTC_MONTH 8 // month of year [1..12]
+#define RTC_YEAR 9 // year [00..99]
+#define RTC_CONTROL_REGISTERA 10 // control register A
+#define RTC_CONTROL_REGISTERB 11 // control register B
+#define RTC_CONTROL_REGISTERC 12 // control register C
+#define RTC_CONTROL_REGISTERD 13 // control register D
+#define RTC_REGNUMBER_RTC_CR1 0x6A // control register 1
+
+
+#endif // __TSUNAMIREG_H__