Commit | Line | Data |
---|---|---|
3a9c3d12 NC |
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$ | |
12 | * $Date$ | |
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 "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 */ |