OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [rdi-share/] [rx.c] - Blame information for rev 578

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 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: 2002-01-16 10:24:34 $
13
 *
14
 *
15
 *   Project: ANGEL
16
 *
17
 *     Title:  Character reception engine
18
 */
19
 
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"
31
 
32
static re_status unexp_stx(struct re_state *rxstate);
33
static re_status unexp_etx(struct re_state *rxstate);
34
 
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;
45
 
46
void Angel_RxEngineInit(const struct re_config *rxconfig,
47
                        struct re_state *rxstate)
48
{
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;
55
}
56
 
57
re_status Angel_RxEngine(unsigned char new_ch, struct data_packet *packet,
58
                         struct re_state *rxstate)
59
{
60
  /*
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
64
   */
65
 
66
  /* see if we're expecting a escaped char */
67
  if ((rxstate->rx_state & RST_ESC) == RST_ESC)
68
  {
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;
75
  }
76
  else if ( (1 << new_ch) & rxstate->config->esc_set )
77
  {
78
    /* see if the incoming char is a special one */
79
    if (new_ch == rxstate->config->esc)
80
    {
81
#ifdef DO_TRACE
82
      __rt_trace("rxe-esc ");
83
#endif
84
      rxstate->rx_state |= RST_ESC;
85
      return RS_IN_PKT;
86
    }
87
    else
88
    {
89
      /*
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
94
       */
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);
99
    }
100
  }
101
 
102
  if (rxstate->rx_state == RST_DAT)
103
  {
104
    /*
105
     * do this to speed up the common case, no real penalty for
106
     * other cases
107
     */
108
#ifdef DO_TRACE
109
    __rt_trace("rxe-dat ");
110
#endif
111
 
112
    rxstate->crc = crc32(&new_ch, 1, rxstate->crc);
113
    (packet->data)[rxstate->index++] = (unsigned int)new_ch & 0xff;
114
 
115
    if (rxstate->index == packet->len)
116
      rxstate->rx_state = RST_CRC;
117
 
118
    return RS_IN_PKT;
119
  }
120
 
121
  /*
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
126
   */
127
  switch (rxstate->rx_state)
128
  {
129
    case RST_STX:
130
      if (new_ch == rxstate->config->stx)
131
      {
132
        rxstate->rx_state = RST_TYP;
133
        rxstate->error = RE_OKAY;
134
        rxstate->crc = startCRC32;
135
        rxstate->index = 0;
136
        return RS_IN_PKT;
137
      }
138
      else
139
      {
140
        rxstate->error = RE_OKAY;
141
        return RS_WAIT_PKT;
142
      }
143
 
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);
153
 
154
      return RS_IN_PKT;
155
 
156
    case RST_LEN:
157
      rxstate->crc = crc32(&new_ch, 1, rxstate->crc);
158
 
159
      if (rxstate->field_c++ == 0)
160
      {
161
        /* first length byte */
162
        packet->len = ((unsigned int)new_ch) << 8;
163
        return RS_IN_PKT;
164
      }
165
      else
166
      {
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
172
 
173
        /* check that the length is ok */
174
        if (packet->len == 0)
175
        {
176
          /* empty pkt */
177
          rxstate->field_c = 0;
178
          rxstate->rx_state = RST_CRC;
179
          return RS_IN_PKT;
180
        }
181
        else
182
        {
183
          if (packet->data == NULL)
184
          {
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;
191
            }
192
          }
193
 
194
          if (packet->len > packet->buf_len)
195
          {
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;
201
          }
202
          else
203
          {
204
            /* packet ok */
205
            rxstate->field_c = 0;
206
            rxstate->rx_state = RST_DAT;
207
            return RS_IN_PKT;
208
          }
209
        }
210
      }
211
 
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;
220
 
221
    case RST_CRC:
222
      if (rxstate->field_c == 0)
223
        packet->crc = 0;
224
 
225
      packet->crc |= (new_ch & 0xFF) << ((3 - rxstate->field_c) * 8);
226
      rxstate->field_c++;
227
 
228
      if (rxstate->field_c == 4)
229
      {
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
236
      }
237
 
238
      return RS_IN_PKT;
239
 
240
    case RST_ETX:
241
      if (new_ch == rxstate->config->etx)
242
      {
243
#if defined(DEBUG) && !defined(NO_PKT_DATA)
244
        {
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");
253
        }
254
#endif
255
 
256
        /* check crc */
257
        if (rxstate->crc == packet->crc)
258
        {
259
          /* crc ok */
260
          rxstate->rx_state = RST_STX;
261
          rxstate->field_c = 0;
262
          return RS_GOOD_PKT;
263
        }
264
        else
265
        {
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;
272
        }
273
      }
274
      else if (new_ch == rxstate->config->stx)
275
        return unexp_stx(rxstate);
276
      else
277
      {
278
        rxstate->rx_state = RST_STX;
279
        rxstate->error = RE_NETX;
280
        return RS_BAD_PKT;
281
      }
282
 
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;
290
  }
291
}
292
 
293
static re_status unexp_stx(struct re_state *rxstate)
294
{
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;
304
}
305
 
306
static re_status unexp_etx(struct re_state *rxstate)
307
{
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;
317
}
318
 
319
/*
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].
322
 *
323
 * Saves duplicating this callback function in every device driver that
324
 * uses the rx engine.
325
 *
326
 * Note that this REQUIRES that the device id is installed as ba_data
327
 * in the rx engine config structure for the driver.
328
 */
329
bool angel_DD_RxEng_BufferAlloc( struct data_packet *packet, void *cb_data )
330
{
331
#ifdef TARGET
332
    DeviceID devid = (DeviceID)cb_data;
333
#else
334
    IGNORE(cb_data);
335
#endif
336
 
337
    if ( packet->type < DC_NUM_CHANNELS )
338
    {
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
349
        {
350
            packet->buf_len = packet->len;
351
            return TRUE;
352
        }
353
    }
354
    else
355
    {
356
        /* bad type field */
357
        return FALSE;
358
    }
359
}
360
 
361
/* EOF rx.c */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.