1 /* 2 * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved. 3 * 4 * This software may be freely used, copied, modified, and distributed 5 * provided that the above copyright notice is preserved in all copies of the 6 * software. 7 */ 8 9 /*-*-C-*- 10 * 11 * $Revision: 1.3 $ 12 * $Date: 2004/12/27 14:00:54 $ 13 * 14 * Project: ANGEL 15 * 16 * Title: Character based packet transmission engine 17 */ 18 19 #include <stdarg.h> /* ANSI varargs support */ 20 #include "angel.h" /* Angel system definitions */ 21 #include "angel_endian.h" /* Endian independant memory access macros */ 22 #include "crc.h" /* crc generation definitions and headers */ 23 #include "rxtx.h" 24 #include "channels.h" 25 #include "buffers.h" 26 #include "logging.h" 27 28 /* definitions to describe the engines state */ 29 #define N_STX 0x0 /* first 2 bits for N_ */ 30 #define N_BODY 0x1 31 #define N_ETX 0x2 32 #define N_IDLE 0x3 33 #define N_MASK 0x3 /* mask for the Encapsulator state */ 34 35 #define E_PLAIN (0x0 << 2) /* 3rd bit for E_ */ 36 #define E_ESC (0x1 << 2) /* 3rd bit for E_ */ 37 #define E_MASK (0x1 << 2) /* mask for the Escaper state */ 38 39 #define F_HEAD (0x0 << 3) /* 4th and 5th bits for F_ */ 40 #define F_DATA (0x1 << 3) 41 #define F_CRC (0x1 << 4) 42 #define F_MASK (0x3 << 3) /* mask for the Escaper state */ 43 44 static unsigned char escape(unsigned char ch_in, struct te_state *txstate); 45 46 void Angel_TxEngineInit(const struct re_config *txconfig, 47 const struct data_packet *packet, 48 struct te_state *txstate){ 49 IGNORE(packet); 50 txstate->tx_state = N_STX | E_PLAIN | F_HEAD; 51 txstate->field_c = 0; 52 txstate->encoded = 0; 53 txstate->config = txconfig; 54 txstate->crc = 0; 55 } 56 57 te_status Angel_TxEngine(const struct data_packet *packet, 58 struct te_state *txstate, 59 unsigned char *tx_ch){ 60 /* TODO: gaurd on long/bad packets */ 61 /* 62 * encapsulate the packet, framing has been moved from a seperate 63 * function into the encapsulation routine as it needed too much 64 * inherited state for it to be sensibly located elsewhere 65 */ 66 switch ((txstate->tx_state) & N_MASK){ 67 case N_STX: 68 #ifdef DO_TRACE 69 __rt_trace("txe-stx "); 70 #endif 71 txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_BODY; 72 *tx_ch = txstate->config->stx; 73 txstate->field_c = 3; /* set up for the header */ 74 txstate->crc = startCRC32; /* set up basic crc */ 75 return TS_IN_PKT; 76 case N_BODY:{ 77 switch (txstate->tx_state & F_MASK) { 78 case F_HEAD: 79 #ifdef DO_TRACE 80 __rt_trace("txe-head "); 81 #endif 82 if (txstate->field_c == 3) { 83 /* send type */ 84 *tx_ch = escape(packet->type, txstate); 85 return TS_IN_PKT; 86 } 87 else { 88 *tx_ch = escape((packet->len >> (txstate->field_c - 1) * 8) & 0xff, 89 txstate); 90 if (txstate->field_c == 0) { 91 /* move on to the next state */ 92 txstate->tx_state = (txstate->tx_state & ~F_MASK) | F_DATA; 93 txstate->field_c = packet->len; 94 } 95 return TS_IN_PKT; 96 } 97 case F_DATA: 98 #ifdef DO_TRACE 99 __rt_trace("txe-data "); 100 #endif 101 *tx_ch = escape(packet->data[packet->len - txstate->field_c], txstate); 102 if (txstate->field_c == 0) { 103 /* move on to the next state */ 104 txstate->tx_state = (txstate->tx_state & ~F_MASK) | F_CRC; 105 txstate->field_c = 4; 106 } 107 return TS_IN_PKT; 108 case F_CRC: 109 #ifdef DO_TRACE 110 __rt_trace("txe-crc "); 111 #endif 112 *tx_ch = escape((txstate->crc >> ((txstate->field_c - 1) * 8)) & 0xff, 113 txstate); 114 115 if (txstate->field_c == 0) { 116 #ifdef DO_TRACE 117 __rt_trace("txe crc = 0x%x\n", txstate->crc); 118 #endif 119 /* move on to the next state */ 120 txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_ETX; 121 } 122 return TS_IN_PKT; 123 } 124 } 125 case N_ETX: 126 #ifdef DO_TRACE 127 __rt_trace("txe-etx\n"); 128 #endif 129 txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_IDLE; 130 *tx_ch = txstate->config->etx; 131 return TS_DONE_PKT; 132 default: 133 #ifdef DEBUG 134 __rt_info("tx default\n"); 135 #endif 136 txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_IDLE; 137 return TS_IDLE; 138 } 139 /* stop a silly -Wall warning */ 140 return (te_status)-1; 141 } 142 143 /* 144 * crc generation occurs in the escape function because it is the only 145 * place where we know that we're putting a real char into the buffer 146 * rather than an escaped one. 147 * We must be careful here not to update the crc when we're sending it 148 */ 149 static unsigned char escape(unsigned char ch_in, struct te_state *txstate) { 150 if (((txstate->tx_state) & E_MASK) == E_ESC) { 151 /* char has been escaped so send the real char */ 152 #ifdef DO_TRACE 153 __rt_trace("txe-echar "); 154 #endif 155 txstate->tx_state = (txstate->tx_state & ~E_MASK) | E_PLAIN; 156 txstate->field_c--; 157 if ((txstate->tx_state & F_MASK) != F_CRC) 158 txstate->crc = crc32( &ch_in, 1, txstate->crc); 159 return ch_in | serial_ESCAPE; 160 } 161 if ((ch_in < 32) && ((txstate->config->esc_set & (1 << ch_in)) != 0)) { 162 /* char needs escaping */ 163 #ifdef DO_TRACE 164 __rt_trace("txe-esc "); 165 #endif 166 txstate->tx_state = (txstate->tx_state & ~E_MASK) | E_ESC; 167 return txstate->config->esc; 168 } 169 /* must be a char that can be sent plain */ 170 txstate->field_c--; 171 if ((txstate->tx_state & F_MASK) != F_CRC) 172 txstate->crc = crc32(&ch_in, 1, txstate->crc); 173 return ch_in; 174 } 175 176 /* EOF tx.c */ 177