This patch extracts generic logic of serial console into a base class isa-serial-basee. The specializations like isa-serial (and mmio-isa-serial in later patch) implement relevant static methods - read_byte() and write_byte() to provide specific way of reading and writing a byte.
Signed-off-by: Waldemar Kozaczuk <[email protected]> --- Makefile | 1 + drivers/{isa-serial.cc => isa-serial-base.cc} | 47 ++++---- drivers/{isa-serial.hh => isa-serial-base.hh} | 23 ++-- drivers/isa-serial.cc | 106 +----------------- drivers/isa-serial.hh | 17 +-- 5 files changed, 40 insertions(+), 154 deletions(-) copy drivers/{isa-serial.cc => isa-serial-base.cc} (70%) copy drivers/{isa-serial.hh => isa-serial-base.hh} (54%) diff --git a/Makefile b/Makefile index 20ddf3b1..99923a34 100644 --- a/Makefile +++ b/Makefile @@ -776,6 +776,7 @@ drivers += drivers/line-discipline.o drivers += drivers/clock.o drivers += drivers/clock-common.o drivers += drivers/clockevent.o +drivers += drivers/isa-serial-base.o drivers += core/elf.o drivers += drivers/random.o drivers += drivers/zfs.o diff --git a/drivers/isa-serial.cc b/drivers/isa-serial-base.cc similarity index 70% copy from drivers/isa-serial.cc copy to drivers/isa-serial-base.cc index b20b30f3..a8e30f0d 100644 --- a/drivers/isa-serial.cc +++ b/drivers/isa-serial-base.cc @@ -1,11 +1,11 @@ /* - * Copyright (C) 2013 Cloudius Systems, Ltd. + * Copyright (C) 2020 Waldemar Kozaczuk. * * This work is open source software, licensed under the terms of the * BSD license as described in the LICENSE file in the top-level directory. */ -#include "isa-serial.hh" +#include "isa-serial-base.hh" namespace console { @@ -50,77 +50,72 @@ enum mcr { LOOPBACK_MODE = 0x16, }; -void isa_serial_console::early_init() +void isa_serial_console_base::common_early_init() { // Set the UART speed to to 115,200 bps, This is done by writing 1,0 to // Divisor Latch registers, but to access these we need to temporarily // set the Divisor Latch Access Bit (DLAB) on the LSR register, because // the UART has fewer ports than registers... - pci::outb(lcr::LEN_8BIT | lcr::DLAB, ioport + regs::LCR); - pci::outb(1, ioport + regs::DLL); - pci::outb(0, ioport + regs::DLM); - pci::outb(lcr::LEN_8BIT, ioport + regs::LCR); + write_byte(lcr::LEN_8BIT | lcr::DLAB, regs::LCR); + write_byte(1, regs::DLL); + write_byte(0, regs::DLM); + write_byte(lcr::LEN_8BIT, regs::LCR); // interrupt threshold - pci::outb(0, ioport + regs::FCR); + write_byte(0, regs::FCR); // disable interrupts - pci::outb(0, ioport + regs::IER); + write_byte(0, regs::IER); // Most physical UARTs need the MCR AUX_OUTPUT_2 bit set to 1 for // interrupts to be generated. QEMU doesn't bother checking this // bit, but interestingly VMWare does, so we must set it. - pci::outb(mcr::AUX_OUTPUT_2, ioport + regs::MCR); + write_byte(mcr::AUX_OUTPUT_2, regs::MCR); } -void isa_serial_console::write(const char *str, size_t len) +void isa_serial_console_base::write(const char *str, size_t len) { while (len-- > 0) putchar(*str++); } -bool isa_serial_console::input_ready() +bool isa_serial_console_base::input_ready() { - u8 val = pci::inb(ioport + regs::LSR); + u8 val = read_byte(regs::LSR); // On VMWare hosts without a serial port, this register always // returns 0xff. Just ignore it instead of spinning incessantly. return (val != 0xff && (val & lsr::RECEIVE_DATA_READY)); } -char isa_serial_console::readch() +char isa_serial_console_base::readch() { u8 val; char letter; do { - val = pci::inb(ioport + regs::LSR); + val = read_byte(regs::LSR); } while (!(val & (lsr::RECEIVE_DATA_READY | lsr::OVERRUN | lsr::PARITY_ERROR | lsr::FRAME_ERROR))); - letter = pci::inb(ioport); + letter = read_byte(0); return letter; } -void isa_serial_console::putchar(const char ch) +void isa_serial_console_base::putchar(const char ch) { u8 val; do { - val = pci::inb(ioport + regs::LSR); + val = read_byte(regs::LSR); } while (!(val & lsr::TRANSMIT_HOLD_EMPTY)); - pci::outb(ch, ioport); + write_byte(ch, 0); } -void isa_serial_console::enable_interrupt() +void isa_serial_console_base::enable_interrupt() { // enable interrupts - pci::outb(1, ioport + regs::IER); -} - -void isa_serial_console::dev_start() { - _irq.reset(new gsi_edge_interrupt(4, [&] { _thread->wake(); })); - enable_interrupt(); + write_byte(1, regs::IER); } } diff --git a/drivers/isa-serial.hh b/drivers/isa-serial-base.hh similarity index 54% copy from drivers/isa-serial.hh copy to drivers/isa-serial-base.hh index e31d125a..88055b43 100644 --- a/drivers/isa-serial.hh +++ b/drivers/isa-serial-base.hh @@ -1,12 +1,12 @@ /* - * Copyright (C) 2013 Cloudius Systems, Ltd. + * Copyright (C) 2020 Waldemar Kozaczuk. * * This work is open source software, licensed under the terms of the * BSD license as described in the LICENSE file in the top-level directory. */ -#ifndef DRIVERS_ISA_SERIAL_HH -#define DRIVERS_ISA_SERIAL_HH +#ifndef DRIVERS_ISA_SERIAL_BASE_HH +#define DRIVERS_ISA_SERIAL_BASE_HH #include "console-driver.hh" #include <osv/pci.hh> @@ -15,23 +15,20 @@ namespace console { -class isa_serial_console : public console_driver { +class isa_serial_console_base : public console_driver { public: - static void early_init(); virtual void write(const char *str, size_t len); virtual void flush() {} virtual bool input_ready() override; virtual char readch(); -private: - std::unique_ptr<gsi_edge_interrupt> _irq; - static const u16 ioport = 0x3f8; - - virtual void dev_start(); +protected: + static void common_early_init(); + static u8 read_byte(int); + static void write_byte(u8, int); void enable_interrupt(); - static void putchar(const char ch); - virtual const char *thread_name() { return "isa-serial-input"; } +private: + void putchar(const char ch); }; - } #endif diff --git a/drivers/isa-serial.cc b/drivers/isa-serial.cc index b20b30f3..5e2b8bbf 100644 --- a/drivers/isa-serial.cc +++ b/drivers/isa-serial.cc @@ -9,113 +9,17 @@ namespace console { -// UART registers, offsets to ioport: -enum regs { - IER = 1, // Interrupt Enable Register - FCR = 2, // FIFO Control Register - LCR = 3, // Line Control Register - MCR = 4, // Modem Control Register - LSR = 5, // Line Control Register - MSR = 6, // Modem Status Register - SCR = 7, // Scratch Register - DLL = 0, // Divisor Latch LSB Register - DLM = 1, // Divisor Latch MSB Register +u8 isa_serial_console_base::read_byte(int reg) { + return pci::inb(isa_serial_console::ioport + reg); }; -enum lcr { - // When bit 7 (DLAB) of LCR is set to 1, the two registers 0 and 1 - // change their meaning and become two bytes controlling the baud rate - DLAB = 0x80, // Divisor Latch Access Bit in LCR register - LEN_8BIT = 3, -}; - -// Various bits of the Line Status Register -enum lsr { - RECEIVE_DATA_READY = 0x1, - OVERRUN = 0x2, - PARITY_ERROR = 0x4, - FRAME_ERROR = 0x8, - BREAK_INTERRUPT = 0x10, - TRANSMIT_HOLD_EMPTY = 0x20, - TRANSMIT_EMPTY = 0x40, - FIFO_ERROR = 0x80, -}; - -// Various bits of the Modem Control Register -enum mcr { - DTR = 0x1, - RTS = 0x2, - AUX_OUTPUT_1 = 0x4, - AUX_OUTPUT_2 = 0x8, - LOOPBACK_MODE = 0x16, +void isa_serial_console_base::write_byte(u8 val, int reg) { + pci::outb(val, isa_serial_console::ioport + reg); }; void isa_serial_console::early_init() { - // Set the UART speed to to 115,200 bps, This is done by writing 1,0 to - // Divisor Latch registers, but to access these we need to temporarily - // set the Divisor Latch Access Bit (DLAB) on the LSR register, because - // the UART has fewer ports than registers... - pci::outb(lcr::LEN_8BIT | lcr::DLAB, ioport + regs::LCR); - pci::outb(1, ioport + regs::DLL); - pci::outb(0, ioport + regs::DLM); - pci::outb(lcr::LEN_8BIT, ioport + regs::LCR); - - // interrupt threshold - pci::outb(0, ioport + regs::FCR); - - // disable interrupts - pci::outb(0, ioport + regs::IER); - - // Most physical UARTs need the MCR AUX_OUTPUT_2 bit set to 1 for - // interrupts to be generated. QEMU doesn't bother checking this - // bit, but interestingly VMWare does, so we must set it. - pci::outb(mcr::AUX_OUTPUT_2, ioport + regs::MCR); -} - -void isa_serial_console::write(const char *str, size_t len) -{ - while (len-- > 0) - putchar(*str++); -} - -bool isa_serial_console::input_ready() -{ - u8 val = pci::inb(ioport + regs::LSR); - // On VMWare hosts without a serial port, this register always - // returns 0xff. Just ignore it instead of spinning incessantly. - return (val != 0xff && (val & lsr::RECEIVE_DATA_READY)); -} - -char isa_serial_console::readch() -{ - u8 val; - char letter; - - do { - val = pci::inb(ioport + regs::LSR); - } while (!(val & (lsr::RECEIVE_DATA_READY | lsr::OVERRUN | lsr::PARITY_ERROR | lsr::FRAME_ERROR))); - - letter = pci::inb(ioport); - - return letter; -} - -void isa_serial_console::putchar(const char ch) -{ - u8 val; - - do { - val = pci::inb(ioport + regs::LSR); - } while (!(val & lsr::TRANSMIT_HOLD_EMPTY)); - - pci::outb(ch, ioport); -} - -void isa_serial_console::enable_interrupt() -{ - // enable interrupts - pci::outb(1, ioport + regs::IER); + common_early_init(); } void isa_serial_console::dev_start() { diff --git a/drivers/isa-serial.hh b/drivers/isa-serial.hh index e31d125a..d7908be2 100644 --- a/drivers/isa-serial.hh +++ b/drivers/isa-serial.hh @@ -8,30 +8,19 @@ #ifndef DRIVERS_ISA_SERIAL_HH #define DRIVERS_ISA_SERIAL_HH -#include "console-driver.hh" -#include <osv/pci.hh> -#include <osv/sched.hh> -#include <osv/interrupt.hh> +#include "isa-serial-base.hh" namespace console { -class isa_serial_console : public console_driver { +class isa_serial_console : public isa_serial_console_base { public: static void early_init(); - virtual void write(const char *str, size_t len); - virtual void flush() {} - virtual bool input_ready() override; - virtual char readch(); + static const u16 ioport = 0x3f8; private: std::unique_ptr<gsi_edge_interrupt> _irq; - static const u16 ioport = 0x3f8; - virtual void dev_start(); - void enable_interrupt(); - static void putchar(const char ch); virtual const char *thread_name() { return "isa-serial-input"; } }; - } #endif -- 2.25.1 -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/osv-dev/20200622041353.24880-1-jwkozaczuk%40gmail.com.
