This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] 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.

Committed.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>

2011-05-14  Mike Frysinger  <vapier@gentoo.org>

	* dv-bfin_uart.c (bfin_uart_write_byte): Add a mcr arg.  Declare a
	local uart.  When LOOP_ENA is set in mcr, write to the saved byte
	and count fields of the uart.
	(bfin_uart_io_write_buffer): Pass uart->mcr to bfin_uart_write_byte
	and bfin_uart_get_next_byte.
	(bfin_uart_get_next_byte): Add a mcr arg.  Move uart->saved_count
	check first, and skip the remaining code when LOOP_ENA is set in mcr.
	* dv-bfin_uart.h (bfin_uart_write_byte): Add an mcr argument.
	(bfin_uart_get_next_byte): Likewise.
	(XOFF, MRTS, RFIT, RFRT, LOOP_ENA, FCPOL, ARTS, ACTS): Define.
	* dv-bfin_uart2.c (bfin_uart_io_write_buffer): Padd uart->mcr when
	calling bfin_uart_write_byte and bfin_uart_get_next_byte.
---
 sim/bfin/dv-bfin_uart.c  |   52 +++++++++++++++++++++++++++++----------------
 sim/bfin/dv-bfin_uart.h  |   14 ++++++++++-
 sim/bfin/dv-bfin_uart2.c |    4 +-
 3 files changed, 47 insertions(+), 23 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;
diff --git a/sim/bfin/dv-bfin_uart.h b/sim/bfin/dv-bfin_uart.h
index ccb7af4..52074f6 100644
--- a/sim/bfin/dv-bfin_uart.h
+++ b/sim/bfin/dv-bfin_uart.h
@@ -26,8 +26,8 @@
 #define BFIN_MMR_UART_SIZE	0x30
 
 struct bfin_uart;
-bu16 bfin_uart_get_next_byte (struct hw *, bu16, bool *fresh);
-bu16 bfin_uart_write_byte (struct hw *, bu16);
+bu16 bfin_uart_get_next_byte (struct hw *, bu16, bu16, bool *fresh);
+bu16 bfin_uart_write_byte (struct hw *, bu16, bu16);
 bu16 bfin_uart_get_status (struct hw *);
 unsigned bfin_uart_write_buffer (struct hw *, const unsigned char *, unsigned);
 unsigned bfin_uart_read_buffer (struct hw *, unsigned char *, unsigned);
@@ -51,4 +51,14 @@ void bfin_uart_reschedule (struct hw *);
 #define ETBEI	(1 << 1)
 #define ELSI	(1 << 2)
 
+/* UART_MCR */
+#define XOFF		(1 << 0)
+#define MRTS		(1 << 1)
+#define RFIT		(1 << 2)
+#define RFRT		(1 << 3)
+#define LOOP_ENA	(1 << 4)
+#define FCPOL		(1 << 5)
+#define ARTS		(1 << 6)
+#define ACTS		(1 << 7)
+
 #endif
diff --git a/sim/bfin/dv-bfin_uart2.c b/sim/bfin/dv-bfin_uart2.c
index 179574d..16ede50 100644
--- a/sim/bfin/dv-bfin_uart2.c
+++ b/sim/bfin/dv-bfin_uart2.c
@@ -89,7 +89,7 @@ bfin_uart_io_write_buffer (struct hw *me, const void *source,
   switch (mmr_off)
     {
     case mmr_offset(thr):
-      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);
       break;
@@ -142,7 +142,7 @@ bfin_uart_io_read_buffer (struct hw *me, void *dest,
   switch (mmr_off)
     {
     case mmr_offset(rbr):
-      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;
     case mmr_offset(ier_set):
-- 
1.7.5.rc3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]