comparison src/g23m-gprs/llc/llc_irxl.c @ 1:fa8dc04885d8

src/g23m-*: import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:25:50 +0000
parents
children
comparison
equal deleted inserted replaced
0:4e78acac3d88 1:fa8dc04885d8
1 /*
2 +-----------------------------------------------------------------------------
3 | Project :
4 | Modul :
5 +-----------------------------------------------------------------------------
6 | Copyright 2002 Texas Instruments Berlin, AG
7 | All rights reserved.
8 |
9 | This file is confidential and a trade secret of Texas
10 | Instruments Berlin, AG
11 | The receipt of or possession of this file does not convey
12 | any rights to reproduce or disclose its contents or to
13 | manufacture, use, or sell anything it may describe, in
14 | whole, or in part, without the specific written consent of
15 | Texas Instruments Berlin, AG.
16 +-----------------------------------------------------------------------------
17 | Purpose : This modul is part of the entity LLC and implements all labels
18 | in the SDL-documentation (IRX-statemachine) that are called from
19 | more than one diagram/place.
20 +-----------------------------------------------------------------------------
21 */
22
23 #ifndef LLC_IRXL_C
24 #define LLC_IRXL_C
25 #endif
26
27 #define ENTITY_LLC
28
29 /*==== INCLUDES =============================================================*/
30
31 #include "typedefs.h" /* to get Condat data types */
32 #include "vsi.h" /* to get a lot of macros */
33 #include "macdef.h"
34 #include "gprs.h"
35 #include "gsm.h" /* to get a lot of macros */
36 #include "cnf_llc.h" /* to get cnf-definitions */
37 #include "mon_llc.h" /* to get mon-definitions */
38 #include "prim.h" /* to get the definitions of used SAP and directions */
39 #include "llc.h" /* to get the global entity definitions */
40
41 #include "llc_irxf.h" /* to get local IRX functions */
42 #include "llc_irxl.h" /* to get local IRX labels */
43 #include "llc_llmes.h" /* to get signal interface to LLME */
44 #include "llc_txs.h" /* to get signal interface to TX */
45
46 /*==== CONST ================================================================*/
47
48 /*==== LOCAL VARS ===========================================================*/
49
50 /*==== PRIVATE FUNCTIONS ====================================================*/
51
52
53 /*
54 +------------------------------------------------------------------------------
55 | Function : irx_get_next_gap
56 +------------------------------------------------------------------------------
57 | Description : Searches queue with already received frames.
58 |
59 | Parameters : next_free - pointer to T_FRAME_NUM, number of the next
60 | frame that has not been received yet.
61 | If queue is empty, this parameter will be
62 | set to (llc_data->sapi->vr + 1) %
63 | (MAX_SEQUENCE_NUMBER + 1).
64 | gap_size - pointer to T_FRAME_NUM, 0, 1 or bigger
65 | Preconditions: llc_data->sapi points to the affected sapi.
66 | There is 1 entry in the queue with vr==ns.
67 |
68 +------------------------------------------------------------------------------
69 */
70 GLOBAL void irx_get_next_gap (T_FRAME_NUM* next_free,
71 T_FRAME_NUM* gap_size)
72 {
73
74 T_IRX_QUEUE* entry = llc_data->irx->queue;
75 BOOL gap_found = FALSE;
76
77 TRACE_FUNCTION("irx_get_next_gap");
78
79 *next_free = (llc_data->sapi->vr + 1) % (MAX_SEQUENCE_NUMBER + 1);
80 *gap_size = 0;
81
82 TRACE_EVENT_P1("*next_free: %d", *next_free);
83
84
85 while ((entry != NULL) &&
86 FRAME_NUM_VALID( entry->ns,
87 llc_data->sapi->vr,
88 llc_data->sapi->vr + *(llc_data->ku)) )
89 {
90 entry = entry->next;
91 }
92
93 /*
94 * If rest of queue is empty, values of next_free and gap_size are ok.
95 */
96 if (entry == NULL)
97 {
98 return;
99 } /* if (entry == NULL) */
100
101 /*
102 * Queue is not empty. Find the first gap.
103 */
104 while ((entry != NULL) && !gap_found)
105 {
106 T_FRAME_NUM num = entry->ns;
107
108 if (num == *next_free)
109 {
110 entry = entry->next;
111 *next_free = (*next_free + 1) % (MAX_SEQUENCE_NUMBER + 1);
112 }
113 else
114 {
115 gap_found = TRUE;
116 *gap_size = (num - *next_free) % (MAX_SEQUENCE_NUMBER + 1);
117 }
118 } /* while ((entry != NULL) && !gap_found) */
119
120 TRACE_EVENT_P2("*next_free: %u *gap_size: %u ", *next_free, *gap_size);
121
122
123 } /* irx_get_next_gap() */
124
125
126
127
128
129
130
131 /*==== PUBLIC FUNCTIONS =====================================================*/
132
133
134 /*
135 +------------------------------------------------------------------------------
136 | Function : irx_label_if
137 +------------------------------------------------------------------------------
138 | Description : Describes label IRX_IF
139 |
140 | Parameters : ll_unitdata_ind - a valid pointer to an LL_UNITDATA_IND
141 | primitive
142 | ns - N(S) of received frame
143 | a_bit - A bit of received frame
144 | state - current state of IRX
145 |
146 +------------------------------------------------------------------------------
147 */
148 GLOBAL void irx_label_if (T_LL_UNITDATA_IND *ll_unitdata_ind,
149 T_FRAME_NUM ns,
150 T_BIT a_bit,
151 UBYTE state)
152 {
153 BOOL is_busy;
154 T_FRAME_NUM vsi;
155 BOOL vsi_found;
156
157
158 TRACE_FUNCTION( "irx_label_if" );
159
160 if (state == IRX_ABM)
161 {
162 /*
163 * Label IRX_IF_ABM
164 */
165 if ( ns == llc_data->sapi->vr )
166 {
167 BOOL found = FALSE;
168 T_FRAME_NUM num = 0;
169 irx_get_last_queued_ns(&found, &num);
170 if (!found)
171 {
172 /*
173 * Store N(S)/V(R) condition
174 */
175 llc_data->irx->last_ns = NS_EQUAL_VR;
176 /*
177 * If N(s) = V(r) increment V(r), handle OC(rx)
178 */
179 llc_data->sapi->vr++;
180
181 if (llc_data->sapi->vr > MAX_SEQUENCE_NUMBER)
182 {
183 llc_data->sapi->oc_i_rx += (MAX_SEQUENCE_NUMBER+1);
184 llc_data->sapi->vr = 0;
185 }
186 }
187 else
188 {
189
190 T_FRAME_NUM next_free = 0;
191 T_FRAME_NUM gap_size = 0;
192
193 irx_get_next_gap (&next_free, &gap_size);
194
195 /*
196 * vr will be set to next_free. If MAX_SEQUENCE_NUMBER is passed,
197 * increment overflow counter.
198 */
199 if (llc_data->sapi->vr > next_free)
200 {
201 llc_data->sapi->oc_i_rx += (MAX_SEQUENCE_NUMBER + 1);
202 }
203
204 llc_data->sapi->vr = next_free;
205
206 if (gap_size == 0) {
207 llc_data->irx->last_ns = NS_EQUAL_VR;
208 } else if (gap_size == 1) {
209 llc_data->irx->last_ns = NS_EQUAL_VR_PLUS_1;
210 } else {
211 llc_data->irx->last_ns = NS_NO_SEQUENCE_ERROR;
212 }
213
214 }
215
216 /*
217 * Expected next frame received.
218 */
219 if ( llc_data->irx->ll_send_ready == TRUE )
220 {
221 /*
222 * Forward the frame to L3
223 */
224 PPASS (ll_unitdata_ind, ll_data_ind, LL_DATA_IND);
225 TRACE_2_OUT_PARA("s:%d len:%d", ll_data_ind->sapi, BYTELEN(ll_data_ind->sdu.l_buf));
226 PSEND (hCommSNDCP, ll_data_ind);
227
228 llc_data->irx->ll_send_ready = FALSE;
229
230 /*
231 * Increment V(f) (= Next frame number to forward to L3)
232 */
233 llc_data->irx->vf += 1;
234 llc_data->irx->vf %= (MAX_SEQUENCE_NUMBER+1);
235
236 /*
237 * Update V(R) if we have the next frames already queued
238 */
239 irx_update_vr ();
240
241 /*
242 * Handle the acknowledgement
243 */
244 irx_send_ack (a_bit);
245
246 /* SET_STATE (IRX, SAME_STATE); */
247 }
248 else
249 {
250 /*
251 * store frame and update V(R) if next frames already stored
252 */
253 irx_queue_store (ll_unitdata_ind, ns, &is_busy);
254 irx_update_vr ();
255
256 if ( is_busy == TRUE )
257 {
258 irx_send_rnr ();
259 SET_STATE (IRX, IRX_ABM_BUSY);
260 }
261 else
262 {
263 irx_send_ack (a_bit);
264 /* SET_STATE (IRX, SAME_STATE); */
265 }
266 }
267 }
268 else
269 {
270 /*
271 * Not the expected next frame received. Check if it is in receive window.
272 */
273 if ( FRAME_NUM_VALID (llc_data->sapi->vr + 1, ns, llc_data->sapi->vr + *(llc_data->ku)) )
274 {
275 /*
276 * Store N(S)/V(R) condition
277 */
278 if (ns == (llc_data->sapi->vr + 1) % (MAX_SEQUENCE_NUMBER+1))
279 {
280 llc_data->irx->last_ns = NS_EQUAL_VR_PLUS_1;
281 }
282 else
283 {
284 /*
285 * Check if we have detect a sequence error or not: If ns equals to
286 * ns + 1 of the last queued frame then we have not detect a new error
287 */
288 irx_get_last_queued_ns (&vsi_found, &vsi);
289
290 if (vsi_found)
291 {
292 if (ns == (vsi + 1) % (MAX_SEQUENCE_NUMBER+1))
293 {
294 /*
295 * ok, seems to be in sequence
296 */
297 llc_data->irx->last_ns = NS_NO_SEQUENCE_ERROR;
298 }
299 else
300 {
301 /*
302 * sequence error found
303 */
304 llc_data->irx->last_ns = NS_IN_RANGE_VR_KU;
305 }
306 }
307 else
308 {
309 /*
310 * sequence error found
311 */
312 llc_data->irx->last_ns = NS_IN_RANGE_VR_KU;
313 }
314 }
315
316 /*
317 * store frame and update V(R)
318 */
319 irx_queue_store (ll_unitdata_ind, ns, &is_busy);
320
321 if ( is_busy == TRUE )
322 {
323 irx_send_rnr ();
324 SET_STATE (IRX, IRX_ABM_BUSY);
325 }
326 else
327 {
328 irx_send_ack (a_bit);
329 /* SET_STATE (IRX, SAME_STATE); */
330 }
331 }
332 else
333 {
334 /*
335 * duplicate frame
336 */
337 TRACE_0_INFO ("Duplicated frame received");
338
339 PFREE (ll_unitdata_ind);
340 irx_send_ack (a_bit);
341 /* SET_STATE (IRX, SAME_STATE); */
342 }
343 }
344 }
345 else
346 {
347 /*
348 * ABM_BUSY
349 */
350 irx_send_rnr ();
351
352 /*
353 * ignore I frame in state 'own receiver busy'
354 */
355 PFREE (ll_unitdata_ind);
356 /* SET_STATE (IRX, SAME_STATE); */
357 }
358
359 return;
360 } /* irx_label_if() */
361