diff options
author | Mike Frysinger <vapier@gentoo.org> | 2011-05-14 15:59:09 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2011-05-14 15:59:09 +0000 |
commit | 28fe96b798c2b0a7abd07b2631f6d4abeaf9d4dd (patch) | |
tree | b36e50567ba4c3b69bd47cea4479e37b2d394d35 /sim/bfin/dv-bfin_uart.c | |
parent | ba4a8bdd81e55d45b97cdf9b91eb111a7ac0d3f9 (diff) | |
download | fsf-binutils-gdb-28fe96b798c2b0a7abd07b2631f6d4abeaf9d4dd.zip fsf-binutils-gdb-28fe96b798c2b0a7abd07b2631f6d4abeaf9d4dd.tar.gz fsf-binutils-gdb-28fe96b798c2b0a7abd07b2631f6d4abeaf9d4dd.tar.bz2 |
sim: bfin: implement loop back support in the UARTs
The UART has a LOOP_ENA bit in its MCR register where writes to the THR
go to the RBR. Implement support for this mode.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
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; |