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