dev: Refactor terminal<->UART interface to make it more generic
authorAndreas Sandberg <Andreas.Sandberg@ARM.com>
Sat, 20 Sep 2014 21:17:50 +0000 (17:17 -0400)
committerAndreas Sandberg <Andreas.Sandberg@ARM.com>
Sat, 20 Sep 2014 21:17:50 +0000 (17:17 -0400)
The terminal currently assumes that the transport to the guest always
inherits from the Uart class. This assumption breaks when
implementing, for example, a VirtIO consoles. This patch removes this
assumption by adding pointer to the from the terminal to the uart and
replacing it with a more general callback interface. The Uart, or any
other class using the terminal, class implements an instance of the
callbacks class and registers it with the terminal.

src/dev/terminal.cc
src/dev/terminal.hh
src/dev/uart.cc
src/dev/uart.hh

index e70a8775fd9029c02e6e5a5aa7a17b49ad3abd1d..8950697742519fd1b4572a9b27208f2bd0d25c09 100644 (file)
@@ -99,8 +99,8 @@ Terminal::DataEvent::process(int revent)
  * Terminal code
  */
 Terminal::Terminal(const Params *p)
-    : SimObject(p), listenEvent(NULL), dataEvent(NULL), number(p->number),
-      data_fd(-1), txbuf(16384), rxbuf(16384), outfile(NULL)
+    : SimObject(p), termDataAvail(NULL), listenEvent(NULL), dataEvent(NULL),
+      number(p->number), data_fd(-1), txbuf(16384), rxbuf(16384), outfile(NULL)
 #if TRACING_ON == 1
       , linebuf(16384)
 #endif
@@ -129,6 +129,17 @@ Terminal::~Terminal()
         delete dataEvent;
 }
 
+void
+Terminal::regDataAvailCallback(Callback *c)
+{
+    // This can happen if the user has connected multiple UARTs to the
+    // same terminal. In that case, each of them tries to register
+    // callbacks.
+    if (termDataAvail)
+        fatal("Terminal already has already been associated with a UART.\n");
+    termDataAvail = c;
+}
+
 ///////////////////////////////////////////////////////////////////////
 // socket creation and terminal attach
 //
@@ -215,7 +226,8 @@ Terminal::data()
     if (len) {
         rxbuf.write((char *)buf, len);
         // Inform the UART there is data available
-        uart->dataAvailable();
+        assert(termDataAvail);
+        termDataAvail->process();
     }
 }
 
index e2322d7c242ab56fd7cdb7878a35587f8185679c..f7a860ac5c07bde70d678dd1bcfecc5c229814f1 100644 (file)
@@ -38,6 +38,7 @@
 
 #include <iostream>
 
+#include "base/callback.hh"
 #include "base/circlebuf.hh"
 #include "base/pollevent.hh"
 #include "base/socket.hh"
 #include "sim/sim_object.hh"
 
 class TerminalListener;
-class Uart;
 
 class Terminal : public SimObject
 {
   public:
-    Uart *uart;
+    /**
+     * Register a data available callback into the transport layer.
+     *
+     * The terminal needs to call the underlying transport layer to
+     * inform it of available data. The transport layer uses this
+     * method to register a callback that informs it of pending data.
+     *
+     * @param c Callback instance from transport layer.
+     */
+    void regDataAvailCallback(Callback *c);
+
+  protected:
+    /** Currently registered transport layer callbacks */
+    Callback *termDataAvail;
 
   protected:
     class ListenEvent : public PollEvent
index 084511444acf83a1ab54cf24a183f46c8d74a675..f232f0f2847c5916f49d88ed7f9f5e000032998b 100644 (file)
 using namespace std;
 
 Uart::Uart(const Params *p, Addr pio_size)
-    : BasicPioDevice(p, pio_size), platform(p->platform), term(p->terminal)
+    : BasicPioDevice(p, pio_size),
+      platform(p->platform), term(p->terminal),
+      callbackDataAvail(this)
 {
     status = 0;
 
-    // set back pointers
-    term->uart = this;
+    // setup terminal callbacks
+    term->regDataAvailCallback(&callbackDataAvail);
 }
index f1a26fda8d7700d388b8e6849fee877288949b53..6c9c08ee7cab27b3ce6ff7fc4ee21643d420c754 100644 (file)
@@ -36,9 +36,9 @@
 #define __UART_HH__
 
 #include "dev/io_device.hh"
+#include "dev/terminal.hh"
 #include "params/Uart.hh"
 
-class Terminal;
 class Platform;
 
 const int RX_INT = 0x1;
@@ -46,7 +46,6 @@ const int TX_INT = 0x2;
 
 class Uart : public BasicPioDevice
 {
-
   protected:
     int status;
     Platform *platform;
@@ -72,6 +71,9 @@ class Uart : public BasicPioDevice
      * @return interrupt status
      */
     bool intStatus() { return status ? true : false; }
+
+  protected:
+    MakeCallback<Uart, &Uart::dataAvailable> callbackDataAvail;
 };
 
 #endif // __UART_HH__