aboutsummaryrefslogtreecommitdiff
path: root/gdb/rdi-share/tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/rdi-share/tx.c')
-rw-r--r--gdb/rdi-share/tx.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/gdb/rdi-share/tx.c b/gdb/rdi-share/tx.c
new file mode 100644
index 0000000..a52286c
--- /dev/null
+++ b/gdb/rdi-share/tx.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
+ *
+ * This software may be freely used, copied, modified, and distributed
+ * provided that the above copyright notice is preserved in all copies of the
+ * software.
+ */
+
+/*-*-C-*-
+ *
+ * $Revision$
+ * $Date$
+ *
+ * Project: ANGEL
+ *
+ * Title: Character based packet transmission engine
+ */
+
+#include <stdarg.h> /* ANSI varargs support */
+#include "angel.h" /* Angel system definitions */
+#include "endian.h" /* Endian independant memory access macros */
+#include "crc.h" /* crc generation definitions and headers */
+#include "rxtx.h"
+#include "channels.h"
+#include "buffers.h"
+#include "logging.h"
+
+/* definitions to describe the engines state */
+#define N_STX 0x0 /* first 2 bits for N_ */
+#define N_BODY 0x1
+#define N_ETX 0x2
+#define N_IDLE 0x3
+#define N_MASK 0x3 /* mask for the Encapsulator state */
+
+#define E_PLAIN (0x0 << 2) /* 3rd bit for E_ */
+#define E_ESC (0x1 << 2) /* 3rd bit for E_ */
+#define E_MASK (0x1 << 2) /* mask for the Escaper state */
+
+#define F_HEAD (0x0 << 3) /* 4th and 5th bits for F_ */
+#define F_DATA (0x1 << 3)
+#define F_CRC (0x1 << 4)
+#define F_MASK (0x3 << 3) /* mask for the Escaper state */
+
+static unsigned char escape(unsigned char ch_in, struct te_state *txstate);
+
+void Angel_TxEngineInit(const struct re_config *txconfig,
+ const struct data_packet *packet,
+ struct te_state *txstate){
+ IGNORE(packet);
+ txstate->tx_state = N_STX | E_PLAIN | F_HEAD;
+ txstate->field_c = 0;
+ txstate->encoded = 0;
+ txstate->config = txconfig;
+ txstate->crc = 0;
+}
+
+te_status Angel_TxEngine(const struct data_packet *packet,
+ struct te_state *txstate,
+ unsigned char *tx_ch){
+ /* TODO: gaurd on long/bad packets */
+ /*
+ * encapsulate the packet, framing has been moved from a seperate
+ * function into the encapsulation routine as it needed too much
+ * inherited state for it to be sensibly located elsewhere
+ */
+ switch ((txstate->tx_state) & N_MASK){
+ case N_STX:
+#ifdef DO_TRACE
+ __rt_trace("txe-stx ");
+#endif
+ txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_BODY;
+ *tx_ch = txstate->config->stx;
+ txstate->field_c = 3; /* set up for the header */
+ txstate->crc = startCRC32; /* set up basic crc */
+ return TS_IN_PKT;
+ case N_BODY:{
+ switch (txstate->tx_state & F_MASK) {
+ case F_HEAD:
+#ifdef DO_TRACE
+ __rt_trace("txe-head ");
+#endif
+ if (txstate->field_c == 3) {
+ /* send type */
+ *tx_ch = escape(packet->type, txstate);
+ return TS_IN_PKT;
+ }
+ else {
+ *tx_ch = escape((packet->len >> (txstate->field_c - 1) * 8) & 0xff,
+ txstate);
+ if (txstate->field_c == 0) {
+ /* move on to the next state */
+ txstate->tx_state = (txstate->tx_state & ~F_MASK) | F_DATA;
+ txstate->field_c = packet->len;
+ }
+ return TS_IN_PKT;
+ }
+ case F_DATA:
+#ifdef DO_TRACE
+ __rt_trace("txe-data ");
+#endif
+ *tx_ch = escape(packet->data[packet->len - txstate->field_c], txstate);
+ if (txstate->field_c == 0) {
+ /* move on to the next state */
+ txstate->tx_state = (txstate->tx_state & ~F_MASK) | F_CRC;
+ txstate->field_c = 4;
+ }
+ return TS_IN_PKT;
+ case F_CRC:
+#ifdef DO_TRACE
+ __rt_trace("txe-crc ");
+#endif
+ *tx_ch = escape((txstate->crc >> ((txstate->field_c - 1) * 8)) & 0xff,
+ txstate);
+
+ if (txstate->field_c == 0) {
+#ifdef DO_TRACE
+ __rt_trace("txe crc = 0x%x\n", txstate->crc);
+#endif
+ /* move on to the next state */
+ txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_ETX;
+ }
+ return TS_IN_PKT;
+ }
+ }
+ case N_ETX:
+#ifdef DO_TRACE
+ __rt_trace("txe-etx\n");
+#endif
+ txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_IDLE;
+ *tx_ch = txstate->config->etx;
+ return TS_DONE_PKT;
+ default:
+#ifdef DEBUG
+ __rt_info("tx default\n");
+#endif
+ txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_IDLE;
+ return TS_IDLE;
+ }
+ /* stop a silly -Wall warning */
+ return (te_status)-1;
+}
+
+/*
+ * crc generation occurs in the escape function because it is the only
+ * place where we know that we're putting a real char into the buffer
+ * rather than an escaped one.
+ * We must be careful here not to update the crc when we're sending it
+ */
+static unsigned char escape(unsigned char ch_in, struct te_state *txstate) {
+ if (((txstate->tx_state) & E_MASK) == E_ESC) {
+ /* char has been escaped so send the real char */
+#ifdef DO_TRACE
+ __rt_trace("txe-echar ");
+#endif
+ txstate->tx_state = (txstate->tx_state & ~E_MASK) | E_PLAIN;
+ txstate->field_c--;
+ if ((txstate->tx_state & F_MASK) != F_CRC)
+ txstate->crc = crc32( &ch_in, 1, txstate->crc);
+ return ch_in | serial_ESCAPE;
+ }
+ if ((ch_in < 32) && ((txstate->config->esc_set & (1 << ch_in)) != 0)) {
+ /* char needs escaping */
+#ifdef DO_TRACE
+ __rt_trace("txe-esc ");
+#endif
+ txstate->tx_state = (txstate->tx_state & ~E_MASK) | E_ESC;
+ return txstate->config->esc;
+ }
+ /* must be a char that can be sent plain */
+ txstate->field_c--;
+ if ((txstate->tx_state & F_MASK) != F_CRC)
+ txstate->crc = crc32(&ch_in, 1, txstate->crc);
+ return ch_in;
+}
+
+/* EOF tx.c */