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 */