From: Andreas Sandberg Date: Thu, 20 Jul 2017 10:58:06 +0000 (+0100) Subject: dev: Move generic serial devices to src/dev/serial X-Git-Tag: v19.0.0.0~2580 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=20de3bb759a36dbffed10adae2159e376b7cb68c;p=gem5.git dev: Move generic serial devices to src/dev/serial Change-Id: I104227fc460f8b561e7375b329a541c1fce881b2 Signed-off-by: Andreas Sandberg Reviewed-by: Curtis Dunham Reviewed-on: https://gem5-review.googlesource.com/4291 Reviewed-by: Gabe Black --- diff --git a/src/dev/SConscript b/src/dev/SConscript index b95d3606c..6939e03d1 100644 --- a/src/dev/SConscript +++ b/src/dev/SConscript @@ -44,9 +44,6 @@ if env['TARGET_ISA'] == 'null': SimObject('BadDevice.py') SimObject('Platform.py') -SimObject('Serial.py') -SimObject('Terminal.py') -SimObject('Uart.py') Source('baddev.cc') Source('intel_8254_timer.cc') @@ -54,13 +51,6 @@ Source('mc146818.cc') Source('pixelpump.cc') Source('platform.cc') Source('ps2.cc') -Source('serial.cc') -Source('terminal.cc') -Source('uart.cc') -Source('uart8250.cc') DebugFlag('Intel8254Timer') DebugFlag('MC146818') -DebugFlag('Terminal') -DebugFlag('TerminalVerbose') -DebugFlag('Uart') diff --git a/src/dev/Serial.py b/src/dev/Serial.py deleted file mode 100644 index 7871b487b..000000000 --- a/src/dev/Serial.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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" - -class SerialNullDevice(SerialDevice): - type = 'SerialNullDevice' - cxx_header = "dev/serial.hh" diff --git a/src/dev/Terminal.py b/src/dev/Terminal.py deleted file mode 100644 index 9b50111cd..000000000 --- a/src/dev/Terminal.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (c) 2005-2007 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. -# -# Authors: Nathan Binkert - -from m5.SimObject import SimObject -from m5.params import * -from m5.proxy import * -from Serial import SerialDevice - -class Terminal(SerialDevice): - type = 'Terminal' - cxx_header = "dev/terminal.hh" - intr_control = Param.IntrControl(Parent.any, "interrupt controller") - port = Param.TcpPort(3456, "listen port") - number = Param.Int(0, "terminal number") - output = Param.Bool(True, "Enable output dump to file") diff --git a/src/dev/Uart.py b/src/dev/Uart.py deleted file mode 100644 index c3bfd1bc2..000000000 --- a/src/dev/Uart.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (c) 2005-2007 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. -# -# Authors: Nathan Binkert - -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.") - device = Param.SerialDevice(Parent.any, "The terminal") - -class Uart8250(Uart): - type = 'Uart8250' - cxx_header = "dev/uart8250.hh" diff --git a/src/dev/alpha/backdoor.cc b/src/dev/alpha/backdoor.cc index 5187e5bae..e2de19773 100644 --- a/src/dev/alpha/backdoor.cc +++ b/src/dev/alpha/backdoor.cc @@ -52,7 +52,7 @@ #include "dev/alpha/tsunami_io.hh" #include "dev/platform.hh" #include "dev/storage/simple_disk.hh" -#include "dev/terminal.hh" +#include "dev/serial/terminal.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" #include "mem/physical.hh" diff --git a/src/dev/alpha/tsunami.cc b/src/dev/alpha/tsunami.cc index 82a38129b..30df89d0c 100644 --- a/src/dev/alpha/tsunami.cc +++ b/src/dev/alpha/tsunami.cc @@ -44,7 +44,6 @@ #include "dev/alpha/tsunami_cchip.hh" #include "dev/alpha/tsunami_io.hh" #include "dev/alpha/tsunami_pchip.hh" -#include "dev/terminal.hh" using namespace std; //Should this be AlphaISA? diff --git a/src/dev/arm/gic_pl390.cc b/src/dev/arm/gic_pl390.cc index d2ec1d79b..4818be6c9 100644 --- a/src/dev/arm/gic_pl390.cc +++ b/src/dev/arm/gic_pl390.cc @@ -48,7 +48,6 @@ #include "debug/GIC.hh" #include "debug/IPI.hh" #include "debug/Interrupt.hh" -#include "dev/terminal.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" diff --git a/src/dev/arm/pl011.hh b/src/dev/arm/pl011.hh index d6c839c4d..2317b3114 100644 --- a/src/dev/arm/pl011.hh +++ b/src/dev/arm/pl011.hh @@ -50,7 +50,7 @@ #define __DEV_ARM_PL011_H__ #include "dev/arm/amba_device.hh" -#include "dev/uart.hh" +#include "dev/serial/uart.hh" class BaseGic; struct Pl011Params; diff --git a/src/dev/arm/realview.cc b/src/dev/arm/realview.cc index e5e7afdc0..8524b23c0 100644 --- a/src/dev/arm/realview.cc +++ b/src/dev/arm/realview.cc @@ -53,7 +53,6 @@ #include "config/the_isa.hh" #include "cpu/intr_control.hh" #include "dev/arm/base_gic.hh" -#include "dev/terminal.hh" #include "sim/system.hh" using namespace std; diff --git a/src/dev/arm/vgic.cc b/src/dev/arm/vgic.cc index cc8ad7788..529520403 100644 --- a/src/dev/arm/vgic.cc +++ b/src/dev/arm/vgic.cc @@ -43,7 +43,6 @@ #include "debug/Checkpoint.hh" #include "debug/VGIC.hh" #include "dev/arm/base_gic.hh" -#include "dev/terminal.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" diff --git a/src/dev/mips/malta.cc b/src/dev/mips/malta.cc index 8843d4bf2..a25904780 100755 --- a/src/dev/mips/malta.cc +++ b/src/dev/mips/malta.cc @@ -44,7 +44,6 @@ #include "debug/Malta.hh" #include "dev/mips/malta_cchip.hh" #include "dev/mips/malta_io.hh" -#include "dev/terminal.hh" #include "params/Malta.hh" #include "sim/system.hh" diff --git a/src/dev/serial.cc b/src/dev/serial.cc deleted file mode 100644 index 68fc94c57..000000000 --- a/src/dev/serial.cc +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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" -#include "params/SerialNullDevice.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(); -} - - - - -SerialNullDevice::SerialNullDevice(const SerialNullDeviceParams *p) - : SerialDevice(p) -{ -} - -uint8_t -SerialNullDevice::readData() -{ - panic("SerialNullDevice does not have pending data.\n"); -} - - - -SerialNullDevice * -SerialNullDeviceParams::create() -{ - return new SerialNullDevice(this); -} diff --git a/src/dev/serial.hh b/src/dev/serial.hh deleted file mode 100644 index 230ecaa74..000000000 --- a/src/dev/serial.hh +++ /dev/null @@ -1,158 +0,0 @@ -/* - * 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; -struct SerialNullDeviceParams; - -/** - * 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; -}; - -/** - * Dummy serial device that discards all data sent to it. - */ -class SerialNullDevice : public SerialDevice -{ - public: - SerialNullDevice(const SerialNullDeviceParams *p); - - public: - bool dataAvailable() const override { return false; } - void writeData(uint8_t c) override {}; - uint8_t readData() override; -}; - -#endif // __DEV_SERIAL_HH__ diff --git a/src/dev/serial/SConscript b/src/dev/serial/SConscript new file mode 100644 index 000000000..b9f13f54b --- /dev/null +++ b/src/dev/serial/SConscript @@ -0,0 +1,59 @@ +# -*- mode:python -*- + +# Copyright (c) 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. +# +# Copyright (c) 2006 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. +# +# Authors: Andreas Sandberg + +Import('*') + +if env['TARGET_ISA'] == 'null': + Return() + +SimObject('Serial.py') +SimObject('Terminal.py') +SimObject('Uart.py') + +Source('serial.cc') +Source('terminal.cc') +Source('uart.cc') +Source('uart8250.cc') + +DebugFlag('Terminal') +DebugFlag('TerminalVerbose') +DebugFlag('Uart') diff --git a/src/dev/serial/Serial.py b/src/dev/serial/Serial.py new file mode 100644 index 000000000..3f62ef37f --- /dev/null +++ b/src/dev/serial/Serial.py @@ -0,0 +1,48 @@ +# 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/serial.hh" + +class SerialNullDevice(SerialDevice): + type = 'SerialNullDevice' + cxx_header = "dev/serial/serial.hh" diff --git a/src/dev/serial/Terminal.py b/src/dev/serial/Terminal.py new file mode 100644 index 000000000..863c4871c --- /dev/null +++ b/src/dev/serial/Terminal.py @@ -0,0 +1,40 @@ +# Copyright (c) 2005-2007 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. +# +# Authors: Nathan Binkert + +from m5.SimObject import SimObject +from m5.params import * +from m5.proxy import * +from Serial import SerialDevice + +class Terminal(SerialDevice): + type = 'Terminal' + cxx_header = "dev/serial/terminal.hh" + intr_control = Param.IntrControl(Parent.any, "interrupt controller") + port = Param.TcpPort(3456, "listen port") + number = Param.Int(0, "terminal number") + output = Param.Bool(True, "Enable output dump to file") diff --git a/src/dev/serial/Uart.py b/src/dev/serial/Uart.py new file mode 100644 index 000000000..53337059b --- /dev/null +++ b/src/dev/serial/Uart.py @@ -0,0 +1,43 @@ +# Copyright (c) 2005-2007 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. +# +# Authors: Nathan Binkert + +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/serial/uart.hh" + platform = Param.Platform(Parent.any, "Platform this device is part of.") + device = Param.SerialDevice(Parent.any, "The terminal") + +class Uart8250(Uart): + type = 'Uart8250' + cxx_header = "dev/serial/uart8250.hh" diff --git a/src/dev/serial/serial.cc b/src/dev/serial/serial.cc new file mode 100644 index 000000000..873366860 --- /dev/null +++ b/src/dev/serial/serial.cc @@ -0,0 +1,95 @@ +/* + * 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/serial.hh" + +#include "base/misc.hh" +#include "params/SerialDevice.hh" +#include "params/SerialNullDevice.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(); +} + + + + +SerialNullDevice::SerialNullDevice(const SerialNullDeviceParams *p) + : SerialDevice(p) +{ +} + +uint8_t +SerialNullDevice::readData() +{ + panic("SerialNullDevice does not have pending data.\n"); +} + + + +SerialNullDevice * +SerialNullDeviceParams::create() +{ + return new SerialNullDevice(this); +} diff --git a/src/dev/serial/serial.hh b/src/dev/serial/serial.hh new file mode 100644 index 000000000..230ecaa74 --- /dev/null +++ b/src/dev/serial/serial.hh @@ -0,0 +1,158 @@ +/* + * 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; +struct SerialNullDeviceParams; + +/** + * 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; +}; + +/** + * Dummy serial device that discards all data sent to it. + */ +class SerialNullDevice : public SerialDevice +{ + public: + SerialNullDevice(const SerialNullDeviceParams *p); + + public: + bool dataAvailable() const override { return false; } + void writeData(uint8_t c) override {}; + uint8_t readData() override; +}; + +#endif // __DEV_SERIAL_HH__ diff --git a/src/dev/serial/terminal.cc b/src/dev/serial/terminal.cc new file mode 100644 index 000000000..7230698d3 --- /dev/null +++ b/src/dev/serial/terminal.cc @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2001-2005 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. + * + * Authors: Nathan Binkert + * Ali Saidi + */ + +/* @file + * Implements the user interface to a serial terminal + */ + +#include + +#if defined(__FreeBSD__) +#include + +#else +#include + +#endif +#include "dev/serial/terminal.hh" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "base/atomicio.hh" +#include "base/misc.hh" +#include "base/output.hh" +#include "base/socket.hh" +#include "base/trace.hh" +#include "debug/Terminal.hh" +#include "debug/TerminalVerbose.hh" +#include "dev/platform.hh" +#include "dev/serial/uart.hh" + +using namespace std; + + +/* + * Poll event for the listen socket + */ +Terminal::ListenEvent::ListenEvent(Terminal *t, int fd, int e) + : PollEvent(fd, e), term(t) +{ +} + +void +Terminal::ListenEvent::process(int revent) +{ + term->accept(); +} + +/* + * Poll event for the data socket + */ +Terminal::DataEvent::DataEvent(Terminal *t, int fd, int e) + : PollEvent(fd, e), term(t) +{ +} + +void +Terminal::DataEvent::process(int revent) +{ + // As a consequence of being called from the PollQueue, we might + // have been called from a different thread. Migrate to "our" + // thread. + EventQueue::ScopedMigration migrate(term->eventQueue()); + + if (revent & POLLIN) + term->data(); + else if (revent & POLLNVAL) + term->detach(); +} + +/* + * Terminal code + */ +Terminal::Terminal(const Params *p) + : 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 + , linebuf(16384) +#endif +{ + if (outfile) + outfile->stream()->setf(ios::unitbuf); + + if (p->port) + listen(p->port); +} + +Terminal::~Terminal() +{ + if (data_fd != -1) + ::close(data_fd); + + if (listenEvent) + delete listenEvent; + + if (dataEvent) + delete dataEvent; +} + + +/////////////////////////////////////////////////////////////////////// +// socket creation and terminal attach +// + +void +Terminal::listen(int port) +{ + if (ListenSocket::allDisabled()) { + warn_once("Sockets disabled, not accepting terminal connections"); + return; + } + + while (!listener.listen(port, true)) { + DPRINTF(Terminal, + ": can't bind address terminal port %d inuse PID %d\n", + port, getpid()); + port++; + } + + int p1, p2; + p2 = name().rfind('.') - 1; + p1 = name().rfind('.', p2); + ccprintf(cerr, "Listening for %s connection on port %d\n", + name().substr(p1+1,p2-p1), port); + + listenEvent = new ListenEvent(this, listener.getfd(), POLLIN); + pollQueue.schedule(listenEvent); +} + +void +Terminal::accept() +{ + if (!listener.islistening()) + panic("%s: cannot accept a connection if not listening!", name()); + + int fd = listener.accept(true); + if (data_fd != -1) { + char message[] = "terminal already attached!\n"; + atomic_write(fd, message, sizeof(message)); + ::close(fd); + return; + } + + data_fd = fd; + dataEvent = new DataEvent(this, data_fd, POLLIN); + pollQueue.schedule(dataEvent); + + stringstream stream; + ccprintf(stream, "==== m5 slave terminal: Terminal %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 terminal %d\n", number); + char buf[1024]; + for (size_t i = 0; i < txbuf.size(); i += sizeof(buf)) { + const size_t chunk_len(std::min(txbuf.size() - i, sizeof(buf))); + txbuf.peek(buf, i, chunk_len); + write((const uint8_t *)buf, chunk_len); + } +} + +void +Terminal::detach() +{ + if (data_fd != -1) { + ::close(data_fd); + data_fd = -1; + } + + pollQueue.remove(dataEvent); + delete dataEvent; + dataEvent = NULL; + + DPRINTFN("detach terminal %d\n", number); +} + +void +Terminal::data() +{ + uint8_t buf[1024]; + int len; + + len = read(buf, sizeof(buf)); + if (len) { + rxbuf.write((char *)buf, len); + notifyInterface(); + } +} + +size_t +Terminal::read(uint8_t *buf, size_t len) +{ + if (data_fd < 0) + panic("Terminal not properly attached.\n"); + + ssize_t ret; + do { + ret = ::read(data_fd, buf, len); + } while (ret == -1 && errno == EINTR); + + + if (ret < 0) + DPRINTFN("Read failed.\n"); + + if (ret <= 0) { + detach(); + return 0; + } + + return ret; +} + +// Terminal output. +size_t +Terminal::write(const uint8_t *buf, size_t len) +{ + if (data_fd < 0) + panic("Terminal not properly attached.\n"); + + ssize_t ret = atomic_write(data_fd, buf, len); + if (ret < len) + 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) + +uint8_t +Terminal::readData() +{ + uint8_t c; + + assert(!rxbuf.empty()); + rxbuf.read((char *)&c, 1); + + DPRINTF(TerminalVerbose, "in: \'%c\' %#02x more: %d\n", + isprint(c) ? c : ' ', c, !rxbuf.empty()); + + return c; +} + +uint64_t +Terminal::console_in() +{ + uint64_t value; + + if (dataAvailable()) { + value = RECEIVE_SUCCESS | readData(); + if (!rxbuf.empty()) + value |= MORE_PENDING; + } else { + value = RECEIVE_NONE; + } + + DPRINTF(TerminalVerbose, "console_in: return: %#x\n", value); + + return value; +} + +void +Terminal::writeData(uint8_t c) +{ +#if TRACING_ON == 1 + if (DTRACE(Terminal)) { + 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(Terminal, "%s\n", buffer); + delete [] buffer; + } else { + linebuf.write(&c, 1); + } + } + + last = c; + } +#endif + + txbuf.write(&c, 1); + + if (data_fd >= 0) + write(c); + + if (outfile) + outfile->stream()->put((char)c); + + DPRINTF(TerminalVerbose, "out: \'%c\' %#02x\n", + isprint(c) ? c : ' ', (int)c); + +} + +Terminal * +TerminalParams::create() +{ + return new Terminal(this); +} diff --git a/src/dev/serial/terminal.hh b/src/dev/serial/terminal.hh new file mode 100644 index 000000000..48bfc0771 --- /dev/null +++ b/src/dev/serial/terminal.hh @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2001-2005 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. + * + * Authors: Nathan Binkert + * Ali Saidi + */ + +/* @file + * User Terminal Interface + */ + +#ifndef __DEV_TERMINAL_HH__ +#define __DEV_TERMINAL_HH__ + +#include + +#include "base/callback.hh" +#include "base/circlebuf.hh" +#include "base/pollevent.hh" +#include "base/socket.hh" +#include "cpu/intr_control.hh" +#include "dev/serial/serial.hh" +#include "params/Terminal.hh" +#include "sim/sim_object.hh" + +class OutputStream; +class TerminalListener; + +class Terminal : public SerialDevice +{ + protected: + class ListenEvent : public PollEvent + { + protected: + Terminal *term; + + public: + ListenEvent(Terminal *t, int fd, int e); + void process(int revent); + }; + + friend class ListenEvent; + ListenEvent *listenEvent; + + class DataEvent : public PollEvent + { + protected: + Terminal *term; + + public: + DataEvent(Terminal *t, int fd, int e); + void process(int revent); + }; + + friend class DataEvent; + DataEvent *dataEvent; + + protected: + int number; + int data_fd; + + public: + typedef TerminalParams Params; + Terminal(const Params *p); + ~Terminal(); + + protected: + ListenSocket listener; + + void listen(int port); + void accept(); + + protected: + CircleBuf txbuf; + CircleBuf rxbuf; + OutputStream *outfile; +#if TRACING_ON == 1 + CircleBuf linebuf; +#endif + + public: + /////////////////////// + // Terminal Interface + + void data(); + + 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 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 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(); +}; + +#endif // __DEV_TERMINAL_HH__ diff --git a/src/dev/serial/uart.cc b/src/dev/serial/uart.cc new file mode 100644 index 000000000..3a4c13c43 --- /dev/null +++ b/src/dev/serial/uart.cc @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2004-2005 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. + * + * Authors: Ali Saidi + */ + +/** @file + * Implements a base class for UARTs + */ + +#include "dev/serial/uart.hh" + +Uart::Uart(const Params *p, Addr pio_size) + : BasicPioDevice(p, pio_size), + platform(p->platform), device(p->device), + callbackDataAvail(this) +{ + status = 0; + + // setup serial device callbacks + device->regInterfaceCallback(&callbackDataAvail); +} diff --git a/src/dev/serial/uart.hh b/src/dev/serial/uart.hh new file mode 100644 index 000000000..04e9ec2e0 --- /dev/null +++ b/src/dev/serial/uart.hh @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2004-2005 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. + * + * Authors: Ali Saidi + */ + +/** @file + * Base class for UART + */ + +#ifndef __UART_HH__ +#define __UART_HH__ + +#include "base/callback.hh" +#include "dev/io_device.hh" +#include "dev/serial/serial.hh" +#include "params/Uart.hh" + +class Platform; + +const int RX_INT = 0x1; +const int TX_INT = 0x2; + +class Uart : public BasicPioDevice +{ + protected: + int status; + Platform *platform; + SerialDevice *device; + + public: + typedef UartParams Params; + Uart(const Params *p, Addr pio_size); + + const Params * + params() const + { + return dynamic_cast(_params); + } + + /** + * Inform the uart that there is data available. + */ + virtual void dataAvailable() = 0; + + /** + * Return if we have an interrupt pending + * @return interrupt status + */ + bool intStatus() { return status ? true : false; } + + protected: + MakeCallback callbackDataAvail; +}; + +#endif // __UART_HH__ diff --git a/src/dev/serial/uart8250.cc b/src/dev/serial/uart8250.cc new file mode 100644 index 000000000..43300f5e8 --- /dev/null +++ b/src/dev/serial/uart8250.cc @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2005 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. + * + * Authors: Ali Saidi + */ + +/** @file + * Implements a 8250 UART + */ + +#include "dev/serial/uart8250.hh" + +#include +#include + +#include "base/inifile.hh" +#include "base/trace.hh" +#include "config/the_isa.hh" +#include "debug/Uart.hh" +#include "dev/platform.hh" +#include "mem/packet.hh" +#include "mem/packet_access.hh" + +using namespace std; +using namespace TheISA; + +void +Uart8250::processIntrEvent(int intrBit) +{ + if (intrBit & IER) { + DPRINTF(Uart, "UART InterEvent, interrupting\n"); + platform->postConsoleInt(); + status |= intrBit; + lastTxInt = curTick(); + } + else + DPRINTF(Uart, "UART InterEvent, not interrupting\n"); + +} + +/* The linux serial driver (8250.c about line 1182) loops reading from + * the device until the device reports it has no more data to + * read. After a maximum of 255 iterations the code prints "serial8250 + * too much work for irq X," and breaks out of the loop. Since the + * simulated system is so much slower than the actual system, if a + * user is typing on the keyboard it is very easy for them to provide + * input at a fast enough rate to not allow the loop to exit and thus + * the error to be printed. This magic number provides a delay between + * the time the UART receives a character to send to the simulated + * system and the time it actually notifies the system it has a + * character to send to alleviate this problem. --Ali + */ +void +Uart8250::scheduleIntr(Event *event) +{ + static const Tick interval = 225 * SimClock::Int::ns; + DPRINTF(Uart, "Scheduling IER interrupt for %s, at cycle %lld\n", + event->name(), curTick() + interval); + if (!event->scheduled()) + schedule(event, curTick() + interval); + else + reschedule(event, curTick() + interval); +} + + +Uart8250::Uart8250(const Params *p) + : Uart(p, 8), IER(0), DLAB(0), LCR(0), MCR(0), lastTxInt(0), + txIntrEvent([this]{ processIntrEvent(TX_INT); }, "TX"), + rxIntrEvent([this]{ processIntrEvent(RX_INT); }, "RX") +{ +} + +Tick +Uart8250::read(PacketPtr pkt) +{ + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + assert(pkt->getSize() == 1); + + Addr daddr = pkt->getAddr() - pioAddr; + + DPRINTF(Uart, " read register %#x\n", daddr); + + switch (daddr) { + case 0x0: + if (!(LCR & 0x80)) { // read byte + if (device->dataAvailable()) + pkt->set(device->readData()); + else { + pkt->set((uint8_t)0); + // A limited amount of these are ok. + DPRINTF(Uart, "empty read of RX register\n"); + } + status &= ~RX_INT; + platform->clearConsoleInt(); + + if (device->dataAvailable() && (IER & UART_IER_RDI)) + scheduleIntr(&rxIntrEvent); + } else { // dll divisor latch + ; + } + break; + case 0x1: + if (!(LCR & 0x80)) { // Intr Enable Register(IER) + pkt->set(IER); + } else { // DLM divisor latch MSB + ; + } + break; + case 0x2: // Intr Identification Register (IIR) + DPRINTF(Uart, "IIR Read, status = %#x\n", (uint32_t)status); + + if (status & RX_INT) /* Rx data interrupt has a higher priority */ + pkt->set(IIR_RXID); + else if (status & TX_INT) { + pkt->set(IIR_TXID); + //Tx interrupts are cleared on IIR reads + status &= ~TX_INT; + } else + pkt->set(IIR_NOPEND); + + break; + case 0x3: // Line Control Register (LCR) + pkt->set(LCR); + break; + case 0x4: // Modem Control Register (MCR) + pkt->set(MCR); + break; + case 0x5: // Line Status Register (LSR) + uint8_t lsr; + lsr = 0; + // check if there are any bytes to be read + if (device->dataAvailable()) + lsr = UART_LSR_DR; + lsr |= UART_LSR_TEMT | UART_LSR_THRE; + pkt->set(lsr); + break; + case 0x6: // Modem Status Register (MSR) + pkt->set((uint8_t)0); + break; + case 0x7: // Scratch Register (SCR) + pkt->set((uint8_t)0); // doesn't exist with at 8250. + break; + default: + panic("Tried to access a UART port that doesn't exist\n"); + break; + } +/* uint32_t d32 = *data; + DPRINTF(Uart, "Register read to register %#x returned %#x\n", daddr, d32); +*/ + pkt->makeAtomicResponse(); + return pioDelay; +} + +Tick +Uart8250::write(PacketPtr pkt) +{ + + assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); + assert(pkt->getSize() == 1); + + Addr daddr = pkt->getAddr() - pioAddr; + + DPRINTF(Uart, " write register %#x value %#x\n", daddr, pkt->get()); + + switch (daddr) { + case 0x0: + if (!(LCR & 0x80)) { // write byte + device->writeData(pkt->get()); + platform->clearConsoleInt(); + status &= ~TX_INT; + if (UART_IER_THRI & IER) + scheduleIntr(&txIntrEvent); + } else { // dll divisor latch + ; + } + break; + case 0x1: + if (!(LCR & 0x80)) { // Intr Enable Register(IER) + IER = pkt->get(); + if (UART_IER_THRI & IER) + { + DPRINTF(Uart, "IER: IER_THRI set, scheduling TX intrrupt\n"); + if (curTick() - lastTxInt > 225 * SimClock::Int::ns) { + DPRINTF(Uart, "-- Interrupting Immediately... %d,%d\n", + curTick(), lastTxInt); + txIntrEvent.process(); + } else { + DPRINTF(Uart, "-- Delaying interrupt... %d,%d\n", + curTick(), lastTxInt); + scheduleIntr(&txIntrEvent); + } + } + else + { + DPRINTF(Uart, "IER: IER_THRI cleared, descheduling TX intrrupt\n"); + if (txIntrEvent.scheduled()) + deschedule(txIntrEvent); + if (status & TX_INT) + platform->clearConsoleInt(); + status &= ~TX_INT; + } + + if ((UART_IER_RDI & IER) && device->dataAvailable()) { + DPRINTF(Uart, "IER: IER_RDI set, scheduling RX intrrupt\n"); + scheduleIntr(&rxIntrEvent); + } else { + DPRINTF(Uart, "IER: IER_RDI cleared, descheduling RX intrrupt\n"); + if (rxIntrEvent.scheduled()) + deschedule(rxIntrEvent); + if (status & RX_INT) + platform->clearConsoleInt(); + status &= ~RX_INT; + } + } else { // DLM divisor latch MSB + ; + } + break; + case 0x2: // FIFO Control Register (FCR) + break; + case 0x3: // Line Control Register (LCR) + LCR = pkt->get(); + break; + case 0x4: // Modem Control Register (MCR) + if (pkt->get() == (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; + } + pkt->makeAtomicResponse(); + return pioDelay; +} + +void +Uart8250::dataAvailable() +{ + // if the kernel wants an interrupt when we have data + if (IER & UART_IER_RDI) + { + platform->postConsoleInt(); + status |= RX_INT; + } + +} + +AddrRangeList +Uart8250::getAddrRanges() const +{ + AddrRangeList ranges; + ranges.push_back(RangeSize(pioAddr, pioSize)); + return ranges; +} + +void +Uart8250::serialize(CheckpointOut &cp) const +{ + SERIALIZE_SCALAR(status); + SERIALIZE_SCALAR(IER); + SERIALIZE_SCALAR(DLAB); + SERIALIZE_SCALAR(LCR); + SERIALIZE_SCALAR(MCR); + Tick rxintrwhen; + if (rxIntrEvent.scheduled()) + rxintrwhen = rxIntrEvent.when(); + else + rxintrwhen = 0; + Tick txintrwhen; + if (txIntrEvent.scheduled()) + txintrwhen = txIntrEvent.when(); + else + txintrwhen = 0; + SERIALIZE_SCALAR(rxintrwhen); + SERIALIZE_SCALAR(txintrwhen); +} + +void +Uart8250::unserialize(CheckpointIn &cp) +{ + UNSERIALIZE_SCALAR(status); + UNSERIALIZE_SCALAR(IER); + UNSERIALIZE_SCALAR(DLAB); + UNSERIALIZE_SCALAR(LCR); + UNSERIALIZE_SCALAR(MCR); + Tick rxintrwhen; + Tick txintrwhen; + UNSERIALIZE_SCALAR(rxintrwhen); + UNSERIALIZE_SCALAR(txintrwhen); + if (rxintrwhen != 0) + schedule(rxIntrEvent, rxintrwhen); + if (txintrwhen != 0) + schedule(txIntrEvent, txintrwhen); +} + +Uart8250 * +Uart8250Params::create() +{ + return new Uart8250(this); +} diff --git a/src/dev/serial/uart8250.hh b/src/dev/serial/uart8250.hh new file mode 100644 index 000000000..585fbb21e --- /dev/null +++ b/src/dev/serial/uart8250.hh @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2005 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. + * + * Authors: Ali Saidi + */ + +/** @file + * Defines a 8250 UART + */ + +#ifndef __DEV_UART8250_HH__ +#define __DEV_UART8250_HH__ + +#include "dev/io_device.hh" +#include "dev/serial/uart.hh" +#include "params/Uart8250.hh" + +/* UART8250 Interrupt ID Register + * bit 0 Interrupt Pending 0 = true, 1 = false + * bit 2:1 ID of highest priority interrupt + * bit 7:3 zeroes + */ +const uint8_t IIR_NOPEND = 0x1; + +// Interrupt IDs +const uint8_t IIR_MODEM = 0x00; /* Modem Status (lowest priority) */ +const uint8_t IIR_TXID = 0x02; /* Tx Data */ +const uint8_t IIR_RXID = 0x04; /* Rx Data */ +const uint8_t IIR_LINE = 0x06; /* Rx Line Status (highest priority)*/ + +const uint8_t UART_IER_RDI = 0x01; +const uint8_t UART_IER_THRI = 0x02; +const uint8_t UART_IER_RLSI = 0x04; + + +const uint8_t UART_LSR_TEMT = 0x40; +const uint8_t UART_LSR_THRE = 0x20; +const uint8_t UART_LSR_DR = 0x01; + +const uint8_t UART_MCR_LOOP = 0x10; + + +class Terminal; +class Platform; + +class Uart8250 : public Uart +{ + protected: + uint8_t IER, DLAB, LCR, MCR; + Tick lastTxInt; + + void processIntrEvent(int intrBit); + void scheduleIntr(Event *event); + + EventFunctionWrapper txIntrEvent; + EventFunctionWrapper rxIntrEvent; + + public: + typedef Uart8250Params Params; + const Params * + params() const + { + return dynamic_cast(_params); + } + Uart8250(const Params *p); + + Tick read(PacketPtr pkt) override; + Tick write(PacketPtr pkt) override; + AddrRangeList getAddrRanges() const override; + + /** + * Inform the uart that there is data available. + */ + void dataAvailable() override; + + + /** + * Return if we have an interrupt pending + * @return interrupt status + */ + virtual bool intStatus() { return status ? true : false; } + + void serialize(CheckpointOut &cp) const override; + void unserialize(CheckpointIn &cp) override; +}; + +#endif // __TSUNAMI_UART_HH__ diff --git a/src/dev/sparc/t1000.cc b/src/dev/sparc/t1000.cc index f65846297..0bc7ad87d 100644 --- a/src/dev/sparc/t1000.cc +++ b/src/dev/sparc/t1000.cc @@ -40,7 +40,6 @@ #include "config/the_isa.hh" #include "cpu/intr_control.hh" -#include "dev/terminal.hh" #include "sim/system.hh" using namespace std; diff --git a/src/dev/terminal.cc b/src/dev/terminal.cc deleted file mode 100644 index 4f9881ddd..000000000 --- a/src/dev/terminal.cc +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright (c) 2001-2005 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. - * - * Authors: Nathan Binkert - * Ali Saidi - */ - -/* @file - * Implements the user interface to a serial terminal - */ - -#include - -#if defined(__FreeBSD__) -#include - -#else -#include - -#endif -#include "dev/terminal.hh" - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "base/atomicio.hh" -#include "base/misc.hh" -#include "base/output.hh" -#include "base/socket.hh" -#include "base/trace.hh" -#include "debug/Terminal.hh" -#include "debug/TerminalVerbose.hh" -#include "dev/platform.hh" -#include "dev/uart.hh" - -using namespace std; - - -/* - * Poll event for the listen socket - */ -Terminal::ListenEvent::ListenEvent(Terminal *t, int fd, int e) - : PollEvent(fd, e), term(t) -{ -} - -void -Terminal::ListenEvent::process(int revent) -{ - term->accept(); -} - -/* - * Poll event for the data socket - */ -Terminal::DataEvent::DataEvent(Terminal *t, int fd, int e) - : PollEvent(fd, e), term(t) -{ -} - -void -Terminal::DataEvent::process(int revent) -{ - // As a consequence of being called from the PollQueue, we might - // have been called from a different thread. Migrate to "our" - // thread. - EventQueue::ScopedMigration migrate(term->eventQueue()); - - if (revent & POLLIN) - term->data(); - else if (revent & POLLNVAL) - term->detach(); -} - -/* - * Terminal code - */ -Terminal::Terminal(const Params *p) - : 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 - , linebuf(16384) -#endif -{ - if (outfile) - outfile->stream()->setf(ios::unitbuf); - - if (p->port) - listen(p->port); -} - -Terminal::~Terminal() -{ - if (data_fd != -1) - ::close(data_fd); - - if (listenEvent) - delete listenEvent; - - if (dataEvent) - delete dataEvent; -} - - -/////////////////////////////////////////////////////////////////////// -// socket creation and terminal attach -// - -void -Terminal::listen(int port) -{ - if (ListenSocket::allDisabled()) { - warn_once("Sockets disabled, not accepting terminal connections"); - return; - } - - while (!listener.listen(port, true)) { - DPRINTF(Terminal, - ": can't bind address terminal port %d inuse PID %d\n", - port, getpid()); - port++; - } - - int p1, p2; - p2 = name().rfind('.') - 1; - p1 = name().rfind('.', p2); - ccprintf(cerr, "Listening for %s connection on port %d\n", - name().substr(p1+1,p2-p1), port); - - listenEvent = new ListenEvent(this, listener.getfd(), POLLIN); - pollQueue.schedule(listenEvent); -} - -void -Terminal::accept() -{ - if (!listener.islistening()) - panic("%s: cannot accept a connection if not listening!", name()); - - int fd = listener.accept(true); - if (data_fd != -1) { - char message[] = "terminal already attached!\n"; - atomic_write(fd, message, sizeof(message)); - ::close(fd); - return; - } - - data_fd = fd; - dataEvent = new DataEvent(this, data_fd, POLLIN); - pollQueue.schedule(dataEvent); - - stringstream stream; - ccprintf(stream, "==== m5 slave terminal: Terminal %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 terminal %d\n", number); - char buf[1024]; - for (size_t i = 0; i < txbuf.size(); i += sizeof(buf)) { - const size_t chunk_len(std::min(txbuf.size() - i, sizeof(buf))); - txbuf.peek(buf, i, chunk_len); - write((const uint8_t *)buf, chunk_len); - } -} - -void -Terminal::detach() -{ - if (data_fd != -1) { - ::close(data_fd); - data_fd = -1; - } - - pollQueue.remove(dataEvent); - delete dataEvent; - dataEvent = NULL; - - DPRINTFN("detach terminal %d\n", number); -} - -void -Terminal::data() -{ - uint8_t buf[1024]; - int len; - - len = read(buf, sizeof(buf)); - if (len) { - rxbuf.write((char *)buf, len); - notifyInterface(); - } -} - -size_t -Terminal::read(uint8_t *buf, size_t len) -{ - if (data_fd < 0) - panic("Terminal not properly attached.\n"); - - ssize_t ret; - do { - ret = ::read(data_fd, buf, len); - } while (ret == -1 && errno == EINTR); - - - if (ret < 0) - DPRINTFN("Read failed.\n"); - - if (ret <= 0) { - detach(); - return 0; - } - - return ret; -} - -// Terminal output. -size_t -Terminal::write(const uint8_t *buf, size_t len) -{ - if (data_fd < 0) - panic("Terminal not properly attached.\n"); - - ssize_t ret = atomic_write(data_fd, buf, len); - if (ret < len) - 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) - -uint8_t -Terminal::readData() -{ - uint8_t c; - - assert(!rxbuf.empty()); - rxbuf.read((char *)&c, 1); - - DPRINTF(TerminalVerbose, "in: \'%c\' %#02x more: %d\n", - isprint(c) ? c : ' ', c, !rxbuf.empty()); - - return c; -} - -uint64_t -Terminal::console_in() -{ - uint64_t value; - - if (dataAvailable()) { - value = RECEIVE_SUCCESS | readData(); - if (!rxbuf.empty()) - value |= MORE_PENDING; - } else { - value = RECEIVE_NONE; - } - - DPRINTF(TerminalVerbose, "console_in: return: %#x\n", value); - - return value; -} - -void -Terminal::writeData(uint8_t c) -{ -#if TRACING_ON == 1 - if (DTRACE(Terminal)) { - 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(Terminal, "%s\n", buffer); - delete [] buffer; - } else { - linebuf.write(&c, 1); - } - } - - last = c; - } -#endif - - txbuf.write(&c, 1); - - if (data_fd >= 0) - write(c); - - if (outfile) - outfile->stream()->put((char)c); - - DPRINTF(TerminalVerbose, "out: \'%c\' %#02x\n", - isprint(c) ? c : ' ', (int)c); - -} - -Terminal * -TerminalParams::create() -{ - return new Terminal(this); -} diff --git a/src/dev/terminal.hh b/src/dev/terminal.hh deleted file mode 100644 index 8b6ec0b7f..000000000 --- a/src/dev/terminal.hh +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2001-2005 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. - * - * Authors: Nathan Binkert - * Ali Saidi - */ - -/* @file - * User Terminal Interface - */ - -#ifndef __DEV_TERMINAL_HH__ -#define __DEV_TERMINAL_HH__ - -#include - -#include "base/callback.hh" -#include "base/circlebuf.hh" -#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 SerialDevice -{ - protected: - class ListenEvent : public PollEvent - { - protected: - Terminal *term; - - public: - ListenEvent(Terminal *t, int fd, int e); - void process(int revent); - }; - - friend class ListenEvent; - ListenEvent *listenEvent; - - class DataEvent : public PollEvent - { - protected: - Terminal *term; - - public: - DataEvent(Terminal *t, int fd, int e); - void process(int revent); - }; - - friend class DataEvent; - DataEvent *dataEvent; - - protected: - int number; - int data_fd; - - public: - typedef TerminalParams Params; - Terminal(const Params *p); - ~Terminal(); - - protected: - ListenSocket listener; - - void listen(int port); - void accept(); - - protected: - CircleBuf txbuf; - CircleBuf rxbuf; - OutputStream *outfile; -#if TRACING_ON == 1 - CircleBuf linebuf; -#endif - - public: - /////////////////////// - // Terminal Interface - - void data(); - - 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 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 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(); -}; - -#endif // __DEV_TERMINAL_HH__ diff --git a/src/dev/uart.cc b/src/dev/uart.cc deleted file mode 100644 index ff952cc7f..000000000 --- a/src/dev/uart.cc +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2004-2005 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. - * - * Authors: Ali Saidi - */ - -/** @file - * Implements a base class for UARTs - */ - -#include "dev/uart.hh" - -#include "dev/serial.hh" - -using namespace std; - -Uart::Uart(const Params *p, Addr pio_size) - : BasicPioDevice(p, pio_size), - platform(p->platform), device(p->device), - callbackDataAvail(this) -{ - status = 0; - - // setup serial device callbacks - device->regInterfaceCallback(&callbackDataAvail); -} diff --git a/src/dev/uart.hh b/src/dev/uart.hh deleted file mode 100644 index bf3dcf7c3..000000000 --- a/src/dev/uart.hh +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2004-2005 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. - * - * Authors: Ali Saidi - */ - -/** @file - * Base class for UART - */ - -#ifndef __UART_HH__ -#define __UART_HH__ - -#include "base/callback.hh" -#include "dev/io_device.hh" -#include "dev/serial.hh" -#include "params/Uart.hh" - -class Platform; - -const int RX_INT = 0x1; -const int TX_INT = 0x2; - -class Uart : public BasicPioDevice -{ - protected: - int status; - Platform *platform; - SerialDevice *device; - - public: - typedef UartParams Params; - Uart(const Params *p, Addr pio_size); - - const Params * - params() const - { - return dynamic_cast(_params); - } - - /** - * Inform the uart that there is data available. - */ - virtual void dataAvailable() = 0; - - /** - * Return if we have an interrupt pending - * @return interrupt status - */ - bool intStatus() { return status ? true : false; } - - protected: - MakeCallback callbackDataAvail; -}; - -#endif // __UART_HH__ diff --git a/src/dev/uart8250.cc b/src/dev/uart8250.cc deleted file mode 100644 index f99b2472b..000000000 --- a/src/dev/uart8250.cc +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Copyright (c) 2005 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. - * - * Authors: Ali Saidi - */ - -/** @file - * Implements a 8250 UART - */ - -#include "dev/uart8250.hh" - -#include -#include - -#include "base/inifile.hh" -#include "base/trace.hh" -#include "config/the_isa.hh" -#include "debug/Uart.hh" -#include "dev/platform.hh" -#include "mem/packet.hh" -#include "mem/packet_access.hh" - -using namespace std; -using namespace TheISA; - -void -Uart8250::processIntrEvent(int intrBit) -{ - if (intrBit & IER) { - DPRINTF(Uart, "UART InterEvent, interrupting\n"); - platform->postConsoleInt(); - status |= intrBit; - lastTxInt = curTick(); - } - else - DPRINTF(Uart, "UART InterEvent, not interrupting\n"); - -} - -/* The linux serial driver (8250.c about line 1182) loops reading from - * the device until the device reports it has no more data to - * read. After a maximum of 255 iterations the code prints "serial8250 - * too much work for irq X," and breaks out of the loop. Since the - * simulated system is so much slower than the actual system, if a - * user is typing on the keyboard it is very easy for them to provide - * input at a fast enough rate to not allow the loop to exit and thus - * the error to be printed. This magic number provides a delay between - * the time the UART receives a character to send to the simulated - * system and the time it actually notifies the system it has a - * character to send to alleviate this problem. --Ali - */ -void -Uart8250::scheduleIntr(Event *event) -{ - static const Tick interval = 225 * SimClock::Int::ns; - DPRINTF(Uart, "Scheduling IER interrupt for %s, at cycle %lld\n", - event->name(), curTick() + interval); - if (!event->scheduled()) - schedule(event, curTick() + interval); - else - reschedule(event, curTick() + interval); -} - - -Uart8250::Uart8250(const Params *p) - : Uart(p, 8), IER(0), DLAB(0), LCR(0), MCR(0), lastTxInt(0), - txIntrEvent([this]{ processIntrEvent(TX_INT); }, "TX"), - rxIntrEvent([this]{ processIntrEvent(RX_INT); }, "RX") -{ -} - -Tick -Uart8250::read(PacketPtr pkt) -{ - assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); - assert(pkt->getSize() == 1); - - Addr daddr = pkt->getAddr() - pioAddr; - - DPRINTF(Uart, " read register %#x\n", daddr); - - switch (daddr) { - case 0x0: - if (!(LCR & 0x80)) { // read byte - if (device->dataAvailable()) - pkt->set(device->readData()); - else { - pkt->set((uint8_t)0); - // A limited amount of these are ok. - DPRINTF(Uart, "empty read of RX register\n"); - } - status &= ~RX_INT; - platform->clearConsoleInt(); - - if (device->dataAvailable() && (IER & UART_IER_RDI)) - scheduleIntr(&rxIntrEvent); - } else { // dll divisor latch - ; - } - break; - case 0x1: - if (!(LCR & 0x80)) { // Intr Enable Register(IER) - pkt->set(IER); - } else { // DLM divisor latch MSB - ; - } - break; - case 0x2: // Intr Identification Register (IIR) - DPRINTF(Uart, "IIR Read, status = %#x\n", (uint32_t)status); - - if (status & RX_INT) /* Rx data interrupt has a higher priority */ - pkt->set(IIR_RXID); - else if (status & TX_INT) { - pkt->set(IIR_TXID); - //Tx interrupts are cleared on IIR reads - status &= ~TX_INT; - } else - pkt->set(IIR_NOPEND); - - break; - case 0x3: // Line Control Register (LCR) - pkt->set(LCR); - break; - case 0x4: // Modem Control Register (MCR) - pkt->set(MCR); - break; - case 0x5: // Line Status Register (LSR) - uint8_t lsr; - lsr = 0; - // check if there are any bytes to be read - if (device->dataAvailable()) - lsr = UART_LSR_DR; - lsr |= UART_LSR_TEMT | UART_LSR_THRE; - pkt->set(lsr); - break; - case 0x6: // Modem Status Register (MSR) - pkt->set((uint8_t)0); - break; - case 0x7: // Scratch Register (SCR) - pkt->set((uint8_t)0); // doesn't exist with at 8250. - break; - default: - panic("Tried to access a UART port that doesn't exist\n"); - break; - } -/* uint32_t d32 = *data; - DPRINTF(Uart, "Register read to register %#x returned %#x\n", daddr, d32); -*/ - pkt->makeAtomicResponse(); - return pioDelay; -} - -Tick -Uart8250::write(PacketPtr pkt) -{ - - assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); - assert(pkt->getSize() == 1); - - Addr daddr = pkt->getAddr() - pioAddr; - - DPRINTF(Uart, " write register %#x value %#x\n", daddr, pkt->get()); - - switch (daddr) { - case 0x0: - if (!(LCR & 0x80)) { // write byte - device->writeData(pkt->get()); - platform->clearConsoleInt(); - status &= ~TX_INT; - if (UART_IER_THRI & IER) - scheduleIntr(&txIntrEvent); - } else { // dll divisor latch - ; - } - break; - case 0x1: - if (!(LCR & 0x80)) { // Intr Enable Register(IER) - IER = pkt->get(); - if (UART_IER_THRI & IER) - { - DPRINTF(Uart, "IER: IER_THRI set, scheduling TX intrrupt\n"); - if (curTick() - lastTxInt > 225 * SimClock::Int::ns) { - DPRINTF(Uart, "-- Interrupting Immediately... %d,%d\n", - curTick(), lastTxInt); - txIntrEvent.process(); - } else { - DPRINTF(Uart, "-- Delaying interrupt... %d,%d\n", - curTick(), lastTxInt); - scheduleIntr(&txIntrEvent); - } - } - else - { - DPRINTF(Uart, "IER: IER_THRI cleared, descheduling TX intrrupt\n"); - if (txIntrEvent.scheduled()) - deschedule(txIntrEvent); - if (status & TX_INT) - platform->clearConsoleInt(); - status &= ~TX_INT; - } - - if ((UART_IER_RDI & IER) && device->dataAvailable()) { - DPRINTF(Uart, "IER: IER_RDI set, scheduling RX intrrupt\n"); - scheduleIntr(&rxIntrEvent); - } else { - DPRINTF(Uart, "IER: IER_RDI cleared, descheduling RX intrrupt\n"); - if (rxIntrEvent.scheduled()) - deschedule(rxIntrEvent); - if (status & RX_INT) - platform->clearConsoleInt(); - status &= ~RX_INT; - } - } else { // DLM divisor latch MSB - ; - } - break; - case 0x2: // FIFO Control Register (FCR) - break; - case 0x3: // Line Control Register (LCR) - LCR = pkt->get(); - break; - case 0x4: // Modem Control Register (MCR) - if (pkt->get() == (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; - } - pkt->makeAtomicResponse(); - return pioDelay; -} - -void -Uart8250::dataAvailable() -{ - // if the kernel wants an interrupt when we have data - if (IER & UART_IER_RDI) - { - platform->postConsoleInt(); - status |= RX_INT; - } - -} - -AddrRangeList -Uart8250::getAddrRanges() const -{ - AddrRangeList ranges; - ranges.push_back(RangeSize(pioAddr, pioSize)); - return ranges; -} - -void -Uart8250::serialize(CheckpointOut &cp) const -{ - SERIALIZE_SCALAR(status); - SERIALIZE_SCALAR(IER); - SERIALIZE_SCALAR(DLAB); - SERIALIZE_SCALAR(LCR); - SERIALIZE_SCALAR(MCR); - Tick rxintrwhen; - if (rxIntrEvent.scheduled()) - rxintrwhen = rxIntrEvent.when(); - else - rxintrwhen = 0; - Tick txintrwhen; - if (txIntrEvent.scheduled()) - txintrwhen = txIntrEvent.when(); - else - txintrwhen = 0; - SERIALIZE_SCALAR(rxintrwhen); - SERIALIZE_SCALAR(txintrwhen); -} - -void -Uart8250::unserialize(CheckpointIn &cp) -{ - UNSERIALIZE_SCALAR(status); - UNSERIALIZE_SCALAR(IER); - UNSERIALIZE_SCALAR(DLAB); - UNSERIALIZE_SCALAR(LCR); - UNSERIALIZE_SCALAR(MCR); - Tick rxintrwhen; - Tick txintrwhen; - UNSERIALIZE_SCALAR(rxintrwhen); - UNSERIALIZE_SCALAR(txintrwhen); - if (rxintrwhen != 0) - schedule(rxIntrEvent, rxintrwhen); - if (txintrwhen != 0) - schedule(txIntrEvent, txintrwhen); -} - -Uart8250 * -Uart8250Params::create() -{ - return new Uart8250(this); -} diff --git a/src/dev/uart8250.hh b/src/dev/uart8250.hh deleted file mode 100644 index b7fefc534..000000000 --- a/src/dev/uart8250.hh +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2005 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. - * - * Authors: Ali Saidi - */ - -/** @file - * Defines a 8250 UART - */ - -#ifndef __DEV_UART8250_HH__ -#define __DEV_UART8250_HH__ - -#include "dev/io_device.hh" -#include "dev/uart.hh" -#include "params/Uart8250.hh" - -/* UART8250 Interrupt ID Register - * bit 0 Interrupt Pending 0 = true, 1 = false - * bit 2:1 ID of highest priority interrupt - * bit 7:3 zeroes - */ -const uint8_t IIR_NOPEND = 0x1; - -// Interrupt IDs -const uint8_t IIR_MODEM = 0x00; /* Modem Status (lowest priority) */ -const uint8_t IIR_TXID = 0x02; /* Tx Data */ -const uint8_t IIR_RXID = 0x04; /* Rx Data */ -const uint8_t IIR_LINE = 0x06; /* Rx Line Status (highest priority)*/ - -const uint8_t UART_IER_RDI = 0x01; -const uint8_t UART_IER_THRI = 0x02; -const uint8_t UART_IER_RLSI = 0x04; - - -const uint8_t UART_LSR_TEMT = 0x40; -const uint8_t UART_LSR_THRE = 0x20; -const uint8_t UART_LSR_DR = 0x01; - -const uint8_t UART_MCR_LOOP = 0x10; - - -class Terminal; -class Platform; - -class Uart8250 : public Uart -{ - protected: - uint8_t IER, DLAB, LCR, MCR; - Tick lastTxInt; - - void processIntrEvent(int intrBit); - void scheduleIntr(Event *event); - - EventFunctionWrapper txIntrEvent; - EventFunctionWrapper rxIntrEvent; - - public: - typedef Uart8250Params Params; - const Params * - params() const - { - return dynamic_cast(_params); - } - Uart8250(const Params *p); - - Tick read(PacketPtr pkt) override; - Tick write(PacketPtr pkt) override; - AddrRangeList getAddrRanges() const override; - - /** - * Inform the uart that there is data available. - */ - void dataAvailable() override; - - - /** - * Return if we have an interrupt pending - * @return interrupt status - */ - virtual bool intStatus() { return status ? true : false; } - - void serialize(CheckpointOut &cp) const override; - void unserialize(CheckpointIn &cp) override; -}; - -#endif // __TSUNAMI_UART_HH__ diff --git a/src/dev/virtio/block.hh b/src/dev/virtio/block.hh index fbbb51854..be88bd035 100644 --- a/src/dev/virtio/block.hh +++ b/src/dev/virtio/block.hh @@ -42,7 +42,6 @@ #include "dev/virtio/base.hh" #include "dev/storage/disk_image.hh" -#include "dev/terminal.hh" struct VirtIOBlockParams; diff --git a/src/dev/virtio/console.hh b/src/dev/virtio/console.hh index 720b60044..cd044b12e 100644 --- a/src/dev/virtio/console.hh +++ b/src/dev/virtio/console.hh @@ -40,7 +40,7 @@ #ifndef __DEV_VIRTIO_CONSOLE_HH__ #define __DEV_VIRTIO_CONSOLE_HH__ -#include "dev/serial.hh" +#include "dev/serial/serial.hh" #include "dev/virtio/base.hh" struct VirtIOConsoleParams; diff --git a/src/dev/x86/pc.cc b/src/dev/x86/pc.cc index 6d182c078..6746b5026 100644 --- a/src/dev/x86/pc.cc +++ b/src/dev/x86/pc.cc @@ -42,7 +42,6 @@ #include "arch/x86/x86_traits.hh" #include "config/the_isa.hh" #include "cpu/intr_control.hh" -#include "dev/terminal.hh" #include "dev/x86/i82094aa.hh" #include "dev/x86/i8254.hh" #include "dev/x86/i8259.hh"