xref: /openbsd-src/gnu/usr.bin/binutils/gdb/rdi-share/rx.c (revision 63addd46c1e40ca0f49488ddcdc4ab598023b0c1)
1b725ae77Skettenis /*
2b725ae77Skettenis  * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
3b725ae77Skettenis  *
4b725ae77Skettenis  * This software may be freely used, copied, modified, and distributed
5b725ae77Skettenis  * provided that the above copyright notice is preserved in all copies of the
6b725ae77Skettenis  * software.
7b725ae77Skettenis  */
8b725ae77Skettenis 
9b725ae77Skettenis /*-*-C-*-
10b725ae77Skettenis  *
11*63addd46Skettenis  * $Revision: 1.3 $
12*63addd46Skettenis  *     $Date: 2004/12/27 14:00:54 $
13b725ae77Skettenis  *
14b725ae77Skettenis  *
15b725ae77Skettenis  *   Project: ANGEL
16b725ae77Skettenis  *
17b725ae77Skettenis  *     Title:  Character reception engine
18b725ae77Skettenis  */
19b725ae77Skettenis 
20b725ae77Skettenis #include <stdarg.h>    /* ANSI varargs support */
21b725ae77Skettenis #include "angel.h"     /* Angel system definitions */
22b725ae77Skettenis #include "angel_endian.h"    /* Endian independant memory access macros */
23b725ae77Skettenis #include "crc.h"       /* crc generation definitions and headers */
24b725ae77Skettenis #include "rxtx.h"
25b725ae77Skettenis #include "channels.h"
26b725ae77Skettenis #include "buffers.h"
27b725ae77Skettenis #ifdef TARGET
28b725ae77Skettenis #  include "devdriv.h"
29b725ae77Skettenis #endif
30b725ae77Skettenis #include "logging.h"
31b725ae77Skettenis 
32b725ae77Skettenis static re_status unexp_stx(struct re_state *rxstate);
33b725ae77Skettenis static re_status unexp_etx(struct re_state *rxstate);
34b725ae77Skettenis 
35b725ae77Skettenis /* bitfield for the rx_engine state */
36b725ae77Skettenis typedef enum rx_state_flag{
37b725ae77Skettenis   RST_STX,
38b725ae77Skettenis   RST_TYP,
39b725ae77Skettenis   RST_LEN,
40b725ae77Skettenis   RST_DAT,
41b725ae77Skettenis   RST_CRC,
42b725ae77Skettenis   RST_ETX,
43b725ae77Skettenis   RST_ESC = (0x1 << 0x3)
44b725ae77Skettenis } rx_state_flag;
45b725ae77Skettenis 
Angel_RxEngineInit(const struct re_config * rxconfig,struct re_state * rxstate)46b725ae77Skettenis void Angel_RxEngineInit(const struct re_config *rxconfig,
47b725ae77Skettenis                         struct re_state *rxstate)
48b725ae77Skettenis {
49b725ae77Skettenis   rxstate->rx_state = RST_STX;
50b725ae77Skettenis   rxstate->field_c = 0;
51b725ae77Skettenis   rxstate->index = 0;
52b725ae77Skettenis   rxstate->crc = 0;
53b725ae77Skettenis   rxstate->error = RE_OKAY;
54b725ae77Skettenis   rxstate->config = rxconfig;
55b725ae77Skettenis }
56b725ae77Skettenis 
Angel_RxEngine(unsigned char new_ch,struct data_packet * packet,struct re_state * rxstate)57b725ae77Skettenis re_status Angel_RxEngine(unsigned char new_ch, struct data_packet *packet,
58b725ae77Skettenis                          struct re_state *rxstate)
59b725ae77Skettenis {
60b725ae77Skettenis   /*
61b725ae77Skettenis    * TODO: add the flow control bits in
62b725ae77Skettenis    * Note: We test for the data field in a seperate case so we can
63b725ae77Skettenis    * completely avoid entering the switch for most chars
64b725ae77Skettenis    */
65b725ae77Skettenis 
66b725ae77Skettenis   /* see if we're expecting a escaped char */
67b725ae77Skettenis   if ((rxstate->rx_state & RST_ESC) == RST_ESC)
68b725ae77Skettenis   {
69b725ae77Skettenis     /* unescape the char and unset the flag*/
70b725ae77Skettenis     new_ch &= ~serial_ESCAPE;
71b725ae77Skettenis #ifdef DO_TRACE
72b725ae77Skettenis     __rt_trace("rxe-echar-%2x ", new_ch);
73b725ae77Skettenis #endif
74b725ae77Skettenis     rxstate->rx_state &= ~RST_ESC;
75b725ae77Skettenis   }
76b725ae77Skettenis   else if ( (1 << new_ch) & rxstate->config->esc_set )
77b725ae77Skettenis   {
78b725ae77Skettenis     /* see if the incoming char is a special one */
79b725ae77Skettenis     if (new_ch == rxstate->config->esc)
80b725ae77Skettenis     {
81b725ae77Skettenis #ifdef DO_TRACE
82b725ae77Skettenis       __rt_trace("rxe-esc ");
83b725ae77Skettenis #endif
84b725ae77Skettenis       rxstate->rx_state |= RST_ESC;
85b725ae77Skettenis       return RS_IN_PKT;
86b725ae77Skettenis     }
87b725ae77Skettenis     else
88b725ae77Skettenis     {
89b725ae77Skettenis       /*
90b725ae77Skettenis        * must be a normal packet so do some unexpected etx/stx checking
91b725ae77Skettenis        * we haven't been told to escape or received an escape so unless
92b725ae77Skettenis        * we are expecting an stx or etx then we can take the unexpected
93b725ae77Skettenis        * stx/etx trap
94b725ae77Skettenis        */
95b725ae77Skettenis       if ((new_ch == (rxstate->config->stx)) && (rxstate->rx_state != RST_STX))
96b725ae77Skettenis         return unexp_stx(rxstate);
97b725ae77Skettenis       if ((new_ch == (rxstate->config->etx)) && (rxstate->rx_state != RST_ETX))
98b725ae77Skettenis         return unexp_etx(rxstate);
99b725ae77Skettenis     }
100b725ae77Skettenis   }
101b725ae77Skettenis 
102b725ae77Skettenis   if (rxstate->rx_state == RST_DAT)
103b725ae77Skettenis   {
104b725ae77Skettenis     /*
105b725ae77Skettenis      * do this to speed up the common case, no real penalty for
106b725ae77Skettenis      * other cases
107b725ae77Skettenis      */
108b725ae77Skettenis #ifdef DO_TRACE
109b725ae77Skettenis     __rt_trace("rxe-dat ");
110b725ae77Skettenis #endif
111b725ae77Skettenis 
112b725ae77Skettenis     rxstate->crc = crc32(&new_ch, 1, rxstate->crc);
113b725ae77Skettenis     (packet->data)[rxstate->index++] = (unsigned int)new_ch & 0xff;
114b725ae77Skettenis 
115b725ae77Skettenis     if (rxstate->index == packet->len)
116b725ae77Skettenis       rxstate->rx_state = RST_CRC;
117b725ae77Skettenis 
118b725ae77Skettenis     return RS_IN_PKT;
119b725ae77Skettenis   }
120b725ae77Skettenis 
121b725ae77Skettenis   /*
122b725ae77Skettenis    * Now that the common case is out of the way we can test for everything
123b725ae77Skettenis    * else without worrying quite so much about the speed, changing the
124b725ae77Skettenis    * order to len,crc,stx,etx,typ might gain a tiny bit of speed but lets
125b725ae77Skettenis    * leave that for the moment
126b725ae77Skettenis    */
127b725ae77Skettenis   switch (rxstate->rx_state)
128b725ae77Skettenis   {
129b725ae77Skettenis     case RST_STX:
130b725ae77Skettenis       if (new_ch == rxstate->config->stx)
131b725ae77Skettenis       {
132b725ae77Skettenis         rxstate->rx_state = RST_TYP;
133b725ae77Skettenis         rxstate->error = RE_OKAY;
134b725ae77Skettenis         rxstate->crc = startCRC32;
135b725ae77Skettenis         rxstate->index = 0;
136b725ae77Skettenis         return RS_IN_PKT;
137b725ae77Skettenis       }
138b725ae77Skettenis       else
139b725ae77Skettenis       {
140b725ae77Skettenis         rxstate->error = RE_OKAY;
141b725ae77Skettenis         return RS_WAIT_PKT;
142b725ae77Skettenis       }
143b725ae77Skettenis 
144b725ae77Skettenis     case RST_TYP:
145b725ae77Skettenis       packet->type = (DevChanID)new_ch;
146b725ae77Skettenis       rxstate->rx_state = RST_LEN;
147b725ae77Skettenis       rxstate->error = RE_OKAY;
148b725ae77Skettenis       rxstate->field_c = 0; /* set up here for the length that follows */
149b725ae77Skettenis #ifdef DO_TRACE
150b725ae77Skettenis       __rt_trace("rxe-type-%2x ", packet->type);
151b725ae77Skettenis #endif
152b725ae77Skettenis       rxstate->crc = crc32(&new_ch, 1, rxstate->crc);
153b725ae77Skettenis 
154b725ae77Skettenis       return RS_IN_PKT;
155b725ae77Skettenis 
156b725ae77Skettenis     case RST_LEN:
157b725ae77Skettenis       rxstate->crc = crc32(&new_ch, 1, rxstate->crc);
158b725ae77Skettenis 
159b725ae77Skettenis       if (rxstate->field_c++ == 0)
160b725ae77Skettenis       {
161b725ae77Skettenis         /* first length byte */
162b725ae77Skettenis         packet->len = ((unsigned int)new_ch) << 8;
163b725ae77Skettenis         return RS_IN_PKT;
164b725ae77Skettenis       }
165b725ae77Skettenis       else
166b725ae77Skettenis       {
167b725ae77Skettenis         /* got the whole legth */
168b725ae77Skettenis         packet->len |= new_ch;
169b725ae77Skettenis #ifdef DO_TRACE
170b725ae77Skettenis         __rt_trace("rxe-len-%4x\n", packet->len);
171b725ae77Skettenis #endif
172b725ae77Skettenis 
173b725ae77Skettenis         /* check that the length is ok */
174b725ae77Skettenis         if (packet->len == 0)
175b725ae77Skettenis         {
176b725ae77Skettenis           /* empty pkt */
177b725ae77Skettenis           rxstate->field_c = 0;
178b725ae77Skettenis           rxstate->rx_state = RST_CRC;
179b725ae77Skettenis           return RS_IN_PKT;
180b725ae77Skettenis         }
181b725ae77Skettenis         else
182b725ae77Skettenis         {
183b725ae77Skettenis           if (packet->data == NULL)
184b725ae77Skettenis           {
185b725ae77Skettenis             /* need to alloc the data buffer */
186b725ae77Skettenis             if (!rxstate->config->ba_callback(
187b725ae77Skettenis                 packet, rxstate->config->ba_data)) {
188b725ae77Skettenis               rxstate->rx_state = RST_STX;
189b725ae77Skettenis               rxstate->error = RE_INTERNAL;
190b725ae77Skettenis               return RS_BAD_PKT;
191b725ae77Skettenis             }
192b725ae77Skettenis           }
193b725ae77Skettenis 
194b725ae77Skettenis           if (packet->len > packet->buf_len)
195b725ae77Skettenis           {
196b725ae77Skettenis             /* pkt bigger than buffer */
197b725ae77Skettenis             rxstate->field_c = 0;
198b725ae77Skettenis             rxstate->rx_state = RST_STX;
199b725ae77Skettenis             rxstate->error = RE_LEN;
200b725ae77Skettenis             return RS_BAD_PKT;
201b725ae77Skettenis           }
202b725ae77Skettenis           else
203b725ae77Skettenis           {
204b725ae77Skettenis             /* packet ok */
205b725ae77Skettenis             rxstate->field_c = 0;
206b725ae77Skettenis             rxstate->rx_state = RST_DAT;
207b725ae77Skettenis             return RS_IN_PKT;
208b725ae77Skettenis           }
209b725ae77Skettenis         }
210b725ae77Skettenis       }
211b725ae77Skettenis 
212b725ae77Skettenis     case RST_DAT:
213b725ae77Skettenis       /* dummy case (dealt with earlier) */
214b725ae77Skettenis #ifdef ASSERTIONS_ENABLED
215b725ae77Skettenis       __rt_warning("ERROR: hit RST_dat in switch\n");
216b725ae77Skettenis #endif
217b725ae77Skettenis       rxstate->rx_state = RST_STX;
218b725ae77Skettenis       rxstate->error = RE_INTERNAL;
219b725ae77Skettenis       return RS_BAD_PKT;
220b725ae77Skettenis 
221b725ae77Skettenis     case RST_CRC:
222b725ae77Skettenis       if (rxstate->field_c == 0)
223b725ae77Skettenis         packet->crc = 0;
224b725ae77Skettenis 
225b725ae77Skettenis       packet->crc |= (new_ch & 0xFF) << ((3 - rxstate->field_c) * 8);
226b725ae77Skettenis       rxstate->field_c++;
227b725ae77Skettenis 
228b725ae77Skettenis       if (rxstate->field_c == 4)
229b725ae77Skettenis       {
230b725ae77Skettenis         /* last crc field */
231b725ae77Skettenis         rxstate->field_c = 0;
232b725ae77Skettenis         rxstate->rx_state = RST_ETX;
233b725ae77Skettenis #ifdef DO_TRACE
234b725ae77Skettenis         __rt_trace("rxe-rcrc-%8x ", packet->crc);
235b725ae77Skettenis #endif
236b725ae77Skettenis       }
237b725ae77Skettenis 
238b725ae77Skettenis       return RS_IN_PKT;
239b725ae77Skettenis 
240b725ae77Skettenis     case RST_ETX:
241b725ae77Skettenis       if (new_ch == rxstate->config->etx)
242b725ae77Skettenis       {
243b725ae77Skettenis #if defined(DEBUG) && !defined(NO_PKT_DATA)
244b725ae77Skettenis         {
245b725ae77Skettenis           int c;
246b725ae77Skettenis # ifdef DO_TRACE
247b725ae77Skettenis           __rt_trace("\n");
248b725ae77Skettenis # endif
249b725ae77Skettenis           __rt_info("RXE Data =");
250b725ae77Skettenis           for (c=0; c < packet->len; c++)
251b725ae77Skettenis             __rt_info("%02x", packet->data[c]);
252b725ae77Skettenis           __rt_info("\n");
253b725ae77Skettenis         }
254b725ae77Skettenis #endif
255b725ae77Skettenis 
256b725ae77Skettenis         /* check crc */
257b725ae77Skettenis         if (rxstate->crc == packet->crc)
258b725ae77Skettenis         {
259b725ae77Skettenis           /* crc ok */
260b725ae77Skettenis           rxstate->rx_state = RST_STX;
261b725ae77Skettenis           rxstate->field_c = 0;
262b725ae77Skettenis           return RS_GOOD_PKT;
263b725ae77Skettenis         }
264b725ae77Skettenis         else
265b725ae77Skettenis         {
266b725ae77Skettenis #ifdef ASSERTIONS_ENABLED
267b725ae77Skettenis           __rt_warning("Bad crc, rx calculates it should be 0x%x\n", rxstate->crc);
268b725ae77Skettenis #endif
269b725ae77Skettenis           rxstate->rx_state = RST_STX;
270b725ae77Skettenis           rxstate->error = RE_CRC;
271b725ae77Skettenis           return RS_BAD_PKT;
272b725ae77Skettenis         }
273b725ae77Skettenis       }
274b725ae77Skettenis       else if (new_ch == rxstate->config->stx)
275b725ae77Skettenis         return unexp_stx(rxstate);
276b725ae77Skettenis       else
277b725ae77Skettenis       {
278b725ae77Skettenis         rxstate->rx_state = RST_STX;
279b725ae77Skettenis         rxstate->error = RE_NETX;
280b725ae77Skettenis         return RS_BAD_PKT;
281b725ae77Skettenis       }
282b725ae77Skettenis 
283b725ae77Skettenis     default:
284b725ae77Skettenis #ifdef ASSERTIONS_ENABLED
285b725ae77Skettenis       __rt_warning("ERROR fell through rxengine\n");
286b725ae77Skettenis #endif
287b725ae77Skettenis       rxstate->rx_state = RST_STX;
288b725ae77Skettenis       rxstate->error = RE_INTERNAL;
289b725ae77Skettenis       return RS_BAD_PKT;
290b725ae77Skettenis   }
291b725ae77Skettenis }
292b725ae77Skettenis 
unexp_stx(struct re_state * rxstate)293b725ae77Skettenis static re_status unexp_stx(struct re_state *rxstate)
294b725ae77Skettenis {
295b725ae77Skettenis #ifdef ASSERTIONS_ENABLED
296b725ae77Skettenis   __rt_warning("Unexpected stx\n");
297b725ae77Skettenis #endif
298b725ae77Skettenis   rxstate->crc = startCRC32;
299b725ae77Skettenis   rxstate->index = 0;
300b725ae77Skettenis   rxstate->rx_state = RST_TYP;
301b725ae77Skettenis   rxstate->error = RE_U_STX;
302b725ae77Skettenis   rxstate->field_c = 0;
303b725ae77Skettenis   return RS_BAD_PKT;
304b725ae77Skettenis }
305b725ae77Skettenis 
unexp_etx(struct re_state * rxstate)306b725ae77Skettenis static re_status unexp_etx(struct re_state *rxstate)
307b725ae77Skettenis {
308b725ae77Skettenis #ifdef ASSERTIONS_ENABLED
309b725ae77Skettenis   __rt_warning("Unexpected etx, rxstate: index= 0x%2x, field_c=0x%2x, state=0x%2x\n", rxstate->index, rxstate->field_c, rxstate->rx_state);
310b725ae77Skettenis #endif
311b725ae77Skettenis   rxstate->crc = 0;
312b725ae77Skettenis   rxstate->index = 0;
313b725ae77Skettenis   rxstate->rx_state = RST_STX;
314b725ae77Skettenis   rxstate->error = RE_U_ETX;
315b725ae77Skettenis   rxstate->field_c = 0;
316b725ae77Skettenis   return RS_BAD_PKT;
317b725ae77Skettenis }
318b725ae77Skettenis 
319b725ae77Skettenis /*
320b725ae77Skettenis  * This can be used as the buffer allocation callback for the rx engine,
321b725ae77Skettenis  * and makes use of angel_DD_GetBuffer() [in devdrv.h].
322b725ae77Skettenis  *
323b725ae77Skettenis  * Saves duplicating this callback function in every device driver that
324b725ae77Skettenis  * uses the rx engine.
325b725ae77Skettenis  *
326b725ae77Skettenis  * Note that this REQUIRES that the device id is installed as ba_data
327b725ae77Skettenis  * in the rx engine config structure for the driver.
328b725ae77Skettenis  */
angel_DD_RxEng_BufferAlloc(struct data_packet * packet,void * cb_data)329b725ae77Skettenis bool angel_DD_RxEng_BufferAlloc( struct data_packet *packet, void *cb_data )
330b725ae77Skettenis {
331b725ae77Skettenis #ifdef TARGET
332b725ae77Skettenis     DeviceID devid = (DeviceID)cb_data;
333b725ae77Skettenis #else
334b725ae77Skettenis     IGNORE(cb_data);
335b725ae77Skettenis #endif
336b725ae77Skettenis 
337b725ae77Skettenis     if ( packet->type < DC_NUM_CHANNELS )
338b725ae77Skettenis     {
339b725ae77Skettenis         /* request a buffer down from the channels layer */
340b725ae77Skettenis #ifdef TARGET
341b725ae77Skettenis         packet->data = angel_DD_GetBuffer( devid, packet->type,
342b725ae77Skettenis                                            packet->len              );
343b725ae77Skettenis #else
344b725ae77Skettenis         packet->data = malloc(packet->len);
345b725ae77Skettenis #endif
346b725ae77Skettenis         if ( packet->data == NULL )
347b725ae77Skettenis            return FALSE;
348b725ae77Skettenis         else
349b725ae77Skettenis         {
350b725ae77Skettenis             packet->buf_len = packet->len;
351b725ae77Skettenis             return TRUE;
352b725ae77Skettenis         }
353b725ae77Skettenis     }
354b725ae77Skettenis     else
355b725ae77Skettenis     {
356b725ae77Skettenis         /* bad type field */
357b725ae77Skettenis         return FALSE;
358b725ae77Skettenis     }
359b725ae77Skettenis }
360b725ae77Skettenis 
361b725ae77Skettenis /* EOF rx.c */
362