dev: Refactor terminal<->UART interface to make it more generic

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.
This commit is contained in:
Andreas Sandberg 2014-09-20 17:17:50 -04:00
parent 0fa128bbd0
commit 0c5139310d
4 changed files with 39 additions and 10 deletions

View 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();
}
}

View file

@ -38,6 +38,7 @@
#include <iostream>
#include "base/callback.hh"
#include "base/circlebuf.hh"
#include "base/pollevent.hh"
#include "base/socket.hh"
@ -46,12 +47,24 @@
#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

View file

@ -39,10 +39,12 @@
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);
}

View 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__