xref: /openbsd/gnu/usr.bin/binutils/gdb/rdi-share/tx.c (revision 63addd46)
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  *   Project: ANGEL
15b725ae77Skettenis  *
16b725ae77Skettenis  *     Title: Character based packet transmission engine
17b725ae77Skettenis  */
18b725ae77Skettenis 
19b725ae77Skettenis #include <stdarg.h>    /* ANSI varargs support */
20b725ae77Skettenis #include "angel.h"     /* Angel system definitions */
21b725ae77Skettenis #include "angel_endian.h"    /* Endian independant memory access macros */
22b725ae77Skettenis #include "crc.h"       /* crc generation definitions and headers */
23b725ae77Skettenis #include "rxtx.h"
24b725ae77Skettenis #include "channels.h"
25b725ae77Skettenis #include "buffers.h"
26b725ae77Skettenis #include "logging.h"
27b725ae77Skettenis 
28b725ae77Skettenis /* definitions to describe the engines state */
29b725ae77Skettenis #define N_STX           0x0  /* first 2 bits for N_ */
30b725ae77Skettenis #define N_BODY          0x1
31b725ae77Skettenis #define N_ETX           0x2
32b725ae77Skettenis #define N_IDLE          0x3
33b725ae77Skettenis #define N_MASK          0x3 /* mask for the Encapsulator state */
34b725ae77Skettenis 
35b725ae77Skettenis #define E_PLAIN         (0x0 << 2) /* 3rd bit for E_ */
36b725ae77Skettenis #define E_ESC           (0x1 << 2) /* 3rd bit for E_ */
37b725ae77Skettenis #define E_MASK          (0x1 << 2) /* mask for the Escaper state */
38b725ae77Skettenis 
39b725ae77Skettenis #define F_HEAD          (0x0 << 3) /* 4th and 5th bits for F_ */
40b725ae77Skettenis #define F_DATA          (0x1 << 3)
41b725ae77Skettenis #define F_CRC           (0x1 << 4)
42b725ae77Skettenis #define F_MASK          (0x3 << 3) /* mask for the Escaper state */
43b725ae77Skettenis 
44b725ae77Skettenis static unsigned char escape(unsigned char ch_in, struct te_state *txstate);
45b725ae77Skettenis 
Angel_TxEngineInit(const struct re_config * txconfig,const struct data_packet * packet,struct te_state * txstate)46b725ae77Skettenis void Angel_TxEngineInit(const struct re_config *txconfig,
47b725ae77Skettenis                         const struct data_packet *packet,
48b725ae77Skettenis                         struct te_state *txstate){
49b725ae77Skettenis   IGNORE(packet);
50b725ae77Skettenis   txstate->tx_state = N_STX | E_PLAIN | F_HEAD;
51b725ae77Skettenis   txstate->field_c = 0;
52b725ae77Skettenis   txstate->encoded = 0;
53b725ae77Skettenis   txstate->config = txconfig;
54b725ae77Skettenis   txstate->crc = 0;
55b725ae77Skettenis }
56b725ae77Skettenis 
Angel_TxEngine(const struct data_packet * packet,struct te_state * txstate,unsigned char * tx_ch)57b725ae77Skettenis te_status Angel_TxEngine(const struct data_packet *packet,
58b725ae77Skettenis                          struct te_state *txstate,
59b725ae77Skettenis                          unsigned char *tx_ch){
60b725ae77Skettenis   /* TODO: gaurd on long/bad packets */
61b725ae77Skettenis   /*
62b725ae77Skettenis    * encapsulate the packet, framing has been moved from a seperate
63b725ae77Skettenis    * function into the encapsulation routine as it needed too much
64b725ae77Skettenis    * inherited state for it to be sensibly located elsewhere
65b725ae77Skettenis    */
66b725ae77Skettenis   switch ((txstate->tx_state) & N_MASK){
67b725ae77Skettenis   case N_STX:
68b725ae77Skettenis #ifdef DO_TRACE
69b725ae77Skettenis     __rt_trace("txe-stx ");
70b725ae77Skettenis #endif
71b725ae77Skettenis     txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_BODY;
72b725ae77Skettenis     *tx_ch = txstate->config->stx;
73b725ae77Skettenis     txstate->field_c = 3; /* set up for the header */
74b725ae77Skettenis     txstate->crc = startCRC32; /* set up basic crc */
75b725ae77Skettenis     return TS_IN_PKT;
76b725ae77Skettenis   case N_BODY:{
77b725ae77Skettenis     switch (txstate->tx_state & F_MASK) {
78b725ae77Skettenis     case F_HEAD:
79b725ae77Skettenis #ifdef DO_TRACE
80b725ae77Skettenis     __rt_trace("txe-head ");
81b725ae77Skettenis #endif
82b725ae77Skettenis       if (txstate->field_c == 3) {
83b725ae77Skettenis         /* send type */
84b725ae77Skettenis         *tx_ch = escape(packet->type, txstate);
85b725ae77Skettenis         return TS_IN_PKT;
86b725ae77Skettenis       }
87b725ae77Skettenis       else {
88b725ae77Skettenis         *tx_ch = escape((packet->len >> (txstate->field_c - 1) * 8) & 0xff,
89b725ae77Skettenis                       txstate);
90b725ae77Skettenis           if (txstate->field_c == 0) {
91b725ae77Skettenis             /* move on to the next state */
92b725ae77Skettenis             txstate->tx_state = (txstate->tx_state & ~F_MASK) | F_DATA;
93b725ae77Skettenis             txstate->field_c = packet->len;
94b725ae77Skettenis           }
95b725ae77Skettenis         return TS_IN_PKT;
96b725ae77Skettenis       }
97b725ae77Skettenis     case F_DATA:
98b725ae77Skettenis #ifdef DO_TRACE
99b725ae77Skettenis     __rt_trace("txe-data ");
100b725ae77Skettenis #endif
101b725ae77Skettenis       *tx_ch = escape(packet->data[packet->len - txstate->field_c], txstate);
102b725ae77Skettenis       if (txstate->field_c == 0) {
103b725ae77Skettenis         /* move on to the next state */
104b725ae77Skettenis         txstate->tx_state = (txstate->tx_state & ~F_MASK) | F_CRC;
105b725ae77Skettenis         txstate->field_c = 4;
106b725ae77Skettenis       }
107b725ae77Skettenis       return TS_IN_PKT;
108b725ae77Skettenis     case F_CRC:
109b725ae77Skettenis #ifdef DO_TRACE
110b725ae77Skettenis     __rt_trace("txe-crc ");
111b725ae77Skettenis #endif
112b725ae77Skettenis      *tx_ch = escape((txstate->crc >> ((txstate->field_c - 1) * 8)) & 0xff,
113b725ae77Skettenis                       txstate);
114b725ae77Skettenis 
115b725ae77Skettenis       if (txstate->field_c == 0) {
116b725ae77Skettenis #ifdef DO_TRACE
117b725ae77Skettenis         __rt_trace("txe crc = 0x%x\n", txstate->crc);
118b725ae77Skettenis #endif
119b725ae77Skettenis         /* move on to the next state */
120b725ae77Skettenis         txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_ETX;
121b725ae77Skettenis       }
122b725ae77Skettenis       return TS_IN_PKT;
123b725ae77Skettenis     }
124b725ae77Skettenis   }
125b725ae77Skettenis   case N_ETX:
126b725ae77Skettenis #ifdef DO_TRACE
127b725ae77Skettenis     __rt_trace("txe-etx\n");
128b725ae77Skettenis #endif
129b725ae77Skettenis     txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_IDLE;
130b725ae77Skettenis     *tx_ch = txstate->config->etx;
131b725ae77Skettenis     return TS_DONE_PKT;
132b725ae77Skettenis   default:
133b725ae77Skettenis #ifdef DEBUG
134b725ae77Skettenis     __rt_info("tx default\n");
135b725ae77Skettenis #endif
136b725ae77Skettenis     txstate->tx_state = (txstate->tx_state & ~N_MASK) | N_IDLE;
137b725ae77Skettenis     return TS_IDLE;
138b725ae77Skettenis   }
139b725ae77Skettenis   /* stop a silly -Wall warning */
140b725ae77Skettenis   return (te_status)-1;
141b725ae77Skettenis }
142b725ae77Skettenis 
143b725ae77Skettenis /*
144b725ae77Skettenis  * crc generation occurs in the escape function because it is the only
145b725ae77Skettenis  * place where we know that we're putting a real char into the buffer
146b725ae77Skettenis  * rather than an escaped one.
147b725ae77Skettenis  * We must be careful here not to update the crc when we're sending it
148b725ae77Skettenis  */
escape(unsigned char ch_in,struct te_state * txstate)149b725ae77Skettenis static unsigned char escape(unsigned char ch_in, struct te_state *txstate) {
150b725ae77Skettenis    if (((txstate->tx_state) & E_MASK) == E_ESC) {
151b725ae77Skettenis       /* char has been escaped so send the real char */
152b725ae77Skettenis #ifdef DO_TRACE
153b725ae77Skettenis      __rt_trace("txe-echar ");
154b725ae77Skettenis #endif
155b725ae77Skettenis       txstate->tx_state = (txstate->tx_state & ~E_MASK) | E_PLAIN;
156b725ae77Skettenis       txstate->field_c--;
157b725ae77Skettenis       if ((txstate->tx_state & F_MASK) != F_CRC)
158b725ae77Skettenis         txstate->crc = crc32( &ch_in, 1, txstate->crc);
159b725ae77Skettenis       return ch_in | serial_ESCAPE;
160b725ae77Skettenis    }
161b725ae77Skettenis    if ((ch_in < 32) && ((txstate->config->esc_set & (1 << ch_in)) != 0)) {
162b725ae77Skettenis      /* char needs escaping */
163b725ae77Skettenis #ifdef DO_TRACE
164b725ae77Skettenis      __rt_trace("txe-esc ");
165b725ae77Skettenis #endif
166b725ae77Skettenis      txstate->tx_state = (txstate->tx_state & ~E_MASK) | E_ESC;
167b725ae77Skettenis      return txstate->config->esc;
168b725ae77Skettenis    }
169b725ae77Skettenis    /* must be a char that can be sent plain */
170b725ae77Skettenis    txstate->field_c--;
171b725ae77Skettenis    if ((txstate->tx_state & F_MASK) != F_CRC)
172b725ae77Skettenis      txstate->crc = crc32(&ch_in, 1, txstate->crc);
173b725ae77Skettenis    return ch_in;
174b725ae77Skettenis }
175b725ae77Skettenis 
176b725ae77Skettenis /* EOF tx.c */
177