* Contribute CGEN simulator build support code.
[binutils-gdb.git] / gdb / rdi-share / rx.c
blobcaf833ad24b1cbc27852c865400f247bd67edeea
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 */
9 /*-*-C-*-
11 * $Revision$
12 * $Date$
15 * Project: ANGEL
17 * Title: Character reception engine
20 #include <stdarg.h> /* ANSI varargs support */
21 #include "angel.h" /* Angel system definitions */
22 #include "angel_endian.h" /* Endian independant memory access macros */
23 #include "crc.h" /* crc generation definitions and headers */
24 #include "rxtx.h"
25 #include "channels.h"
26 #include "buffers.h"
27 #ifdef TARGET
28 # include "devdriv.h"
29 #endif
30 #include "logging.h"
32 static re_status unexp_stx(struct re_state *rxstate);
33 static re_status unexp_etx(struct re_state *rxstate);
35 /* bitfield for the rx_engine state */
36 typedef enum rx_state_flag{
37 RST_STX,
38 RST_TYP,
39 RST_LEN,
40 RST_DAT,
41 RST_CRC,
42 RST_ETX,
43 RST_ESC = (0x1 << 0x3)
44 } rx_state_flag;
46 void Angel_RxEngineInit(const struct re_config *rxconfig,
47 struct re_state *rxstate)
49 rxstate->rx_state = RST_STX;
50 rxstate->field_c = 0;
51 rxstate->index = 0;
52 rxstate->crc = 0;
53 rxstate->error = RE_OKAY;
54 rxstate->config = rxconfig;
57 re_status Angel_RxEngine(unsigned char new_ch, struct data_packet *packet,
58 struct re_state *rxstate)
61 * TODO: add the flow control bits in
62 * Note: We test for the data field in a seperate case so we can
63 * completely avoid entering the switch for most chars
66 /* see if we're expecting a escaped char */
67 if ((rxstate->rx_state & RST_ESC) == RST_ESC)
69 /* unescape the char and unset the flag*/
70 new_ch &= ~serial_ESCAPE;
71 #ifdef DO_TRACE
72 __rt_trace("rxe-echar-%2x ", new_ch);
73 #endif
74 rxstate->rx_state &= ~RST_ESC;
76 else if ( (1 << new_ch) & rxstate->config->esc_set )
78 /* see if the incoming char is a special one */
79 if (new_ch == rxstate->config->esc)
81 #ifdef DO_TRACE
82 __rt_trace("rxe-esc ");
83 #endif
84 rxstate->rx_state |= RST_ESC;
85 return RS_IN_PKT;
87 else
90 * must be a normal packet so do some unexpected etx/stx checking
91 * we haven't been told to escape or received an escape so unless
92 * we are expecting an stx or etx then we can take the unexpected
93 * stx/etx trap
95 if ((new_ch == (rxstate->config->stx)) && (rxstate->rx_state != RST_STX))
96 return unexp_stx(rxstate);
97 if ((new_ch == (rxstate->config->etx)) && (rxstate->rx_state != RST_ETX))
98 return unexp_etx(rxstate);
102 if (rxstate->rx_state == RST_DAT)
105 * do this to speed up the common case, no real penalty for
106 * other cases
108 #ifdef DO_TRACE
109 __rt_trace("rxe-dat ");
110 #endif
112 rxstate->crc = crc32(&new_ch, 1, rxstate->crc);
113 (packet->data)[rxstate->index++] = (unsigned int)new_ch & 0xff;
115 if (rxstate->index == packet->len)
116 rxstate->rx_state = RST_CRC;
118 return RS_IN_PKT;
122 * Now that the common case is out of the way we can test for everything
123 * else without worrying quite so much about the speed, changing the
124 * order to len,crc,stx,etx,typ might gain a tiny bit of speed but lets
125 * leave that for the moment
127 switch (rxstate->rx_state)
129 case RST_STX:
130 if (new_ch == rxstate->config->stx)
132 rxstate->rx_state = RST_TYP;
133 rxstate->error = RE_OKAY;
134 rxstate->crc = startCRC32;
135 rxstate->index = 0;
136 return RS_IN_PKT;
138 else
140 rxstate->error = RE_OKAY;
141 return RS_WAIT_PKT;
144 case RST_TYP:
145 packet->type = (DevChanID)new_ch;
146 rxstate->rx_state = RST_LEN;
147 rxstate->error = RE_OKAY;
148 rxstate->field_c = 0; /* set up here for the length that follows */
149 #ifdef DO_TRACE
150 __rt_trace("rxe-type-%2x ", packet->type);
151 #endif
152 rxstate->crc = crc32(&new_ch, 1, rxstate->crc);
154 return RS_IN_PKT;
156 case RST_LEN:
157 rxstate->crc = crc32(&new_ch, 1, rxstate->crc);
159 if (rxstate->field_c++ == 0)
161 /* first length byte */
162 packet->len = ((unsigned int)new_ch) << 8;
163 return RS_IN_PKT;
165 else
167 /* got the whole legth */
168 packet->len |= new_ch;
169 #ifdef DO_TRACE
170 __rt_trace("rxe-len-%4x\n", packet->len);
171 #endif
173 /* check that the length is ok */
174 if (packet->len == 0)
176 /* empty pkt */
177 rxstate->field_c = 0;
178 rxstate->rx_state = RST_CRC;
179 return RS_IN_PKT;
181 else
183 if (packet->data == NULL)
185 /* need to alloc the data buffer */
186 if (!rxstate->config->ba_callback(
187 packet, rxstate->config->ba_data)) {
188 rxstate->rx_state = RST_STX;
189 rxstate->error = RE_INTERNAL;
190 return RS_BAD_PKT;
194 if (packet->len > packet->buf_len)
196 /* pkt bigger than buffer */
197 rxstate->field_c = 0;
198 rxstate->rx_state = RST_STX;
199 rxstate->error = RE_LEN;
200 return RS_BAD_PKT;
202 else
204 /* packet ok */
205 rxstate->field_c = 0;
206 rxstate->rx_state = RST_DAT;
207 return RS_IN_PKT;
212 case RST_DAT:
213 /* dummy case (dealt with earlier) */
214 #ifdef ASSERTIONS_ENABLED
215 __rt_warning("ERROR: hit RST_dat in switch\n");
216 #endif
217 rxstate->rx_state = RST_STX;
218 rxstate->error = RE_INTERNAL;
219 return RS_BAD_PKT;
221 case RST_CRC:
222 if (rxstate->field_c == 0)
223 packet->crc = 0;
225 packet->crc |= (new_ch & 0xFF) << ((3 - rxstate->field_c) * 8);
226 rxstate->field_c++;
228 if (rxstate->field_c == 4)
230 /* last crc field */
231 rxstate->field_c = 0;
232 rxstate->rx_state = RST_ETX;
233 #ifdef DO_TRACE
234 __rt_trace("rxe-rcrc-%8x ", packet->crc);
235 #endif
238 return RS_IN_PKT;
240 case RST_ETX:
241 if (new_ch == rxstate->config->etx)
243 #if defined(DEBUG) && !defined(NO_PKT_DATA)
245 int c;
246 # ifdef DO_TRACE
247 __rt_trace("\n");
248 # endif
249 __rt_info("RXE Data =");
250 for (c=0; c < packet->len; c++)
251 __rt_info("%02x", packet->data[c]);
252 __rt_info("\n");
254 #endif
256 /* check crc */
257 if (rxstate->crc == packet->crc)
259 /* crc ok */
260 rxstate->rx_state = RST_STX;
261 rxstate->field_c = 0;
262 return RS_GOOD_PKT;
264 else
266 #ifdef ASSERTIONS_ENABLED
267 __rt_warning("Bad crc, rx calculates it should be 0x%x\n", rxstate->crc);
268 #endif
269 rxstate->rx_state = RST_STX;
270 rxstate->error = RE_CRC;
271 return RS_BAD_PKT;
274 else if (new_ch == rxstate->config->stx)
275 return unexp_stx(rxstate);
276 else
278 rxstate->rx_state = RST_STX;
279 rxstate->error = RE_NETX;
280 return RS_BAD_PKT;
283 default:
284 #ifdef ASSERTIONS_ENABLED
285 __rt_warning("ERROR fell through rxengine\n");
286 #endif
287 rxstate->rx_state = RST_STX;
288 rxstate->error = RE_INTERNAL;
289 return RS_BAD_PKT;
293 static re_status unexp_stx(struct re_state *rxstate)
295 #ifdef ASSERTIONS_ENABLED
296 __rt_warning("Unexpected stx\n");
297 #endif
298 rxstate->crc = startCRC32;
299 rxstate->index = 0;
300 rxstate->rx_state = RST_TYP;
301 rxstate->error = RE_U_STX;
302 rxstate->field_c = 0;
303 return RS_BAD_PKT;
306 static re_status unexp_etx(struct re_state *rxstate)
308 #ifdef ASSERTIONS_ENABLED
309 __rt_warning("Unexpected etx, rxstate: index= 0x%2x, field_c=0x%2x, state=0x%2x\n", rxstate->index, rxstate->field_c, rxstate->rx_state);
310 #endif
311 rxstate->crc = 0;
312 rxstate->index = 0;
313 rxstate->rx_state = RST_STX;
314 rxstate->error = RE_U_ETX;
315 rxstate->field_c = 0;
316 return RS_BAD_PKT;
320 * This can be used as the buffer allocation callback for the rx engine,
321 * and makes use of angel_DD_GetBuffer() [in devdrv.h].
323 * Saves duplicating this callback function in every device driver that
324 * uses the rx engine.
326 * Note that this REQUIRES that the device id is installed as ba_data
327 * in the rx engine config structure for the driver.
329 bool angel_DD_RxEng_BufferAlloc( struct data_packet *packet, void *cb_data )
331 #ifdef TARGET
332 DeviceID devid = (DeviceID)cb_data;
333 #else
334 IGNORE(cb_data);
335 #endif
337 if ( packet->type < DC_NUM_CHANNELS )
339 /* request a buffer down from the channels layer */
340 #ifdef TARGET
341 packet->data = angel_DD_GetBuffer( devid, packet->type,
342 packet->len );
343 #else
344 packet->data = malloc(packet->len);
345 #endif
346 if ( packet->data == NULL )
347 return FALSE;
348 else
350 packet->buf_len = packet->len;
351 return TRUE;
354 else
356 /* bad type field */
357 return FALSE;
361 /* EOF rx.c */