From: Andreas Sandberg Date: Thu, 20 Jul 2017 10:20:17 +0000 (+0100) Subject: dev: Refactor UART->Terminal interface X-Git-Tag: v19.0.0.0~2582 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d6c204c67d42a3cea9d603888ec52a8d8dacf1a3;p=gem5.git dev: Refactor UART->Terminal interface The UART models currently assume that they are always wired to a terminal. While true at the moment, this isn't necessarily a valid assumption. This change introduces the SerialDevice class that defines the interface for serial devices. Currently, Terminal is the only class that implements this interface. Change-Id: I74fefafbbaf5ac1ec0d4ec0b5a0f4b246fdad305 Signed-off-by: Andreas Sandberg Reviewed-by: Curtis Dunham Reviewed-on: https://gem5-review.googlesource.com/4289 Reviewed-by: Gabe Black --- diff --git a/src/dev/SConscript b/src/dev/SConscript index 9cfda0544..b95d3606c 100644 --- a/src/dev/SConscript +++ b/src/dev/SConscript @@ -44,6 +44,7 @@ if env['TARGET_ISA'] == 'null': SimObject('BadDevice.py') SimObject('Platform.py') +SimObject('Serial.py') SimObject('Terminal.py') SimObject('Uart.py') @@ -53,6 +54,7 @@ Source('mc146818.cc') Source('pixelpump.cc') Source('platform.cc') Source('ps2.cc') +Source('serial.cc') Source('terminal.cc') Source('uart.cc') Source('uart8250.cc') diff --git a/src/dev/Serial.py b/src/dev/Serial.py new file mode 100644 index 000000000..bbc792b67 --- /dev/null +++ b/src/dev/Serial.py @@ -0,0 +1,44 @@ +# Copyright (c) 2014, 2017 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# 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. +# +# Authors: Andreas Sandberg + +from m5.params import * +from m5.SimObject import SimObject + +class SerialDevice(SimObject): + type = 'SerialDevice' + abstract = True + cxx_header = "dev/serial.hh" diff --git a/src/dev/Terminal.py b/src/dev/Terminal.py index 2b54f9d5e..9b50111cd 100644 --- a/src/dev/Terminal.py +++ b/src/dev/Terminal.py @@ -29,8 +29,9 @@ from m5.SimObject import SimObject from m5.params import * from m5.proxy import * +from Serial import SerialDevice -class Terminal(SimObject): +class Terminal(SerialDevice): type = 'Terminal' cxx_header = "dev/terminal.hh" intr_control = Param.IntrControl(Parent.any, "interrupt controller") diff --git a/src/dev/Uart.py b/src/dev/Uart.py index c3bc9dd0f..c3bfd1bc2 100644 --- a/src/dev/Uart.py +++ b/src/dev/Uart.py @@ -29,13 +29,14 @@ from m5.params import * from m5.proxy import * from Device import BasicPioDevice +from Serial import SerialDevice class Uart(BasicPioDevice): type = 'Uart' abstract = True cxx_header = "dev/uart.hh" platform = Param.Platform(Parent.any, "Platform this device is part of.") - terminal = Param.Terminal(Parent.any, "The terminal") + device = Param.SerialDevice(Parent.any, "The terminal") class Uart8250(Uart): type = 'Uart8250' diff --git a/src/dev/alpha/backdoor.cc b/src/dev/alpha/backdoor.cc index 5c627ca34..5187e5bae 100644 --- a/src/dev/alpha/backdoor.cc +++ b/src/dev/alpha/backdoor.cc @@ -233,7 +233,7 @@ AlphaBackdoor::write(PacketPtr pkt) break; case offsetof(AlphaAccess, outputChar): - terminal->out((char)(val & 0xff)); + terminal->writeData((char)(val & 0xff)); break; default: diff --git a/src/dev/arm/pl011.cc b/src/dev/arm/pl011.cc index 479a28bd8..b6b41f9c3 100644 --- a/src/dev/arm/pl011.cc +++ b/src/dev/arm/pl011.cc @@ -48,7 +48,6 @@ #include "debug/Uart.hh" #include "dev/arm/amba_device.hh" #include "dev/arm/base_gic.hh" -#include "dev/terminal.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" #include "params/Pl011.hh" @@ -81,12 +80,12 @@ Pl011::read(PacketPtr pkt) switch(daddr) { case UART_DR: data = 0; - if (term->dataAvailable()) { - data = term->in(); + if (device->dataAvailable()) { + data = device->readData(); // Since we don't simulate a FIFO for incoming data, we // assume it's empty and clear RXINTR and RTINTR. clearInterrupts(UART_RXINTR | UART_RTINTR); - if (term->dataAvailable()) { + if (device->dataAvailable()) { DPRINTF(Uart, "Re-raising interrupt due to more data " "after UART_DR read\n"); dataAvailable(); @@ -97,7 +96,7 @@ Pl011::read(PacketPtr pkt) data = UART_FR_CTS | // Clear To Send // Given we do not simulate a FIFO we are either empty or full. - (!term->dataAvailable() ? UART_FR_RXFE : UART_FR_RXFF) | + (!device->dataAvailable() ? UART_FR_RXFE : UART_FR_RXFF) | UART_FR_TXFE; // TX FIFO empty DPRINTF(Uart, @@ -199,7 +198,7 @@ Pl011::write(PacketPtr pkt) if ((data & 0xFF) == 0x04 && endOnEOT) exitSimLoop("UART received EOT", 0); - term->out(data & 0xFF); + device->writeData(data & 0xFF); // We're supposed to clear TXINTR when this register is // written to, however. since we're also infinitely fast, we // need to immediately raise it again. @@ -229,7 +228,7 @@ Pl011::write(PacketPtr pkt) case UART_ICR: DPRINTF(Uart, "Clearing interrupts 0x%x\n", data); clearInterrupts(data); - if (term->dataAvailable()) { + if (device->dataAvailable()) { DPRINTF(Uart, "Re-raising interrupt due to more data after " "UART_ICR write\n"); dataAvailable(); diff --git a/src/dev/serial.cc b/src/dev/serial.cc new file mode 100644 index 000000000..63e8a382b --- /dev/null +++ b/src/dev/serial.cc @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014, 2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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. + * + * Authors: Andreas Sandberg + */ + +#include "dev/serial.hh" + +#include "base/misc.hh" +#include "params/SerialDevice.hh" + +SerialDevice::SerialDevice(const SerialDeviceParams *p) + : SimObject(p), interfaceCallback(nullptr) +{ +} + +SerialDevice::~SerialDevice() +{ +} + +void +SerialDevice::regInterfaceCallback(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 (interfaceCallback) + fatal("A UART has already been associated with this device.\n"); + interfaceCallback = c; +} + +void +SerialDevice::notifyInterface() +{ + assert(dataAvailable()); + // Registering a callback is optional. + if (interfaceCallback) + interfaceCallback->process(); +} + diff --git a/src/dev/serial.hh b/src/dev/serial.hh new file mode 100644 index 000000000..4ea2f5ea8 --- /dev/null +++ b/src/dev/serial.hh @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2014, 2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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. + * + * Authors: Andreas Sandberg + */ + +#ifndef __DEV_SERIAL_HH__ +#define __DEV_SERIAL_HH__ + +#include "base/callback.hh" +#include "sim/sim_object.hh" + +struct SerialDeviceParams; + +/** + * Base class for serial devices such as terminals. + * + * This class provides a unified interface that all serial (RS232 or + * similar) devices must implement. A device can be wired to exactly + * one host serial interface (serial port model). + * + * SerialDevices are passive devices that are driven by the + * serial interface using the writeData(c) (the interface sends a + * character) and readData() (the interface reads a character) + * methods. Serial devices need to override these methods to + * communicate with the host interface layer. + * + * To implement basic flow control, serial devices must implement the + * dataAvailable() method. This method returns true if a valid + * character can be read using the readData() method. When data + * becomes available, the serial device must call the + * notifyInterface() method to send a callback to the interface layer. + * + * To send a character (host to device), the interface layer calls + * writeData(char) to send a character to the serial device. + * + * To read a character (device to host), the interface layer calls + * dataAvailable() to determine if there is a character pending. If + * there is data available, it immediately calls readData() to get the + * character. The receive loop in the serial device typically looks + * like this: + * + * \code{.cc} + * while (device.dataAvailable()) { + * printf("%c", (int)device.readData()); + * } + * \endcode + * + * To avoid polling, the interface layer may register a data available + * callback using the regInterfaceCallback() method. The device uses + * this callback to notify the interface layer whenever there is new + * data pending. Note that devices will normally only notify the + * interface layer when there is a state transition in the + * device. E.g., the dataAvailable() transitions from false to + * true. This means that there can be multiple pending characters when + * the interface layer receives the callback. + */ +class SerialDevice : public SimObject +{ + public: + SerialDevice(const SerialDeviceParams *p); + ~SerialDevice(); + + public: // Serial device API (UART->Device) + /** + * Register a data available callback into the host interface layer. + * + * Serial devices need to call the underlying host interface layer + * to inform it of state change such as pending data that can be + * read from the device by the interface layer using the readData() + * method. The interface layer may use this method to register a + * callback that informs it of pending data. + * + * @param c Callback instance from interface layer. + */ + void regInterfaceCallback(Callback *c); + + /** + * Check if there is pending data from the serial device. + * + * @return true if there is data pending that can be read using + * the readData() method. + */ + virtual bool dataAvailable() const = 0; + + /** + * Transmit a character from the host interface to the device. + * + * @param c Received data. + */ + virtual void writeData(uint8_t c) = 0; + + /** + * Read a character from the device. + * + * @return Character from the device's output buffer, undefined if + * no data is pending. + */ + virtual uint8_t readData() = 0; + + protected: + /** Notify the host interface of pending data. */ + void notifyInterface(); + + private: + /** Currently regisxtered host interface layer callback */ + Callback *interfaceCallback; +}; + +#endif // __DEV_SERIAL_HH__ diff --git a/src/dev/terminal.cc b/src/dev/terminal.cc index 9f0ea5ea3..4f9881ddd 100644 --- a/src/dev/terminal.cc +++ b/src/dev/terminal.cc @@ -107,7 +107,7 @@ Terminal::DataEvent::process(int revent) * Terminal code */ Terminal::Terminal(const Params *p) - : SimObject(p), termDataAvail(NULL), listenEvent(NULL), dataEvent(NULL), + : SerialDevice(p), listenEvent(NULL), dataEvent(NULL), number(p->number), data_fd(-1), txbuf(16384), rxbuf(16384), outfile(p->output ? simout.findOrCreate(p->name) : NULL) #if TRACING_ON == 1 @@ -133,16 +133,6 @@ 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 @@ -233,9 +223,7 @@ Terminal::data() len = read(buf, sizeof(buf)); if (len) { rxbuf.write((char *)buf, len); - // Inform the UART there is data available - assert(termDataAvail); - termDataAvail->process(); + notifyInterface(); } } @@ -282,7 +270,7 @@ Terminal::write(const uint8_t *buf, size_t len) #define RECEIVE_ERROR (ULL(3) << 62) uint8_t -Terminal::in() +Terminal::readData() { uint8_t c; @@ -301,7 +289,7 @@ Terminal::console_in() uint64_t value; if (dataAvailable()) { - value = RECEIVE_SUCCESS | in(); + value = RECEIVE_SUCCESS | readData(); if (!rxbuf.empty()) value |= MORE_PENDING; } else { @@ -314,7 +302,7 @@ Terminal::console_in() } void -Terminal::out(char c) +Terminal::writeData(uint8_t c) { #if TRACING_ON == 1 if (DTRACE(Terminal)) { @@ -343,7 +331,7 @@ Terminal::out(char c) write(c); if (outfile) - outfile->stream()->write(&c, 1); + outfile->stream()->put((char)c); DPRINTF(TerminalVerbose, "out: \'%c\' %#02x\n", isprint(c) ? c : ' ', (int)c); diff --git a/src/dev/terminal.hh b/src/dev/terminal.hh index 41c2a9e26..8b6ec0b7f 100644 --- a/src/dev/terminal.hh +++ b/src/dev/terminal.hh @@ -43,30 +43,15 @@ #include "base/pollevent.hh" #include "base/socket.hh" #include "cpu/intr_control.hh" +#include "dev/serial.hh" #include "params/Terminal.hh" #include "sim/sim_object.hh" class OutputStream; class TerminalListener; -class Terminal : public SimObject +class Terminal : public SerialDevice { - public: - /** - * 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 { @@ -129,13 +114,15 @@ class Terminal : public SimObject size_t write(const uint8_t *buf, size_t len); void detach(); + public: // SerialDevice interface + uint8_t readData() override; + void writeData(uint8_t c) override; + bool dataAvailable() const override { return !rxbuf.empty(); } + public: ///////////////// // OS interface - // Get a character from the terminal. - uint8_t in(); - // get a character from the terminal in the console specific format // corresponds to GETC: // retval<63:61> @@ -149,12 +136,6 @@ class Terminal : public SimObject // // Interrupts are cleared when the buffer is empty. uint64_t console_in(); - - // Send a character to the terminal - void out(char c); - - // Ask the terminal if data is available - bool dataAvailable() { return !rxbuf.empty(); } }; #endif // __DEV_TERMINAL_HH__ diff --git a/src/dev/uart.cc b/src/dev/uart.cc index 01900445f..ff952cc7f 100644 --- a/src/dev/uart.cc +++ b/src/dev/uart.cc @@ -34,18 +34,17 @@ #include "dev/uart.hh" -#include "dev/platform.hh" -#include "dev/terminal.hh" +#include "dev/serial.hh" using namespace std; Uart::Uart(const Params *p, Addr pio_size) : BasicPioDevice(p, pio_size), - platform(p->platform), term(p->terminal), + platform(p->platform), device(p->device), callbackDataAvail(this) { status = 0; - // setup terminal callbacks - term->regDataAvailCallback(&callbackDataAvail); + // setup serial device callbacks + device->regInterfaceCallback(&callbackDataAvail); } diff --git a/src/dev/uart.hh b/src/dev/uart.hh index 6c9c08ee7..bf3dcf7c3 100644 --- a/src/dev/uart.hh +++ b/src/dev/uart.hh @@ -35,8 +35,9 @@ #ifndef __UART_HH__ #define __UART_HH__ +#include "base/callback.hh" #include "dev/io_device.hh" -#include "dev/terminal.hh" +#include "dev/serial.hh" #include "params/Uart.hh" class Platform; @@ -49,7 +50,7 @@ class Uart : public BasicPioDevice protected: int status; Platform *platform; - Terminal *term; + SerialDevice *device; public: typedef UartParams Params; diff --git a/src/dev/uart8250.cc b/src/dev/uart8250.cc index 482135c7b..f99b2472b 100644 --- a/src/dev/uart8250.cc +++ b/src/dev/uart8250.cc @@ -42,7 +42,6 @@ #include "config/the_isa.hh" #include "debug/Uart.hh" #include "dev/platform.hh" -#include "dev/terminal.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" @@ -108,8 +107,8 @@ Uart8250::read(PacketPtr pkt) switch (daddr) { case 0x0: if (!(LCR & 0x80)) { // read byte - if (term->dataAvailable()) - pkt->set(term->in()); + if (device->dataAvailable()) + pkt->set(device->readData()); else { pkt->set((uint8_t)0); // A limited amount of these are ok. @@ -118,7 +117,7 @@ Uart8250::read(PacketPtr pkt) status &= ~RX_INT; platform->clearConsoleInt(); - if (term->dataAvailable() && (IER & UART_IER_RDI)) + if (device->dataAvailable() && (IER & UART_IER_RDI)) scheduleIntr(&rxIntrEvent); } else { // dll divisor latch ; @@ -154,7 +153,7 @@ Uart8250::read(PacketPtr pkt) uint8_t lsr; lsr = 0; // check if there are any bytes to be read - if (term->dataAvailable()) + if (device->dataAvailable()) lsr = UART_LSR_DR; lsr |= UART_LSR_TEMT | UART_LSR_THRE; pkt->set(lsr); @@ -190,7 +189,7 @@ Uart8250::write(PacketPtr pkt) switch (daddr) { case 0x0: if (!(LCR & 0x80)) { // write byte - term->out(pkt->get()); + device->writeData(pkt->get()); platform->clearConsoleInt(); status &= ~TX_INT; if (UART_IER_THRI & IER) @@ -225,7 +224,7 @@ Uart8250::write(PacketPtr pkt) status &= ~TX_INT; } - if ((UART_IER_RDI & IER) && term->dataAvailable()) { + if ((UART_IER_RDI & IER) && device->dataAvailable()) { DPRINTF(Uart, "IER: IER_RDI set, scheduling RX intrrupt\n"); scheduleIntr(&rxIntrEvent); } else { diff --git a/src/dev/virtio/VirtIOConsole.py b/src/dev/virtio/VirtIOConsole.py index cd73d6509..bce5e1de2 100644 --- a/src/dev/virtio/VirtIOConsole.py +++ b/src/dev/virtio/VirtIOConsole.py @@ -40,6 +40,7 @@ from m5.params import * from m5.proxy import * from VirtIO import VirtIODeviceBase +from Serial import SerialDevice class VirtIOConsole(VirtIODeviceBase): type = 'VirtIOConsole' @@ -48,4 +49,4 @@ class VirtIOConsole(VirtIODeviceBase): qRecvSize = Param.Unsigned(16, "Receive queue size (descriptors)") qTransSize = Param.Unsigned(16, "Transmit queue size (descriptors)") - terminal = Param.Terminal(Parent.any, "The terminal") + device = Param.SerialDevice("Serial device attached to this device") diff --git a/src/dev/virtio/console.cc b/src/dev/virtio/console.cc index e3428e951..1027925bb 100644 --- a/src/dev/virtio/console.cc +++ b/src/dev/virtio/console.cc @@ -47,7 +47,7 @@ VirtIOConsole::VirtIOConsole(Params *params) : VirtIODeviceBase(params, ID_CONSOLE, sizeof(Config), F_SIZE), qRecv(params->system->physProxy, params->qRecvSize, *this), qTrans(params->system->physProxy, params->qTransSize, *this), - term(*params->terminal), callbackDataAvail(qRecv) + device(*params->device), callbackDataAvail(qRecv) { registerQueue(qRecv); registerQueue(qTrans); @@ -55,7 +55,7 @@ VirtIOConsole::VirtIOConsole(Params *params) config.cols = 80; config.rows = 24; - term.regDataAvailCallback(&callbackDataAvail); + device.regInterfaceCallback(&callbackDataAvail); } @@ -81,11 +81,11 @@ VirtIOConsole::TermRecvQueue::trySend() // get free descriptors (i.e., there are buffers available to // send) from the guest. VirtDescriptor *d; - while (parent.term.dataAvailable() && (d = consumeDescriptor())) { + while (parent.device.dataAvailable() && (d = consumeDescriptor())) { DPRINTF(VIOConsole, "Got descriptor (len: %i)\n", d->size()); size_t len(0); - while (parent.term.dataAvailable() && len < d->size()) { - uint8_t in(parent.term.in()); + while (parent.device.dataAvailable() && len < d->size()) { + uint8_t in(parent.device.readData()); d->chainWrite(len, &in, sizeof(uint8_t)); ++len; } @@ -108,7 +108,7 @@ VirtIOConsole::TermTransQueue::onNotifyDescriptor(VirtDescriptor *desc) uint8_t data[size]; desc->chainRead(0, data, size); for (int i = 0; i < desc->size(); ++i) - parent.term.out(data[i]); + parent.device.writeData(data[i]); // Tell the guest that we are done with this descriptor. produceDescriptor(desc, 0); diff --git a/src/dev/virtio/console.hh b/src/dev/virtio/console.hh index e41ff9a65..720b60044 100644 --- a/src/dev/virtio/console.hh +++ b/src/dev/virtio/console.hh @@ -40,8 +40,8 @@ #ifndef __DEV_VIRTIO_CONSOLE_HH__ #define __DEV_VIRTIO_CONSOLE_HH__ +#include "dev/serial.hh" #include "dev/virtio/base.hh" -#include "dev/terminal.hh" struct VirtIOConsoleParams; @@ -147,7 +147,7 @@ class VirtIOConsole : public VirtIODeviceBase TermTransQueue qTrans; protected: - Terminal &term; + SerialDevice &device; MakeCallback callbackDataAvail; };