1 |
106 |
markom |
/*
|
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.1.1.1 $
|
12 |
|
|
* $Date: 2001-05-18 11:16:46 $
|
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 */
|