diff options
Diffstat (limited to 'sim/bfin/dv-bfin_uart.c')
-rw-r--r-- | sim/bfin/dv-bfin_uart.c | 52 |
1 files changed, 33 insertions, 19 deletions
diff --git a/sim/bfin/dv-bfin_uart.c b/sim/bfin/dv-bfin_uart.c index f05ee15..697fa96 100644 --- a/sim/bfin/dv-bfin_uart.c +++ b/sim/bfin/dv-bfin_uart.c @@ -117,10 +117,21 @@ bfin_uart_reschedule (struct hw *me) } bu16 -bfin_uart_write_byte (struct hw *me, bu16 thr) +bfin_uart_write_byte (struct hw *me, bu16 thr, bu16 mcr) { + struct bfin_uart *uart = hw_data (me); unsigned char ch = thr; + + if (mcr & LOOP_ENA) + { + /* XXX: This probably doesn't work exactly right with + external FIFOs ... */ + uart->saved_byte = thr; + uart->saved_count = 1; + } + bfin_uart_write_buffer (me, &ch, 1); + return thr; } @@ -149,7 +160,7 @@ bfin_uart_io_write_buffer (struct hw *me, const void *source, uart->dll = value; else { - uart->thr = bfin_uart_write_byte (me, value); + uart->thr = bfin_uart_write_byte (me, value, uart->mcr); if (uart->ier & ETBEI) hw_port_event (me, DV_PORT_TX, 1); @@ -184,7 +195,7 @@ bfin_uart_io_write_buffer (struct hw *me, const void *source, /* Switch between socket and stdin on the fly. */ bu16 -bfin_uart_get_next_byte (struct hw *me, bu16 rbr, bool *fresh) +bfin_uart_get_next_byte (struct hw *me, bu16 rbr, bu16 mcr, bool *fresh) { SIM_DESC sd = hw_system (me); struct bfin_uart *uart = hw_data (me); @@ -197,23 +208,26 @@ bfin_uart_get_next_byte (struct hw *me, bu16 rbr, bool *fresh) fresh = &_fresh; *fresh = false; - if (status & DV_SOCKSER_DISCONNECTED) + + if (uart->saved_count > 0) + { + *fresh = true; + rbr = uart->saved_byte; + --uart->saved_count; + } + else if (mcr & LOOP_ENA) + { + /* RX is disconnected, so only return local data. */ + } + else if (status & DV_SOCKSER_DISCONNECTED) { - if (uart->saved_count > 0) + char byte; + int ret = sim_io_poll_read (sd, 0/*STDIN*/, &byte, 1); + + if (ret > 0) { *fresh = true; - rbr = uart->saved_byte; - --uart->saved_count; - } - else - { - char byte; - int ret = sim_io_poll_read (sd, 0/*STDIN*/, &byte, 1); - if (ret > 0) - { - *fresh = true; - rbr = byte; - } + rbr = byte; } } else @@ -239,7 +253,7 @@ bfin_uart_get_status (struct hw *me) } else lsr |= (status & DV_SOCKSER_INPUT_EMPTY ? 0 : DR) | - (status & DV_SOCKSER_OUTPUT_EMPTY ? TEMT | THRE : 0); + (status & DV_SOCKSER_OUTPUT_EMPTY ? TEMT | THRE : 0); return lsr; } @@ -266,7 +280,7 @@ bfin_uart_io_read_buffer (struct hw *me, void *dest, dv_store_2 (dest, uart->dll); else { - uart->rbr = bfin_uart_get_next_byte (me, uart->rbr, NULL); + uart->rbr = bfin_uart_get_next_byte (me, uart->rbr, uart->mcr, NULL); dv_store_2 (dest, uart->rbr); } break; |