aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--riscv/devices.h3
-rw-r--r--riscv/ns16550.cc10
2 files changed, 12 insertions, 1 deletions
diff --git a/riscv/devices.h b/riscv/devices.h
index 0030da8..040fe3e 100644
--- a/riscv/devices.h
+++ b/riscv/devices.h
@@ -148,6 +148,9 @@ class ns16550_t : public abstract_device_t {
void update_interrupt(void);
uint8_t rx_byte(void);
void tx_byte(uint8_t val);
+
+ int backoff_counter;
+ static const int MAX_BACKOFF = 16;
};
class mmio_plugin_device_t : public abstract_device_t {
diff --git a/riscv/ns16550.cc b/riscv/ns16550.cc
index 7bc1d20..8d7e4de 100644
--- a/riscv/ns16550.cc
+++ b/riscv/ns16550.cc
@@ -71,7 +71,7 @@
ns16550_t::ns16550_t(class bus_t *bus, abstract_interrupt_controller_t *intctrl,
uint32_t interrupt_id, uint32_t reg_shift, uint32_t reg_io_width)
- : bus(bus), intctrl(intctrl), interrupt_id(interrupt_id), reg_shift(reg_shift), reg_io_width(reg_io_width)
+ : bus(bus), intctrl(intctrl), interrupt_id(interrupt_id), reg_shift(reg_shift), reg_io_width(reg_io_width), backoff_counter(0)
{
ier = 0;
iir = UART_IIR_NO_INT;
@@ -300,11 +300,19 @@ void ns16550_t::tick(void)
return;
}
+ if (backoff_counter > 0 && backoff_counter < MAX_BACKOFF) {
+ backoff_counter++;
+ return;
+ }
+
int rc = canonical_terminal_t::read();
if (rc < 0) {
+ backoff_counter = 1;
return;
}
+ backoff_counter = 0;
+
rx_queue.push((uint8_t)rc);
lsr |= UART_LSR_DR;
update_interrupt();