FreeCalypso > hg > fc-magnetite
comparison src/g23m-gprs/llc/llc_uirxf.c @ 183:219afcfc6250
src/g23m-gprs: initial import from TCS3.2/LoCosto
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 13 Oct 2016 04:24:13 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
182:f02d0a0e1849 | 183:219afcfc6250 |
---|---|
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 |