2 * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
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
17 * Title: Character reception engine
20 #include <stdarg.h> /* ANSI varargs support */
21 #include "angel.h" /* Angel system definitions */
22 #include "endian.h" /* Endian independant memory access macros */
23 #include "crc.h" /* crc generation definitions and headers */
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
{
43 RST_ESC
= (0x1 << 0x3)
46 void Angel_RxEngineInit(const struct re_config
*rxconfig
,
47 struct re_state
*rxstate
)
49 rxstate
->rx_state
= RST_STX
;
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
;
72 __rt_trace("rxe-echar-%2x ", new_ch
);
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
)
82 __rt_trace("rxe-esc ");
84 rxstate
->rx_state
|= RST_ESC
;
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
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
109 __rt_trace("rxe-dat ");
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
;
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
)
130 if (new_ch
== rxstate
->config
->stx
)
132 rxstate
->rx_state
= RST_TYP
;
133 rxstate
->error
= RE_OKAY
;
134 rxstate
->crc
= startCRC32
;
140 rxstate
->error
= RE_OKAY
;
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 */
150 __rt_trace("rxe-type-%2x ", packet
->type
);
152 rxstate
->crc
= crc32(&new_ch
, 1, rxstate
->crc
);
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;
167 /* got the whole legth */
168 packet
->len
|= new_ch
;
170 __rt_trace("rxe-len-%4x\n", packet
->len
);
173 /* check that the length is ok */
174 if (packet
->len
== 0)
177 rxstate
->field_c
= 0;
178 rxstate
->rx_state
= RST_CRC
;
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
;
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
;
205 rxstate
->field_c
= 0;
206 rxstate
->rx_state
= RST_DAT
;
213 /* dummy case (dealt with earlier) */
214 #ifdef ASSERTIONS_ENABLED
215 __rt_warning("ERROR: hit RST_dat in switch\n");
217 rxstate
->rx_state
= RST_STX
;
218 rxstate
->error
= RE_INTERNAL
;
222 if (rxstate
->field_c
== 0)
225 packet
->crc
|= (new_ch
& 0xFF) << ((3 - rxstate
->field_c
) * 8);
228 if (rxstate
->field_c
== 4)
231 rxstate
->field_c
= 0;
232 rxstate
->rx_state
= RST_ETX
;
234 __rt_trace("rxe-rcrc-%8x ", packet
->crc
);
241 if (new_ch
== rxstate
->config
->etx
)
243 #if defined(DEBUG) && !defined(NO_PKT_DATA)
249 __rt_info("RXE Data =");
250 for (c
=0; c
< packet
->len
; c
++)
251 __rt_info("%02x", packet
->data
[c
]);
257 if (rxstate
->crc
== packet
->crc
)
260 rxstate
->rx_state
= RST_STX
;
261 rxstate
->field_c
= 0;
266 #ifdef ASSERTIONS_ENABLED
267 __rt_warning("Bad crc, rx calculates it should be 0x%x\n", rxstate
->crc
);
269 rxstate
->rx_state
= RST_STX
;
270 rxstate
->error
= RE_CRC
;
274 else if (new_ch
== rxstate
->config
->stx
)
275 return unexp_stx(rxstate
);
278 rxstate
->rx_state
= RST_STX
;
279 rxstate
->error
= RE_NETX
;
284 #ifdef ASSERTIONS_ENABLED
285 __rt_warning("ERROR fell through rxengine\n");
287 rxstate
->rx_state
= RST_STX
;
288 rxstate
->error
= RE_INTERNAL
;
293 static re_status
unexp_stx(struct re_state
*rxstate
)
295 #ifdef ASSERTIONS_ENABLED
296 __rt_warning("Unexpected stx\n");
298 rxstate
->crc
= startCRC32
;
300 rxstate
->rx_state
= RST_TYP
;
301 rxstate
->error
= RE_U_STX
;
302 rxstate
->field_c
= 0;
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
);
313 rxstate
->rx_state
= RST_STX
;
314 rxstate
->error
= RE_U_ETX
;
315 rxstate
->field_c
= 0;
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
)
332 DeviceID devid
= (DeviceID
)cb_data
;
337 if ( packet
->type
< DC_NUM_CHANNELS
)
339 /* request a buffer down from the channels layer */
341 packet
->data
= angel_DD_GetBuffer( devid
, packet
->type
,
344 packet
->data
= malloc(packet
->len
);
346 if ( packet
->data
== NULL
)
350 packet
->buf_len
= packet
->len
;
This page took 0.038154 seconds and 4 git commands to generate.