comparison src/g23m-gprs/llc/llc_uirxf.c @ 1:d393cd9bb723

src/g23m-*: initial import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 15 Jul 2018 04:40:46 +0000
parents
children
comparison
equal deleted inserted replaced
0:b6a5e36de839 1:d393cd9bb723
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
18 | procedures and functions as described in the
19 | SDL-documentation (UIRX-statemachine)
20 +-----------------------------------------------------------------------------
21 */
22
23 #ifndef LLC_UIRXF_C
24 #define LLC_UIRXF_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_uirxf.h" /* to compare own prototyes */
42 /*==== CONST ================================================================*/
43
44 /*==== LOCAL VARS ===========================================================*/
45
46 /*==== PRIVATE FUNCTIONS ====================================================*/
47
48 /*==== PUBLIC FUNCTIONS =====================================================*/
49
50
51 /*
52 +------------------------------------------------------------------------------
53 | Function : uirx_queue_clean
54 +------------------------------------------------------------------------------
55 | Description : This procedure removes all entries from the UIRX queue
56 |
57 | Parameters :
58 |
59 +------------------------------------------------------------------------------
60 */
61 GLOBAL void uirx_queue_clean (void)
62 {
63 T_UIRX_QUEUE** entry = &(llc_data->uirx->queue);
64
65 TRACE_FUNCTION( "uirx_queue_clean" );
66
67 while (*entry)
68 {
69 /*
70 * get pointer to next (=first) entry
71 */
72 T_UIRX_QUEUE* current = *entry;
73
74 /*
75 * Free frame, if one is attached to the entry
76 */
77 if (current->frame != NULL)
78 {
79 PFREE (current->frame);
80 }
81
82 /*
83 * remove next entry from the entry (make second to first)
84 */
85 *entry = current->next;
86
87 /*
88 * free the removed entry
89 */
90 MFREE (current);
91 }
92
93 } /* uirx_queue_clean() */
94
95 /*
96 +------------------------------------------------------------------------------
97 | Function : uirx_queue_store
98 +------------------------------------------------------------------------------
99 | Description : This procedure stores the primitive to the end of the queue.
100 | If the queue is full, an the primitive is freed.
101 |
102 | Parameters :
103 |
104 +------------------------------------------------------------------------------
105 */
106 GLOBAL void uirx_queue_store (T_LL_UNITDATA_IND *ll_unitdata_ind)
107 {
108 T_UIRX_QUEUE** entry = &(llc_data->uirx->queue);
109 int num_entries = 0;
110
111 TRACE_FUNCTION( "uirx_queue_store" );
112
113 /*
114 * Skip, but count, already for L3 ready waiting entries.
115 * If queue is already full, free this primitive.
116 */
117 while (*entry)
118 {
119 num_entries++;
120
121 if (num_entries >= UIRX_QUEUE_SIZE)
122 {
123 PFREE (ll_unitdata_ind);
124 TRACE_EVENT ("LL_UNITDATA_IND ignored -> UIRX queue is full");
125 return;
126 }
127
128 entry = &((*entry)->next);
129 }
130
131 /*
132 * Allocate management memory
133 */
134 MALLOC( *entry, sizeof(T_UIRX_QUEUE) );
135
136 if (*entry)
137 {
138 /*
139 * Queue primitive
140 */
141 (*entry)->next = NULL;
142 (*entry)->frame = ll_unitdata_ind;
143
144 }
145 else
146 {
147 /*
148 * Out of memory
149 */
150 PFREE (ll_unitdata_ind);
151 TRACE_ERROR( "Out of memory in uirx_queue_store()" );
152 }
153
154 } /* uirx_queue_store() */
155
156
157 /*
158 +------------------------------------------------------------------------------
159 | Function : uirx_queue_retrieve
160 +------------------------------------------------------------------------------
161 | Description : Retrieve the next frame, if any.
162 |
163 | Parameters :
164 |
165 +------------------------------------------------------------------------------
166 */
167 GLOBAL BOOL uirx_queue_retrieve (T_LL_UNITDATA_IND **ll_unitdata_ind)
168 {
169 T_UIRX_QUEUE** entry = &(llc_data->uirx->queue);
170
171 TRACE_FUNCTION( "uirx_queue_retrieve" );
172
173 /*
174 * Take the first queue entry, if there is any.
175 */
176 if (*entry)
177 {
178 /*
179 * Store pointer to the entry
180 */
181 T_UIRX_QUEUE* current = *entry;
182
183 /*
184 * Remove entry from the queue (make second to first)
185 */
186 *entry = current->next;
187
188 *ll_unitdata_ind = current->frame;
189
190 /*
191 * Free retrieved management entry
192 */
193 MFREE (current);
194
195 return TRUE;
196 }
197 else
198 {
199 /*
200 * Set default return values
201 */
202 *ll_unitdata_ind = NULL;
203
204 return FALSE;
205 }
206
207 } /* uirx_queue_retrieve() */
208
209 /*
210 +------------------------------------------------------------------------------
211 | Function : uirx_init
212 +------------------------------------------------------------------------------
213 | Description : This procedure initialises all necessary variables of
214 | ui_frames_rx for all SAPIs.
215 |
216 | Parameters :
217 |
218 +------------------------------------------------------------------------------
219 */
220 GLOBAL void uirx_init (void)
221 {
222 UBYTE inc;
223
224 TRACE_FUNCTION( "uirx_init" );
225
226 /*
227 * Initialise every incarnation of UIRX with state TLLI_UNASSIGNED_NOT_READY,
228 * except incarnation 0 (= SAPI 1), because we have no flow control for
229 * SAPI 1.
230 */
231 SWITCH_SERVICE (llc, uirx, 0);
232 INIT_STATE (UIRX_0, UIRX_TLLI_UNASSIGNED_READY);
233
234 SWITCH_SERVICE (llc, uirx, 1);
235 INIT_STATE (UIRX_1, UIRX_TLLI_UNASSIGNED_NOT_READY);
236
237 SWITCH_SERVICE (llc, uirx, 2);
238 INIT_STATE (UIRX_2, UIRX_TLLI_UNASSIGNED_NOT_READY);
239
240 SWITCH_SERVICE (llc, uirx, 3);
241 INIT_STATE (UIRX_3, UIRX_TLLI_UNASSIGNED_NOT_READY);
242
243 SWITCH_SERVICE (llc, uirx, 4);
244 INIT_STATE (UIRX_4, UIRX_TLLI_UNASSIGNED_NOT_READY);
245
246 SWITCH_SERVICE (llc, uirx, 5);
247 INIT_STATE (UIRX_5, UIRX_TLLI_UNASSIGNED_NOT_READY);
248
249 /*
250 * Initialise the UIRX queue structure
251 */
252 for (inc = 0; inc < UIRX_NUM_INC; inc++)
253 {
254 SWITCH_SERVICE (llc, uirx, inc);
255
256 /*
257 * Free old used resources (in case of an LLC restart):
258 */
259 uirx_queue_clean ();
260 llc_data->uirx->queue = NULL;
261 }
262
263 return;
264 } /* uirx_init() */
265
266
267 /*
268 +------------------------------------------------------------------------------
269 | Function : uirx_init_sapi
270 +------------------------------------------------------------------------------
271 | Description : This procedure initialises all necessary variables of
272 | ui_frames_rx for the given SAPI.
273 |
274 | Parameters :
275 |
276 +------------------------------------------------------------------------------
277 */
278 GLOBAL void uirx_init_sapi (void)
279 {
280 TRACE_FUNCTION( "uirx_init_sapi" );
281
282 /*
283 * <R.LLC.TLLI_ASS.A.007>, <R.LLC.TLLI_ASS.A.009>
284 */
285 llc_data->sapi->vur = 0;
286
287 llc_data->uirx->last_32_frames_bitfield = 0L;
288
289 return;
290 } /* uirx_init_sapi() */
291
292
293
294 /*
295 +------------------------------------------------------------------------------
296 | Function : uirx_store_nu
297 +------------------------------------------------------------------------------
298 | Description : This procedure stores the given n(u) in a list of the last 32
299 | received n(u)s concerning the given SAPI. Therefore the
300 | variable v(ur) is passed to the procedure, which contains
301 | the current value of the unacknowledged receive sequence
302 | number.
303 |
304 | Parameters : nu - N(U), must be in the range vur-32 <= nu < vur
305 | vur - V(UR)
306 |
307 +------------------------------------------------------------------------------
308 */
309 GLOBAL void uirx_store_nu (T_FRAME_NUM nu, T_FRAME_NUM vur)
310 {
311 USHORT diff;
312
313
314 TRACE_FUNCTION( "uirx_store_nu" );
315
316 /*
317 * Set the bit for the received N(U) in last_32_frames_bitfield. The
318 * relative bit position referring to V(UR) has already been stored
319 * in diff.
320 */
321 diff = (vur + (MAX_SEQUENCE_NUMBER+1) - nu - 1) % (MAX_SEQUENCE_NUMBER+1);
322
323 llc_data->uirx->last_32_frames_bitfield |= (0x00000001L) << diff;
324
325 return;
326 } /* uirx_store_nu() */
327
328
329
330 /*
331 +------------------------------------------------------------------------------
332 | Function : uirx_check_nu
333 +------------------------------------------------------------------------------
334 | Description : This procedure checks if the given n(u) has already been
335 | received for the current SAPI within the last 32 frames (see
336 | procedure store_nu).
337 |
338 | Parameters : nu - N(U), must be in the range vur-32 <= nu < vur
339 | vur - V(UR)
340 |
341 | Returns : TRUE - if frame was already received.
342 | FALSE - else
343 +------------------------------------------------------------------------------
344 */
345 GLOBAL BOOL uirx_check_nu (T_FRAME_NUM nu, T_FRAME_NUM vur)
346 {
347 USHORT diff;
348
349
350 TRACE_FUNCTION( "uirx_check_nu" );
351
352 /*
353 * The difference (modulo counted) between V(UR) and N(U) is
354 * calculated as follows:
355 * - add 512 (maximum sequence number + 1) to V(UR), in case V(UR)
356 * is smaller than N(U)
357 * - subtract N(U)
358 * - subtract 1 because V(UR) is not contained within
359 * last_32_frames_bitfield and thus the bit shift must be one less
360 * - afterwards apply modulo 512 to get back into the range of
361 * sequence numbers, because we added this value initially to
362 * V(UR)
363 */
364 diff = (vur + (MAX_SEQUENCE_NUMBER+1) - nu - 1) % (MAX_SEQUENCE_NUMBER + 1);
365
366 /*
367 * Check if the corresponding bit of N(U) in last_32_frames_bitfield is
368 * set. The bit is stored in last_32_frames_bitfield relative to V(UR).
369 */
370 return ((llc_data->uirx->last_32_frames_bitfield & (0x00000001L << diff)) != 0L);
371 } /* uirx_check_nu() */
372
373
374 /*
375 +------------------------------------------------------------------------------
376 | Function : uirx_set_new_vur
377 +------------------------------------------------------------------------------
378 | Description : This procedure handles setting vur to a new value. The modulo
379 | operation and the handling of the last_32_frames_bitfield
380 | is done here.
381 |
382 | Parameters : new_vur - V(UR), must be in range V(UR) < new_vur < V(UR)-32
383 |
384 +------------------------------------------------------------------------------
385 */
386 GLOBAL void uirx_set_new_vur (T_FRAME_NUM new_vur)
387 {
388 USHORT diff;
389
390
391 TRACE_FUNCTION( "uirx_set_new_vur" );
392
393 new_vur %= (MAX_SEQUENCE_NUMBER+1);
394
395 /*
396 * The difference (modulo counted) between V(UR) and the new_vur is
397 * calculated as follows:
398 * - add 512 (maximum sequence number + 1) to new_vur
399 * - subtract V(UR)
400 * - afterwards apply modulo 512 to get back into the range of
401 * sequence numbers, because we added this value initially
402 */
403 diff = (new_vur + (MAX_SEQUENCE_NUMBER+1) - llc_data->sapi->vur)
404 % (MAX_SEQUENCE_NUMBER+1);
405
406 /*
407 * Now move the bitfield indicating the last 32 frames numbers. If the diff
408 * from current to new_vur is to large, the bitfild is automaticly cleard
409 * by shifting all bits out.
410 */
411 llc_data->uirx->last_32_frames_bitfield <<= diff;
412
413 /*
414 * Increase oc if necessary. If new_vur is a higher value, no overflow
415 * encountered. If new_vur is lower, an retransmission could be possible
416 * or we have had an overflow. But this function will not be called in
417 * case of a retransmission!
418 */
419 if ( new_vur < llc_data->sapi->vur )
420 {
421 llc_data->sapi->oc_ui_rx += (MAX_SEQUENCE_NUMBER+1);
422 }
423
424 /*
425 * Set net V(UR) value
426 */
427 llc_data->sapi->vur = new_vur;
428
429 } /* uirx_set_new_vur() */
430