diff options
Diffstat (limited to 'gdb/rdi-share/tx.c')
-rw-r--r-- | gdb/rdi-share/tx.c | 176 |
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 */ |