rewrote uart and renamed console.cc to simconsole to reduce confusion
authorAli Saidi <saidi@eecs.umich.edu>
Sun, 27 Jun 2004 01:26:28 +0000 (21:26 -0400)
committerAli Saidi <saidi@eecs.umich.edu>
Sun, 27 Jun 2004 01:26:28 +0000 (21:26 -0400)
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

16 files changed:
base/traceflags.py
dev/alpha_console.cc
dev/console.cc [deleted file]
dev/console.hh [deleted file]
dev/platform.hh
dev/simconsole.cc [new file with mode: 0644]
dev/simconsole.hh [new file with mode: 0644]
dev/tsunami.cc
dev/tsunami_cchip.cc
dev/tsunami_io.cc
dev/tsunami_io.hh
dev/tsunami_uart.cc [deleted file]
dev/tsunami_uart.hh [deleted file]
dev/tsunamireg.h
dev/uart.cc [new file with mode: 0644]
dev/uart.hh [new file with mode: 0644]

index 14e28219a3bd908087da39e01f6cca145e55d148..363d44ffbfb3fae7237beeefd2fa5dc2d98aa932 100644 (file)
@@ -63,7 +63,6 @@ baseFlags = [
     'Console',
     'ConsolePoll',
     'ConsoleVerbose',
-    'TlaserUart',
     'AlphaConsole',
     'Flow',
     'Interrupt',
@@ -114,7 +113,7 @@ baseFlags = [
     'IdeCtrl',
     'IdeDisk',
     'Tsunami',
-    'TsunamiUart'
+    'Uart'
     ]
 
 #
index e94ca82eae128c1d8bbc9b1f17a91e08bcddf973..86851ff8b34dfb83932e2106bc8fe94dd1d908cd 100644 (file)
@@ -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/console.cc b/dev/console.cc
deleted file mode 100644 (file)
index b9bcbb3..0000000
+++ /dev/null
@@ -1,497 +0,0 @@
-/* $Id$ */
-
-
-/* @file
- * User Console Definitions
- */
-
-#include <sys/ioctl.h>
-#include <sys/termios.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <poll.h>
-#include <unistd.h>
-
-#include <iostream>
-#include <fstream>
-#include <sstream>
-#include <string>
-
-#include "base/misc.hh"
-#include "base/socket.hh"
-#include "base/trace.hh"
-#include "dev/console.hh"
-#include "mem/functional_mem/memory_control.hh"
-#include "sim/builder.hh"
-#include "targetarch/ev5.hh"
-#include "dev/platform.hh"
-
-using namespace std;
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-
-SimConsole::Event::Event(SimConsole *c, int fd, int e)
-    : PollEvent(fd, e), cons(c)
-{
-}
-
-void
-SimConsole::Event::process(int revent)
-{
-    if (revent & POLLIN)
-        cons->data();
-    else if (revent & POLLNVAL)
-        cons->detach();
-}
-
-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),
-#if TRACING_ON == 1
-      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()
-{
-    close();
-
-    if (outfile)
-        delete outfile;
-}
-
-void
-SimConsole::close()
-{
-    if (in_fd != -1)
-        ::close(in_fd);
-
-    if (out_fd != in_fd && out_fd != -1)
-        ::close(out_fd);
-}
-
-void
-SimConsole::attach(int in, int out, ConsoleListener *l)
-{
-    in_fd = in;
-    out_fd = out;
-    listener = l;
-
-    event = new Event(this, in, POLLIN);
-    pollQueue.schedule(event);
-
-    stringstream stream;
-    ccprintf(stream, "==== m5 slave console: Console %d ====", number);
-
-    // we need an actual carriage return followed by a newline for the
-    // terminal
-    stream << "\r\n";
-
-    write((const uint8_t *)stream.str().c_str(), stream.str().size());
-
-
-    DPRINTFN("attach console %d\n", number);
-
-    txbuf.readall(out);
-}
-
-void
-SimConsole::detach()
-{
-    close();
-    in_fd = -1;
-    out_fd = -1;
-
-    pollQueue.remove(event);
-
-    if (listener) {
-        listener->add(this);
-        listener = NULL;
-    }
-
-    DPRINTFN("detach console %d\n", number);
-}
-
-void
-SimConsole::data()
-{
-    uint8_t buf[1024];
-    int len;
-
-    len = read(buf, sizeof(buf));
-    if (len) {
-        rxbuf.write((char *)buf, len);
-        raiseInt(ReceiveInterrupt);
-    }
-}
-
-size_t
-SimConsole::read(uint8_t *buf, size_t len)
-{
-    if (in_fd < 0)
-        panic("SimConsole(read): Console not properly attached.\n");
-
-    size_t ret;
-    do {
-      ret = ::read(in_fd, buf, len);
-    } while (ret == -1 && errno == EINTR);
-
-
-    if (ret < 0)
-        DPRINTFN("SimConsole(read): Read failed.\n");
-
-    if (ret <= 0) {
-        detach();
-        return 0;
-    }
-
-    return ret;
-}
-
-// Console output.
-size_t
-SimConsole::write(const uint8_t *buf, size_t len)
-{
-    if (out_fd < 0)
-        panic("SimConsole(write): Console not properly attached.\n");
-
-    size_t ret;
-    for (;;) {
-      ret = ::write(out_fd, buf, len);
-
-      if (ret >= 0)
-        break;
-
-      if (errno != EINTR)
-          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)
-#define RECEIVE_ERROR (ULL(3) << 62)
-
-bool
-SimConsole::in(uint8_t &c)
-{
-    bool empty, ret;
-
-    empty = rxbuf.empty();
-    ret = !empty;
-    if (!empty) {
-        rxbuf.read((char *)&c, 1);
-        empty = rxbuf.empty();
-    }
-
-    if (empty)
-        clearInt(ReceiveInterrupt);
-
-    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())
-            value  |= MORE_PENDING;
-    } else {
-        value = RECEIVE_NONE;
-    }
-
-    DPRINTF(ConsoleVerbose, "console_in: return: %#x\n", value);
-
-    return value;
-}
-
-void
-SimConsole::out(char c, bool raise_int)
-{
-#if TRACING_ON == 1
-    if (DTRACE(Console)) {
-        static char last = '\0';
-
-        if (c != '\n' && c != '\r' ||
-            last != '\n' && last != '\r') {
-            if (c == '\n' || c == '\r') {
-                int size = linebuf.size();
-                char *buffer = new char[size + 1];
-                linebuf.read(buffer, size);
-                buffer[size] = '\0';
-                DPRINTF(Console, "%s\n", buffer);
-                delete [] buffer;
-            } else {
-                linebuf.write(c);
-            }
-        }
-
-        last = c;
-    }
-#endif
-
-    txbuf.write(c);
-
-    if (out_fd >= 0)
-        write(c);
-
-    if (outfile)
-        outfile->write(&c, 1);
-
-    if (raise_int)
-        raiseInt(TransmitInterrupt);
-
-    DPRINTF(ConsoleVerbose, "out: \'%c\' %#02x",
-            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);
-}
-
-
-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;
-
-END_DECLARE_SIM_OBJECT_PARAMS(SimConsole)
-
-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)
-
-END_INIT_SIM_OBJECT_PARAMS(SimConsole)
-
-CREATE_SIM_OBJECT(SimConsole)
-{
-    string filename = output;
-    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)->setPlatform(platform);
-    //((SimConsole *)console)->setInt(SimConsole::TransmitInterrupt |
-    //                                SimConsole::ReceiveInterrupt);
-
-    return console;
-}
-
-REGISTER_SIM_OBJECT("SimConsole", SimConsole)
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-
-ConsoleListener::ConsoleListener(const string &name)
-    : SimObject(name), event(NULL)
-{}
-
-ConsoleListener::~ConsoleListener()
-{
-    if (event)
-        delete event;
-}
-
-void
-ConsoleListener::Event::process(int revent)
-{
-    listener->accept();
-}
-
-///////////////////////////////////////////////////////////////////////
-// socket creation and console attach
-//
-
-void
-ConsoleListener::listen(int port)
-{
-    while (!listener.listen(port, true)) {
-        DPRINTF(Console,
-                ": can't bind address console port %d inuse PID %d\n",
-                port, getpid());
-        port++;
-    }
-
-    ccprintf(cerr, "Listening for console connection on port %d\n", port);
-
-    event = new Event(this, listener.getfd(), POLLIN);
-    pollQueue.schedule(event);
-}
-
-void
-ConsoleListener::add(SimConsole *cons)
-{ ConsoleList.push_back(cons);}
-
-void
-ConsoleListener::accept()
-{
-    if (!listener.islistening())
-        panic("%s: cannot accept a connection if not listening!", name());
-
-    int sfd = listener.accept(true);
-    if (sfd != -1) {
-        iter_t i = ConsoleList.begin();
-        iter_t end = ConsoleList.end();
-        if (i == end) {
-            close(sfd);
-        } else {
-            (*i)->attach(sfd, this);
-            i = ConsoleList.erase(i);
-        }
-    }
-}
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(ConsoleListener)
-
-    Param<int> port;
-
-END_DECLARE_SIM_OBJECT_PARAMS(ConsoleListener)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(ConsoleListener)
-
-    INIT_PARAM_DFLT(port, "listen port", 3456)
-
-END_INIT_SIM_OBJECT_PARAMS(ConsoleListener)
-
-CREATE_SIM_OBJECT(ConsoleListener)
-{
-    ConsoleListener *listener = new ConsoleListener(getInstanceName());
-    listener->listen(port);
-
-    return listener;
-}
-
-REGISTER_SIM_OBJECT("ConsoleListener", ConsoleListener)
diff --git a/dev/console.hh b/dev/console.hh
deleted file mode 100644 (file)
index 87be9cc..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/* $Id$ */
-
-/* @file
- * User Console Interface
- */
-
-#ifndef __CONSOLE_HH__
-#define __CONSOLE_HH__
-
-#include <iostream>
-
-#include "base/circlebuf.hh"
-#include "cpu/intr_control.hh"
-#include "base/pollevent.hh"
-#include "base/socket.hh"
-#include "sim/sim_object.hh"
-
-class ConsoleListener;
-class SimConsole : public SimObject
-{
-  protected:
-    class Event : public PollEvent
-    {
-      protected:
-        SimConsole *cons;
-
-      public:
-        Event(SimConsole *c, int fd, int e);
-        void process(int revent);
-    };
-
-    friend class Event;
-    Event *event;
-
-  protected:
-    int number;
-    int in_fd;
-    int out_fd;
-
-  protected:
-    ConsoleListener *listener;
-
-  public:
-    SimConsole(const std::string &name, const std::string &file, int num);
-    ~SimConsole();
-
-  protected:
-    CircleBuf txbuf;
-    CircleBuf rxbuf;
-    std::ostream *outfile;
-#if TRACING_ON == 1
-    CircleBuf linebuf;
-#endif
-
-  public:
-    ///////////////////////
-    // Terminal Interface
-
-    void attach(int fd, ConsoleListener *l = NULL) { attach(fd, fd, l); }
-    void attach(int in, int out, ConsoleListener *l = NULL);
-    void detach();
-
-    void data();
-
-    void close();
-    void read(uint8_t &c) { read(&c, 1); }
-    size_t read(uint8_t *buf, size_t len);
-    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
-
-    // Get a character from the console.
-    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
-    //     100: failure: no character ready
-    //     110: failure: character received with error
-    //     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 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 setPlatform(Platform *p);
-
-    virtual void serialize(std::ostream &os);
-    virtual void unserialize(Checkpoint *cp, const std::string &section);
-};
-
-class ConsoleListener : public SimObject
-{
-  protected:
-    class Event : public PollEvent
-    {
-      protected:
-        ConsoleListener *listener;
-
-      public:
-        Event(ConsoleListener *l, int fd, int e)
-            : PollEvent(fd, e), listener(l) {}
-        void process(int revent);
-    };
-
-    friend class Event;
-    Event *event;
-
-    typedef std::list<SimConsole *> list_t;
-    typedef list_t::iterator iter_t;
-    list_t ConsoleList;
-
-  protected:
-    ListenSocket listener;
-
-  public:
-    ConsoleListener(const std::string &name);
-    ~ConsoleListener();
-
-    void add(SimConsole *cons);
-
-    void accept();
-    void listen(int port);
-};
-
-#endif // __CONSOLE_HH__
index f0e3d291ba3dfae05b947f57d914bad2230ed785..7920480bc58c54decd8acde299ac592096f78a1b 100644 (file)
@@ -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/simconsole.cc b/dev/simconsole.cc
new file mode 100644 (file)
index 0000000..a150574
--- /dev/null
@@ -0,0 +1,424 @@
+/*
+ * 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 the user interface to a serial console
+ */
+
+#include <sys/ioctl.h>
+#include <sys/termios.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <poll.h>
+#include <unistd.h>
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <string>
+
+#include "base/misc.hh"
+#include "base/socket.hh"
+#include "base/trace.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;
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+
+SimConsole::Event::Event(SimConsole *c, int fd, int e)
+    : PollEvent(fd, e), cons(c)
+{
+}
+
+void
+SimConsole::Event::process(int revent)
+{
+    if (revent & POLLIN)
+        cons->data();
+    else if (revent & POLLNVAL)
+        cons->detach();
+}
+
+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)
+#if TRACING_ON == 1
+      , linebuf(16384)
+#endif
+{
+    if (!file.empty())
+        outfile = new ofstream(file.c_str());
+
+    if (outfile)
+        outfile->setf(ios::unitbuf);
+
+}
+
+SimConsole::~SimConsole()
+{
+    close();
+
+    if (outfile)
+        delete outfile;
+}
+
+void
+SimConsole::close()
+{
+    if (in_fd != -1)
+        ::close(in_fd);
+
+    if (out_fd != in_fd && out_fd != -1)
+        ::close(out_fd);
+}
+
+void
+SimConsole::attach(int in, int out, ConsoleListener *l)
+{
+    in_fd = in;
+    out_fd = out;
+    listener = l;
+
+    event = new Event(this, in, POLLIN);
+    pollQueue.schedule(event);
+
+    stringstream stream;
+    ccprintf(stream, "==== m5 slave console: Console %d ====", number);
+
+    // we need an actual carriage return followed by a newline for the
+    // terminal
+    stream << "\r\n";
+
+    write((const uint8_t *)stream.str().c_str(), stream.str().size());
+
+
+    DPRINTFN("attach console %d\n", number);
+
+    txbuf.readall(out);
+}
+
+void
+SimConsole::detach()
+{
+    close();
+    in_fd = -1;
+    out_fd = -1;
+
+    pollQueue.remove(event);
+
+    if (listener) {
+        listener->add(this);
+        listener = NULL;
+    }
+
+    DPRINTFN("detach console %d\n", number);
+}
+
+void
+SimConsole::data()
+{
+    uint8_t buf[1024];
+    int len;
+
+    len = read(buf, sizeof(buf));
+    if (len) {
+        rxbuf.write((char *)buf, len);
+        // Inform the UART there is data available
+        uart->dataAvailable();
+    }
+}
+
+size_t
+SimConsole::read(uint8_t *buf, size_t len)
+{
+    if (in_fd < 0)
+        panic("Console not properly attached.\n");
+
+    size_t ret;
+    do {
+      ret = ::read(in_fd, buf, len);
+    } while (ret == -1 && errno == EINTR);
+
+
+    if (ret < 0)
+        DPRINTFN("Read failed.\n");
+
+    if (ret <= 0) {
+        detach();
+        return 0;
+    }
+
+    return ret;
+}
+
+// Console output.
+size_t
+SimConsole::write(const uint8_t *buf, size_t len)
+{
+    if (out_fd < 0)
+        panic("Console not properly attached.\n");
+
+    size_t ret;
+    for (;;) {
+      ret = ::write(out_fd, buf, len);
+
+      if (ret >= 0)
+        break;
+
+      if (errno != EINTR)
+      detach();
+    }
+
+    return ret;
+}
+
+#define MORE_PENDING (ULL(1) << 61)
+#define RECEIVE_SUCCESS (ULL(0) << 62)
+#define RECEIVE_NONE (ULL(2) << 62)
+#define RECEIVE_ERROR (ULL(3) << 62)
+
+bool
+SimConsole::in(uint8_t &c)
+{
+    bool empty, ret;
+
+    empty = rxbuf.empty();
+    ret = !empty;
+    if (!empty) {
+        rxbuf.read((char *)&c, 1);
+        empty = rxbuf.empty();
+    }
+
+    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())
+            value  |= MORE_PENDING;
+    } else {
+        value = RECEIVE_NONE;
+    }
+
+    DPRINTF(ConsoleVerbose, "console_in: return: %#x\n", value);
+
+    return value;
+}
+
+void
+SimConsole::out(char c)
+{
+#if TRACING_ON == 1
+    if (DTRACE(Console)) {
+        static char last = '\0';
+
+        if (c != '\n' && c != '\r' ||
+            last != '\n' && last != '\r') {
+            if (c == '\n' || c == '\r') {
+                int size = linebuf.size();
+                char *buffer = new char[size + 1];
+                linebuf.read(buffer, size);
+                buffer[size] = '\0';
+                DPRINTF(Console, "%s\n", buffer);
+                delete [] buffer;
+            } else {
+                linebuf.write(c);
+            }
+        }
+
+        last = c;
+    }
+#endif
+
+    txbuf.write(c);
+
+    if (out_fd >= 0)
+        write(c);
+
+    if (outfile)
+        outfile->write(&c, 1);
+
+    DPRINTF(ConsoleVerbose, "out: \'%c\' %#02x\n",
+            isprint(c) ? c : ' ', (int)c);
+
+}
+
+
+void
+SimConsole::serialize(ostream &os)
+{
+}
+
+void
+SimConsole::unserialize(Checkpoint *cp, const std::string &section)
+{
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimConsole)
+
+    SimObjectParam<ConsoleListener *> listener;
+    SimObjectParam<IntrControl *> intr_control;
+    Param<string> output;
+    Param<bool> append_name;
+    Param<int> number;
+
+END_DECLARE_SIM_OBJECT_PARAMS(SimConsole)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(SimConsole)
+
+    INIT_PARAM(listener, "console listener"),
+    INIT_PARAM(intr_control, "interrupt controller"),
+    INIT_PARAM_DFLT(output, "file to dump output to", ""),
+    INIT_PARAM_DFLT(append_name, "append name() to filename", true),
+    INIT_PARAM_DFLT(number, "console number", 0)
+
+END_INIT_SIM_OBJECT_PARAMS(SimConsole)
+
+CREATE_SIM_OBJECT(SimConsole)
+{
+    string filename = output;
+    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);
+
+    return console;
+}
+
+REGISTER_SIM_OBJECT("SimConsole", SimConsole)
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+
+ConsoleListener::ConsoleListener(const string &name)
+    : SimObject(name), event(NULL)
+{}
+
+ConsoleListener::~ConsoleListener()
+{
+    if (event)
+        delete event;
+}
+
+void
+ConsoleListener::Event::process(int revent)
+{
+    listener->accept();
+}
+
+///////////////////////////////////////////////////////////////////////
+// socket creation and console attach
+//
+
+void
+ConsoleListener::listen(int port)
+{
+    while (!listener.listen(port, true)) {
+        DPRINTF(Console,
+                ": can't bind address console port %d inuse PID %d\n",
+                port, getpid());
+        port++;
+    }
+
+    ccprintf(cerr, "Listening for console connection on port %d\n", port);
+
+    event = new Event(this, listener.getfd(), POLLIN);
+    pollQueue.schedule(event);
+}
+
+void
+ConsoleListener::add(SimConsole *cons)
+{ ConsoleList.push_back(cons);}
+
+void
+ConsoleListener::accept()
+{
+    if (!listener.islistening())
+        panic("%s: cannot accept a connection if not listening!", name());
+
+    int sfd = listener.accept(true);
+    if (sfd != -1) {
+        iter_t i = ConsoleList.begin();
+        iter_t end = ConsoleList.end();
+        if (i == end) {
+            close(sfd);
+        } else {
+            (*i)->attach(sfd, this);
+            i = ConsoleList.erase(i);
+        }
+    }
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(ConsoleListener)
+
+    Param<int> port;
+
+END_DECLARE_SIM_OBJECT_PARAMS(ConsoleListener)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(ConsoleListener)
+
+    INIT_PARAM_DFLT(port, "listen port", 3456)
+
+END_INIT_SIM_OBJECT_PARAMS(ConsoleListener)
+
+CREATE_SIM_OBJECT(ConsoleListener)
+{
+    ConsoleListener *listener = new ConsoleListener(getInstanceName());
+    listener->listen(port);
+
+    return listener;
+}
+
+REGISTER_SIM_OBJECT("ConsoleListener", ConsoleListener)
diff --git a/dev/simconsole.hh b/dev/simconsole.hh
new file mode 100644 (file)
index 0000000..138e2e3
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * 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
+ */
+
+#ifndef __CONSOLE_HH__
+#define __CONSOLE_HH__
+
+#include <iostream>
+
+#include "base/circlebuf.hh"
+#include "cpu/intr_control.hh"
+#include "base/pollevent.hh"
+#include "base/socket.hh"
+#include "sim/sim_object.hh"
+
+class ConsoleListener;
+class Uart;
+
+class SimConsole : public SimObject
+{
+  public:
+    Uart *uart;
+
+  protected:
+    class Event : public PollEvent
+    {
+      protected:
+        SimConsole *cons;
+
+      public:
+        Event(SimConsole *c, int fd, int e);
+        void process(int revent);
+    };
+
+    friend class Event;
+    Event *event;
+
+  protected:
+    int number;
+    int in_fd;
+    int out_fd;
+    ConsoleListener *listener;
+
+  public:
+    SimConsole(const std::string &name, const std::string &file, int num);
+    ~SimConsole();
+
+  protected:
+    CircleBuf txbuf;
+    CircleBuf rxbuf;
+    std::ostream *outfile;
+#if TRACING_ON == 1
+    CircleBuf linebuf;
+#endif
+
+  public:
+    ///////////////////////
+    // Terminal Interface
+
+    void attach(int fd, ConsoleListener *l = NULL) { attach(fd, fd, l); }
+    void attach(int in, int out, ConsoleListener *l = NULL);
+    void detach();
+
+    void data();
+
+    void close();
+    void read(uint8_t &c) { read(&c, 1); }
+    size_t read(uint8_t *buf, size_t len);
+    void write(uint8_t c) { write(&c, 1); }
+    size_t write(const uint8_t *buf, size_t len);
+
+  public:
+    /////////////////
+    // OS interface
+
+    // Get a character from the console.
+    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
+    //     100: failure: no character ready
+    //     110: failure: character received with error
+    //     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 console_in();
+
+    // Send a character to the console
+    void out(char c);
+
+    //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);
+};
+
+class ConsoleListener : public SimObject
+{
+  protected:
+    class Event : public PollEvent
+    {
+      protected:
+        ConsoleListener *listener;
+
+      public:
+        Event(ConsoleListener *l, int fd, int e)
+            : PollEvent(fd, e), listener(l) {}
+        void process(int revent);
+    };
+
+    friend class Event;
+    Event *event;
+
+    typedef std::list<SimConsole *> list_t;
+    typedef list_t::iterator iter_t;
+    list_t ConsoleList;
+
+  protected:
+    ListenSocket listener;
+
+  public:
+    ConsoleListener(const std::string &name);
+    ~ConsoleListener();
+
+    void add(SimConsole *cons);
+
+    void accept();
+    void listen(int port);
+};
+
+#endif // __CONSOLE_HH__
index 1cdd7d72623dcc3de00e3852a42396097252e14e..c44da69b7f134a52ef7b14988bfbe0f5f3dbe0e7 100644 (file)
@@ -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"
index a64f643a29271ad432f2d68893b5361eb68db51f..0fbfcb56f06c51d220acf093bf0d8ae57fcee7ff 100644 (file)
@@ -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"
index ea530b3d2ca5fe0c33ad59d09ea7e023220fa680..4c798a85243fda35e1acf7b57abcb94c06eee310 100644 (file)
@@ -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"
index e6a545689904a3710aa3492fb1c54aa691857f02..75e5d764cd2fc1970c78f2acf9c752c0c776aabd 100644 (file)
@@ -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 (file)
index c6da02c..0000000
+++ /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/tsunami_uart.hh b/dev/tsunami_uart.hh
deleted file mode 100644 (file)
index 14ee42e..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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
- * Tsunami UART
- */
-
-#ifndef __TSUNAMI_UART_HH__
-#define __TSUNAMI_UART_HH__
-
-#include "dev/tsunamireg.h"
-#include "base/range.hh"
-#include "dev/io_device.hh"
-
-class SimConsole;
-
-/*
- * Tsunami UART
- */
-class TsunamiUart : public PioDevice
-{
-  private:
-    Addr addr;
-    static const Addr size = 0x8;
-
-
-  protected:
-    SimConsole *cons;
-    int status_store;
-    uint8_t next_char;
-    bool valid_char;
-    uint8_t IER;
-
-    class IntrEvent : public Event
-    {
-        protected:
-            TsunamiUart *uart;
-        public:
-            IntrEvent(TsunamiUart *u);
-            virtual void process();
-            virtual const char *description();
-            void scheduleIntr();
-    };
-
-    IntrEvent intrEvent;
-
-  public:
-    TsunamiUart(const string &name, SimConsole *c, MemoryController *mmu,
-            Addr a, HierParams *hier, Bus *bus);
-
-    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);
-
-    /**
-     * Return how long this access will take.
-     * @param req the memory request to calcuate
-     * @return Tick when the request is done
-     */
-    Tick cacheAccess(MemReqPtr &req);
-};
-
-#endif // __TSUNAMI_UART_HH__
index 2e4e873a0e512dec313689c878ace95b6371b8d8..876c6bf18f95d87ca4154378ab2a3f5fa201e9ed 100644 (file)
 
 
 // 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 (file)
index 0000000..30dde19
--- /dev/null
@@ -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/uart.hh b/dev/uart.hh
new file mode 100644 (file)
index 0000000..83e1a75
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * 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
+ * Defines a 8250 UART
+ */
+
+#ifndef __TSUNAMI_UART_HH__
+#define __TSUNAMI_UART_HH__
+
+#include "dev/tsunamireg.h"
+#include "base/range.hh"
+#include "dev/io_device.hh"
+
+class SimConsole;
+class Platform;
+
+const int RX_INT = 0x1;
+const int TX_INT = 0x2;
+
+
+class Uart : public PioDevice
+{
+
+  private:
+    Addr addr;
+    Addr size;
+    SimConsole *cons;
+
+
+  protected:
+    int readAddr; // tlaser only
+    uint8_t IER, DLAB, LCR, MCR;
+    int status;
+
+    class IntrEvent : public Event
+    {
+        protected:
+            Uart *uart;
+        public:
+            IntrEvent(Uart *u);
+            virtual void process();
+            virtual const char *description();
+            void scheduleIntr();
+    };
+
+    IntrEvent intrEvent;
+    Platform *platform;
+
+  public:
+    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);
+
+    /**
+     * Return how long this access will take.
+     * @param req the memory request to calcuate
+     * @return Tick when the request is done
+     */
+    Tick cacheAccess(MemReqPtr &req);
+};
+
+#endif // __TSUNAMI_UART_HH__