FreeCalypso > hg > fc-magnetite
comparison src/g23m-gprs/grlc/grlc_ruf.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 : GPRS (8441) | |
4 | Modul : GRLC | |
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 module implements local functions for service RU of | |
18 | entity GRLC. | |
19 +----------------------------------------------------------------------------- | |
20 */ | |
21 | |
22 #ifndef GRLC_RUF_C | |
23 #define GRLC_RUF_C | |
24 #endif | |
25 | |
26 #define ENTITY_GRLC | |
27 | |
28 | |
29 /*==== INCLUDES =============================================================*/ | |
30 | |
31 #include <stdio.h> | |
32 #include "typedefs.h" /* to get Condat data types */ | |
33 #include "vsi.h" /* to get a lot of macros */ | |
34 #include "macdef.h" | |
35 #include "gprs.h" | |
36 #include "gsm.h" /* to get a lot of macros */ | |
37 #include "ccdapi.h" /* to get CCD API */ | |
38 #include "cnf_grlc.h" /* to get cnf-definitions */ | |
39 #include "mon_grlc.h" /* to get mon-definitions */ | |
40 #include "prim.h" /* to get the definitions of used SAP and directions */ | |
41 #include "message.h" | |
42 #include "grlc.h" /* to get the global entity definitions */ | |
43 #include "grlc_f.h" | |
44 #include "grlc_tms.h" | |
45 #include "grlc_rds.h" | |
46 #include "grlc_ruf.h" | |
47 #include <string.h> | |
48 #include "cl_rlcmac.h" | |
49 | |
50 /*==== CONST ================================================================*/ | |
51 | |
52 /*==== LOCAL VARS ===========================================================*/ | |
53 | |
54 /*==== PRIVATE FUNCTIONS ====================================================*/ | |
55 | |
56 /*==== PUBLIC FUNCTIONS =====================================================*/ | |
57 | |
58 | |
59 | |
60 /* | |
61 +------------------------------------------------------------------------------ | |
62 | Function : ru_init | |
63 +------------------------------------------------------------------------------ | |
64 | Description : The function ru_init() set init values in null state. | |
65 | | |
66 | Parameters : dummy - description of parameter dummy | |
67 | | |
68 +------------------------------------------------------------------------------ | |
69 */ | |
70 GLOBAL void ru_init ( void ) | |
71 { | |
72 UBYTE i; | |
73 UBYTE j; | |
74 | |
75 TRACE_FUNCTION( "ru_init" ); | |
76 INIT_STATE(RU,RU_NULL); | |
77 | |
78 /* | |
79 * UBYTE | |
80 */ | |
81 grlc_data->ru.nts = 0xFF; | |
82 grlc_data->ru.nts_max = 0xFF; | |
83 grlc_data->ru.ti = 0xFF; | |
84 grlc_data->ru.next_prim = 0xFF; | |
85 grlc_data->ru.active_prim = 0xFF; | |
86 grlc_data->ru.vs = 0xFF; | |
87 grlc_data->ru.va = 0xFF; | |
88 grlc_data->ru.bsn_ret = 0xFF; | |
89 grlc_data->ru.last_si_block = 0xFF; | |
90 grlc_data->ru.cv = 0xFF; | |
91 grlc_data->ru.N3104 = 0xFF; | |
92 grlc_data->ru.N3104_MAX = 0xFF; | |
93 grlc_data->ru.block_status = 0xFF; | |
94 grlc_data->ru.poll_tn = 0xFF; | |
95 grlc_data->ru.count_cv_0 = 0xFF; | |
96 grlc_data->ru.nr_nacked_blks = 0xFF; | |
97 grlc_data->ru.pdu_cnt = 0xFF; | |
98 grlc_data->ru.pdu_sent = 0xFF; | |
99 grlc_data->ru.pdu_rem = 0xFF; | |
100 grlc_data->ru.pdu_boundaries = 0xFF; | |
101 | |
102 grlc_data->ru.write_pos_index = 0xFF; | |
103 | |
104 /* | |
105 * USHORT | |
106 */ | |
107 grlc_data->ru.rlc_data_size = 0xFFFF; | |
108 grlc_data->ru.sdu_len = 0xFFFF; | |
109 grlc_data->ru.sdu_off = 0xFFFF; | |
110 grlc_data->ru.rlc_octet_cnt = 0xFFFF; | |
111 grlc_data->ru.tbc = 0xFFFF; | |
112 grlc_data->ru.cnt_ts = 0xFFFF; | |
113 | |
114 /* | |
115 * BOOL | |
116 */ | |
117 grlc_data->ru.tlli_cs_type = FALSE; | |
118 grlc_data->ru.cd_active = TRUE; | |
119 grlc_data->ru.first_usf = FALSE; | |
120 grlc_data->ru.release_tbf = FALSE; | |
121 #if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH | |
122 grlc_data->ru.tbf_re_est = FALSE; | |
123 #endif | |
124 | |
125 /* | |
126 * Type | |
127 */ | |
128 grlc_data->ru.cs_type = CS_ZERO; | |
129 /* | |
130 * structs | |
131 */ | |
132 grlc_data->ru.pl_retrans_current.cnt = 0xFF; | |
133 memset(grlc_data->ru.pl_retrans_current.blk, 0xFF, 4); | |
134 /* | |
135 * array | |
136 */ | |
137 for (i=0;i<WIN_SIZE;i++) | |
138 grlc_data->ru.vb[i & WIN_MOD] = VB_INVALID; | |
139 /* | |
140 * global structs | |
141 */ | |
142 for (i=0;i<NEXT_POLL_ARRAY_SIZE;i++) | |
143 { | |
144 /* | |
145 * set free list | |
146 */ | |
147 grlc_data->next_poll_array[i].next = i+1; | |
148 grlc_data->next_poll_array[i].fn = 0xFFFFFFFF; | |
149 grlc_data->next_poll_array[i].cnt = 0; | |
150 for(j=0; j< POLL_TYPE_ARRAY_SIZE; j++) | |
151 grlc_data->next_poll_array[i].poll_type[j] = CGRLC_POLL_NONE; | |
152 } | |
153 /* | |
154 * last free entry points to 0xff | |
155 */ | |
156 grlc_data->next_poll_array[NEXT_POLL_ARRAY_SIZE-1].next = 0xFF; | |
157 /* | |
158 * indicates invalid paramters | |
159 */ | |
160 grlc_data->poll_start_free = 0; | |
161 grlc_data->poll_start_tbf = 0xFF; | |
162 | |
163 } /* ru_init() */ | |
164 | |
165 | |
166 | |
167 /* | |
168 | |
169 +------------------------------------------------------------------------------ | |
170 | Function : ru_within_window | |
171 +------------------------------------------------------------------------------ | |
172 | Description : The function ru_within_window() checks if the bsn_i value is | |
173 | between high_value_i and low_value_i(modulo operating). | |
174 | The return value is result. | |
175 | | |
176 | | |
177 | Parameters : bsn_i - chech this value | |
178 | high_value_i - right side of the window | |
179 | low_value_i - left side of the window | |
180 | | |
181 +------------------------------------------------------------------------------ | |
182 */ | |
183 GLOBAL BOOL ru_within_window ( UBYTE bsn_i, UBYTE high_value_i,UBYTE low_value_i ) | |
184 { | |
185 BOOL result = FALSE; | |
186 TRACE_FUNCTION( "ru_within_window" ); | |
187 | |
188 if( | |
189 ( high_value_i >= low_value_i ) AND /* vs >= va */ | |
190 ( bsn_i > low_value_i ) AND /* ssn > va */ | |
191 ( bsn_i <= high_value_i ) /* vs >= ssn */ | |
192 ) | |
193 { | |
194 result = TRUE; | |
195 } | |
196 else if( ( high_value_i < low_value_i ) /* va > vs */ | |
197 AND | |
198 ( ( ( bsn_i > low_value_i ) AND /* ssn > va */ | |
199 ( bsn_i > high_value_i )) OR /* ssn > vs */ | |
200 ( ( bsn_i < low_value_i ) AND /* ssn > va */ | |
201 ( bsn_i <= high_value_i )) /* ssn <= vs */ | |
202 ) | |
203 ) | |
204 { | |
205 result = TRUE; | |
206 } | |
207 | |
208 /* if(!result) | |
209 { | |
210 TRACE_EVENT_P3("BSN not in range: low=%d bsn=%d high=%d", low_value_i,bsn_i,high_value_i); | |
211 } | |
212 */ | |
213 | |
214 return result; | |
215 } /* ru_within_window() */ | |
216 | |
217 | |
218 | |
219 /* | |
220 +------------------------------------------------------------------------------ | |
221 | Function : ru_recalc_rlc_oct_cnt | |
222 +------------------------------------------------------------------------------ | |
223 | Description : The function ru_recalc_rlc_oct_cnt() the number of octetcs | |
224 | during the TBF. It is needed for starting the countdown procedure | |
225 | | |
226 | Parameters : dummy - description of parameter dummy | |
227 | | |
228 +------------------------------------------------------------------------------ | |
229 */ | |
230 GLOBAL USHORT ru_recalc_rlc_oct_cnt ( void ) | |
231 { | |
232 USHORT result; | |
233 UBYTE next_cnt; | |
234 UBYTE prev_cnt; | |
235 UBYTE rem_pdu_bound; | |
236 ULONG rest_of_pdu; | |
237 UBYTE last_pdu_bound; | |
238 TRACE_FUNCTION( "ru_recalc_rlc_oct_cnt" ); | |
239 | |
240 grlc_data->ru.next_prim = grlc_data->prim_queue[grlc_data->ru.active_prim].next; | |
241 result = grlc_data->ru.sdu_len; | |
242 next_cnt = grlc_data->ru.next_prim; | |
243 if(grlc_data->ru.sdu_len) | |
244 grlc_data->ru.pdu_rem = 1; | |
245 | |
246 /*init calculate nr of pdu boundaries*/ | |
247 rest_of_pdu = grlc_data->ru.sdu_len%grlc_data->ru.rlc_data_size; | |
248 if((rest_of_pdu EQ 0) AND | |
249 ((next_cnt EQ 0xFF) OR /* either no primitive in queue */ | |
250 grlc_data->prim_queue[next_cnt].start_new_tbf)) /* or next primitive belongs to new tbf */ | |
251 rem_pdu_bound = 0; /*fills excatly in cv=0*/ | |
252 else if(rest_of_pdu EQ 0) | |
253 rem_pdu_bound = 2; /*fills exxalty, more pdus rerq, therefore 2 bounds*/ | |
254 else | |
255 rem_pdu_bound = 1; /*normal case*/ | |
256 last_pdu_bound = rem_pdu_bound; | |
257 | |
258 #ifdef _SIMULATION_ | |
259 TRACE_EVENT_P4("pdu_len=%d,rest_of_pdu=%d,rem_pdu_bound=%d,last_pdu_bound=%d", | |
260 grlc_data->ru.sdu_len, | |
261 rest_of_pdu, | |
262 rem_pdu_bound, | |
263 last_pdu_bound ); | |
264 #endif /* #ifdef _SIMULATION_ */ | |
265 | |
266 prev_cnt = grlc_data->ru.active_prim; | |
267 while((next_cnt < PRIM_QUEUE_SIZE_TOTAL) AND | |
268 (grlc_data->prim_queue[next_cnt].start_new_tbf EQ 0) | |
269 ) | |
270 { | |
271 ULONG sdu_len; | |
272 result += grlc_data->prim_queue[next_cnt].prim_ptr->sdu.l_buf/8; | |
273 sdu_len = grlc_data->prim_queue[next_cnt].prim_ptr->sdu.l_buf/8; | |
274 grlc_data->prim_queue[next_cnt].previous = prev_cnt; | |
275 grlc_data->prim_queue[next_cnt].cv_status = FALSE; | |
276 grlc_data->prim_queue[next_cnt].rlc_status = FALSE; | |
277 grlc_data->prim_queue[next_cnt].last_bsn = 0xFF; | |
278 | |
279 prev_cnt = next_cnt; | |
280 next_cnt = grlc_data->prim_queue[next_cnt].next; | |
281 grlc_data->ru.pdu_rem++; | |
282 | |
283 /*init calculate nr of pdu boundaries*/ | |
284 | |
285 rest_of_pdu = ((sdu_len+last_pdu_bound+rest_of_pdu)%grlc_data->ru.rlc_data_size); | |
286 if((rest_of_pdu EQ 0) AND ((next_cnt EQ 0xFF) OR grlc_data->prim_queue[next_cnt].start_new_tbf)) | |
287 { | |
288 rem_pdu_bound += 0; /*fills excatly in cv=0*/ | |
289 last_pdu_bound = 0; | |
290 } | |
291 else if(rest_of_pdu EQ 0) | |
292 { | |
293 rem_pdu_bound += 2; /*fills exxalty, more pdus rerq, therefore 2 bounds*/ | |
294 last_pdu_bound = 2; | |
295 } | |
296 else | |
297 { | |
298 rem_pdu_bound += 1; /*normal case*/ | |
299 last_pdu_bound = 1; | |
300 } | |
301 #ifdef _SIMULATION_ | |
302 TRACE_EVENT_P4("pdu_len=%d,rest_of_pdu=%d,rem_pdu_bound=%d,last_pdu_bound=%d", | |
303 sdu_len, | |
304 rest_of_pdu, | |
305 rem_pdu_bound, | |
306 last_pdu_bound ); | |
307 #endif /* #ifdef _SIMULATION_ */ | |
308 | |
309 } | |
310 grlc_data->ru.pdu_cnt = grlc_data->ru.pdu_rem+grlc_data->ru.pdu_sent; | |
311 grlc_data->ru.pdu_boundaries = rem_pdu_bound; | |
312 #ifdef _SIMULATION_ | |
313 TRACE_EVENT_P4("pdu_cnt=%d,pdu_sent=%d,pdu_rem=%d,needed pdu_boundaries=%d", | |
314 grlc_data->ru.pdu_cnt, | |
315 grlc_data->ru.pdu_sent, | |
316 grlc_data->ru.pdu_rem, | |
317 grlc_data->ru.pdu_boundaries ); | |
318 #endif /* #ifdef _SIMULATION_ */ | |
319 | |
320 grlc_data->tbf_ctrl[grlc_data->ul_index].pdu_cnt = grlc_data->ru.pdu_cnt; | |
321 return result; | |
322 } /* ru_recalc_rlc_oct_cnt() */ | |
323 | |
324 | |
325 | |
326 | |
327 | |
328 /* | |
329 +------------------------------------------------------------------------------ | |
330 | Function : ru_get_next_sdu | |
331 +------------------------------------------------------------------------------ | |
332 | Description : The function ru_get_next_sdu() gets the next GRLC_DATA_REQ from | |
333 | the queue. | |
334 | | |
335 | Parameters : dummy - description of parameter dummy | |
336 | | |
337 +------------------------------------------------------------------------------ | |
338 */ | |
339 GLOBAL void ru_get_next_sdu ( void ) | |
340 { | |
341 TRACE_FUNCTION( "ru_get_next_sdu" ); | |
342 | |
343 grlc_data->ru.pdu_rem--; | |
344 grlc_data->ru.pdu_sent++; | |
345 grlc_data->prim_queue[grlc_data->ru.active_prim].last_bsn = grlc_data->ru.vs; | |
346 | |
347 if((grlc_data->prim_queue[grlc_data->ru.next_prim].start_new_tbf EQ 0) AND | |
348 grlc_data->ru.next_prim NEQ 0xFF) | |
349 { | |
350 grlc_data->ru.active_prim = grlc_data->prim_queue[grlc_data->ru.active_prim].next; | |
351 grlc_data->ru.sdu_len = grlc_data->prim_queue[grlc_data->ru.active_prim].prim_ptr->sdu.l_buf/8; | |
352 grlc_data->ru.sdu_off = grlc_data->prim_queue[grlc_data->ru.active_prim].prim_ptr->sdu.o_buf/8; | |
353 grlc_data->prim_queue[grlc_data->ru.active_prim].rlc_status = TRUE; | |
354 grlc_data->ru.next_prim = grlc_data->prim_queue[grlc_data->ru.active_prim].next; | |
355 } | |
356 else | |
357 { | |
358 grlc_data->ru.sdu_len = 0; | |
359 grlc_data->ru.sdu_off = 0; | |
360 | |
361 } | |
362 | |
363 #ifdef _SIMULATION_ | |
364 TRACE_EVENT_P3("pdu_cnt=%d,pdu_sent=%d,pdu_rem=%d", | |
365 grlc_data->ru.pdu_cnt, | |
366 grlc_data->ru.pdu_sent, | |
367 grlc_data->ru.pdu_rem ); | |
368 #endif /* #ifdef _SIMULATION_ */ | |
369 | |
370 } /* ru_get_next_sdu() */ | |
371 | |
372 | |
373 | |
374 | |
375 | |
376 /* | |
377 +------------------------------------------------------------------------------ | |
378 | Function : ru_calc_rlc_data_size | |
379 +------------------------------------------------------------------------------ | |
380 | Description : The function ru_calc_rlc_data_size() calculates the Data size of | |
381 | an RLC data block without header and TLLI. The size is described | |
382 | in bytes. | |
383 | | |
384 | Parameters : cs_type_i - Coding scheme, determines the size of an RLC data block | |
385 | | |
386 +------------------------------------------------------------------------------ | |
387 */ | |
388 GLOBAL USHORT ru_calc_rlc_data_size ( T_CODING_SCHEME cs_type_i, UBYTE ti_bit_i ) | |
389 { | |
390 USHORT result=0; | |
391 UBYTE tlli_size; | |
392 TRACE_FUNCTION( "ru_calc_rlc_data_size" ); | |
393 | |
394 /* | |
395 * check if tlli must be included in RLC data blocks | |
396 */ | |
397 if (ti_bit_i EQ 0) | |
398 tlli_size = 0; | |
399 else | |
400 { | |
401 tlli_size = TLLI_SIZE; | |
402 if(!(grlc_data->ru.tlli_cs_type)) | |
403 cs_type_i = CS_1; | |
404 #ifdef REL99 | |
405 if(grlc_data->pfi_support) | |
406 { | |
407 tlli_size++; | |
408 } | |
409 #endif | |
410 } | |
411 | |
412 switch( cs_type_i) | |
413 { | |
414 case CS_1: | |
415 result = 20; | |
416 break; | |
417 case CS_2: | |
418 result = 30; | |
419 break; | |
420 case CS_3: | |
421 result = 36; | |
422 break; | |
423 case CS_4: | |
424 result = 50; | |
425 break; | |
426 default: | |
427 if (!result) | |
428 { | |
429 TRACE_EVENT_P2("Unknown coding scheme, tsize=%d, t_cs=%d", | |
430 tlli_size, grlc_data->ru.tlli_cs_type); | |
431 result = 20; /* Going by CS1 coding scheme by default */ | |
432 } | |
433 | |
434 break; | |
435 } | |
436 | |
437 | |
438 result -= tlli_size; | |
439 | |
440 return result; | |
441 } /* ru_calc_rlc_data_size() */ | |
442 | |
443 | |
444 /* | |
445 +------------------------------------------------------------------------------ | |
446 | Function : ru_set_block_status | |
447 +------------------------------------------------------------------------------ | |
448 | Description : The function ru_set_block_status() sets the block status. | |
449 | | |
450 | Parameters : cs_type_i - Coding scheme, determines the block status | |
451 | | |
452 +------------------------------------------------------------------------------ | |
453 */ | |
454 GLOBAL USHORT ru_set_block_status ( T_CODING_SCHEME cs_type_i ) | |
455 { | |
456 USHORT result=0; | |
457 TRACE_FUNCTION( "ru_set_block_status" ); | |
458 | |
459 if(!(grlc_data->ru.tlli_cs_type) AND | |
460 grlc_data->ru.ti) | |
461 cs_type_i = CS_1; | |
462 | |
463 switch( cs_type_i) | |
464 { | |
465 case CS_1: | |
466 result = 2; | |
467 break; | |
468 case CS_2: | |
469 result = 4; | |
470 break; | |
471 case CS_3: | |
472 result = 5; | |
473 break; | |
474 case CS_4: | |
475 result = 6; | |
476 break; | |
477 default: | |
478 TRACE_EVENT_P3("Unknown CS cstype=%d t_cs=%d, ti=%d",cs_type_i, | |
479 grlc_data->ru.tlli_cs_type, grlc_data->ru.ti); | |
480 | |
481 break; | |
482 } | |
483 return result; | |
484 } /* ru_set_block_status() */ | |
485 | |
486 | |
487 /* | |
488 +------------------------------------------------------------------------------ | |
489 | Function : ru_get_cs_type | |
490 +------------------------------------------------------------------------------ | |
491 | Description : The function ru_get_cs_type() returns the coding scheme | |
492 | for the requeseted block status. | |
493 | | |
494 | Parameters : bs_i - requested block status | |
495 | | |
496 +------------------------------------------------------------------------------ | |
497 */ | |
498 GLOBAL T_CODING_SCHEME ru_get_cs_type ( USHORT bs_i ) | |
499 { | |
500 T_CODING_SCHEME result= CS_ZERO; | |
501 ; | |
502 TRACE_FUNCTION( "ru_get_cs_type" ); | |
503 | |
504 | |
505 switch( bs_i) | |
506 { | |
507 case 2: | |
508 result = CS_1; | |
509 break; | |
510 case 4: | |
511 result = CS_2; | |
512 break; | |
513 case 5: | |
514 result = CS_3; | |
515 break; | |
516 case 6: | |
517 result = CS_4; | |
518 break; | |
519 default: | |
520 TRACE_ERROR("unknown block status"); | |
521 break; | |
522 } | |
523 return result; | |
524 } /* ru_get_cs_type() */ | |
525 /* | |
526 +------------------------------------------------------------------------------ | |
527 | Function : ru_tbf_init | |
528 +------------------------------------------------------------------------------ | |
529 | Description : The function ru_tbf_init() sets the parameters at tbf assignment | |
530 | | |
531 | Parameters : dummy - description of parameter dummy | |
532 | | |
533 +------------------------------------------------------------------------------ | |
534 */ | |
535 GLOBAL void ru_tbf_init ( void ) | |
536 { | |
537 UBYTE i; | |
538 | |
539 TRACE_FUNCTION( "ru_tbf_init" ); | |
540 | |
541 grlc_data->ru.rlc_mode = grlc_data->uplink_tbf.rlc_mode; | |
542 grlc_data->ru.nts = grlc_data->uplink_tbf.nts; | |
543 grlc_data->ru.nts_max = grlc_data->uplink_tbf.nts; | |
544 grlc_data->ru.va = 0; | |
545 grlc_data->ul_tn_mask = grlc_data->uplink_tbf.ts_mask; | |
546 #if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH | |
547 grlc_data->ru.tbf_re_est = FALSE; | |
548 #endif | |
549 | |
550 | |
551 /* | |
552 * initate l1 queue parameters | |
553 */ | |
554 grlc_data->ru.write_pos_index = 0; | |
555 for(i=0; i<MAX_UL_TN;i++) | |
556 grlc_data->ru.ul_data[i].block_status = 0; | |
557 | |
558 | |
559 if(grlc_data->ru.rlc_mode EQ CGRLC_RLC_MODE_ACK) | |
560 { | |
561 /* | |
562 * parameters only used in acknowledged mode | |
563 */ | |
564 grlc_data->ru.bsn_ret = 0; | |
565 grlc_data->ru.last_si_block = 0; | |
566 grlc_data->ru.N3104_MAX = 3 * (grlc_data->uplink_tbf.bs_cv_max + 3 ) * grlc_data->ru.nts_max; | |
567 grlc_data->ru.nr_nacked_blks = 0; | |
568 grlc_data->ru.ti = grlc_data->uplink_tbf.ti; | |
569 } | |
570 else if(grlc_data->ru.rlc_mode EQ CGRLC_RLC_MODE_UACK) | |
571 { | |
572 /* | |
573 * parameters only used in unacknowledged mode | |
574 */ | |
575 grlc_data->ru.count_cv_0 = 0; | |
576 /* | |
577 * tlli is not send within data blocks | |
578 */ | |
579 grlc_data->ru.ti = 0; | |
580 } | |
581 | |
582 /* | |
583 * read the first pdu | |
584 */ | |
585 | |
586 grlc_data->ru.active_prim = grlc_data->prim_start_tbf; | |
587 grlc_data->prim_queue[grlc_data->prim_start_tbf].previous = 0xFF; | |
588 grlc_data->ru.next_prim = grlc_data->prim_queue[grlc_data->ru.active_prim].next; | |
589 grlc_data->prim_queue[grlc_data->prim_start_tbf].cv_status = FALSE; | |
590 grlc_data->prim_queue[grlc_data->prim_start_tbf].last_bsn = 0xFF; | |
591 grlc_data->ru.vs = 0; | |
592 grlc_data->ru.cv = 55; | |
593 /* | |
594 * USHORT | |
595 */ | |
596 grlc_data->ru.sdu_len = grlc_data->prim_queue[grlc_data->ru.active_prim].prim_ptr->sdu.l_buf/8; | |
597 grlc_data->ru.sdu_off = grlc_data->prim_queue[grlc_data->ru.active_prim].prim_ptr->sdu.o_buf/8; | |
598 grlc_data->prim_queue[grlc_data->ru.active_prim].rlc_status = TRUE; | |
599 grlc_data->ru.pdu_sent = 0; | |
600 grlc_data->ru.cnt_ts = 0; | |
601 /* | |
602 * ULONG | |
603 */ | |
604 grlc_data->missed_poll_fn = 1; | |
605 | |
606 /* | |
607 * BOOL | |
608 */ | |
609 grlc_data->ru.tlli_cs_type = grlc_data->uplink_tbf.tlli_cs_type; | |
610 grlc_data->ru.cd_active = FALSE; | |
611 grlc_data->ru.reorg_l1_needed = FALSE; | |
612 grlc_data->ru.v_next_tbf_params = FALSE; | |
613 grlc_data->ul_tfi_changed = FALSE; | |
614 grlc_data->ru.release_tbf = FALSE; | |
615 | |
616 /* | |
617 * Type | |
618 */ | |
619 grlc_data->ru.cs_type = grlc_data->uplink_tbf.cs_type; | |
620 grlc_data->ru.last_bsn = LAST_BSN_NOT_BULIT; | |
621 /* | |
622 * struct | |
623 */ | |
624 if(grlc_data->uplink_tbf.mac_mode EQ CGRLC_MAC_MODE_DA) | |
625 { | |
626 /* | |
627 * Start t3164, when starting time is elapsed. | |
628 * Only if contention resolution is needed and not fixed alloc is used. | |
629 */ | |
630 grlc_data->ru.first_usf = TRUE; | |
631 } | |
632 grlc_data->ru.rlc_data_size = ru_calc_rlc_data_size(grlc_data->ru.cs_type, grlc_data->ru.ti); | |
633 grlc_data->ru.block_status = ru_set_block_status(grlc_data->ru.cs_type); | |
634 | |
635 /* | |
636 * handle close ended TBF | |
637 */ | |
638 if (grlc_data->uplink_tbf.rlc_db_granted ) | |
639 { | |
640 ULONG rlc_oct_cnt ; | |
641 | |
642 UBYTE next = grlc_data->prim_queue[grlc_data->prim_start_tbf].next; | |
643 | |
644 rlc_oct_cnt = (grlc_data->prim_queue[grlc_data->prim_start_tbf].prim_ptr->sdu.l_buf/8)+1; | |
645 | |
646 grlc_data->uplink_tbf.rlc_db_granted *= grlc_data->ru.rlc_data_size; | |
647 | |
648 while( (next < PRIM_QUEUE_SIZE) AND | |
649 (!grlc_data->prim_queue[next].start_new_tbf) AND | |
650 ((rlc_oct_cnt+(grlc_data->prim_queue[next].prim_ptr->sdu.l_buf/8)+1) < grlc_data->uplink_tbf.rlc_db_granted)) | |
651 { | |
652 rlc_oct_cnt += (grlc_data->prim_queue[next].prim_ptr->sdu.l_buf/8)+1; | |
653 next = grlc_data->prim_queue[next].next; | |
654 } | |
655 if(next < PRIM_QUEUE_SIZE) | |
656 grlc_data->prim_queue[next].start_new_tbf = 1; | |
657 | |
658 TRACE_EVENT_P4("close ended TBF: rlc_g=%ld rlc_oct =%ld data_size=%d next=%d" | |
659 ,grlc_data->uplink_tbf.rlc_db_granted | |
660 ,rlc_oct_cnt | |
661 ,grlc_data->ru.rlc_data_size | |
662 ,next); | |
663 } | |
664 | |
665 grlc_data->ru.rlc_octet_cnt = ru_recalc_rlc_oct_cnt(); /*rlc data size needed*/ | |
666 grlc_data->ru.pl_retrans_current.cnt = 0; | |
667 | |
668 | |
669 | |
670 | |
671 /* TRACE PARAMS*/ | |
672 grlc_data->ul_index = 0; | |
673 grlc_data->tbf_ctrl[grlc_data->ul_index].tbf_type = TBF_TYPE_UL; | |
674 grlc_data->tbf_ctrl[grlc_data->ul_index].tfi = grlc_data->ul_tfi; | |
675 grlc_data->tbf_ctrl[grlc_data->ul_index].rlc_oct_cnt = 0; | |
676 grlc_data->tbf_ctrl[grlc_data->ul_index].ret_bsn = 0; | |
677 grlc_data->tbf_ctrl[grlc_data->ul_index].ack_cnt = 0; | |
678 grlc_data->tbf_ctrl[grlc_data->ul_index].fbi = 0; | |
679 } /* ru_tbf_init() */ | |
680 | |
681 | |
682 | |
683 /* | |
684 +------------------------------------------------------------------------------ | |
685 | Function : ru_set_T3198 | |
686 +------------------------------------------------------------------------------ | |
687 | Description : The function ru_set_T3198() starts the timer T3198 of the rlc | |
688 | data block with bsn as input parameter. The timer is handled in | |
689 | BS_CV_MAX block periods. | |
690 | | |
691 | Parameters : bsn_i - bsn value of the data block | |
692 | | |
693 +------------------------------------------------------------------------------ | |
694 */ | |
695 GLOBAL void ru_set_T3198 ( UBYTE bsn_i ) | |
696 { | |
697 USHORT block_periods; | |
698 | |
699 | |
700 TRACE_FUNCTION( "ru_set_T3198" ); | |
701 | |
702 | |
703 block_periods = MAXIMUM(1,grlc_data->uplink_tbf.bs_cv_max); | |
704 /* | |
705 * set timer T3198 , | |
706 * the framenumber is set, at which the block is set to negative acknowledged | |
707 */ | |
708 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].T3198 = grlc_decode_tbf_start_rel(grlc_data->ul_fn, --block_periods); | |
709 | |
710 #ifdef _SIMULATION_ | |
711 TRACE_EVENT_P4("SET T3198: bsn %d t3198=%ld c_fn=%ld bs_cv_max=%d" | |
712 ,bsn_i | |
713 ,grlc_data->ru.rlc_data[bsn_i & WIN_MOD].T3198 | |
714 ,grlc_data->ul_fn | |
715 ,grlc_data->uplink_tbf.bs_cv_max); | |
716 #endif | |
717 | |
718 } /* ru_set_T3198() */ | |
719 | |
720 /* | |
721 +------------------------------------------------------------------------------ | |
722 | Function : ru_send_mac_data_req | |
723 +------------------------------------------------------------------------------ | |
724 | Description : The function ru_send_mac_data_req() sends the data block with | |
725 | bsn_i. The claculated block is matched in the PL buffer | |
726 | (and MAC_DATA_REQ primitive, if SIMULATION is defined). | |
727 | | |
728 | Parameters : bsn_i - bsn value of the next to sent data block | |
729 | | |
730 +------------------------------------------------------------------------------ | |
731 */ | |
732 GLOBAL void ru_send_mac_data_req ( UBYTE bsn_i ) | |
733 { | |
734 UBYTE li_cnt; | |
735 UBYTE data_cnt; | |
736 UBYTE i; | |
737 USHORT l_tlli; | |
738 UBYTE len; | |
739 USHORT off; | |
740 UBYTE index; | |
741 UBYTE *ptr_temp; | |
742 TRACE_FUNCTION( "ru_send_mac_data_req" ); | |
743 | |
744 #ifdef _SIMULATION_ | |
745 TRACE_EVENT_P2("BSN=%d mac_header=%x ",bsn_i, grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.mac); | |
746 #endif /* #ifdef _SIMULATION_ */ | |
747 | |
748 | |
749 | |
750 { | |
751 memset(&grlc_data->ru.ul_data[grlc_data->ru.write_pos_index], | |
752 0, | |
753 sizeof(T_ul_data)); | |
754 | |
755 grlc_data->ru.ul_data[grlc_data->ru.write_pos_index].block_status = grlc_data->ru.rlc_data[bsn_i & WIN_MOD].block_status; | |
756 | |
757 ptr_temp = (UBYTE *) (grlc_data->ru.ul_data[grlc_data->ru.write_pos_index].ul_block); | |
758 /* | |
759 * set MAC Header | |
760 */ | |
761 ptr_temp[0] = grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.mac; | |
762 | |
763 ptr_temp[1] = (grlc_data->ul_tfi << 1 | | |
764 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.ti); | |
765 | |
766 ptr_temp[2] = (bsn_i << 1 | | |
767 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.e_bit); /*lint !e415*/ | |
768 /* | |
769 * set Length Indicator field(s) if present | |
770 */ | |
771 li_cnt = grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.li_cnt; | |
772 for(i=3; i<(3+li_cnt);i++) | |
773 ptr_temp[i] = grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.li_me[i-3]; /*lint !e661 !e662*/ | |
774 /* | |
775 * set TLLI field, if present | |
776 */ | |
777 if(grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.ti) | |
778 { | |
779 grlc_set_tlli( &l_tlli, &off, &(ptr_temp[3+li_cnt]), grlc_data->uplink_tbf.tlli ); | |
780 l_tlli /= 8; /* handled in bytes */ | |
781 | |
782 #ifdef REL99 | |
783 if (grlc_data->pfi_support) | |
784 { | |
785 ptr_temp[1] |= 0x40; | |
786 ptr_temp[3+li_cnt+l_tlli] =(grlc_data->pfi_value << 1) | 0x01;/*04.60 7.1.2.6(initial pfi)*/ /*E bit = 1*/ | |
787 l_tlli++; | |
788 } | |
789 #endif | |
790 | |
791 } | |
792 else | |
793 l_tlli = 0; | |
794 /* | |
795 * copy LLC DATA | |
796 */ | |
797 index = 0; | |
798 data_cnt = grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data_cnt; | |
799 for(i=0;i<data_cnt;i++) | |
800 { | |
801 len = grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data[i].l_buf / 8; | |
802 off = grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data[i].o_buf / 8; | |
803 if(!grlc_test_mode_active()) | |
804 { /* | |
805 * get regular data | |
806 */ | |
807 memcpy(&(ptr_temp[3+li_cnt+l_tlli+index]), | |
808 (grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data[i].ptr_data->buf + off), | |
809 len); /*lint !e797*/ | |
810 } | |
811 else | |
812 { | |
813 /* | |
814 * test mode active, get test data | |
815 */ | |
816 if(grlc_data->testmode.mode EQ CGRLC_TEST_RANDOM) | |
817 { | |
818 /* | |
819 * CGRLC_TEST_RANDOM | |
820 */ | |
821 if (!grlc_data->testmode.no_data_calculation) | |
822 { | |
823 /* | |
824 * First call in this block | |
825 */ | |
826 grlc_prbs(COMPUTE_DATA, len, grlc_data->testmode.ptr_test_data); | |
827 grlc_data->testmode.no_data_calculation = 1; | |
828 } | |
829 | |
830 | |
831 if (grlc_data->ru.nts EQ 1) | |
832 { | |
833 /* | |
834 * this block is finished, allow prbs data calculation aigain | |
835 */ | |
836 grlc_data->testmode.no_data_calculation = 0; | |
837 } | |
838 | |
839 /* | |
840 * copy the prbs in | |
841 */ | |
842 memcpy(&(ptr_temp[3+li_cnt+l_tlli+index]), grlc_data->testmode.ptr_test_data, len); /*lint !e797*/ | |
843 } | |
844 else | |
845 { | |
846 /* | |
847 * CGRLC_LOOP | |
848 */ | |
849 /* | |
850 * If the downlink TBF is established on more than one timeslot, the MS shall transmit in | |
851 * the second uplink timeslot (if present) RLC/MAC blocks received on the second downlink | |
852 * timeslot, and shall transmit in the third uplink timeslot (if present) RLC/MAC blocks | |
853 * received in the third downlink timeslot and so on. | |
854 * It is assumed that while transmitting L1 will transmit data blocks in the sequence | |
855 * in which it has received blocks from GRLC. | |
856 */ | |
857 if (grlc_data->downlink_tbf.nts > 1) | |
858 { | |
859 if (grlc_data->ru.write_pos_index EQ 0) | |
860 { | |
861 memcpy(&(ptr_temp[3+li_cnt+l_tlli+index]),grlc_data->testmode.rec_data[0].payload,len); | |
862 TRACE_EVENT_P4("bsn =%d ready for send, cs_type=%ld, e_bit=%d, tn=%d" | |
863 ,bsn_i | |
864 ,grlc_data->ru.ul_data[grlc_data->ru.write_pos_index].block_status | |
865 ,grlc_data->testmode.rec_data[0].e_bit | |
866 ,grlc_data->ru.write_pos_index); | |
867 } | |
868 else | |
869 { | |
870 memcpy(&(ptr_temp[3+li_cnt+l_tlli+index]),grlc_data->testmode.rec_data[1].payload,len); | |
871 TRACE_EVENT_P4("bsn =%d ready for send, cs_type=%ld, e_bit=%d, tn=%d" | |
872 ,bsn_i | |
873 ,grlc_data->ru.ul_data[grlc_data->ru.write_pos_index].block_status | |
874 ,grlc_data->testmode.rec_data[1].e_bit | |
875 ,grlc_data->ru.write_pos_index); | |
876 } | |
877 } | |
878 else | |
879 { | |
880 memcpy(&(ptr_temp[3+li_cnt+l_tlli+index]),grlc_data->testmode.rec_data[0].payload,len); | |
881 TRACE_EVENT_P3("bsn =%d ready for send, cs_type=%ld, e_bit=%d" | |
882 ,bsn_i | |
883 ,grlc_data->ru.ul_data[grlc_data->ru.write_pos_index].block_status | |
884 ,grlc_data->testmode.rec_data[0].e_bit); | |
885 } | |
886 | |
887 | |
888 } | |
889 } | |
890 index += len; | |
891 } | |
892 if((grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.mac & 0x3C) EQ 0) /* countdown value is equal 0*/ | |
893 { | |
894 /* | |
895 * fill rest of last block with 2B | |
896 */ | |
897 USHORT rlc_data_size; | |
898 rlc_data_size = ru_calc_rlc_data_size( ru_get_cs_type(grlc_data->ru.rlc_data[bsn_i & WIN_MOD].block_status) | |
899 , grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.ti); | |
900 len = rlc_data_size-index-li_cnt; | |
901 memset(&(ptr_temp[3+li_cnt+l_tlli+index]), | |
902 0x2B, | |
903 len); /*lint !e797*/ | |
904 } | |
905 | |
906 #ifdef _SIMULATION_ | |
907 { | |
908 PALLOC(mac_data_req,MAC_DATA_REQ); | |
909 memset(&(mac_data_req->ul_data), | |
910 0, | |
911 sizeof(T_ul_data)); | |
912 memcpy(&(mac_data_req->ul_data), | |
913 &(grlc_data->ru.ul_data[grlc_data->ru.write_pos_index]), | |
914 sizeof(T_ul_data)); /*lint !e797*/ | |
915 PSEND(hCommL1,mac_data_req); | |
916 } | |
917 TRACE_EVENT_P1("wpi %d",grlc_data->ru.write_pos_index); | |
918 #else /* #ifdef _SIMULATION_ */ | |
919 { | |
920 TRACE_MEMORY_PRIM ( hCommGRLC, hCommL1, MAC_DATA_REQ, | |
921 &grlc_data->ru.ul_data[grlc_data->ru.write_pos_index], | |
922 sizeof(T_ul_data) ); | |
923 } | |
924 #endif /* #ifdef _SIMULATION_ */ | |
925 | |
926 grlc_data->ru.write_pos_index++; | |
927 | |
928 /* | |
929 * indicates the PL, there is no more block | |
930 */ | |
931 grlc_data->ru.ul_data[grlc_data->ru.write_pos_index].block_status = 0; | |
932 } | |
933 grlc_data->ru.pl_retrans_current.blk[grlc_data->ru.pl_retrans_current.cnt] = bsn_i; | |
934 grlc_data->ru.pl_retrans_current.cnt++; | |
935 grlc_data->ru.nts--; | |
936 grlc_data->ru.vb[bsn_i & WIN_MOD] = VB_PENDING_ACK; | |
937 } /* ru_send_mac_data_req() */ | |
938 | |
939 | |
940 | |
941 | |
942 /* | |
943 +------------------------------------------------------------------------------ | |
944 | Function : ru_set_prim_queue | |
945 +------------------------------------------------------------------------------ | |
946 | Description : The function ru_set_prim_queue() updates the primitive queue. | |
947 | If the countdown procedure is started, all LLC PDUs which belongs | |
948 | to the current tbf are signed with cv_status as true. In this case | |
949 | these LLC PDUs can´t reorginized an more LLC PDU can sent during | |
950 | his TBF. Additionally received LLC PDUs are sent in a new TBF. | |
951 | If the countdown procedure is stopped (i.e. change of cpding | |
952 | scheme) then this functions resets the cv_status to False. | |
953 | | |
954 | Parameters : cd_state_i - if true, the countdown procedue is started, else | |
955 | it is stopped | |
956 | | |
957 +------------------------------------------------------------------------------ | |
958 */ | |
959 GLOBAL void ru_set_prim_queue ( BOOL cd_state_i ) | |
960 { | |
961 UBYTE next; | |
962 TRACE_FUNCTION( "ru_set_prim_queue" ); | |
963 | |
964 next = grlc_data->ru.next_prim; | |
965 grlc_data->prim_queue[grlc_data->ru.active_prim].cv_status = cd_state_i; | |
966 | |
967 while( (grlc_data->prim_queue[next].start_new_tbf EQ 0) AND (next NEQ 0xFF) ) | |
968 { | |
969 grlc_data->prim_queue[next].cv_status = cd_state_i; | |
970 next = grlc_data->prim_queue[next].next; | |
971 } | |
972 | |
973 | |
974 } /* ru_set_prim_queue() */ | |
975 | |
976 | |
977 | |
978 | |
979 /* | |
980 +------------------------------------------------------------------------------ | |
981 | Function : ru_countdown_procedure | |
982 +------------------------------------------------------------------------------ | |
983 | Description : The function ru_countdown_procedure() calculates the countdown | |
984 | value. After Contention resoultion is succesfully completed or | |
985 | at changing of the Coding scheme(indicateded in packet | |
986 | uplink ack/nack or packet timeslot reconfigure), the countdown | |
987 | value must be recalculated. | |
988 | | |
989 | Parameters : dummy - description of parameter dummy | |
990 | | |
991 +------------------------------------------------------------------------------ | |
992 */ | |
993 GLOBAL UBYTE ru_countdown_procedure ( UBYTE ret_blocks ) | |
994 { | |
995 USHORT x; | |
996 UBYTE result; | |
997 TRACE_FUNCTION( "ru_countdown_procedure" ); | |
998 | |
999 /* | |
1000 * ret_blocks is the number of blocks which has to retransmit | |
1001 * formular for cv calculation: x = round((TBC-bsn´-1)/nts) | |
1002 * here tbc = (TBC-bsn) so that | |
1003 * x = round((tbc-1)/nts) | |
1004 * nr of pdu bundaries is also considered for calculating tbc | |
1005 */ | |
1006 | |
1007 #ifdef _SIMULATION_ | |
1008 TRACE_EVENT_P3("bs_cv_max=%d rlc_oct_cnt=%d data_size=%d",grlc_data->uplink_tbf.bs_cv_max,grlc_data->ru.rlc_octet_cnt,grlc_data->ru.rlc_data_size); | |
1009 #endif /* #ifdef _SIMULATION_ */ | |
1010 | |
1011 | |
1012 if(grlc_data->testmode.mode EQ CGRLC_LOOP) | |
1013 { | |
1014 TRACE_EVENT("testmode B: cv value=15"); | |
1015 return (15); | |
1016 } | |
1017 | |
1018 grlc_data->ru.tbc = (grlc_data->ru.rlc_octet_cnt+grlc_data->ru.pdu_boundaries) / grlc_data->ru.rlc_data_size; | |
1019 if( (grlc_data->ru.rlc_octet_cnt+grlc_data->ru.pdu_boundaries) % grlc_data->ru.rlc_data_size) /*round upwards*/ | |
1020 grlc_data->ru.tbc++; | |
1021 | |
1022 | |
1023 x = (grlc_data->ru.tbc -1 + ret_blocks) / grlc_data->ru.nts_max; | |
1024 | |
1025 if( (grlc_data->ru.tbc -1 + ret_blocks ) % grlc_data->ru.nts_max) /*round upwards*/ | |
1026 x++; | |
1027 | |
1028 | |
1029 if(x > grlc_data->uplink_tbf.bs_cv_max) | |
1030 { | |
1031 result = 15; | |
1032 if(grlc_data->ru.cd_active) | |
1033 { | |
1034 grlc_data->ru.cd_active = FALSE; | |
1035 ru_set_prim_queue(grlc_data->ru.cd_active); | |
1036 } | |
1037 } | |
1038 else | |
1039 { | |
1040 result = (UBYTE)x; | |
1041 if(!grlc_data->ru.cd_active AND | |
1042 ((grlc_data->ru.state NEQ RU_WAIT_FOR_FIRST_CALL_ACK) OR (grlc_data->ru.state NEQ RU_WAIT_FOR_FIRST_CALL_UACK))) | |
1043 { | |
1044 grlc_data->ru.cd_active = TRUE; | |
1045 ru_set_prim_queue(grlc_data->ru.cd_active); | |
1046 } | |
1047 } | |
1048 | |
1049 return result; | |
1050 | |
1051 } /* ru_countdown_procedure() */ | |
1052 | |
1053 | |
1054 | |
1055 | |
1056 /* | |
1057 +------------------------------------------------------------------------------ | |
1058 | Function : ru_update_vb | |
1059 +------------------------------------------------------------------------------ | |
1060 | Description : The function ru_update_vb() refreshs the VB array field after | |
1061 | receiving a packet uplink ack/nack. | |
1062 | | |
1063 | Parameters : dummy - description of parameter dummy | |
1064 | | |
1065 +------------------------------------------------------------------------------ | |
1066 */ | |
1067 GLOBAL void ru_update_vb ( void ) | |
1068 { | |
1069 MCAST(d_ul_ack,D_GRLC_UL_ACK); | |
1070 UBYTE bsn, ssn, i; | |
1071 TRACE_FUNCTION( "ru_update_vb" ); | |
1072 | |
1073 ssn = d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.ssn; | |
1074 /* | |
1075 * Check if ssn is valid | |
1076 */ | |
1077 if(!ru_within_window(ssn,grlc_data->ru.vs,grlc_data->ru.va)) | |
1078 { | |
1079 TRACE_EVENT_P4( "SSN OUTSIDE WINDOW: ssn=%d, vs=%d, va=%d f_ack_ind=%d", | |
1080 ssn, | |
1081 grlc_data->ru.vs, | |
1082 grlc_data->ru.va, | |
1083 d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.f_ack_ind); | |
1084 return; | |
1085 } | |
1086 grlc_data->ru.nr_nacked_blks = 0; | |
1087 for(i = 1; i <= WIN_SIZE; i++) | |
1088 { | |
1089 bsn = (ssn - i) & 0x7F; /*mod 128*/ | |
1090 if(d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.rbb[WIN_SIZE-i]) | |
1091 { | |
1092 if(grlc_data->ru.vb[bsn & WIN_MOD] NEQ VB_ACKED) | |
1093 { | |
1094 grlc_data->ru.vb[bsn & WIN_MOD] = VB_ACKED; | |
1095 } | |
1096 } | |
1097 else if(grlc_check_if_tbf_start_is_elapsed ( grlc_data->ru.rlc_data[bsn & WIN_MOD].T3198, grlc_data->ul_fn)) | |
1098 { | |
1099 /* | |
1100 * timeout T3198 | |
1101 */ | |
1102 grlc_data->ru.vb[bsn & WIN_MOD] = VB_NACKED; | |
1103 grlc_data->ru.nr_nacked_blks++; | |
1104 } | |
1105 else | |
1106 { | |
1107 TRACE_EVENT_P3("BSN =%d not acked. T3198=%ld not expired (c_fn=%ld). vb not modified" | |
1108 ,bsn | |
1109 ,grlc_data->ru.rlc_data[bsn & WIN_MOD].T3198 | |
1110 ,grlc_data->ul_fn); | |
1111 } | |
1112 if (bsn EQ grlc_data->ru.va) | |
1113 i = WIN_SIZE+1; /* break cobdition*/ | |
1114 } | |
1115 | |
1116 } /* ru_update_vb() */ | |
1117 | |
1118 | |
1119 | |
1120 | |
1121 /* | |
1122 +------------------------------------------------------------------------------ | |
1123 | Function : ru_calc_rlc_data_block | |
1124 +------------------------------------------------------------------------------ | |
1125 | Description : The funcion ru_calc_rlc_data_block() builds a complete RLC | |
1126 | data block. | |
1127 | | |
1128 | Parameters : bsn_i - bsn value of the calculated RLC data block | |
1129 | | |
1130 +------------------------------------------------------------------------------ | |
1131 */ | |
1132 GLOBAL void ru_calc_rlc_data_block ( UBYTE bsn_i ) | |
1133 { | |
1134 USHORT rlc_len; | |
1135 UBYTE li_cnt, data_cnt; | |
1136 TRACE_FUNCTION( "ru_calc_rlc_data_block" ); | |
1137 | |
1138 /* | |
1139 * calculate the countdown value, no retransmission | |
1140 */ | |
1141 grlc_data->ru.cv = ru_countdown_procedure(0); | |
1142 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].block_status = grlc_data->ru.block_status; | |
1143 | |
1144 /* | |
1145 * set MAC header | |
1146 */ | |
1147 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.mac = (grlc_data->ru.cv << 2 | | |
1148 grlc_data->r_bit ); | |
1149 /* | |
1150 * set RLC header values | |
1151 */ | |
1152 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.ti = grlc_data->ru.ti; | |
1153 | |
1154 /* | |
1155 * data handling | |
1156 */ | |
1157 rlc_len = grlc_data->ru.rlc_data_size; | |
1158 data_cnt = 0; | |
1159 li_cnt = 0; | |
1160 | |
1161 if(grlc_data->testmode.mode EQ CGRLC_LOOP) | |
1162 { | |
1163 grlc_data->ru.sdu_len = 7777; /* random value */ | |
1164 grlc_data->ru.sdu_off = 0; | |
1165 rlc_len = 50; | |
1166 grlc_data->ru.rlc_octet_cnt = 7777; /* to be in line with sdu_len*/ | |
1167 TRACE_EVENT("testmode B: get data from received downlink"); | |
1168 } | |
1169 | |
1170 | |
1171 | |
1172 while ( (grlc_data->ru.sdu_len < rlc_len) AND (grlc_data->ru.sdu_len > 0) ) | |
1173 { | |
1174 /* | |
1175 * end of pdu in block reached | |
1176 */ | |
1177 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.li_me[li_cnt]= (UBYTE) grlc_data->ru.sdu_len; | |
1178 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.li_me[li_cnt] <<= 2; | |
1179 | |
1180 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data[li_cnt].ptr_data = | |
1181 &(grlc_data->prim_queue[grlc_data->ru.active_prim].prim_ptr->sdu); | |
1182 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data[li_cnt].l_buf = grlc_data->ru.sdu_len * 8; | |
1183 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data[li_cnt].o_buf = grlc_data->ru.sdu_off * 8; | |
1184 rlc_len -= grlc_data->ru.sdu_len + 1; | |
1185 grlc_data->ru.rlc_octet_cnt -= grlc_data->ru.sdu_len; | |
1186 grlc_data->ru.sdu_len -= grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data[li_cnt].l_buf/8; | |
1187 grlc_data->ru.sdu_off += grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data[li_cnt].l_buf/8; | |
1188 ru_get_next_sdu(); | |
1189 if((grlc_data->ru.sdu_len > 0) AND rlc_len) | |
1190 { | |
1191 /* | |
1192 * one more sdu in queue | |
1193 */ | |
1194 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.li_me[li_cnt] |= 0x02; | |
1195 } | |
1196 else | |
1197 { | |
1198 /* | |
1199 * no more sdu in queue | |
1200 */ | |
1201 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.li_me[li_cnt] |= 0x01; | |
1202 } | |
1203 data_cnt++; | |
1204 li_cnt++; | |
1205 if(li_cnt > NR_OF_PDUS_PER_RLCMAC_BLOCK) | |
1206 { | |
1207 TRACE_EVENT_P2("li_cnt=%d NR_OF_PDUS_PER_RLCMAC_BLOCK=%d",li_cnt,NR_OF_PDUS_PER_RLCMAC_BLOCK); | |
1208 TRACE_ERROR("ru li_cnt bigger than RD_LI_CNT_MAX (=8)"); | |
1209 TRACE_ASSERT( li_cnt > NR_OF_PDUS_PER_RLCMAC_BLOCK ); | |
1210 return; | |
1211 } | |
1212 } | |
1213 | |
1214 if((grlc_data->ru.sdu_len EQ rlc_len) AND (grlc_data->ru.sdu_len > 0) AND (grlc_data->ru.cv EQ 0)) | |
1215 { | |
1216 /* | |
1217 * end of pdu; rest of pdu match exactly into the rest of a rlc data block, last uplink block | |
1218 */ | |
1219 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data[li_cnt].ptr_data = | |
1220 &(grlc_data->prim_queue[grlc_data->ru.active_prim].prim_ptr->sdu); /*lint !e661*/ | |
1221 | |
1222 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data[li_cnt].l_buf = grlc_data->ru.sdu_len *8; /*lint !e661*/ | |
1223 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data[li_cnt].o_buf = grlc_data->ru.sdu_off *8; /*lint !e661*/ | |
1224 data_cnt++; | |
1225 grlc_data->ru.rlc_octet_cnt -= rlc_len; | |
1226 ru_get_next_sdu(); | |
1227 } | |
1228 else if((grlc_data->ru.sdu_len EQ rlc_len) AND (grlc_data->ru.sdu_len > 0)) | |
1229 { | |
1230 /* | |
1231 * end of pdu; rest of pdu match exactly into the rest of a rlc data block, | |
1232 * split into two blocks, len set to zero, indicates that the end of pdu is not reached | |
1233 */ | |
1234 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.li_me[li_cnt] = 0x01; /*lint !e661*/ | |
1235 | |
1236 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data[li_cnt].ptr_data = | |
1237 &(grlc_data->prim_queue[grlc_data->ru.active_prim].prim_ptr->sdu); /*lint !e661*/ | |
1238 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data[li_cnt].l_buf = (grlc_data->ru.sdu_len-1) *8; /*lint !e661*/ | |
1239 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data[li_cnt].o_buf = grlc_data->ru.sdu_off *8; /*lint !e661*/ | |
1240 data_cnt++; | |
1241 li_cnt++; | |
1242 rlc_len--; | |
1243 grlc_data->ru.sdu_len -= rlc_len; | |
1244 grlc_data->ru.sdu_off += rlc_len; | |
1245 grlc_data->ru.rlc_octet_cnt -= rlc_len; | |
1246 if(li_cnt > NR_OF_PDUS_PER_RLCMAC_BLOCK) | |
1247 { | |
1248 TRACE_EVENT_P2("li_cnt=%d NR_OF_PDUS_PER_RLCMAC_BLOCK=%d",li_cnt,NR_OF_PDUS_PER_RLCMAC_BLOCK); | |
1249 TRACE_ERROR("ru2 li_cnt bigger than RD_LI_CNT_MAX (=8)"); | |
1250 TRACE_ASSERT( li_cnt > NR_OF_PDUS_PER_RLCMAC_BLOCK ); | |
1251 return; | |
1252 } | |
1253 } | |
1254 else if( (grlc_data->ru.sdu_len > 0) AND rlc_len) | |
1255 { | |
1256 /* | |
1257 * only a part of the sdu matches into the rlc data block | |
1258 */ | |
1259 if(grlc_data->testmode.mode EQ CGRLC_LOOP) | |
1260 { | |
1261 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data[li_cnt].ptr_data = NULL; /*lint !e661*/ | |
1262 TRACE_EVENT("set data ptr for testmode B to NULL"); | |
1263 } | |
1264 else | |
1265 { | |
1266 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data[li_cnt].ptr_data = | |
1267 &(grlc_data->prim_queue[grlc_data->ru.active_prim].prim_ptr->sdu); /*lint !e661*/ | |
1268 } | |
1269 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data[li_cnt].l_buf = rlc_len * 8; /*lint !e661*/ | |
1270 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data[li_cnt].o_buf = grlc_data->ru.sdu_off * 8; /*lint !e661*/ | |
1271 data_cnt++; | |
1272 grlc_data->ru.sdu_len -= rlc_len; | |
1273 grlc_data->ru.sdu_off += rlc_len; | |
1274 grlc_data->ru.rlc_octet_cnt -= rlc_len; | |
1275 } | |
1276 /* | |
1277 * LI fied parameters are set | |
1278 */ | |
1279 if(grlc_data->testmode.mode EQ CGRLC_LOOP) | |
1280 { | |
1281 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.e_bit = grlc_data->testmode.rec_data[0].e_bit; | |
1282 } | |
1283 else if(li_cnt) | |
1284 { | |
1285 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.e_bit = 0; | |
1286 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.li_me[li_cnt-1] |= 0x01; | |
1287 grlc_data->ru.pdu_boundaries -= li_cnt; | |
1288 #ifdef _SIMULATION_ | |
1289 TRACE_EVENT_P2("li_cnt=%d,remaining pdu boundaries=%d", | |
1290 li_cnt, | |
1291 grlc_data->ru.pdu_boundaries); | |
1292 #endif /* #ifdef _SIMULATION_ */ | |
1293 | |
1294 } | |
1295 else | |
1296 { | |
1297 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.e_bit = 1; | |
1298 } | |
1299 | |
1300 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].header.li_cnt = li_cnt; | |
1301 grlc_data->ru.rlc_data[bsn_i & WIN_MOD].data_cnt = data_cnt; | |
1302 | |
1303 | |
1304 | |
1305 } /* ru_calc_rlc_data_block() */ | |
1306 | |
1307 | |
1308 /* | |
1309 +------------------------------------------------------------------------------ | |
1310 | Function : ru_handle_n3102 | |
1311 +------------------------------------------------------------------------------ | |
1312 | Description : The function ru_handle_n3102() handles the counter N3102. | |
1313 | If the input parameter ia PAN_INC, then the counter is | |
1314 | incremented. If the input parameter ia PAN_DEC, then the | |
1315 | counter is decremented. | |
1316 | | |
1317 | Parameters : pan_cnt_i - determines, if the counter is either in- or | |
1318 | decremented | |
1319 | | |
1320 +------------------------------------------------------------------------------ | |
1321 */ | |
1322 GLOBAL void ru_handle_n3102 ( T_PAN_CNT pan_cnt_i ) | |
1323 { | |
1324 TRACE_FUNCTION( "ru_handle_n3102" ); | |
1325 | |
1326 if((grlc_data->N3102 NEQ 0xFF) AND | |
1327 grlc_data->pan_struct.inc AND | |
1328 grlc_data->pan_struct.dec AND | |
1329 grlc_data->pan_struct.pmax) | |
1330 { | |
1331 | |
1332 switch( pan_cnt_i ) | |
1333 { | |
1334 case PAN_INC: | |
1335 grlc_data->N3102 += grlc_data->pan_struct.inc; | |
1336 grlc_data->N3102 = MINIMUM(grlc_data->N3102,grlc_data->pan_struct.pmax); | |
1337 | |
1338 /*TRACE_EVENT_P4( "INC N3102: inc=%d, dec=%d, pan_max=%d n3102=%d", | |
1339 grlc_data->pan_struct.inc, | |
1340 grlc_data->pan_struct.dec, | |
1341 pgrlc_data->pan_struct.pmax, | |
1342 grlc_data->N3102 );*/ | |
1343 break; | |
1344 case PAN_DEC: | |
1345 if( grlc_data->N3102 > grlc_data->pan_struct.dec ) | |
1346 { | |
1347 grlc_data->N3102 -= grlc_data->pan_struct.dec; | |
1348 | |
1349 TRACE_EVENT_P4( "DEC1 N3102: inc=%d, dec=%d, pan_max=%d n3102=%d", | |
1350 grlc_data->pan_struct.inc, | |
1351 grlc_data->pan_struct.dec, | |
1352 grlc_data->pan_struct.pmax, | |
1353 grlc_data->N3102 ); | |
1354 | |
1355 sig_ru_tm_error_ra(); | |
1356 } | |
1357 else | |
1358 { | |
1359 grlc_data->N3102 = 0; | |
1360 | |
1361 TRACE_EVENT_P4( "DEC2 N3102: inc=%d, dec=%d, pan_max=%d n3102=%d", | |
1362 grlc_data->pan_struct.inc, | |
1363 grlc_data->pan_struct.dec, | |
1364 grlc_data->pan_struct.pmax, | |
1365 grlc_data->N3102); | |
1366 sig_ru_tm_error_ra(); | |
1367 } | |
1368 break; | |
1369 default: | |
1370 TRACE_ERROR("unknown type for pan_cnt_i"); | |
1371 break; | |
1372 } | |
1373 } | |
1374 else if(pan_cnt_i EQ PAN_DEC) | |
1375 { | |
1376 TRACE_EVENT( "IGNORE N3102" ); | |
1377 | |
1378 sig_ru_tm_error_ra(); | |
1379 } | |
1380 } /* ru_handle_n3102() */ | |
1381 | |
1382 | |
1383 | |
1384 /* | |
1385 +------------------------------------------------------------------------------ | |
1386 | Function : ru_calc_va | |
1387 +------------------------------------------------------------------------------ | |
1388 | Description : The function ru_calc_va() claculates the block, that was | |
1389 | negatively acknowledged and must be retransmitted in the next | |
1390 | uplink block. | |
1391 | | |
1392 | Parameters : dummy - description of parameter dummy | |
1393 | | |
1394 +------------------------------------------------------------------------------ | |
1395 */ | |
1396 GLOBAL UBYTE ru_calc_va ( void ) | |
1397 { | |
1398 UBYTE result; | |
1399 TRACE_FUNCTION( "ru_calc_va" ); | |
1400 | |
1401 result = (grlc_data->ru.va) & 0x7F /*mod 128*/; | |
1402 | |
1403 while( (grlc_data->ru.vb[result & WIN_MOD] EQ VB_ACKED) AND | |
1404 (result NEQ grlc_data->ru.vs)) | |
1405 { | |
1406 result = (result+1) & 0x7F /*mod 128*/; | |
1407 } | |
1408 return result; | |
1409 } /* ru_calc_va() */ | |
1410 | |
1411 | |
1412 /* | |
1413 +------------------------------------------------------------------------------ | |
1414 | Function : ru_set_next_bsn_ret() | |
1415 +------------------------------------------------------------------------------ | |
1416 | Description : The function ru_set_next_bsn_ret sets the next valid bsn, | |
1417 | which shall be transmitted as next retransmission | |
1418 | | |
1419 | Parameters : - description of parameter dummy | |
1420 | | |
1421 +------------------------------------------------------------------------------ | |
1422 */ | |
1423 | |
1424 GLOBAL UBYTE ru_set_next_bsn_ret ( void) | |
1425 { | |
1426 UBYTE new_bsn_ret; | |
1427 TRACE_FUNCTION( "ru_set_next_bsn_ret" ); | |
1428 | |
1429 | |
1430 new_bsn_ret = (grlc_data->ru.bsn_ret+1) & 0x7F; | |
1431 while( (grlc_data->ru.vb[new_bsn_ret & WIN_MOD] NEQ VB_PENDING_ACK) AND | |
1432 (grlc_data->ru.vb[new_bsn_ret & WIN_MOD] NEQ VB_NACKED) AND | |
1433 new_bsn_ret NEQ grlc_data->ru.vs ) | |
1434 { | |
1435 new_bsn_ret = (new_bsn_ret+1) & 0x7F; | |
1436 } | |
1437 if( new_bsn_ret EQ grlc_data->ru.vs ) | |
1438 { | |
1439 grlc_data->ru.nr_nacked_blks = 0 ; | |
1440 new_bsn_ret = grlc_data->ru.va; | |
1441 } | |
1442 | |
1443 return new_bsn_ret; | |
1444 | |
1445 } /* ru_set_next_bsn_ret() */ | |
1446 | |
1447 | |
1448 /* | |
1449 +------------------------------------------------------------------------------ | |
1450 | Function : ru_ret_bsn | |
1451 +------------------------------------------------------------------------------ | |
1452 | Description : The function ru_ret_bsn() is called in RU_REL_ACK. In this state | |
1453 | all RLC data blocks are transmitted, but not acknowledged. If | |
1454 | more uplink PDCHs are available(i.e. the PL reads valid USF | |
1455 | flags), then the blocks which currently where not acked are | |
1456 | retransmitted. The bsn value of the next block is controled by | |
1457 | bsn_ret. | |
1458 | | |
1459 | Parameters : dummy | |
1460 | | |
1461 +------------------------------------------------------------------------------ | |
1462 */ | |
1463 GLOBAL void ru_ret_bsn ( void ) | |
1464 { | |
1465 | |
1466 TRACE_FUNCTION( "ru_ret_bsn" ); | |
1467 | |
1468 /* TRACE_EVENT_P3("BSN RET: bsn=%d, cv=%d vb=%d" | |
1469 ,grlc_data->ru.bsn_ret | |
1470 ,grlc_data->ru.rlc_data[grlc_data->ru.bsn_ret & WIN_MOD].header.cv | |
1471 ,grlc_data->ru.vb[grlc_data->ru.bsn_ret & WIN_MOD]); | |
1472 */ | |
1473 ru_send_mac_data_req(grlc_data->ru.bsn_ret); | |
1474 grlc_data->ru.bsn_ret = ru_set_next_bsn_ret(); | |
1475 | |
1476 } /* ru_ret_bsn() */ | |
1477 | |
1478 | |
1479 | |
1480 | |
1481 | |
1482 /* | |
1483 +------------------------------------------------------------------------------ | |
1484 | Function : ru_change_of_cs | |
1485 +------------------------------------------------------------------------------ | |
1486 | Description : The function ru_change_of_cs() handles the change of the coding | |
1487 | scheme. Folling values must be recalculated. | |
1488 | 1. rlc_data_len | |
1489 | 2. rlc_octet_cnt | |
1490 | | |
1491 | Parameters : cs_type_i - new coding scheme | |
1492 | | |
1493 +------------------------------------------------------------------------------ | |
1494 */ | |
1495 GLOBAL void ru_change_of_cs ( T_CODING_SCHEME cs_type_i ) | |
1496 { | |
1497 TRACE_FUNCTION( "ru_change_of_cs" ); | |
1498 | |
1499 grlc_data->ru.rlc_data_size = ru_calc_rlc_data_size(cs_type_i,grlc_data->ru.ti); | |
1500 grlc_data->ru.block_status = ru_set_block_status(grlc_data->ru.cs_type); | |
1501 if(grlc_data->ru.last_bsn NEQ LAST_BSN_IS_SENT) | |
1502 { | |
1503 grlc_data->ru.rlc_octet_cnt = ru_recalc_rlc_oct_cnt(); | |
1504 grlc_data->ru.reorg_l1_needed = TRUE; | |
1505 } | |
1506 else | |
1507 { | |
1508 TRACE_EVENT_P3("No REORG dueto CS change requried: rlc_cnt=%ld l_bsn=%d cv=%d" | |
1509 ,grlc_data->ru.rlc_octet_cnt | |
1510 ,grlc_data->ru.last_bsn | |
1511 ,grlc_data->ru.cv); | |
1512 } | |
1513 } /* ru_change_of_cs() */ | |
1514 | |
1515 | |
1516 | |
1517 /* | |
1518 +------------------------------------------------------------------------------ | |
1519 | Function : ru_contention_resolution | |
1520 +------------------------------------------------------------------------------ | |
1521 | Description : The function ru_contention_resolution() checks at one phase | |
1522 | access after receiving a packet uplink ack/nack message the | |
1523 | contention resolution TLLI. | |
1524 | | |
1525 | Parameters : dummy - description of parameter dummy | |
1526 | | |
1527 +------------------------------------------------------------------------------ | |
1528 */ | |
1529 GLOBAL BOOL ru_contention_resolution ( void ) | |
1530 { | |
1531 MCAST(d_ul_ack,D_GRLC_UL_ACK); | |
1532 BOOL result = FALSE; | |
1533 | |
1534 TRACE_FUNCTION( "ru_contention_resolution" ); | |
1535 | |
1536 if((grlc_data->ru.ti) AND (d_ul_ack->gprs_ul_ack_nack_info.v_cr_tlli) ) | |
1537 { | |
1538 ULONG tlli; | |
1539 /* | |
1540 * TLLI received and Contention resolution not yet processed | |
1541 */ | |
1542 tlli = grlc_buffer2ulong( &d_ul_ack->gprs_ul_ack_nack_info.cr_tlli ); | |
1543 if(tlli EQ grlc_data->uplink_tbf.tlli) | |
1544 result = TRUE; | |
1545 grlc_data->ru.N3104 = 0; | |
1546 vsi_t_stop(GRLC_handle,T3166); | |
1547 if(result) | |
1548 { | |
1549 /* | |
1550 * correct TLLI received, contention resolution succesful | |
1551 */ | |
1552 grlc_data->ru.ti = 0; | |
1553 grlc_data->ru.rlc_data_size = ru_calc_rlc_data_size(grlc_data->ru.cs_type,grlc_data->ru.ti); | |
1554 grlc_data->ru.block_status = ru_set_block_status(grlc_data->ru.cs_type); | |
1555 /* | |
1556 * needed, because nr of pdu boundaries could be change | |
1557 */ | |
1558 grlc_data->ru.rlc_octet_cnt = ru_recalc_rlc_oct_cnt(); | |
1559 sig_ru_tm_cs(); | |
1560 result = FALSE; | |
1561 grlc_data->ru.reorg_l1_needed = TRUE; | |
1562 } | |
1563 else | |
1564 { | |
1565 /* | |
1566 * wrong TLLI received, contention resolution failed, TBF will be aborted | |
1567 */ | |
1568 result = TRUE; | |
1569 TRACE_ERROR( "TLLI error occured" ); | |
1570 sig_ru_tm_error_ra(); | |
1571 } | |
1572 } | |
1573 else if(grlc_data->ru.ti EQ 0) | |
1574 result = FALSE; | |
1575 | |
1576 return result; | |
1577 | |
1578 } /* ru_contention_resolution() */ | |
1579 | |
1580 | |
1581 | |
1582 /* | |
1583 +------------------------------------------------------------------------------ | |
1584 | Function : ru_delete_prims | |
1585 +------------------------------------------------------------------------------ | |
1586 | Description : The function ru_delete_prims() deletes LLC PDUs from the | |
1587 | primitive queue which are positivlely acknowledged(indirectly | |
1588 | by the highest bsn value in the rrb field included in the | |
1589 | packet uplink ack/nack). | |
1590 | | |
1591 | Parameters : last_bsn_i - all primitives including last_bsn_i are deleted. | |
1592 | | |
1593 +------------------------------------------------------------------------------ | |
1594 */ | |
1595 GLOBAL void ru_delete_prims ( UBYTE last_bsn_i ) | |
1596 { | |
1597 UBYTE cnt=0, prim_type=CGRLC_PRIM_TYPE_OTHER; | |
1598 BOOL all_null_frames = TRUE; | |
1599 | |
1600 TRACE_FUNCTION( "ru_delete_prims" ); | |
1601 /* | |
1602 * check if last_bsn_i is outside window | |
1603 */ | |
1604 while( (grlc_data->prim_start_tbf < PRIM_QUEUE_SIZE_TOTAL) AND | |
1605 (grlc_data->prim_queue[grlc_data->prim_start_tbf].last_bsn NEQ 0xFF) AND | |
1606 (ru_within_window( last_bsn_i, | |
1607 grlc_data->ru.vs, | |
1608 grlc_data->prim_queue[grlc_data->prim_start_tbf].last_bsn))) | |
1609 { | |
1610 cnt++; | |
1611 | |
1612 if( (prim_type NEQ CGRLC_PRIM_TYPE_GMM) AND | |
1613 (grlc_data->prim_queue[grlc_data->prim_start_tbf].prim_ptr->cause EQ GRLC_DTACS_MOBILITY_MANAGEMENT) ) | |
1614 { | |
1615 prim_type = CGRLC_PRIM_TYPE_GMM; | |
1616 } | |
1617 | |
1618 if( (all_null_frames EQ TRUE) AND | |
1619 (grlc_data->prim_queue[grlc_data->prim_start_tbf].prim_ptr->cause NEQ | |
1620 GRLC_DTACS_CELL_NOTIFI_NULL_FRAME) ) | |
1621 { | |
1622 /* This variable is set to FALSE in case there is at least ont not NULL frame */ | |
1623 all_null_frames = FALSE; | |
1624 } | |
1625 | |
1626 sig_ru_tm_prim_delete(); | |
1627 } | |
1628 | |
1629 if(cnt) | |
1630 { | |
1631 if( grlc_data->ready_timer.handling EQ READY_TIMER_HANDLING_ENABLED AND | |
1632 all_null_frames EQ FALSE AND | |
1633 grlc_data->ready_timer.value NEQ CGRLC_STANDBY ) | |
1634 { | |
1635 if (grlc_data->ready_timer.value NEQ CGRLC_DEACTIVATED) | |
1636 { | |
1637 /* The Ready Timer will be restarted in case of at least one not NULL frame and | |
1638 valid value (<>0 and <> 0xFFFFFFFF) */ | |
1639 vsi_t_start(GRLC_handle,T3314, grlc_data->ready_timer.value ); | |
1640 } | |
1641 | |
1642 grlc_enter_ready_state( ); | |
1643 } | |
1644 | |
1645 if( grlc_data->ready_timer.handling EQ READY_TIMER_HANDLING_DISABLED OR | |
1646 ( grlc_data->ready_timer.handling EQ READY_TIMER_HANDLING_ENABLED AND | |
1647 prim_type EQ CGRLC_PRIM_TYPE_GMM ) ) | |
1648 { | |
1649 PALLOC(cgrlc_trigger_ind,CGRLC_TRIGGER_IND); /* T_CGRLC_TRIGGER_IND */ | |
1650 cgrlc_trigger_ind->prim_type = prim_type; | |
1651 PSEND(hCommGMM,cgrlc_trigger_ind); | |
1652 } | |
1653 } | |
1654 | |
1655 | |
1656 | |
1657 #ifdef _SIMULATION_ | |
1658 TRACE_EVENT_P5("%d PRIMS deleted: last_bsn=%d vs=%d prim_start_tbf=%d, prim_cnt=%d ", | |
1659 cnt,last_bsn_i,grlc_data->ru.vs,grlc_data->prim_start_tbf,grlc_data->grlc_data_req_cnt); | |
1660 | |
1661 TRACE_EVENT_P3("pdu_cnt=%d,pdu_sent=%d,pdu_rem=%d", | |
1662 grlc_data->ru.pdu_cnt, | |
1663 grlc_data->ru.pdu_sent, | |
1664 grlc_data->ru.pdu_rem ); | |
1665 #endif /* #ifdef _SIMULATION_ */ | |
1666 } /* ru_delete_prims() */ | |
1667 | |
1668 | |
1669 | |
1670 /* | |
1671 +------------------------------------------------------------------------------ | |
1672 | Function : ru_handle_n3104 | |
1673 +------------------------------------------------------------------------------ | |
1674 | Description : The function ru_handle_n3104() controls the counter N3104. If | |
1675 | the counter reaches it maximum value, then the tbf is released. | |
1676 | The counter is ignored, if the contention resolution is | |
1677 | successfully completed. Evry time at receiption a packet uplink | |
1678 | ack/nack without including TLLI the counter is incremented. | |
1679 | | |
1680 | Parameters : dummy - description of parameter dummy | |
1681 | | |
1682 +------------------------------------------------------------------------------ | |
1683 */ | |
1684 GLOBAL BOOL ru_handle_n3104 ( void) | |
1685 { | |
1686 UBYTE result = FALSE; | |
1687 TRACE_FUNCTION( "ru_handle_n3104" ); | |
1688 | |
1689 if(grlc_data->ru.ti) | |
1690 { | |
1691 grlc_data->ru.N3104 = (UBYTE)grlc_data->ru.cnt_ts; | |
1692 if(grlc_data->ru.N3104 EQ grlc_data->ru.N3104_MAX) | |
1693 { | |
1694 result = TRUE; | |
1695 vsi_t_stop(GRLC_handle,T3166); | |
1696 } | |
1697 } | |
1698 return result; | |
1699 | |
1700 } /* ru_handle_n3104() */ | |
1701 | |
1702 | |
1703 | |
1704 /* | |
1705 +------------------------------------------------------------------------------ | |
1706 | Function : ru_send_control_block | |
1707 +------------------------------------------------------------------------------ | |
1708 | Description : The function ru_send_control_block() sends a control block | |
1709 | instead of RLC data block | |
1710 | | |
1711 | Parameters : dummy - description of parameter dummy | |
1712 | | |
1713 +------------------------------------------------------------------------------ | |
1714 */ | |
1715 GLOBAL void ru_send_control_block ( void ) | |
1716 { | |
1717 UBYTE index; | |
1718 | |
1719 TRACE_FUNCTION( "ru_send_control_block" ); | |
1720 | |
1721 #ifdef _SIMULATION_ | |
1722 | |
1723 memset( &grlc_data->ru.ul_data[grlc_data->ru.write_pos_index], | |
1724 0, sizeof( T_ul_data ) ); | |
1725 | |
1726 #endif /* #ifdef _SIMULATION_ */ | |
1727 | |
1728 grlc_data->ru.ul_data[grlc_data->ru.write_pos_index].block_status = 2; | |
1729 | |
1730 index = tm_cpy_ctrl_blk_to_buffer | |
1731 ( ( UBYTE* )grlc_data->ru.ul_data[grlc_data->ru.write_pos_index].ul_block ); | |
1732 | |
1733 #ifdef _SIMULATION_ | |
1734 { | |
1735 PALLOC(mac_data_req,MAC_DATA_REQ); | |
1736 memset(&(mac_data_req->ul_data), | |
1737 0, | |
1738 sizeof(T_ul_data)); | |
1739 memcpy(&(mac_data_req->ul_data), | |
1740 &(grlc_data->ru.ul_data[grlc_data->ru.write_pos_index]), | |
1741 sizeof(T_ul_data)); | |
1742 PSEND(hCommL1,mac_data_req); | |
1743 } | |
1744 TRACE_EVENT_P1("wpi %d",grlc_data->ru.write_pos_index); | |
1745 #else /* #ifdef _SIMULATION_ */ | |
1746 { | |
1747 TRACE_MEMORY_PRIM ( hCommGRLC, hCommL1, MAC_DATA_REQ, | |
1748 &grlc_data->ru.ul_data[grlc_data->ru.write_pos_index], | |
1749 sizeof(T_ul_data) ); | |
1750 } | |
1751 #endif /* #ifdef _SIMULATION_ */ | |
1752 | |
1753 { | |
1754 UBYTE* ul_block = ( UBYTE* )grlc_data->ru.ul_data[grlc_data->ru.write_pos_index].ul_block; | |
1755 | |
1756 TRACE_BINDUMP( hCommGRLC, TC_USER4, | |
1757 cl_rlcmac_get_msg_name | |
1758 ( ( UBYTE )( ul_block[1] >> 2 ), RLC_MAC_ROUTE_UL ), | |
1759 ul_block, MAX_L2_FRAME_SIZE ); /*lint !e569*/ | |
1760 } | |
1761 | |
1762 grlc_data->ru.write_pos_index++; | |
1763 grlc_data->ru.ul_data[grlc_data->ru.write_pos_index].block_status = 0; | |
1764 | |
1765 | |
1766 grlc_data->ru.pl_retrans_current.blk[grlc_data->ru.pl_retrans_current.cnt] = | |
1767 index + OFFSET_CTRL_BLOCK_IDX; | |
1768 grlc_data->ru.pl_retrans_current.cnt++; | |
1769 grlc_data->ru.nts--; | |
1770 | |
1771 | |
1772 } /* ru_send_control_block() */ | |
1773 | |
1774 | |
1775 /* | |
1776 +------------------------------------------------------------------------------ | |
1777 | Function : ru_stall_ind | |
1778 +------------------------------------------------------------------------------ | |
1779 | Description : The function ru_stall_ind() handles the stall indication. | |
1780 | If stall indication occurs, the the window is retransmitted if | |
1781 | uplink PDCHs are available. | |
1782 | | |
1783 | Parameters : dummy - description of parameter dummy | |
1784 | | |
1785 +------------------------------------------------------------------------------ | |
1786 */ | |
1787 GLOBAL void ru_stall_ind ( void) | |
1788 { | |
1789 TRACE_FUNCTION( "ru_stall_ind" ); | |
1790 | |
1791 /* set the si bit */ | |
1792 grlc_data->ru.rlc_data[grlc_data->ru.last_si_block & WIN_MOD].header.mac |= 0x02; | |
1793 /* send block with set si bit */ | |
1794 ru_send_mac_data_req(grlc_data->ru.last_si_block); | |
1795 /* reset the si bit */ | |
1796 grlc_data->ru.rlc_data[grlc_data->ru.last_si_block & WIN_MOD].header.mac &= 0xFD; | |
1797 | |
1798 grlc_data->ru.last_si_block = (grlc_data->ru.last_si_block+1) & 0x7F; | |
1799 if(grlc_data->ru.last_si_block EQ grlc_data->ru.vs) | |
1800 grlc_data->ru.last_si_block = grlc_data->ru.va ; | |
1801 | |
1802 } /* ru_stall_ind() */ | |
1803 | |
1804 | |
1805 /* | |
1806 +------------------------------------------------------------------------------ | |
1807 | Function : ru_new_data | |
1808 +------------------------------------------------------------------------------ | |
1809 | Description : The function ru_new_data() calculates the next in sequence data | |
1810 | and transmits it. | |
1811 | | |
1812 | Parameters : dummy - description of parameter dummy | |
1813 | | |
1814 +------------------------------------------------------------------------------ | |
1815 */ | |
1816 GLOBAL void ru_new_data ( void) | |
1817 { | |
1818 TRACE_FUNCTION( "ru_new_data" ); | |
1819 | |
1820 ru_calc_rlc_data_block(grlc_data->ru.vs); | |
1821 ru_send_mac_data_req(grlc_data->ru.vs); | |
1822 grlc_data->ru.rlc_data[grlc_data->ru.vs & WIN_MOD].cnt_pl_trans = 0; /*first try to transmit*/ | |
1823 grlc_data->ru.vs = (grlc_data->ru.vs+1) & 0x7F /*mod 128*/; | |
1824 } /* ru_new_data() */ | |
1825 | |
1826 | |
1827 | |
1828 | |
1829 /* | |
1830 +------------------------------------------------------------------------------ | |
1831 | Function : ru_reorg_l1 | |
1832 +------------------------------------------------------------------------------ | |
1833 | Description : The function ru_reorg_l1() recalculates data blocks which are | |
1834 | passed to l1 but wasn´t sent due to usf only after succesfull | |
1835 | contention resolution or change of coding scheme. | |
1836 | | |
1837 | Parameters : sent_blks_i - description of parameter dummy | |
1838 | | |
1839 +------------------------------------------------------------------------------ | |
1840 */ | |
1841 GLOBAL void ru_reorg_l1 ( UBYTE sent_blks_i ) | |
1842 { | |
1843 UBYTE cnt_reog_blks; /* number of reorged blks */ | |
1844 UBYTE reorged_blks = 0; /*counts the number of modified blocks*/ | |
1845 UBYTE i, bsn; | |
1846 | |
1847 TRACE_FUNCTION( "ru_reorg_l1" ); | |
1848 | |
1849 | |
1850 cnt_reog_blks = grlc_data->ru.nts_max - sent_blks_i; | |
1851 | |
1852 for (i=0; i < cnt_reog_blks; i++) | |
1853 { | |
1854 UBYTE index; | |
1855 | |
1856 index = grlc_data->ru.pl_retrans_current.cnt - 1 - i; | |
1857 bsn = grlc_data->ru.pl_retrans_current.blk[index]; | |
1858 if(bsn <= BSN_MAX) | |
1859 { | |
1860 #ifdef _SIMULATION_ | |
1861 TRACE_EVENT_P1("bsn %d",bsn); | |
1862 #endif | |
1863 if(!grlc_data->ru.rlc_data[bsn & WIN_MOD].cnt_pl_trans) | |
1864 {/* not transmitted over physical link */ | |
1865 UBYTE cnt_data_parts; | |
1866 reorged_blks++; | |
1867 grlc_data->ru.vs--; | |
1868 grlc_data->ru.vs = grlc_data->ru.vs & 0x7F; | |
1869 | |
1870 cnt_data_parts = grlc_data->ru.rlc_data[bsn & WIN_MOD].data_cnt - 1; | |
1871 grlc_data->ru.sdu_len += (grlc_data->ru.rlc_data[bsn & WIN_MOD].data[cnt_data_parts].l_buf/8); | |
1872 grlc_data->ru.sdu_off = (grlc_data->ru.rlc_data[bsn & WIN_MOD].data[cnt_data_parts].o_buf/8); | |
1873 grlc_data->ru.rlc_octet_cnt += (grlc_data->ru.rlc_data[bsn & WIN_MOD].data[cnt_data_parts].l_buf/8); | |
1874 | |
1875 if(cnt_data_parts) | |
1876 grlc_data->ru.sdu_len = 0; /* pdu bound in block*/ | |
1877 | |
1878 while(cnt_data_parts--) | |
1879 { | |
1880 grlc_data->ru.sdu_len += (grlc_data->ru.rlc_data[bsn & WIN_MOD].data[cnt_data_parts].l_buf/8); | |
1881 grlc_data->ru.sdu_off = grlc_data->ru.rlc_data[bsn & WIN_MOD].data[cnt_data_parts].o_buf/8; | |
1882 grlc_data->ru.rlc_octet_cnt += (grlc_data->ru.rlc_data[bsn & WIN_MOD].data[cnt_data_parts].l_buf/8); | |
1883 grlc_data->ru.next_prim = grlc_data->ru.active_prim; | |
1884 grlc_data->ru.active_prim = grlc_data->prim_queue[grlc_data->ru.active_prim].previous; | |
1885 grlc_data->prim_queue[grlc_data->ru.active_prim].last_bsn = grlc_data->prim_queue[grlc_data->ru.next_prim].last_bsn; | |
1886 TRACE_EVENT("parts of pdu present"); | |
1887 } | |
1888 /* | |
1889 * handle pdu parametes | |
1890 */ | |
1891 if((grlc_data->ru.rlc_data[bsn & WIN_MOD].header.mac & 0x3C) EQ 0) /* countdown value is equal 0*/ | |
1892 { | |
1893 grlc_data->ru.pdu_rem += grlc_data->ru.rlc_data[bsn & WIN_MOD].data_cnt; | |
1894 grlc_data->ru.pdu_sent -= grlc_data->ru.rlc_data[bsn & WIN_MOD].data_cnt; | |
1895 } | |
1896 else if(grlc_data->ru.rlc_data[bsn & WIN_MOD].header.li_cnt AND | |
1897 ((grlc_data->ru.rlc_data[bsn & WIN_MOD].header.li_me[grlc_data->ru.rlc_data[bsn & WIN_MOD].header.li_cnt-1] & 0xFC) EQ 0)) | |
1898 { | |
1899 grlc_data->ru.pdu_rem += grlc_data->ru.rlc_data[bsn & WIN_MOD].data_cnt; | |
1900 grlc_data->ru.pdu_sent -= grlc_data->ru.rlc_data[bsn & WIN_MOD].data_cnt; | |
1901 } | |
1902 else | |
1903 { | |
1904 grlc_data->ru.pdu_rem += grlc_data->ru.rlc_data[bsn & WIN_MOD].header.li_cnt; | |
1905 grlc_data->ru.pdu_sent -= grlc_data->ru.rlc_data[bsn & WIN_MOD].header.li_cnt; | |
1906 } | |
1907 if(grlc_data->ru.state EQ RU_REL_ACK) | |
1908 { | |
1909 SET_STATE(RU,RU_ACK); | |
1910 } | |
1911 else if(grlc_data->ru.state EQ RU_REL_UACK) | |
1912 { | |
1913 SET_STATE(RU,RU_UACK); | |
1914 } | |
1915 /* | |
1916 * Stop Countdown procedure, if bsn was the first block with CV NEQ 15 | |
1917 */ | |
1918 if(grlc_data->ru.cd_active AND | |
1919 (grlc_data->ru.rlc_data[((--bsn) & 0x7F) & WIN_MOD].header.mac & 0x3C) EQ 15) | |
1920 { | |
1921 TRACE_EVENT_P4("stop CNT DWN during reorg bsn-1 =%d bs_cv_max=%d,ru.cv=%d rlc_oc_ctn=%ld" | |
1922 ,((bsn--) & 0x7F) | |
1923 ,grlc_data->uplink_tbf.bs_cv_max | |
1924 ,grlc_data->ru.cv | |
1925 ,grlc_data->ru.rlc_octet_cnt); | |
1926 grlc_data->ru.cd_active = FALSE; | |
1927 ru_set_prim_queue(grlc_data->ru.cd_active); | |
1928 } | |
1929 | |
1930 } | |
1931 else | |
1932 { | |
1933 /* | |
1934 * block was once transmitted over physical link | |
1935 */ | |
1936 reorged_blks++; | |
1937 /* | |
1938 TRACE_EVENT("block was transmitted over pl link, do not modify"); | |
1939 */ | |
1940 } | |
1941 } | |
1942 else | |
1943 { | |
1944 TRACE_EVENT("CTRL BLK in L1 queue: reorg not needed"); | |
1945 } | |
1946 } | |
1947 if(reorged_blks) | |
1948 { | |
1949 grlc_data->ru.write_pos_index -= reorged_blks; | |
1950 grlc_data->ru.pl_retrans_current.cnt -= reorged_blks; | |
1951 memset(&grlc_data->ru.pl_retrans_current.blk[grlc_data->ru.pl_retrans_current.cnt], | |
1952 0xFF, | |
1953 reorged_blks); | |
1954 } | |
1955 ru_recalc_rlc_oct_cnt(); | |
1956 | |
1957 } /* ru_reorg_l1() */ | |
1958 | |
1959 | |
1960 | |
1961 /* | |
1962 +------------------------------------------------------------------------------ | |
1963 | Function : ru_del_prim_in_uack_mode | |
1964 +------------------------------------------------------------------------------ | |
1965 | Description : The function ru_del_prim_in_uack_mode() deletes primitvies in | |
1966 | rlc unackknowledged mode | |
1967 | | |
1968 | Parameters : dummy - description of parameter dummy | |
1969 | | |
1970 +------------------------------------------------------------------------------ | |
1971 */ | |
1972 GLOBAL void ru_del_prim_in_uack_mode ( UBYTE rlc_blocks_sent_i) | |
1973 { | |
1974 UBYTE highest_bsn = BSN_MAX + 1; /* this represents the highest bsn sent on air */ | |
1975 UBYTE counter = 0; | |
1976 TRACE_FUNCTION( "ru_del_prim_in_uack_mode" ); | |
1977 | |
1978 for(counter = rlc_blocks_sent_i;counter > 0;counter--) | |
1979 { | |
1980 | |
1981 highest_bsn = grlc_data->ru.pl_retrans_current.blk[counter-1]; | |
1982 if( highest_bsn < (BSN_MAX + 1) ) | |
1983 { | |
1984 /* data block has been transmitted on air, valid bsn found. */ | |
1985 highest_bsn=(highest_bsn+1) & BSN_MAX; | |
1986 if(grlc_data->ru.cv NEQ 0) | |
1987 { | |
1988 ru_delete_prims(highest_bsn); | |
1989 } | |
1990 else if((grlc_data->ru.cv EQ 0) AND (grlc_data->ru.count_cv_0 EQ 4)) | |
1991 { | |
1992 ru_delete_prims(highest_bsn); | |
1993 } | |
1994 break; | |
1995 } | |
1996 /* if highest_bsn is greater than BSN_MAX then it is a control block. we should check in | |
1997 * next radio block | |
1998 */ | |
1999 } | |
2000 } /* ru_del_prim_in_uack_mode() */ | |
2001 | |
2002 | |
2003 /* | |
2004 +------------------------------------------------------------------------------ | |
2005 | Function : ru_handle_timers | |
2006 +------------------------------------------------------------------------------ | |
2007 | Description : The function ru_handle_timers handles the following timers: | |
2008 | T3164, T3166, T3180, T3182, T3198 | |
2009 | | |
2010 | Parameters : dummy - description of parameter dummy | |
2011 | | |
2012 +------------------------------------------------------------------------------ | |
2013 */ | |
2014 GLOBAL void ru_handle_timers ( UBYTE rlc_blocks_sent_i) | |
2015 { | |
2016 UBYTE i; | |
2017 TRACE_FUNCTION( "ru_handle_timers" ); | |
2018 | |
2019 /* | |
2020 * start timter T3198, l1 has transmitted a block | |
2021 */ | |
2022 for(i=0 ; i < rlc_blocks_sent_i;i++) | |
2023 { | |
2024 if (grlc_data->ru.pl_retrans_current.blk[i] <= BSN_MAX ) | |
2025 ru_set_T3198(grlc_data->ru.pl_retrans_current.blk[i]); | |
2026 } | |
2027 /* | |
2028 * first usf is read: stop T3164; wait for first ack/nack: start T3166 | |
2029 */ | |
2030 if( rlc_blocks_sent_i AND grlc_data->ru.first_usf) | |
2031 { | |
2032 vsi_t_stop(GRLC_handle,T3164); | |
2033 grlc_data->ru.first_usf = FALSE; | |
2034 grlc_data->t3164_to_cnt = 0; | |
2035 } | |
2036 if(grlc_data->ru.ti AND rlc_blocks_sent_i AND (!grlc_data->ru.cnt_ts)) | |
2037 { | |
2038 /* | |
2039 * Only started in phase access when first data block was sent | |
2040 * in case of fixed allocation, after sending the first rlc data block | |
2041 * T3166 must be started(Wait for the first acknowledge). | |
2042 */ | |
2043 vsi_t_start(GRLC_handle,T3166,T3166_VALUE); | |
2044 } | |
2045 /* | |
2046 * start T3182 if at stall indication or | |
2047 * start T3182 if final data block was sent or | |
2048 * restart T3180 if a data block was sent, only in dynamic allocation | |
2049 */ | |
2050 if (rlc_blocks_sent_i AND grlc_data->uplink_tbf.mac_mode EQ CGRLC_MAC_MODE_DA) | |
2051 { | |
2052 vsi_t_stop(GRLC_handle,T3180); | |
2053 vsi_t_start(GRLC_handle,T3180,T3180_VALUE); | |
2054 } | |
2055 if( grlc_data->ru.last_bsn EQ LAST_BSN_STALL_CONDITION | |
2056 AND (grlc_t_status( T3182 ) EQ 0)) | |
2057 { | |
2058 vsi_t_start(GRLC_handle,T3182,T3182_VALUE); | |
2059 TRACE_EVENT_P6("SI:T3182 is started: vs=%d va=%d dl_fn=%ld rlc_bs=%d bsn[0]=%d bsn[1]=%d" | |
2060 ,grlc_data->ru.vs | |
2061 ,grlc_data->ru.va | |
2062 ,grlc_data->dl_fn | |
2063 ,rlc_blocks_sent_i | |
2064 ,grlc_data->ru.pl_retrans_current.blk[0] | |
2065 ,grlc_data->ru.pl_retrans_current.blk[1]); | |
2066 } | |
2067 else if( (grlc_data->ru.last_bsn EQ LAST_BSN_IS_SENT) | |
2068 AND (grlc_t_status( T3182 ) EQ 0) /* timer is not running */ | |
2069 AND (!grlc_data->ru.nr_nacked_blks)) | |
2070 { | |
2071 vsi_t_start(GRLC_handle,T3182,T3182_VALUE); | |
2072 TRACE_EVENT_P3("T3182 started : vs=%d va=%d last_bsn=%d " | |
2073 ,grlc_data->ru.vs | |
2074 ,grlc_data->ru.va | |
2075 ,grlc_data->ru.last_bsn); | |
2076 } | |
2077 /* else | |
2078 { | |
2079 TRACE_EVENT_P6("NO TIMER START: vs=%d va=%d last_bsn=%d t3182=%ld t3180=%d rlc_blocks_sent_i=%d" | |
2080 ,grlc_data->ru.vs | |
2081 ,grlc_data->ru.va | |
2082 ,grlc_data->ru.last_bsn | |
2083 ,grlc_t_status( T3182 ) | |
2084 ,grlc_t_status( T3180 ) | |
2085 ,rlc_blocks_sent_i); | |
2086 } | |
2087 */ | |
2088 } /* ru_handle_timers() */ | |
2089 | |
2090 | |
2091 | |
2092 | |
2093 /* | |
2094 +------------------------------------------------------------------------------ | |
2095 | Function : ru_handle_nts | |
2096 +------------------------------------------------------------------------------ | |
2097 | Description : The function ru_handle_nts recalutates the parameter | |
2098 | grlc_data->ru.nts in case of layer 1 queue reorganisation | |
2099 | | |
2100 | Parameters : dummy - description of parameter dummy | |
2101 | | |
2102 +------------------------------------------------------------------------------ | |
2103 */ | |
2104 | |
2105 GLOBAL void ru_handle_nts (UBYTE rlc_blocks_sent_i) | |
2106 { | |
2107 UBYTE i; | |
2108 TRACE_FUNCTION( "ru_handle_nts" ); | |
2109 | |
2110 | |
2111 if( grlc_data->testmode.mode EQ CGRLC_LOOP AND | |
2112 (rlc_blocks_sent_i < grlc_data->ru.nts_max) ) | |
2113 { | |
2114 TRACE_EVENT_P2("TESTMODE B REORG L1: blk_sent = %d nts=nts_max=%d",rlc_blocks_sent_i,grlc_data->ru.nts_max); | |
2115 grlc_data->ru.reorg_l1_needed = TRUE; | |
2116 } | |
2117 | |
2118 | |
2119 grlc_data->ru.nts = rlc_blocks_sent_i; | |
2120 | |
2121 /* | |
2122 * check whether there is a reorganisation of the tansmit queue needed | |
2123 * due to pending control blocks | |
2124 */ | |
2125 if( tm_get_num_ctrl_blck( ) NEQ 0 ) | |
2126 { | |
2127 grlc_data->ru.reorg_l1_needed = TRUE; | |
2128 } | |
2129 | |
2130 | |
2131 if( grlc_data->ru.reorg_l1_needed | |
2132 AND (rlc_blocks_sent_i < grlc_data->ru.nts_max ) | |
2133 AND grlc_data->ru.pl_retrans_current.cnt | |
2134 AND grlc_data->ru.pl_retrans_current.blk[0] NEQ 0xFF) /* dummy blocks in queue*/ | |
2135 { | |
2136 ru_reorg_l1(rlc_blocks_sent_i); | |
2137 grlc_data->ru.nts = grlc_data->ru.nts_max; | |
2138 } | |
2139 else if (!grlc_data->ru.pl_retrans_current.cnt) | |
2140 { /* no data block in queue, put max nuber in queue*/ | |
2141 grlc_data->ru.nts = grlc_data->ru.nts_max; | |
2142 } | |
2143 /********otherwise check if a positive acknowledged block is queue**********/ | |
2144 else | |
2145 { | |
2146 for(i=0; i < grlc_data->ru.pl_retrans_current.cnt;i++) | |
2147 { | |
2148 if(grlc_data->ru.pl_retrans_current.blk[i] <= BSN_MAX AND | |
2149 (grlc_data->ru.vb[grlc_data->ru.pl_retrans_current.blk[i] & WIN_MOD] EQ VB_ACKED)) | |
2150 { | |
2151 grlc_data->ru.nts = (grlc_data->ru.nts_max -i); | |
2152 grlc_data->ru.pl_retrans_current.cnt -= (grlc_data->ru.nts - rlc_blocks_sent_i); | |
2153 memset(&grlc_data->ru.pl_retrans_current.blk[i], | |
2154 0xFF, | |
2155 grlc_data->ru.nts); | |
2156 grlc_data->ru.write_pos_index -= grlc_data->ru.nts - rlc_blocks_sent_i; | |
2157 break; | |
2158 } | |
2159 } | |
2160 } | |
2161 /***********************check if a bsn_ret block is in queue*****************/ | |
2162 for(i=0; i < grlc_data->ru.pl_retrans_current.cnt;i++) | |
2163 { | |
2164 if(grlc_data->ru.pl_retrans_current.blk[i] EQ grlc_data->ru.bsn_ret) | |
2165 { | |
2166 grlc_data->ru.bsn_ret = ru_set_next_bsn_ret(); | |
2167 } | |
2168 } | |
2169 /****************************************************************************/ | |
2170 grlc_data->ru.reorg_l1_needed = FALSE; | |
2171 | |
2172 | |
2173 | |
2174 } /* ru_handle_nts() */ | |
2175 | |
2176 | |
2177 /* | |
2178 +------------------------------------------------------------------------------ | |
2179 | Function : ru_check_pl_ret | |
2180 +------------------------------------------------------------------------------ | |
2181 | Description : handles the restart of timer T3198, and first call of RU | |
2182 | (to stop T3164) | |
2183 | | |
2184 | Parameters : rlc_blocks_sent_i - number of needed blocks by PL(is equal to | |
2185 | the number of sent blocks in the previous radio block) | |
2186 | | |
2187 +------------------------------------------------------------------------------ | |
2188 */ | |
2189 GLOBAL void ru_check_pl_ret ( UBYTE rlc_blocks_sent_i) | |
2190 { | |
2191 UBYTE i; | |
2192 UBYTE bsn; | |
2193 | |
2194 TRACE_FUNCTION( "ru_check_pl_ret" ); | |
2195 | |
2196 | |
2197 /* | |
2198 * handle the sent blocks | |
2199 */ | |
2200 for(i=0;i<rlc_blocks_sent_i;i++) | |
2201 { | |
2202 bsn = grlc_data->ru.pl_retrans_current.blk[i]; | |
2203 /* | |
2204 * chek if the range is OK | |
2205 */ | |
2206 if( bsn <= BSN_MAX ) /* data block was sent */ | |
2207 { | |
2208 /* | |
2209 * trace parametes: 1. retranmission counter, byte counter | |
2210 */ | |
2211 grlc_data->ru.rlc_data[bsn & WIN_MOD].cnt_pl_trans++; | |
2212 if(grlc_data->ru.rlc_data[bsn & WIN_MOD].cnt_pl_trans > 1) | |
2213 grlc_data->tbf_ctrl[grlc_data->ul_index].ret_bsn++; | |
2214 else | |
2215 { | |
2216 UBYTE j; | |
2217 for(j=0;j<grlc_data->ru.rlc_data[bsn & WIN_MOD].data_cnt;j++) | |
2218 grlc_data->tbf_ctrl[grlc_data->ul_index].rlc_oct_cnt +=grlc_data->ru.rlc_data[bsn & WIN_MOD].data[j].l_buf/8; | |
2219 } | |
2220 /* | |
2221 * a retransmitted block was sent | |
2222 */ | |
2223 if(bsn EQ grlc_data->ru.bsn_ret) | |
2224 { | |
2225 grlc_data->ru.bsn_ret = ru_set_next_bsn_ret(); | |
2226 } | |
2227 /* | |
2228 * last bsn is sent | |
2229 */ | |
2230 if((grlc_data->ru.rlc_data[bsn & WIN_MOD].header.mac & 0x3C) EQ 0) /* countdown value is equal 0*/ | |
2231 { | |
2232 grlc_data->ru.last_bsn = LAST_BSN_IS_SENT; | |
2233 } | |
2234 else if(bsn EQ ((grlc_data->ru.va+WIN_SIZE-1) & 0x7F) | |
2235 AND (grlc_data->ru.last_bsn NEQ LAST_BSN_STALL_CONDITION)) | |
2236 { | |
2237 /* | |
2238 * stall indication detected | |
2239 */ | |
2240 grlc_data->ru.last_bsn = LAST_BSN_STALL_CONDITION; | |
2241 TRACE_EVENT_P6("NEXT DATA STALL INDICATION bsn=%d va=%d vs=%d cnt_ts=%d last_bsn=%ld dl_fn=%ld" | |
2242 ,bsn | |
2243 ,grlc_data->ru.va | |
2244 ,grlc_data->ru.vs | |
2245 ,grlc_data->ru.cnt_ts | |
2246 ,grlc_data->ru.last_bsn | |
2247 ,grlc_data->dl_fn); | |
2248 } | |
2249 } | |
2250 else if( bsn >= OFFSET_CTRL_BLOCK_IDX AND bsn < 0xFF ) /* control block was sent */ | |
2251 { | |
2252 sig_ru_tm_ctrl_blk_sent( (UBYTE)( bsn - OFFSET_CTRL_BLOCK_IDX ) ); | |
2253 } | |
2254 else if (bsn EQ 0xFF) | |
2255 { | |
2256 /* nothing to do : dummy block sent*/ | |
2257 } | |
2258 else /*invalid block was sent, should not appear */ | |
2259 { | |
2260 TRACE_ERROR("INVALID bsn range neither data or control block"); | |
2261 TRACE_EVENT("INVALID bsn range neither data or control block"); | |
2262 TRACE_EVENT_P1("bsn = %d ", bsn); | |
2263 } | |
2264 } | |
2265 ru_handle_timers(rlc_blocks_sent_i); | |
2266 /******************delete sent blocks from pl_retrans_current**************/ | |
2267 memcpy(grlc_data->ru.pl_retrans_current.blk, | |
2268 &grlc_data->ru.pl_retrans_current.blk[rlc_blocks_sent_i], | |
2269 (grlc_data->ru.nts_max - rlc_blocks_sent_i)); | |
2270 grlc_data->ru.pl_retrans_current.cnt -= rlc_blocks_sent_i; | |
2271 grlc_data->ru.cnt_ts += rlc_blocks_sent_i; | |
2272 | |
2273 } /* ru_check_pl_ret() */ | |
2274 | |
2275 | |
2276 | |
2277 | |
2278 | |
2279 | |
2280 /* | |
2281 +------------------------------------------------------------------------------ | |
2282 | Function : ru_send_ul_dummy_block | |
2283 +------------------------------------------------------------------------------ | |
2284 | Description : The function ru_send_ul_dummy_block() sends a uplink dummy | |
2285 | control block instead of RLC data block | |
2286 | | |
2287 | Parameters : dummy - description of parameter dummy | |
2288 | | |
2289 +------------------------------------------------------------------------------ | |
2290 */ | |
2291 GLOBAL void ru_send_ul_dummy_block ( void ) | |
2292 { | |
2293 MCAST (ul_dummy,U_GRLC_UL_DUMMY); | |
2294 | |
2295 TRACE_FUNCTION( "ru_send_ul_dummy_block" ); | |
2296 | |
2297 | |
2298 memset(&grlc_data->ru.ul_data[grlc_data->ru.write_pos_index], | |
2299 0, | |
2300 sizeof(T_ul_data)); | |
2301 | |
2302 grlc_data->ru.ul_data[grlc_data->ru.write_pos_index].block_status = 2; | |
2303 | |
2304 /* | |
2305 * set uplink dummy block | |
2306 */ | |
2307 ul_dummy->msg_type = U_GRLC_UL_DUMMY_c; | |
2308 | |
2309 grlc_set_buf_tlli( &ul_dummy->tlli_value, grlc_data->uplink_tbf.tlli ); | |
2310 grlc_encode_ul_ctrl_block( ( UBYTE* ) grlc_data->ru.ul_data[grlc_data->ru.write_pos_index].ul_block, | |
2311 ( UBYTE* )ul_dummy ); | |
2312 | |
2313 #ifdef _SIMULATION_ | |
2314 { | |
2315 PALLOC(mac_data_req,MAC_DATA_REQ); | |
2316 memset(&(mac_data_req->ul_data), | |
2317 0, | |
2318 sizeof(T_ul_data)); | |
2319 memcpy(&(mac_data_req->ul_data), | |
2320 &(grlc_data->ru.ul_data[grlc_data->ru.write_pos_index]), | |
2321 sizeof(T_ul_data)); | |
2322 PSEND(hCommL1,mac_data_req); | |
2323 } | |
2324 TRACE_EVENT_P1("wpi %d",grlc_data->ru.write_pos_index); | |
2325 #else /* #ifdef _SIMULATION_ */ | |
2326 { | |
2327 TRACE_MEMORY_PRIM ( hCommGRLC, hCommL1, MAC_DATA_REQ, | |
2328 &grlc_data->ru.ul_data[grlc_data->ru.write_pos_index], | |
2329 sizeof(T_ul_data) ); | |
2330 } | |
2331 #endif /* #ifdef _SIMULATION_ */ | |
2332 | |
2333 { | |
2334 UBYTE* ul_block = ( UBYTE* )grlc_data->ru.ul_data[grlc_data->ru.write_pos_index].ul_block; | |
2335 | |
2336 TRACE_BINDUMP( hCommGRLC, TC_USER5, | |
2337 cl_rlcmac_get_msg_name | |
2338 ( ( UBYTE )( ul_block[1] >> 2 ), RLC_MAC_ROUTE_UL ), | |
2339 ul_block, MAX_L2_FRAME_SIZE ); /*lint !e569*/ | |
2340 } | |
2341 | |
2342 grlc_data->ru.write_pos_index++; | |
2343 grlc_data->ru.ul_data[grlc_data->ru.write_pos_index].block_status = 0; | |
2344 | |
2345 grlc_data->ru.pl_retrans_current.blk[grlc_data->ru.pl_retrans_current.cnt] = 255; | |
2346 grlc_data->ru.pl_retrans_current.cnt++; | |
2347 grlc_data->ru.nts--; | |
2348 } /* ru_send_ul_dummy_block() */ | |
2349 | |
2350 | |
2351 | |
2352 | |
2353 /* | |
2354 +------------------------------------------------------------------------------ | |
2355 | Function : ru_handle_stall_ind | |
2356 +------------------------------------------------------------------------------ | |
2357 | Description : The function ru_handle_stall_ind() checks, if there was a stall | |
2358 | condition, and if it is canceled. | |
2359 | | |
2360 | Parameters : dummy - description of parameter dummy | |
2361 | | |
2362 +------------------------------------------------------------------------------ | |
2363 */ | |
2364 GLOBAL void ru_handle_stall_ind ( void ) | |
2365 { | |
2366 TRACE_FUNCTION( "ru_handle_stall_ind" ); | |
2367 | |
2368 if(grlc_data->ru.last_bsn EQ LAST_BSN_STALL_CONDITION) | |
2369 { | |
2370 if(!(grlc_data->ru.vs EQ ((grlc_data->ru.va + WIN_SIZE) & 0x7F))) | |
2371 {/*stall condition eliminated*/ | |
2372 grlc_data->ru.reorg_l1_needed = TRUE; /* remove stalled blocks from data queue */ | |
2373 vsi_t_stop(GRLC_handle,T3182); | |
2374 ru_handle_n3102(PAN_INC); | |
2375 if(grlc_data->ru.rlc_mode EQ CGRLC_RLC_MODE_UACK) | |
2376 { /*resume with data transfer after stall indication in rlc unacknowledged problem*/ | |
2377 grlc_data->ru.last_bsn = LAST_BSN_RESUME_UACK_MODE_AFTER_SI; | |
2378 } | |
2379 else | |
2380 { | |
2381 grlc_data->ru.last_bsn = LAST_BSN_NOT_BULIT; | |
2382 } | |
2383 } | |
2384 } | |
2385 else | |
2386 { | |
2387 ru_handle_n3102(PAN_INC); | |
2388 grlc_data->ru.last_si_block = grlc_data->ru.va; | |
2389 } | |
2390 } /* ru_handle_stall_ind() */ | |
2391 | |
2392 | |
2393 /* | |
2394 +------------------------------------------------------------------------------ | |
2395 | Function : ru_handle_tbf_start_in_ptm | |
2396 +------------------------------------------------------------------------------ | |
2397 | Description : The function ru_handle_tbf_start_in_ptm() modifies the parameters | |
2398 | for the tbf at reaching the starting time | |
2399 | | |
2400 | Parameters : rlc_blocks_sent_i - number of blocks sent in current in radio block | |
2401 | return value is set, if only nts is decrased and not all blocks are sent | |
2402 | | |
2403 +------------------------------------------------------------------------------ | |
2404 */ | |
2405 GLOBAL void ru_handle_tbf_start_in_ptm ( UBYTE rlc_blocks_sent_i ) | |
2406 { | |
2407 UBYTE ctrl_blk_active_idx; | |
2408 BOOL realloc_prr_allowed = FALSE; | |
2409 TRACE_FUNCTION( "ru_handle_tbf_start_in_ptm" ); | |
2410 /* | |
2411 * reassignment of uplink and tbf starting time elapsed, received either with packet uplink assignment | |
2412 * or packet timeslot reconfigure | |
2413 */ | |
2414 | |
2415 | |
2416 if(grlc_data->ul_tfi_changed) | |
2417 { | |
2418 if((rlc_blocks_sent_i < grlc_data->ru.nts_max) AND /* nr of locks which are not sent */ | |
2419 (grlc_data->ru.cs_type EQ grlc_data->ru.next_tbf_params.cs_type) AND /* coding scheme has not changed */ | |
2420 (grlc_data->ru.nts_max <= grlc_data->ru.next_tbf_params.nts)) /* nts increased or equal */ | |
2421 { | |
2422 UBYTE i, bsn[4],cnt; | |
2423 /* | |
2424 * change the tfi for blocks which are in l1 queue | |
2425 */ | |
2426 cnt = grlc_data->ru.pl_retrans_current.cnt; | |
2427 bsn[0] = grlc_data->ru.pl_retrans_current.blk[0]; | |
2428 bsn[1] = grlc_data->ru.pl_retrans_current.blk[1]; | |
2429 grlc_data->ru.pl_retrans_current.cnt = 0; | |
2430 for (i = 0; i< cnt;i++) | |
2431 { | |
2432 if(bsn[i] <= BSN_MAX) | |
2433 { | |
2434 grlc_data->ru.write_pos_index--; | |
2435 ru_send_mac_data_req(bsn[i]); | |
2436 TRACE_EVENT_P1("bsn %d modified while tfi is changed",bsn[i]); | |
2437 } | |
2438 else | |
2439 { | |
2440 TRACE_EVENT_P1("bsn %d :TFI FOR CTRL BLOCK CHANGED. no modification",bsn[i]); | |
2441 } | |
2442 } | |
2443 } | |
2444 grlc_data->ul_tfi_changed = FALSE; | |
2445 } | |
2446 | |
2447 | |
2448 | |
2449 grlc_data->ru.tlli_cs_type = grlc_data->ru.next_tbf_params.tlli_cs_type; | |
2450 if(grlc_data->ru.cs_type NEQ grlc_data->ru.next_tbf_params.cs_type) | |
2451 { | |
2452 TRACE_EVENT_P2("UL assign: CS changed from %d to %d ",grlc_data->ru.cs_type,grlc_data->ru.next_tbf_params.cs_type); | |
2453 grlc_data->ru.cs_type = grlc_data->ru.next_tbf_params.cs_type; | |
2454 ru_change_of_cs(grlc_data->ru.cs_type); | |
2455 } | |
2456 if(grlc_data->ru.nts_max < grlc_data->ru.next_tbf_params.nts) | |
2457 { | |
2458 TRACE_EVENT_P6("nts increased from %d to %d, tfi=%d,cnt_ts=%d,vs=%d,va=%d", | |
2459 grlc_data->ru.nts_max, | |
2460 grlc_data->ru.next_tbf_params.nts, | |
2461 grlc_data->ul_tfi, | |
2462 grlc_data->ru.cnt_ts, | |
2463 grlc_data->ru.vs, | |
2464 grlc_data->ru.va); | |
2465 grlc_data->ru.nts = (grlc_data->ru.next_tbf_params.nts - grlc_data->ru.nts_max); | |
2466 grlc_data->ru.nts_max = grlc_data->ru.next_tbf_params.nts; | |
2467 | |
2468 while( grlc_data->ru.nts AND | |
2469 tm_get_num_ctrl_blck( ) NEQ 0 AND | |
2470 ru_ctrl_blk_selection_allowed() ) | |
2471 | |
2472 { /* | |
2473 * next uplink block is a control block, | |
2474 * check if countdown procedure is statred or not | |
2475 */ | |
2476 ru_send_control_block( ); | |
2477 } | |
2478 while(grlc_data->ru.nts) | |
2479 { | |
2480 ctrl_blk_active_idx = ru_peek_for_ctrl_blk(); | |
2481 if ((ctrl_blk_active_idx EQ 0xFF) OR | |
2482 realloc_prr_allowed EQ TRUE) /*No control block , form data block*/ | |
2483 { | |
2484 while(grlc_data->ru.nts AND grlc_data->ru.sdu_len) | |
2485 { | |
2486 ru_new_data(); | |
2487 } | |
2488 while(grlc_data->ru.nts) | |
2489 { | |
2490 ru_ret_bsn(); | |
2491 } | |
2492 realloc_prr_allowed = FALSE; | |
2493 break; | |
2494 } | |
2495 else | |
2496 { | |
2497 | |
2498 TRACE_EVENT_P1("reallocation of llc pdu (index)=%d",ctrl_blk_active_idx); | |
2499 | |
2500 /* if already one PRR in L1 Buffer , replace it with new PRR */ | |
2501 if (grlc_data->ru.pl_retrans_current.blk[0] | |
2502 EQ (BLK_INDEX_TM + OFFSET_CTRL_BLOCK_IDX)) | |
2503 { | |
2504 grlc_data->ru.write_pos_index--; | |
2505 grlc_data->ru.pl_retrans_current.cnt--; | |
2506 grlc_data->ru.nts++; | |
2507 TRACE_EVENT("prr in l1 buffer queue,replace with new prr"); | |
2508 } | |
2509 sig_ru_tm_end_of_pdu(ctrl_blk_active_idx); | |
2510 ru_send_control_block(); | |
2511 realloc_prr_allowed = TRUE; | |
2512 } | |
2513 } | |
2514 if(grlc_data->ru.cv EQ 0 AND | |
2515 grlc_data->ru.rlc_mode EQ CGRLC_RLC_MODE_ACK ) | |
2516 { | |
2517 SET_STATE(RU,RU_REL_ACK); | |
2518 } | |
2519 else if(grlc_data->ru.rlc_mode EQ CGRLC_RLC_MODE_ACK) | |
2520 { | |
2521 SET_STATE(RU,RU_ACK); | |
2522 } | |
2523 else if(grlc_data->ru.cv EQ 0 AND | |
2524 grlc_data->ru.rlc_mode EQ CGRLC_RLC_MODE_UACK ) | |
2525 { | |
2526 SET_STATE(RU,RU_REL_UACK); | |
2527 } | |
2528 else if(grlc_data->ru.rlc_mode EQ CGRLC_RLC_MODE_UACK) | |
2529 { | |
2530 SET_STATE(RU,RU_UACK); | |
2531 } | |
2532 else | |
2533 { | |
2534 TRACE_EVENT_P2("RLC MODE ??? cv=%d rlc_mode=%d",grlc_data->ru.cv,grlc_data->ru.rlc_mode); | |
2535 } | |
2536 } | |
2537 else if(grlc_data->ru.nts_max > grlc_data->ru.next_tbf_params.nts) | |
2538 { | |
2539 /* Reorg layer 1 */ | |
2540 ru_reorg_l1((UBYTE)(rlc_blocks_sent_i)); | |
2541 TRACE_EVENT_P7("nts decrased from %d to %d tfi=%d,cnt_ts=%d,va=%d,vs=%d blk_s=%d ", | |
2542 grlc_data->ru.nts_max, | |
2543 grlc_data->ru.next_tbf_params.nts, | |
2544 grlc_data->ul_tfi, | |
2545 grlc_data->ru.cnt_ts, | |
2546 grlc_data->ru.va, | |
2547 grlc_data->ru.vs, | |
2548 rlc_blocks_sent_i); | |
2549 grlc_data->ru.nts_max = grlc_data->ru.next_tbf_params.nts; | |
2550 } | |
2551 else | |
2552 { | |
2553 TRACE_EVENT_P6("ul tbf reassignment with tfi=%d,cnt_ts=%d,va=%d,vs=%d,nts_max=%d tbf_st_time=%ld", | |
2554 grlc_data->ul_tfi, | |
2555 grlc_data->ru.cnt_ts, | |
2556 grlc_data->ru.va, | |
2557 grlc_data->ru.vs, | |
2558 grlc_data->ru.nts_max, | |
2559 grlc_data->ul_tbf_start_time); | |
2560 } | |
2561 grlc_data->ru.v_next_tbf_params = FALSE; | |
2562 | |
2563 } /* ru_handle_tbf_start_in_ptm() */ | |
2564 | |
2565 | |
2566 /* | |
2567 +------------------------------------------------------------------------------ | |
2568 | Function : ru_switch_ul_buffer | |
2569 +------------------------------------------------------------------------------ | |
2570 | Description : The function ru_switch_ul_buffer () .... | |
2571 | | |
2572 | Parameters : - | |
2573 | | |
2574 +------------------------------------------------------------------------------ | |
2575 */ | |
2576 GLOBAL void ru_switch_ul_buffer ( UBYTE rlc_blocks_sent_i ) | |
2577 { | |
2578 | |
2579 UBYTE i; | |
2580 | |
2581 TRACE_FUNCTION( "ru_switch_ul_buffer " ); | |
2582 | |
2583 /* | |
2584 * switch uplink buffer, it means, rlc blocks which are not sent | |
2585 * by PL are switched to the top of the ul buffer | |
2586 */ | |
2587 if (rlc_blocks_sent_i) | |
2588 { | |
2589 i = rlc_blocks_sent_i; | |
2590 while((i < MAX_UL_TN) AND (grlc_data->ru.ul_data[i].block_status NEQ 0)) | |
2591 { | |
2592 grlc_data->ru.ul_data[i - rlc_blocks_sent_i] = grlc_data->ru.ul_data[i]; | |
2593 i++; | |
2594 } | |
2595 grlc_data->ru.write_pos_index -= rlc_blocks_sent_i; | |
2596 } | |
2597 } /* ru_switch_ul_buffer () */ | |
2598 | |
2599 /* | |
2600 +------------------------------------------------------------------------------ | |
2601 | Function : ru_cgrlc_st_time_ind | |
2602 +------------------------------------------------------------------------------ | |
2603 | Description : The function ru_cgrlc_st_time_ind () informs higher layers | |
2604 | that the starting time is elapsed | |
2605 | | |
2606 | Parameters : - | |
2607 | | |
2608 +------------------------------------------------------------------------------ | |
2609 */ | |
2610 GLOBAL void ru_cgrlc_st_time_ind ( void ) | |
2611 { | |
2612 PALLOC(cgrlc_starting_time_ind,CGRLC_STARTING_TIME_IND); /* T_CGRLC_STARTING_TIME_IND */ | |
2613 | |
2614 TRACE_FUNCTION( "ru_cgrlc_st_time_ind " ); | |
2615 | |
2616 cgrlc_starting_time_ind->tbf_mode = CGRLC_TBF_MODE_UL; | |
2617 cgrlc_starting_time_ind->tfi = grlc_data->ul_tfi; | |
2618 | |
2619 PSEND(hCommGRR,cgrlc_starting_time_ind); | |
2620 | |
2621 grlc_data->ul_tn_mask = grlc_data->uplink_tbf.ts_mask; | |
2622 | |
2623 | |
2624 } /* ru_cgrlc_st_time_ind () */ | |
2625 | |
2626 /* | |
2627 +------------------------------------------------------------------------------ | |
2628 | Function : ru_ctrl_blk_selection_allowed | |
2629 +------------------------------------------------------------------------------ | |
2630 | Description : This function gets called from sig_gff_ru_mac_ready_ind handler | |
2631 | and also from the function which handles ul reassignment | |
2632 | (ru_handle_tbf_start_in_ptm). In mac ready indicate handler | |
2633 | this is calld only when ru is in rel_ack state. | |
2634 | This function returns true or false according to the following | |
2635 | table. The table applies for uack mode also. | |
2636 | When this function returns true, then control block should be | |
2637 | selected for transmission by RU. | |
2638 | When it returns False, then control block is selected by RD. | |
2639 | | |
2640 | ru_rel_ack state rd_rel_ack - TRUE | |
2641 | ru_ack rd_ack - TRUE | |
2642 | ru_ack rd_rel_ack - TRUE | |
2643 | ru_rel_ack rd_ack - FALSE | |
2644 | ru_ack NO DL TBF(rd_null) - TRUE | |
2645 | ru_rel_ack NO DL TBF(rd_null) - TRUE | |
2646 | | |
2647 | This function should be called only in PTM. | |
2648 | | |
2649 | Parameters : None | |
2650 +------------------------------------------------------------------------------ | |
2651 */ | |
2652 GLOBAL BOOL ru_ctrl_blk_selection_allowed() | |
2653 { | |
2654 BOOL ru_in_release_mode = FALSE, ctrl_blk_allowed = TRUE, dl_release_started = TRUE; | |
2655 | |
2656 if(grlc_data->tbf_type EQ TBF_TYPE_CONC) | |
2657 { | |
2658 /* In ru_send_pca stete, ctrl blocks are not sent. No need to | |
2659 * check for that here. | |
2660 */ | |
2661 if((GET_STATE(RU) EQ RU_REL_ACK) OR (GET_STATE(RU) EQ RU_REL_UACK)) | |
2662 { | |
2663 ru_in_release_mode = TRUE; | |
2664 } | |
2665 | |
2666 sig_ru_rd_get_downlink_release_state(&dl_release_started); | |
2667 | |
2668 /* rd_rel_state would be true if fbi=1 has been received | |
2669 * in downlink. | |
2670 */ | |
2671 if(ru_in_release_mode AND (dl_release_started EQ FALSE) ) | |
2672 { | |
2673 ctrl_blk_allowed = FALSE; | |
2674 } | |
2675 } | |
2676 return ctrl_blk_allowed; | |
2677 } | |
2678 | |
2679 /* | |
2680 +------------------------------------------------------------------------------ | |
2681 | Function : ru_peek_for_ctrl_blk | |
2682 +------------------------------------------------------------------------------ | |
2683 | Description : The function would peek to see if there is reallocation set, | |
2684 | then it returns TRUE, so that PRR can be constructed. | |
2685 | Also if the rlc block has more than one llc pdu with re-allocation | |
2686 | set , then prr os sent for the latest llc pdu. | |
2687 | Parameters : None. | |
2688 | | |
2689 +------------------------------------------------------------------------------ | |
2690 */ | |
2691 | |
2692 #ifndef CF_FAST_EXEC | |
2693 | |
2694 GLOBAL UBYTE ru_peek_for_ctrl_blk() | |
2695 { | |
2696 BOOL ctrlblk_found = FALSE; | |
2697 USHORT rlc_len; | |
2698 USHORT sdu_len; | |
2699 UBYTE active_prim,next_prim,active_prr_idx = 0xFF; | |
2700 | |
2701 TRACE_FUNCTION( "ru_peek_for_ctrl_blk" ); | |
2702 | |
2703 sdu_len = grlc_data->ru.sdu_len; | |
2704 active_prim = grlc_data->ru.active_prim; | |
2705 next_prim = grlc_data->ru.next_prim; | |
2706 rlc_len = grlc_data->ru.rlc_data_size; | |
2707 | |
2708 | |
2709 while ( (sdu_len < rlc_len) AND (sdu_len > 0) ) | |
2710 { | |
2711 rlc_len -= sdu_len + 1; /* 1 is for length indicator */ | |
2712 | |
2713 if (!grlc_data->ru.cd_active) | |
2714 { | |
2715 ctrlblk_found = ru_peek_next_sdu(&sdu_len,&active_prim,&next_prim); | |
2716 active_prr_idx = ctrlblk_found ? active_prim:0xFF; | |
2717 } | |
2718 else | |
2719 { | |
2720 #ifdef _SIMULATION_ | |
2721 TRACE_EVENT("countdown in progress and extended tbf not supported,cant build PRR"); | |
2722 #endif | |
2723 return active_prr_idx; | |
2724 } | |
2725 | |
2726 } | |
2727 | |
2728 return (ctrlblk_found ? active_prr_idx : 0xFF); | |
2729 }/*ru_peek_for_ctrl_blk*/ | |
2730 #endif /* CF_FAST_EXEC */ | |
2731 | |
2732 | |
2733 /* | |
2734 +------------------------------------------------------------------------------ | |
2735 | Function : ru_peek_next_sdu | |
2736 +------------------------------------------------------------------------------ | |
2737 | Description : The function would peek to see if there is reallocation set, | |
2738 | for the current llc PDU. | |
2739 | | |
2740 | Parameters : None. | |
2741 | | |
2742 +------------------------------------------------------------------------------ | |
2743 */ | |
2744 #ifndef CF_FAST_EXEC | |
2745 | |
2746 GLOBAL BOOL ru_peek_next_sdu(USHORT *sdu_len,UBYTE *active_prim,UBYTE *next_prim) | |
2747 { | |
2748 BOOL prr_build = FALSE; | |
2749 | |
2750 TRACE_FUNCTION( "ru_peek_next_sdu"); | |
2751 | |
2752 if( *next_prim NEQ 0xFF AND | |
2753 (grlc_data->prim_queue[*next_prim].start_new_tbf EQ 0)) | |
2754 { | |
2755 *active_prim = grlc_data->prim_queue[*active_prim].next; | |
2756 /* This signal allows TM to initiate resource re-allocation | |
2757 * if required | |
2758 */ | |
2759 prr_build = grlc_data->prim_queue[*active_prim].re_allocation; | |
2760 | |
2761 *sdu_len = grlc_data->prim_queue[*active_prim].prim_ptr->sdu.l_buf/8; | |
2762 *next_prim = grlc_data->prim_queue[*active_prim].next; | |
2763 } | |
2764 else | |
2765 { | |
2766 *sdu_len = 0; | |
2767 } | |
2768 return prr_build; | |
2769 }/*ru_peek_next_sdu*/ | |
2770 #endif /* CF_FAST_EXEC */ |