summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Saidi <saidi@eecs.umich.edu>2004-06-26 21:26:28 -0400
committerAli Saidi <saidi@eecs.umich.edu>2004-06-26 21:26:28 -0400
commit54b49f933abe452a48bf13c9c948946672bb784b (patch)
tree3f26334dcc4e6acbfebcaf70116058a89f05e6e1
parent4799a7b87439913765029117eb51fcacd6f07edb (diff)
downloadgem5-54b49f933abe452a48bf13c9c948946672bb784b.tar.xz
rewrote uart and renamed console.cc to simconsole to reduce confusion
base/traceflags.py: removed TsunamiUart/TlaserUart and added a plain Uart dev/alpha_console.cc: updated for new simconsole dev/platform.hh: added a uart member to platform dev/simconsole.cc: dev/simconsole.hh: removed lots of legacy code, it should all be ours now. converted tabs to 8 spaces added our copyright dev/tsunami.cc: uses simconsole.hh rather than console.hh dev/tsunami_cchip.cc: dev/tsunami_io.cc: never needed console.hh dev/tsunami_io.hh: this does need eventq.hh and it just happend to be working whenn console.hh was included everywhere dev/tsunamireg.h: added a couple more 8250/16550 uart defines dev/uart.cc: new uart code, rewritten to support both tlaser and tsunami (both a 8250 and 8530 uart). dev/uart.hh: updated for new uart, legacy code removed --HG-- rename : dev/console.cc => dev/simconsole.cc rename : dev/console.hh => dev/simconsole.hh rename : dev/tsunami_uart.cc => dev/uart.cc rename : dev/tsunami_uart.hh => dev/uart.hh extra : convert_revision : e663352d49d4c2d3c95643030cf73c0e85ba2f08
-rw-r--r--base/traceflags.py3
-rw-r--r--dev/alpha_console.cc4
-rw-r--r--dev/platform.hh4
-rw-r--r--dev/simconsole.cc (renamed from dev/console.cc)155
-rw-r--r--dev/simconsole.hh (renamed from dev/console.hh)67
-rw-r--r--dev/tsunami.cc2
-rw-r--r--dev/tsunami_cchip.cc1
-rw-r--r--dev/tsunami_io.cc1
-rw-r--r--dev/tsunami_io.hh1
-rw-r--r--dev/tsunami_uart.cc308
-rw-r--r--dev/tsunamireg.h8
-rw-r--r--dev/uart.cc433
-rw-r--r--dev/uart.hh (renamed from dev/tsunami_uart.hh)45
13 files changed, 556 insertions, 476 deletions
diff --git a/base/traceflags.py b/base/traceflags.py
index 14e28219a..363d44ffb 100644
--- a/base/traceflags.py
+++ b/base/traceflags.py
@@ -63,7 +63,6 @@ baseFlags = [
'Console',
'ConsolePoll',
'ConsoleVerbose',
- 'TlaserUart',
'AlphaConsole',
'Flow',
'Interrupt',
@@ -114,7 +113,7 @@ baseFlags = [
'IdeCtrl',
'IdeDisk',
'Tsunami',
- 'TsunamiUart'
+ 'Uart'
]
#
diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc
index e94ca82ea..86851ff8b 100644
--- a/dev/alpha_console.cc
+++ b/dev/alpha_console.cc
@@ -40,7 +40,7 @@
#include "cpu/base_cpu.hh"
#include "cpu/exec_context.hh"
#include "dev/alpha_console.hh"
-#include "dev/console.hh"
+#include "dev/simconsole.hh"
#include "dev/simple_disk.hh"
#include "dev/tlaser_clock.hh"
#include "mem/bus/bus.hh"
@@ -226,7 +226,7 @@ AlphaConsole::write(MemReqPtr &req, const uint8_t *data)
break;
case offsetof(AlphaAccess, outputChar):
- console->out((char)(val & 0xff), false);
+ console->out((char)(val & 0xff));
break;
case offsetof(AlphaAccess, bootStrapImpure):
diff --git a/dev/platform.hh b/dev/platform.hh
index f0e3d291b..7920480bc 100644
--- a/dev/platform.hh
+++ b/dev/platform.hh
@@ -39,6 +39,7 @@
class PciConfigAll;
class IntrControl;
class SimConsole;
+class Uart;
class Platform : public SimObject
{
@@ -50,6 +51,9 @@ class Platform : public SimObject
/** Pointer to the PCI configuration space */
PciConfigAll *pciconfig;
+ /** Pointer to the UART, set by the uart */
+ Uart *uart;
+
int interrupt_frequency;
public:
diff --git a/dev/console.cc b/dev/simconsole.cc
index b9bcbb3d1..a15057402 100644
--- a/dev/console.cc
+++ b/dev/simconsole.cc
@@ -1,8 +1,33 @@
-/* $Id$ */
-
+/*
+ * 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.
+ */
/* @file
- * User Console Definitions
+ * Implements the user interface to a serial console
*/
#include <sys/ioctl.h>
@@ -20,10 +45,11 @@
#include "base/misc.hh"
#include "base/socket.hh"
#include "base/trace.hh"
-#include "dev/console.hh"
+#include "dev/simconsole.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;
@@ -48,17 +74,17 @@ SimConsole::Event::process(int revent)
SimConsole::SimConsole(const string &name, const string &file, 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(NULL)
#if TRACING_ON == 1
- linebuf(16384),
+ , linebuf(16384)
#endif
- _status(0), _enable(0), intr(NULL), platform(NULL)
{
if (!file.empty())
outfile = new ofstream(file.c_str());
if (outfile)
outfile->setf(ios::unitbuf);
+
}
SimConsole::~SimConsole()
@@ -130,7 +156,8 @@ SimConsole::data()
len = read(buf, sizeof(buf));
if (len) {
rxbuf.write((char *)buf, len);
- raiseInt(ReceiveInterrupt);
+ // Inform the UART there is data available
+ uart->dataAvailable();
}
}
@@ -138,7 +165,7 @@ size_t
SimConsole::read(uint8_t *buf, size_t len)
{
if (in_fd < 0)
- panic("SimConsole(read): Console not properly attached.\n");
+ panic("Console not properly attached.\n");
size_t ret;
do {
@@ -147,7 +174,7 @@ SimConsole::read(uint8_t *buf, size_t len)
if (ret < 0)
- DPRINTFN("SimConsole(read): Read failed.\n");
+ DPRINTFN("Read failed.\n");
if (ret <= 0) {
detach();
@@ -162,7 +189,7 @@ size_t
SimConsole::write(const uint8_t *buf, size_t len)
{
if (out_fd < 0)
- panic("SimConsole(write): Console not properly attached.\n");
+ panic("Console not properly attached.\n");
size_t ret;
for (;;) {
@@ -172,33 +199,12 @@ SimConsole::write(const uint8_t *buf, size_t len)
break;
if (errno != EINTR)
- detach();
+ detach();
}
return ret;
}
-void
-SimConsole::configTerm()
-{
- struct termios ios;
-
- if (isatty(out_fd)) {
- if (tcgetattr(out_fd, &ios) < 0) {
- panic( "tcgetattr\n");
- }
- ios.c_iflag &= ~(ISTRIP|ICRNL|IGNCR|ICRNL|IXOFF|IXON);
- ios.c_oflag &= ~(OPOST);
- ios.c_oflag &= (ONLCR);
- ios.c_lflag &= ~(ISIG|ICANON|ECHO);
- ios.c_cc[VMIN] = 1;
- ios.c_cc[VTIME] = 0;
- if (tcsetattr(out_fd, TCSANOW, &ios) < 0) {
- panic( "tcsetattr\n");
- }
- }
-}
-
#define MORE_PENDING (ULL(1) << 61)
#define RECEIVE_SUCCESS (ULL(0) << 62)
#define RECEIVE_NONE (ULL(2) << 62)
@@ -216,9 +222,6 @@ SimConsole::in(uint8_t &c)
empty = rxbuf.empty();
}
- if (empty)
- clearInt(ReceiveInterrupt);
-
DPRINTF(ConsoleVerbose, "in: \'%c\' %#02x more: %d, return: %d\n",
isprint(c) ? c : ' ', c, !empty, ret);
@@ -245,7 +248,7 @@ SimConsole::console_in()
}
void
-SimConsole::out(char c, bool raise_int)
+SimConsole::out(char c)
{
#if TRACING_ON == 1
if (DTRACE(Console)) {
@@ -277,90 +280,20 @@ SimConsole::out(char c, bool raise_int)
if (outfile)
outfile->write(&c, 1);
- if (raise_int)
- raiseInt(TransmitInterrupt);
-
- DPRINTF(ConsoleVerbose, "out: \'%c\' %#02x",
+ DPRINTF(ConsoleVerbose, "out: \'%c\' %#02x\n",
isprint(c) ? c : ' ', (int)c);
- if (raise_int)
- DPRINTF(ConsoleVerbose, "status: %#x\n", _status);
- else
- DPRINTF(ConsoleVerbose, "\n");
-}
-
-inline bool
-MaskStatus(int status, int mask)
-{ return (status & mask) != 0; }
-
-int
-SimConsole::clearInt(int i)
-{
- int old = _status;
- _status &= ~i;
- //if (MaskStatus(old, _enable) != MaskStatus(_status, _enable) && intr)
- platform->clearConsoleInt();
-
- return old;
-}
-
-void
-SimConsole::raiseInt(int i)
-{
- //int old = _status;
- _status |= i;
- //if (MaskStatus(old, _enable) != MaskStatus(_status, _enable) && intr)
- platform->postConsoleInt();
-}
-
-void
-SimConsole::initInt(IntrControl *i)
-{
- if (intr)
- panic("Console has already been initialized.");
-
- intr = i;
}
-void
-SimConsole::setInt(int bits)
-{
- int old;
-
- if (bits & ~(TransmitInterrupt | ReceiveInterrupt))
- panic("An interrupt was not set!");
-
- old = _enable;
- _enable |= bits;
-
- //if (MaskStatus(_status, old) != MaskStatus(_status, _enable) && intr) {
- if (intr) {
- if (MaskStatus(_status, _enable))
- platform->postConsoleInt();
- else
- platform->clearConsoleInt();
- }
-}
-
-void
-SimConsole::setPlatform(Platform *p)
-{
- platform = p;
- platform->cons = this;
-}
void
SimConsole::serialize(ostream &os)
{
- SERIALIZE_SCALAR(_status);
- SERIALIZE_SCALAR(_enable);
}
void
SimConsole::unserialize(Checkpoint *cp, const std::string &section)
{
- UNSERIALIZE_SCALAR(_status);
- UNSERIALIZE_SCALAR(_enable);
}
@@ -368,7 +301,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimConsole)
SimObjectParam<ConsoleListener *> listener;
SimObjectParam<IntrControl *> intr_control;
- SimObjectParam<Platform *> platform;
Param<string> output;
Param<bool> append_name;
Param<int> number;
@@ -379,7 +311,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SimConsole)
INIT_PARAM(listener, "console listener"),
INIT_PARAM(intr_control, "interrupt controller"),
- INIT_PARAM(platform, "platform"),
INIT_PARAM_DFLT(output, "file to dump output to", ""),
INIT_PARAM_DFLT(append_name, "append name() to filename", true),
INIT_PARAM_DFLT(number, "console number", 0)
@@ -401,10 +332,6 @@ CREATE_SIM_OBJECT(SimConsole)
SimConsole *console = new SimConsole(getInstanceName(), filename, number);
((ConsoleListener *)listener)->add(console);
- ((SimConsole *)console)->initInt(intr_control);
- ((SimConsole *)console)->setPlatform(platform);
- //((SimConsole *)console)->setInt(SimConsole::TransmitInterrupt |
- // SimConsole::ReceiveInterrupt);
return console;
}
diff --git a/dev/console.hh b/dev/simconsole.hh
index 87be9ccbc..138e2e36a 100644
--- a/dev/console.hh
+++ b/dev/simconsole.hh
@@ -1,4 +1,30 @@
-/* $Id$ */
+/*
+ * 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.
+ */
/* @file
* User Console Interface
@@ -16,8 +42,13 @@
#include "sim/sim_object.hh"
class ConsoleListener;
+class Uart;
+
class SimConsole : public SimObject
{
+ public:
+ Uart *uart;
+
protected:
class Event : public PollEvent
{
@@ -36,8 +67,6 @@ class SimConsole : public SimObject
int number;
int in_fd;
int out_fd;
-
- protected:
ConsoleListener *listener;
public:
@@ -68,18 +97,6 @@ class SimConsole : public SimObject
void write(uint8_t c) { write(&c, 1); }
size_t write(const uint8_t *buf, size_t len);
- void configTerm();
-
- protected:
- // interrupt status/enable
- int _status;
- int _enable;
-
- // interrupt handle
- IntrControl *intr;
- // Platform so we can post interrupts
- Platform *platform;
-
public:
/////////////////
// OS interface
@@ -102,24 +119,10 @@ class SimConsole : public SimObject
uint64_t console_in();
// Send a character to the console
- void out(char c, bool raise_int = true);
-
- enum {
- TransmitInterrupt = 1,
- ReceiveInterrupt = 2
- };
-
- // Read the current interrupt status of this console.
- int intStatus() { return _status; }
-
- // Set the interrupt enable bits.
- int clearInt(int i);
- void raiseInt(int i);
-
- void initInt(IntrControl *i);
- void setInt(int bits);
+ void out(char c);
- void setPlatform(Platform *p);
+ //Ask the console if data is available
+ bool dataAvailable() { return !rxbuf.empty(); }
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
diff --git a/dev/tsunami.cc b/dev/tsunami.cc
index 1cdd7d726..c44da69b7 100644
--- a/dev/tsunami.cc
+++ b/dev/tsunami.cc
@@ -31,7 +31,7 @@
#include <vector>
#include "cpu/intr_control.hh"
-#include "dev/console.hh"
+#include "dev/simconsole.hh"
#include "dev/etherdev.hh"
#include "dev/ide_ctrl.hh"
#include "dev/tlaser_clock.hh"
diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc
index a64f643a2..0fbfcb56f 100644
--- a/dev/tsunami_cchip.cc
+++ b/dev/tsunami_cchip.cc
@@ -35,7 +35,6 @@
#include <vector>
#include "base/trace.hh"
-#include "dev/console.hh"
#include "dev/tsunami_cchip.hh"
#include "dev/tsunamireg.h"
#include "dev/tsunami.hh"
diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc
index ea530b3d2..4c798a852 100644
--- a/dev/tsunami_io.cc
+++ b/dev/tsunami_io.cc
@@ -37,7 +37,6 @@
#include <vector>
#include "base/trace.hh"
-#include "dev/console.hh"
#include "dev/tsunami_io.hh"
#include "dev/tsunami.hh"
#include "mem/bus/bus.hh"
diff --git a/dev/tsunami_io.hh b/dev/tsunami_io.hh
index e6a545689..75e5d764c 100644
--- a/dev/tsunami_io.hh
+++ b/dev/tsunami_io.hh
@@ -36,6 +36,7 @@
#include "dev/io_device.hh"
#include "base/range.hh"
#include "dev/tsunami.hh"
+#include "sim/eventq.hh"
/** How often the RTC interrupts */
static const int RTC_RATE = 1024;
diff --git a/dev/tsunami_uart.cc b/dev/tsunami_uart.cc
deleted file mode 100644
index c6da02cf4..000000000
--- a/dev/tsunami_uart.cc
+++ /dev/null
@@ -1,308 +0,0 @@
-/* $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/bus/bus.hh"
-#include "mem/bus/pio_interface.hh"
-#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;
-
-#define CONS_INT_TX 0x01 // interrupt enable / state bits
-#define CONS_INT_RX 0x02
-
-
-TsunamiUart::IntrEvent::IntrEvent(TsunamiUart *u)
- : Event(&mainEventQueue), uart(u)
-{
- DPRINTF(TsunamiUart, "UART Interrupt Event Initilizing\n");
-}
-
-const char *
-TsunamiUart::IntrEvent::description()
-{
- return "tsunami uart interrupt delay event";
-}
-
-void
-TsunamiUart::IntrEvent::process()
-{
- if (UART_IER_THRI & uart->IER) {
- DPRINTF(TsunamiUart, "UART InterEvent, interrupting\n");
- uart->cons->raiseInt(CONS_INT_TX);
- }
- else
- DPRINTF(TsunamiUart, "UART InterEvent, not interrupting\n");
-
-}
-
-void
-TsunamiUart::IntrEvent::scheduleIntr()
-{
- DPRINTF(TsunamiUart, "Scheduling IER interrupt\n");
- if (!scheduled())
- schedule(curTick + 300);
- else
- reschedule(curTick + 300);
-}
-
-
-
-TsunamiUart::TsunamiUart(const string &name, SimConsole *c,
- MemoryController *mmu, Addr a,
- HierParams *hier, Bus *bus)
- : PioDevice(name), addr(a), cons(c), status_store(0), valid_char(false),
- intrEvent(this)
-{
- mmu->add_child(this, Range<Addr>(addr, addr + size));
-
- if (bus) {
- pioInterface = newPioInterface(name, hier, bus, this,
- &TsunamiUart::cacheAccess);
- pioInterface->addAddrRange(addr, addr + size - 1);
- }
-
- IER = 0;
-}
-
-Fault
-TsunamiUart::read(MemReqPtr &req, uint8_t *data)
-{
- Addr daddr = req->paddr - (addr & PA_IMPL_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 0x5: // 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 0x0: // Data register (RX)
- 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 0x1: // Interrupt Enable Register
- // This is the lovely way linux checks there is actually a serial
- // port at the desired address
- if (IER == 0)
- *data = 0;
- else if (IER == 0x0F)
- *data = 0x0F;
- else
- *data = 0;
- return No_Fault;
- case 0x2:
- // High two bits need to be clear for an 8250 (simple) serial port
- // Low bit of IIR is 0 for a pending interrupt, 1 otherwise.
- int status = cons->intStatus();
- status = (status & 0x1) | (status >> 1);
- *data = (~status) & 0x1 ;
- 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 & PA_IMPL_MASK);
-
- DPRINTF(TsunamiUart, " write register %#x value %#x\n", daddr, *(uint8_t*)data);
-
- switch (daddr) {
- case 0x3:
- 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",
- *(uint8_t *)data);
- return No_Fault;
- }
-
- case 0x0: // Data register (TX)
- char ourchar;
- ourchar = *(uint8_t *)data;
- if ((isprint(ourchar) || iscntrl(ourchar)) && (ourchar != 0x0C))
- cons->out(ourchar);
- cons->clearInt(CONS_INT_TX);
- intrEvent.scheduleIntr();
- return No_Fault;
- break;
- case 0x1: // IER
- IER = *(uint8_t*)data;
- DPRINTF(TsunamiUart, "writing to IER [%#x]\n", IER);
- if (UART_IER_THRI & IER)
- cons->raiseInt(CONS_INT_TX);
- else {
- cons->clearInt(CONS_INT_TX);
- if (intrEvent.scheduled())
- intrEvent.deschedule();
- }
- return No_Fault;
- break;
- case 0x4: // MCR
- DPRINTF(TsunamiUart, "writing to MCR %#x\n", *(uint8_t*)data);
- return No_Fault;
-
- }
-
- return No_Fault;
-}
-
-Tick
-TsunamiUart::cacheAccess(MemReqPtr &req)
-{
- return curTick + 1000;
-}
-
-void
-TsunamiUart::serialize(ostream &os)
-{
- SERIALIZE_SCALAR(status_store);
- SERIALIZE_SCALAR(next_char);
- SERIALIZE_SCALAR(valid_char);
- SERIALIZE_SCALAR(IER);
- Tick intrwhen;
- if (intrEvent.scheduled())
- intrwhen = intrEvent.when();
- else
- intrwhen = 0;
- SERIALIZE_SCALAR(intrwhen);
-
-
-}
-
-void
-TsunamiUart::unserialize(Checkpoint *cp, const std::string &section)
-{
- UNSERIALIZE_SCALAR(status_store);
- UNSERIALIZE_SCALAR(next_char);
- UNSERIALIZE_SCALAR(valid_char);
- UNSERIALIZE_SCALAR(IER);
- Tick intrwhen;
- UNSERIALIZE_SCALAR(intrwhen);
- if (intrwhen != 0)
- intrEvent.schedule(intrwhen);
-
-}
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiUart)
-
- SimObjectParam<SimConsole *> console;
- SimObjectParam<MemoryController *> mmu;
- Param<Addr> addr;
- SimObjectParam<Bus*> io_bus;
- SimObjectParam<HierParams *> hier;
-
-
-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_DFLT(io_bus, "The IO Bus to attach to", NULL),
- INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
-
-END_INIT_SIM_OBJECT_PARAMS(TsunamiUart)
-
-CREATE_SIM_OBJECT(TsunamiUart)
-{
- return new TsunamiUart(getInstanceName(), console, mmu, addr, hier, io_bus);
-}
-
-REGISTER_SIM_OBJECT("TsunamiUart", TsunamiUart)
diff --git a/dev/tsunamireg.h b/dev/tsunamireg.h
index 2e4e873a0..876c6bf18 100644
--- a/dev/tsunamireg.h
+++ b/dev/tsunamireg.h
@@ -140,7 +140,15 @@
// UART Defines
+#define UART_IER_RDI 0x01
#define UART_IER_THRI 0x02
#define UART_IER_RLSI 0x04
+
+#define UART_LSR_TEMT 0x40
+#define UART_LSR_THRE 0x20
+#define UART_LSR_DR 0x01
+
+#define UART_MCR_LOOP 0x10
+
#endif // __TSUNAMIREG_H__
diff --git a/dev/uart.cc b/dev/uart.cc
new file mode 100644
index 000000000..30dde1984
--- /dev/null
+++ b/dev/uart.cc
@@ -0,0 +1,433 @@
+/*
+ * 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.
+ */
+
+/* @file
+ * Implements a 8250 UART
+ */
+
+#include <string>
+#include <vector>
+
+#include "base/inifile.hh"
+#include "base/str.hh" // for to_number
+#include "base/trace.hh"
+#include "dev/simconsole.hh"
+#include "dev/uart.hh"
+#include "dev/platform.hh"
+#include "mem/bus/bus.hh"
+#include "mem/bus/pio_interface.hh"
+#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;
+
+Uart::IntrEvent::IntrEvent(Uart *u)
+ : Event(&mainEventQueue), uart(u)
+{
+ DPRINTF(Uart, "UART Interrupt Event Initilizing\n");
+}
+
+const char *
+Uart::IntrEvent::description()
+{
+ return "uart interrupt delay event";
+}
+
+void
+Uart::IntrEvent::process()
+{
+ if (UART_IER_THRI & uart->IER) {
+ DPRINTF(Uart, "UART InterEvent, interrupting\n");
+ uart->platform->postConsoleInt();
+ uart->status |= TX_INT;
+ }
+ else
+ DPRINTF(Uart, "UART InterEvent, not interrupting\n");
+
+}
+
+void
+Uart::IntrEvent::scheduleIntr()
+{
+ DPRINTF(Uart, "Scheduling IER interrupt\n");
+ if (!scheduled())
+ schedule(curTick + 300);
+ else
+ reschedule(curTick + 300);
+}
+
+Uart::Uart(const string &name, SimConsole *c, MemoryController *mmu, Addr a,
+ Addr s, HierParams *hier, Bus *bus, Platform *p)
+ : PioDevice(name), addr(a), size(s), cons(c), intrEvent(this), platform(p)
+{
+ mmu->add_child(this, Range<Addr>(addr, addr + size));
+
+
+ if (bus) {
+ pioInterface = newPioInterface(name, hier, bus, this,
+ &Uart::cacheAccess);
+ pioInterface->addAddrRange(addr, addr + size - 1);
+ }
+
+ readAddr = 0;
+ IER = 0;
+ DLAB = 0;
+ LCR = 0;
+ MCR = 0;
+ status = 0;
+
+ // set back pointers
+ cons->uart = this;
+ platform->uart = this;
+
+}
+
+Fault
+Uart::read(MemReqPtr &req, uint8_t *data)
+{
+ Addr daddr = req->paddr - (addr & PA_IMPL_MASK);
+ DPRINTF(Uart, " read register %#x\n", daddr);
+
+
+
+#ifdef ALPHA_TLASER
+
+ 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 0x80: // Status Register
+ if (readAddr == 3) {
+ readAddr = 0;
+ if (status & TX_INT)
+ *data = (1 << 4);
+ else if (status & RX_INT)
+ *data = (1 << 5);
+ else
+ DPRINTF(Uart, "spurious read\n");
+
+ } else {
+ *data = (1 << 2);
+ if (status & RX_INT)
+ *data |= (1 << 0);
+ }
+ break;
+
+ case 0xc0: // Data register (RX)
+ if (!cons->dataAvailable())
+ panic("No data to read");
+
+ cons->in(*data);
+
+ if (!cons->dataAvailable()) {
+ platform->clearConsoleInt();
+ status &= ~RX_INT;
+ }
+
+ DPRINTF(Uart, "read data register \'%c\' %2x\n",
+ isprint(*data) ? *data : ' ', *data);
+ break;
+ }
+
+
+#else
+
+
+ assert(req->size == 1);
+
+ switch (daddr) {
+ case 0x0:
+ if (!(LCR & 0x80)) { // read byte
+ //assert(cons->dataAvailable());
+ if (cons->dataAvailable())
+ cons->in(*data);
+ else {
+ *(uint8_t*)data = 0;
+ // A limited amount of these are ok.
+ DPRINTF(Uart, "empty read of RX register\n");
+ }
+
+ if (cons->dataAvailable())
+ platform->postConsoleInt();
+ else
+ {
+ status &= ~RX_INT;
+ platform->clearConsoleInt();
+ }
+ } else { // dll divisor latch
+ ;
+ }
+ break;
+ case 0x1:
+ if (!(LCR & 0x80)) { // Intr Enable Register(IER)
+ *(uint8_t*)data = IER;
+ } else { // DLM divisor latch MSB
+ ;
+ }
+ break;
+ case 0x2: // Intr Identification Register (IIR)
+ if (status)
+ *(uint8_t*)data = 1;
+ else
+ *(uint8_t*)data = 0;
+ break;
+ case 0x3: // Line Control Register (LCR)
+ *(uint8_t*)data = LCR;
+ break;
+ case 0x4: // Modem Control Register (MCR)
+ break;
+ case 0x5: // Line Status Register (LSR)
+ uint8_t lsr;
+ lsr = 0;
+ // check if there are any bytes to be read
+ if (cons->dataAvailable())
+ lsr = UART_LSR_DR;
+ lsr |= UART_LSR_TEMT | UART_LSR_THRE;
+ *(uint8_t*)data = lsr;
+ break;
+ case 0x6: // Modem Status Register (MSR)
+ *(uint8_t*)data = 0;
+ break;
+ case 0x7: // Scratch Register (SCR)
+ *(uint8_t*)data = 0; // doesn't exist with at 8250.
+ break;
+ default:
+ panic("Tried to access a UART port that doesn't exist\n");
+ break;
+ }
+
+#endif
+ return No_Fault;
+
+}
+
+Fault
+Uart::write(MemReqPtr &req, const uint8_t *data)
+{
+ Addr daddr = req->paddr - (addr & PA_IMPL_MASK);
+
+ DPRINTF(Uart, " write register %#x value %#x\n", daddr, *(uint8_t*)data);
+
+#ifdef ALPHA_TLASER
+
+ switch (daddr) {
+ case 0x80:
+ readAddr = *data;
+ switch (*data) {
+ case 0x28: // Ack of TX
+ if ((status & TX_INT) == 0)
+ panic("Ack of transmit, though there was no interrupt");
+
+ status &= ~TX_INT;
+ platform->clearConsoleInt();
+ break;
+ case 0x00:
+ case 0x01:
+ case 0x03: // going to read RR3
+ case 0x12:
+ break;
+ default:
+ DPRINTF(Uart, "writing status register %#x \n",
+ *(uint64_t *)data);
+ break;
+ }
+ break;
+
+ case 0xc0: // Data register (TX)
+ cons->out(*(uint64_t *)data);
+ platform->postConsoleInt();
+ status |= TX_INT;
+ break;
+ }
+
+
+#else
+ switch (daddr) {
+ case 0x0:
+ if (!(LCR & 0x80)) { // write byte
+ cons->out(*(uint64_t *)data);
+ platform->clearConsoleInt();
+ status &= ~TX_INT;
+ if (UART_IER_THRI & IER)
+ intrEvent.scheduleIntr();
+ } else { // dll divisor latch
+ ;
+ }
+ break;
+ case 0x1:
+ if (!(LCR & 0x80)) { // Intr Enable Register(IER)
+ IER = *(uint8_t*)data;
+ if ((UART_IER_THRI & IER) || ((UART_IER_RDI & IER) && cons->dataAvailable()))
+ platform->postConsoleInt();
+ else
+ {
+ platform->clearConsoleInt();
+ if (intrEvent.scheduled())
+ intrEvent.deschedule();
+
+ }
+ if (!(UART_IER_THRI & IER))
+ status &= ~TX_INT;
+ if (!((UART_IER_RDI & IER) && cons->dataAvailable()))
+ status &= ~RX_INT;
+ } else { // DLM divisor latch MSB
+ ;
+ }
+ break;
+ case 0x2: // FIFO Control Register (FCR)
+ break;
+ case 0x3: // Line Control Register (LCR)
+ LCR = *(uint8_t*)data;
+ break;
+ case 0x4: // Modem Control Register (MCR)
+ if (*(uint8_t*)data == (UART_MCR_LOOP | 0x0A))
+ MCR = 0x9A;
+ break;
+ case 0x7: // Scratch Register (SCR)
+ // We are emulating a 8250 so we don't have a scratch reg
+ break;
+ default:
+ panic("Tried to access a UART port that doesn't exist\n");
+ break;
+ }
+#endif
+
+ return No_Fault;
+}
+
+void
+Uart::dataAvailable()
+{
+#ifdef ALPHA_TLASER
+ platform->postConsoleInt();
+ status |= RX_INT;
+#else
+
+ // if the kernel wants an interrupt when we have data
+ if (IER & UART_IER_RDI)
+ {
+ platform->postConsoleInt();
+ status |= RX_INT;
+ }
+
+#endif
+}
+
+Tick
+Uart::cacheAccess(MemReqPtr &req)
+{
+ return curTick + 1000;
+}
+
+void
+Uart::serialize(ostream &os)
+{
+#ifdef ALPHA_TLASER
+ SERIALIZE_SCALAR(readAddr);
+ SERIALIZE_SCALAR(status);
+#else
+ SERIALIZE_SCALAR(status);
+ SERIALIZE_SCALAR(IER);
+ SERIALIZE_SCALAR(DLAB);
+ SERIALIZE_SCALAR(LCR);
+ SERIALIZE_SCALAR(MCR);
+ Tick intrwhen;
+ if (intrEvent.scheduled())
+ intrwhen = intrEvent.when();
+ else
+ intrwhen = 0;
+ SERIALIZE_SCALAR(intrwhen);
+#endif
+}
+
+void
+Uart::unserialize(Checkpoint *cp, const std::string &section)
+{
+#ifdef ALPHA_TLASER
+ UNSERIALIZE_SCALAR(readAddr);
+ UNSERIALIZE_SCALAR(status);
+#else
+ UNSERIALIZE_SCALAR(status);
+ UNSERIALIZE_SCALAR(IER);
+ UNSERIALIZE_SCALAR(DLAB);
+ UNSERIALIZE_SCALAR(LCR);
+ UNSERIALIZE_SCALAR(MCR);
+ Tick intrwhen;
+ UNSERIALIZE_SCALAR(intrwhen);
+ if (intrwhen != 0)
+ intrEvent.schedule(intrwhen);
+#endif
+
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Uart)
+
+ SimObjectParam<SimConsole *> console;
+ SimObjectParam<MemoryController *> mmu;
+ SimObjectParam<Platform *> platform;
+ Param<Addr> addr;
+ Param<Addr> size;
+ SimObjectParam<Bus*> io_bus;
+ SimObjectParam<HierParams *> hier;
+
+
+END_DECLARE_SIM_OBJECT_PARAMS(Uart)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(Uart)
+
+ INIT_PARAM(console, "The console"),
+ INIT_PARAM(mmu, "Memory Controller"),
+ INIT_PARAM(platform, "Pointer to platfrom"),
+ INIT_PARAM(addr, "Device Address"),
+ INIT_PARAM_DFLT(size, "Device size", 0x8),
+ INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
+ INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
+
+END_INIT_SIM_OBJECT_PARAMS(Uart)
+
+CREATE_SIM_OBJECT(Uart)
+{
+ return new Uart(getInstanceName(), console, mmu, addr, size, hier, io_bus,
+ platform);
+}
+
+REGISTER_SIM_OBJECT("Uart", Uart)
diff --git a/dev/tsunami_uart.hh b/dev/uart.hh
index 14ee42e8b..83e1a758c 100644
--- a/dev/tsunami_uart.hh
+++ b/dev/uart.hh
@@ -27,7 +27,7 @@
*/
/* @file
- * Tsunami UART
+ * Defines a 8250 UART
*/
#ifndef __TSUNAMI_UART_HH__
@@ -38,45 +38,60 @@
#include "dev/io_device.hh"
class SimConsole;
+class Platform;
-/*
- * Tsunami UART
- */
-class TsunamiUart : public PioDevice
+const int RX_INT = 0x1;
+const int TX_INT = 0x2;
+
+
+class Uart : public PioDevice
{
+
private:
Addr addr;
- static const Addr size = 0x8;
+ Addr size;
+ SimConsole *cons;
protected:
- SimConsole *cons;
- int status_store;
- uint8_t next_char;
- bool valid_char;
- uint8_t IER;
+ int readAddr; // tlaser only
+ uint8_t IER, DLAB, LCR, MCR;
+ int status;
class IntrEvent : public Event
{
protected:
- TsunamiUart *uart;
+ Uart *uart;
public:
- IntrEvent(TsunamiUart *u);
+ IntrEvent(Uart *u);
virtual void process();
virtual const char *description();
void scheduleIntr();
};
IntrEvent intrEvent;
+ Platform *platform;
public:
- TsunamiUart(const string &name, SimConsole *c, MemoryController *mmu,
- Addr a, HierParams *hier, Bus *bus);
+ Uart(const string &name, SimConsole *c, MemoryController *mmu,
+ Addr a, Addr s, HierParams *hier, Bus *bus, Platform *p);
Fault read(MemReqPtr &req, uint8_t *data);
Fault write(MemReqPtr &req, const uint8_t *data);
+ /**
+ * Inform the uart that there is data available.
+ */
+ void dataAvailable();
+
+
+ /**
+ * Return if we have an interrupt pending
+ * @return interrupt status
+ */
+ bool intStatus() { return status ? true : false; }
+
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);