comparison src/g23m-gprs/grlc/grlc_rdf.c @ 1:d393cd9bb723

src/g23m-*: initial import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 15 Jul 2018 04:40:46 +0000
parents
children
comparison
equal deleted inserted replaced
0:b6a5e36de839 1:d393cd9bb723
1 /*
2 +-----------------------------------------------------------------------------
3 | Project : 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 RD of
18 | entity GRLC.
19 +-----------------------------------------------------------------------------
20 */
21
22 #ifndef GRLC_RDF_C
23 #define GRLC_RDF_C
24 #endif
25
26 #define ENTITY_GRLC
27
28 /*==== INCLUDES =============================================================*/
29
30 #include "typedefs.h" /* to get Condat data types */
31 #include "vsi.h" /* to get a lot of macros */
32 #include "macdef.h"
33 #include "gprs.h"
34 #include "gsm.h" /* to get a lot of macros */
35 #include "ccdapi.h" /* to get CCD API */
36 #include "cnf_grlc.h" /* to get cnf-definitions */
37 #include "mon_grlc.h" /* to get mon-definitions */
38 #include "prim.h" /* to get the definitions of used SAP and directions */
39 #include "message.h"
40 #include "grlc.h" /* to get the global entity definitions */
41 #include "grlc_tms.h"
42 #include <string.h> /* memcpy */
43 #include "grlc_f.h"
44 #include "grlc_rdf.h"
45 #include "grlc_meass.h"
46
47 /*==== CONST ================================================================*/
48
49 /*==== LOCAL VARS ===========================================================*/
50
51 /*==== PRIVATE FUNCTIONS ====================================================*/
52
53 /*==== PUBLIC FUNCTIONS =====================================================*/
54
55
56 /*
57 +------------------------------------------------------------------------------
58 | Function : rd_init
59 +------------------------------------------------------------------------------
60 | Description : The function rd_init() ....
61 |
62 | Parameters : dummy - description of parameter dummy
63 |
64 +------------------------------------------------------------------------------
65 */
66 GLOBAL void rd_init ( void )
67 {
68 TRACE_FUNCTION( "rd_init" );
69
70 /*
71 * UBYTE
72 */
73 grlc_data->rd.vq = 0xFF;
74 grlc_data->rd.vr = 0xFF;
75 grlc_data->rd.li_cnt = 0xFF;
76 grlc_data->rd.rlc_data_len = 0xFF;
77 grlc_data->rd.f_ack_ind = 0xFF;
78 grlc_data->rd.ssn = 0xFF;
79
80 /*
81 * USHORT
82 */
83 grlc_data->rd.pdu_len = 0xFFFF;
84 /*
85 * BOOL
86 */
87 grlc_data->rd.pdu_complete = TRUE;
88 grlc_data->rd.channel_req = FALSE;
89 grlc_data->rd.ch_req_in_ack_prog = FALSE;
90 grlc_data->rd.inSequence = TRUE;
91 /*
92 * struct
93 */
94 grlc_data->rd.ptr_grlc = NULL;
95 grlc_data->rd.next_poll_block = NEXT_POLL_BLOCK_NONE;
96
97 INIT_STATE(RD,RD_NULL);
98
99 } /* rd_init() */
100
101
102
103
104
105 /*
106 +------------------------------------------------------------------------------
107 | Function : rd_tbf_init
108 +------------------------------------------------------------------------------
109 | Description : The function rd_tbf_init() ....
110 |
111 | Parameters : dummy - description of parameter dummy
112 |
113 +------------------------------------------------------------------------------
114 */
115 GLOBAL void rd_tbf_init ( void )
116 {
117 TRACE_FUNCTION( "rd_tbf_init" );
118
119 /*
120 * UBYTE
121 */
122 grlc_data->rd.vq = 0;
123 grlc_data->rd.vr = 0;
124 grlc_data->rd.li_cnt = 0;
125 grlc_data->rd.ssn = 0;
126 grlc_data->rd.last_bsn = 0xFF;
127 grlc_data->rd.bsn_pdu_start = 0xFF; /*set to zero at receiving the first data block*/
128 grlc_data->rd.cnt_sent_f_ack = 0;
129 grlc_data->rd.f_ack_ind = 0;
130 grlc_data->dl_tn_mask = grlc_data->downlink_tbf.ts_mask;
131
132 /*
133 * USHORT
134 */
135 grlc_data->rd.pdu_len = 0;
136
137 /*
138 * BOOL
139 */
140 grlc_data->rd.release_tbf = FALSE;
141 grlc_data->rd.pdu_complete = TRUE;
142 grlc_data->rd.ch_req_in_ack_prog = FALSE;
143 grlc_data->rd.v_next_tbf_params = FALSE;
144 grlc_data->rd.ignore_pdu = FALSE;
145
146
147 grlc_data->rd.fn_p_tbf_rel = 0xFFFFFFFF;
148 /*
149 * struct
150 */
151 grlc_data->rd.rlc_mode = grlc_data->downlink_tbf.rlc_mode;
152 grlc_data->rd.cs_type = CS_ZERO;
153 /*
154 * arrays
155 */
156
157 memset(grlc_data->rd.data_array, 0 , WIN_SIZE * sizeof(grlc_data->rd.data_array[0]) );
158 memset(grlc_data->rd.vn , VN_INVALID, WIN_SIZE * sizeof(grlc_data->rd.vn[0]) );
159 memset(grlc_data->rd.li , 0 , RD_LI_CNT_MAX * sizeof(grlc_data->rd.li[0]) );
160 memset(grlc_data->rd.m , 0 , RD_LI_CNT_MAX );
161
162 } /* rd_tbf_init() */
163
164
165
166 /*
167 +------------------------------------------------------------------------------
168 | Function : rd_read_li_m_of_block
169 +------------------------------------------------------------------------------
170 | Description : The function rd_read_li_m_of_block() ....
171 |
172 | Parameters : dummy - description of parameter dummy
173 |
174 +------------------------------------------------------------------------------
175 */
176 GLOBAL BOOL rd_read_li_m_of_block ( UBYTE * ptr_data_i, UBYTE e_bit_i )
177 {
178 USHORT len_sum;
179 BOOL result;
180
181 TRACE_FUNCTION( "rd_read_li_m_of_block" );
182
183 len_sum = 0;
184 grlc_data->rd.li_cnt = 0;
185
186 while(!(e_bit_i))
187 {
188 grlc_data->rd.li[grlc_data->rd.li_cnt] =
189 (ptr_data_i[grlc_data->rd.li_cnt] & 0xFC) >> 2;
190 grlc_data->rd.m [grlc_data->rd.li_cnt] =
191 (ptr_data_i[grlc_data->rd.li_cnt] & 0x02) >> 1;
192 e_bit_i = (ptr_data_i[grlc_data->rd.li_cnt] & 0x01);
193 len_sum += grlc_data->rd.li[grlc_data->rd.li_cnt];
194 if((e_bit_i EQ 0)
195 AND (!grlc_data->rd.m [grlc_data->rd.li_cnt]))
196 {
197 /*SZML-RD/001*/
198 return FALSE;
199 }
200 else if(!(grlc_data->rd.li[grlc_data->rd.li_cnt])
201 AND (grlc_data->rd.m [grlc_data->rd.li_cnt]))
202 {
203 TRACE_ERROR("dl block with li=0 and m=1: NOT ALLOWED");
204 return FALSE;
205 }
206 grlc_data->rd.li_cnt++;
207 }
208
209 if(grlc_data->rd.li_cnt > RD_LI_CNT_MAX)
210 {
211 TRACE_EVENT_P2("li_cnt=%d RD_LI_CNT_MAX=%d",grlc_data->rd.li_cnt,RD_LI_CNT_MAX);
212 TRACE_ERROR("rd li_cnt bigger than RD_LI_CNT_MAX (=8)");
213 TRACE_ASSERT( grlc_data->rd.li_cnt > RD_LI_CNT_MAX );
214 return FALSE;
215 }
216
217 /*
218 * check if sum of LIs is longer than a rlc data block len
219 */
220 len_sum += grlc_data->rd.li_cnt;
221 if( (len_sum > grlc_data->rd.rlc_data_len)
222 OR
223 ((len_sum EQ grlc_data->rd.rlc_data_len) AND (grlc_data->rd.m [grlc_data->rd.li_cnt-1])) )
224 result = FALSE;
225 else
226 result = TRUE;
227
228 return result;
229
230 } /* rd_read_li_m_of_block() */
231
232
233
234 /*
235 +------------------------------------------------------------------------------
236 | Function : rd_out_grlc_data_ind
237 +------------------------------------------------------------------------------
238 | Description : The function rd_out_grlc_data_ind() ....
239 |
240 | Parameters : dummy - description of parameter dummy
241 |
242 +------------------------------------------------------------------------------
243 */
244 GLOBAL void rd_out_grlc_data_ind( void )
245 {
246 T_GRLC_DATA_IND *prim_ptr;
247 TRACE_FUNCTION( "rd_out_grlc_data_ind" );
248
249 if(grlc_data->rd.ignore_pdu OR
250 grlc_test_mode_active())
251 {
252 /*
253 * this pdu is not passed to LLC because MAX_LLC_PDU_SIZE was exceed or testmode is active
254 */
255 grlc_data->rd.ignore_pdu = FALSE;
256
257 TRACE_EVENT_P4("TARGET PDU END reached at will be ignored: len=%ld, bsn=pdu_start=%d vr = %d testmode=%d "
258 ,grlc_data->rd.pdu_len
259 ,grlc_data->rd.bsn_pdu_start
260 ,grlc_data->rd.vr
261 ,grlc_test_mode_active());
262
263 rd_free_desc_list_partions();
264 return;
265 }
266
267 if(grlc_data->rd.rlc_mode EQ CGRLC_RLC_MODE_ACK)
268 {
269 PALLOC_DESC (grlc_data_ind, GRLC_DATA_IND);//lint !e413
270 prim_ptr = grlc_data_ind;
271 }
272 else
273 {
274 PALLOC_DESC (grlc_unitdata_ind, GRLC_UNITDATA_IND);//lint !e413
275 prim_ptr = (T_GRLC_DATA_IND*)grlc_unitdata_ind;
276 }
277
278 memcpy( prim_ptr,
279 &grlc_data->rd.grlc_data_ind,
280 sizeof(T_GRLC_DATA_IND) );
281 PSEND(hCommLLC, prim_ptr);
282
283 grlc_data->rd.grlc_data_ind.desc_list.first = NULL;
284 grlc_data->rd.pdu_complete = TRUE;
285 grlc_data->tbf_ctrl[grlc_data->dl_index].rlc_oct_cnt += grlc_data->rd.pdu_len;
286 grlc_data->tbf_ctrl[grlc_data->dl_index].pdu_cnt++;
287
288 } /* rd_out_grlc_data_ind() */
289
290 #ifdef _SIMULATION_
291
292 /*
293 +------------------------------------------------------------------------------
294 | Function : rd_out_grlc_data_ind_test
295 +------------------------------------------------------------------------------
296 | Description : The function rd_out_grlc_data_ind_test() ....
297 |
298 | Parameters : dummy - description of parameter dummy
299 |
300 +------------------------------------------------------------------------------
301 */
302 GLOBAL void rd_out_grlc_data_ind_test( void )
303 {
304 T_NEXT_ARRAY *ptr_next_array = NULL;
305 T_NEXT_ARRAY *ptr_help = NULL;
306 UBYTE *ptr_pos = NULL,cnt=0;
307 USHORT sdu_len_in_bits;
308 T_GRLC_DATA_IND_TEST *prim_ptr = NULL;
309
310 TRACE_FUNCTION( "rd_out_grlc_data_ind_test" );
311
312
313 if(grlc_data->rd.ignore_pdu OR
314 grlc_test_mode_active())
315 {
316 /*
317 * this pdu is not passed to LLC because MAX_LLC_PDU_SIZE was exceed or testmode is active
318 */
319 grlc_data->rd.ignore_pdu = FALSE;
320
321 TRACE_EVENT_P4("SIMULATION PDU END reached at will be ignored: len=%ld, bsn=pdu_start=%d vr = %d testmode=%d"
322 ,grlc_data->rd.pdu_len
323 ,grlc_data->rd.bsn_pdu_start
324 ,grlc_data->rd.vr
325 ,grlc_test_mode_active());
326 rd_free_desc_list_partions();
327 return;
328 }
329 sdu_len_in_bits = grlc_data->rd.pdu_len * 8;
330
331 if(grlc_data->rd.rlc_mode EQ CGRLC_RLC_MODE_ACK)
332 {
333 PALLOC_SDU (grlc_data_ind_test, GRLC_DATA_IND_TEST, sdu_len_in_bits);
334 prim_ptr = grlc_data_ind_test;
335 }
336 else
337 {
338 PALLOC_SDU (grlc_unitdata_ind_test, GRLC_UNITDATA_IND_TEST, sdu_len_in_bits);
339 prim_ptr = (T_GRLC_DATA_IND_TEST*)grlc_unitdata_ind_test;
340 }
341 {
342 /*
343 * copy from description list to test primitive
344 */
345 prim_ptr->tlli = grlc_data->downlink_tbf.tlli;
346 prim_ptr->sdu.l_buf = grlc_data->rd.pdu_len * 8;
347 prim_ptr->sdu.o_buf = 0;
348 ptr_next_array =
349 (T_NEXT_ARRAY*)grlc_data->rd.grlc_data_ind.desc_list.first;
350 ptr_pos = prim_ptr->sdu.buf;
351 cnt=0;
352 do
353 {
354 cnt++;
355 memcpy(ptr_pos,
356 ptr_next_array->data,
357 ptr_next_array->len );
358 ptr_pos = &ptr_pos[ptr_next_array->len];
359 ptr_next_array = (T_NEXT_ARRAY*)ptr_next_array->next;
360 }
361 while(ptr_next_array NEQ NULL);
362 PSEND(hCommLLC, prim_ptr);
363 TRACE_EVENT_P1("SEND PARTIONS =%d",cnt);
364
365 }
366
367 grlc_data->tbf_ctrl[grlc_data->dl_index].rlc_oct_cnt += grlc_data->rd.pdu_len;
368 grlc_data->tbf_ctrl[grlc_data->dl_index].pdu_cnt++;
369
370
371 /* delete blocks which are sent to LLC: only possible in test environment
372 * usally, deleting of the description list is task of LLC
373 */
374 rd_free_desc_list_partions();
375
376 } /* rd_out_grlc_data_ind_test() */
377
378 #endif /* _SIMULATION_ */
379
380
381
382
383 /*
384 +------------------------------------------------------------------------------
385 | Function : rd_send_grlc_data_ind
386 +------------------------------------------------------------------------------
387 | Description : The function rd_send_grlc_data_ind() ....
388 |
389 | Parameters : dummy - description of parameter dummy
390 |
391 +------------------------------------------------------------------------------
392 */
393 GLOBAL void rd_send_grlc_data_ind ( UBYTE bsn_i )
394 {
395 T_NEXT_ARRAY *ptr_block;
396 UBYTE pdu_cnt;
397 UBYTE compl_pdu;
398 TRACE_FUNCTION( "rd_send_grlc_data_ind" );
399
400
401 pdu_cnt = grlc_data->rd.data_array[bsn_i & WIN_MOD].pdu_cnt;
402
403 if(grlc_data->rd.data_array[bsn_i & WIN_MOD].pdu_complete)
404 compl_pdu = grlc_data->rd.data_array[bsn_i & WIN_MOD].pdu_cnt;
405 else if (pdu_cnt)
406 compl_pdu = grlc_data->rd.data_array[bsn_i & WIN_MOD].pdu_cnt -1;
407 else
408 compl_pdu = 0;
409
410 if ((ptr_block = grlc_data->rd.data_array[bsn_i & WIN_MOD].first) EQ NULL)
411 {
412 TRACE_EVENT_P4("NO DATA IND first empty bsn=%d bsn_mod=%d vr=%d vq=%d", bsn_i, bsn_i&WIN_MOD,grlc_data->rd.vr,grlc_data->rd.vq);
413 return;
414 }
415
416 do
417 {
418 if(grlc_data->rd.pdu_complete)
419 {
420 grlc_data->rd.ptr_grlc = ptr_block;
421 grlc_data->rd.grlc_data_ind.desc_list.first = (ULONG) grlc_data->rd.ptr_grlc;
422 grlc_data->rd.pdu_len = ptr_block->len;
423 grlc_data->rd.bsn_pdu_start = bsn_i;
424 }
425 else
426 {
427 grlc_data->rd.pdu_len += ptr_block->len;
428 grlc_data->rd.ptr_grlc->next = (ULONG*) ptr_block;
429 grlc_data->rd.ptr_grlc = (T_NEXT_ARRAY*) grlc_data->rd.ptr_grlc->next;
430 }
431 grlc_data->rd.pdu_complete = FALSE;
432
433 if(grlc_data->rd.pdu_len > MAX_LLC_PDU_SIZE)
434 {
435 TRACE_EVENT_P5("PDU SIZE TO BIG = %ld pdu_st=%d vr=%d compl_pdu=%d pdu_cnt=%d"
436 ,grlc_data->rd.pdu_len
437 ,grlc_data->rd.bsn_pdu_start
438 ,grlc_data->rd.vr
439 ,compl_pdu
440 ,pdu_cnt);
441 if(!compl_pdu)
442 {
443 /* no pdu in data block */
444 grlc_data->rd.ignore_pdu = TRUE;
445
446 /* free only linked partions */
447 rd_free_desc_list_partions();
448
449 return;
450 }
451 else
452 {
453 /* pdu boundary in data block */
454 ptr_block = (T_NEXT_ARRAY*) ptr_block->next;
455 grlc_data->rd.ptr_grlc->next = NULL;
456
457 /*
458 * free only linked partions
459 */
460 rd_free_desc_list_partions();
461
462 compl_pdu--;
463 }
464
465 }
466 else if( compl_pdu )
467 {
468
469 TRACE_EVENT_P5("GRLC_DATA_IND len=%ld bsn_start=%d bsn_end=%d las_len=%d dl_fn=%ld"
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491 ,grlc_data->rd.pdu_len
492 ,grlc_data->rd.bsn_pdu_start
493 ,bsn_i
494 ,ptr_block->len
495 ,grlc_data->dl_fn);
496 ptr_block = (T_NEXT_ARRAY*) ptr_block->next;
497 grlc_data->rd.ptr_grlc->next = NULL;
498 grlc_data->rd.grlc_data_ind.desc_list.list_len = grlc_data->rd.pdu_len;
499 grlc_data->rd.grlc_data_ind.tlli = grlc_data->downlink_tbf.tlli;
500
501 #ifdef _TARGET_
502 {
503 rd_out_grlc_data_ind();
504 }
505 # endif
506
507 # ifdef _SIMULATION_
508 {
509 rd_out_grlc_data_ind_test();
510 }
511 # endif
512 grlc_data->rd.pdu_complete = TRUE;
513 compl_pdu--;
514 }
515 if(!pdu_cnt)
516 pdu_cnt = 0;
517 else
518 pdu_cnt--;
519 }
520 while(pdu_cnt);
521
522 grlc_data->rd.pdu_complete = grlc_data->rd.data_array[bsn_i & WIN_MOD].pdu_complete;
523
524 /*
525 * block combined, first element reseted
526 */
527 grlc_data->rd.data_array[bsn_i & WIN_MOD].first = NULL;
528
529 } /* rd_send_grlc_data_ind() */
530
531
532
533 /*
534 +------------------------------------------------------------------------------
535 | Function : rd_check_window_size
536 +------------------------------------------------------------------------------
537 | Description : The function rd_check_window_size() ....
538 |
539 | Parameters : dummy - description of parameter dummy
540 |
541 +------------------------------------------------------------------------------
542 */
543 GLOBAL BOOL rd_check_window_size ( UBYTE bsn_i )
544 {
545 BOOL result;
546
547 TRACE_FUNCTION( "rd_check_window_size" );
548
549 if(grlc_data->rd.rlc_mode EQ CGRLC_RLC_MODE_ACK)
550 {
551 if( bsn_i >= grlc_data->rd.ssn )
552 {
553 if((bsn_i - grlc_data->rd.ssn) < WIN_SIZE)
554 {
555 result = TRUE;
556 }
557 else
558 {
559 result = FALSE;
560 }
561 }
562 else
563 {
564 if((bsn_i + 128 - grlc_data->rd.ssn) < WIN_SIZE)
565 {
566 result = TRUE;
567 }
568 else
569 {
570 result = FALSE;
571 }
572 }
573 }
574 else if(grlc_data->rd.rlc_mode EQ CGRLC_RLC_MODE_UACK)
575 {
576 if( bsn_i >= grlc_data->rd.vr )
577 {
578 if((bsn_i - grlc_data->rd.vr) < WIN_SIZE)
579 {
580 result = TRUE;
581 }
582 else
583 {
584 result = FALSE;
585 }
586 }
587 else
588 {
589 if((bsn_i + 128 - grlc_data->rd.vr) < WIN_SIZE)
590 {
591 result = TRUE;
592 }
593 else
594 {
595 result = FALSE;
596 }
597 }
598 }
599 else
600 {
601 result =FALSE;
602 TRACE_EVENT_P4("unknown rlc mode in rd_check_window_size: rlc_mode=%d, bsn_i=%d,ssn=%d,vr=%d "
603 ,grlc_data->rd.rlc_mode
604 ,bsn_i
605 ,grlc_data->rd.ssn
606 ,grlc_data->rd.vr);
607 }
608
609
610 return result;
611 } /* rd_check_window_size() */
612
613
614
615 /*
616 +------------------------------------------------------------------------------
617 | Function : rd_save_block
618 +------------------------------------------------------------------------------
619 | Description : The function rd_save_block() ....
620 |
621 | Parameters : bsn_i - block sequence number of the saved block
622 | *ptr_data_block_i - pointer the data field of the rlc data
623 | block without header and li field
624 | fbi_i - final block indication bit of the received
625 | data block
626 |
627 +------------------------------------------------------------------------------
628 */
629 GLOBAL void rd_save_block ( UBYTE bsn_i, UBYTE * ptr_data_block_i, UBYTE fbi_i)
630 {
631 T_NEXT_ARRAY *ptr_temp=NULL;
632 UBYTE block_nr;
633 UBYTE i;
634 UBYTE *ptr_data;
635 USHORT len;
636 TRACE_FUNCTION( "rd_save_block" );
637
638 if(!(grlc_data->rd.li_cnt))
639 {
640 /*
641 * only a part of a pdu
642 */
643 MALLOC(ptr_temp, sizeof(T_NEXT_ARRAY));
644 ptr_temp->next = NULL;
645 ptr_temp->len = grlc_data->rd.rlc_data_len;
646 memcpy((ptr_temp->data),(ptr_data_block_i),(ptr_temp->len));
647 grlc_data->rd.data_array[bsn_i & WIN_MOD].first = ptr_temp;
648 if(fbi_i)
649 {
650 grlc_data->rd.data_array[bsn_i & WIN_MOD].pdu_cnt = 1;
651 grlc_data->rd.data_array[bsn_i & WIN_MOD].pdu_complete =TRUE;
652 }
653 else
654 {
655 grlc_data->rd.data_array[bsn_i & WIN_MOD].pdu_cnt = 0;
656 grlc_data->rd.data_array[bsn_i & WIN_MOD].pdu_complete =FALSE;
657 }
658
659 }
660 else
661 {
662 /*
663 * for the first part
664 */
665 MALLOC(ptr_temp, sizeof(T_NEXT_ARRAY));
666 if(grlc_data->rd.li[0] EQ 0 )
667 ptr_temp->len = grlc_data->rd.rlc_data_len-1;
668 else
669 ptr_temp->len = grlc_data->rd.li[0];
670
671 ptr_data = ptr_data_block_i;
672 memcpy((ptr_temp->data),
673 (ptr_data),
674 (ptr_temp->len));
675 grlc_data->rd.data_array[bsn_i & WIN_MOD].first = ptr_temp;
676 block_nr = 1;
677 while((block_nr <= grlc_data->rd.li_cnt) AND (grlc_data->rd.m[block_nr-1]))
678 {
679 ptr_data = &(ptr_data[ptr_temp->len]);
680 MALLOC(ptr_temp->next, sizeof(T_NEXT_ARRAY));
681 ptr_temp = (T_NEXT_ARRAY *)ptr_temp->next;
682 /*
683 * check if it islast pdu in rlc data block
684 */
685 if((block_nr EQ grlc_data->rd.li_cnt)
686 OR (grlc_data->rd.li[block_nr] EQ 0))
687 {
688 /*
689 * last block, len is REST
690 */
691 len = 0;
692 for(i=0; i < grlc_data->rd.li_cnt; i++)
693 len += grlc_data->rd.li[i];
694 ptr_temp->len = grlc_data->rd.rlc_data_len - grlc_data->rd.li_cnt - len;
695 }
696 else
697 {
698 /*
699 * not last part
700 */
701 ptr_temp->len = grlc_data->rd.li[block_nr];
702 }
703 memcpy((ptr_temp->data),
704 (ptr_data),
705 (ptr_temp->len));
706 block_nr++;
707 }
708 ptr_temp->next = NULL;
709 if(grlc_data->rd.m[grlc_data->rd.li_cnt-1] EQ 0)
710 grlc_data->rd.data_array[bsn_i & WIN_MOD].pdu_cnt = grlc_data->rd.li_cnt;
711 else
712 grlc_data->rd.data_array[bsn_i & WIN_MOD].pdu_cnt = grlc_data->rd.li_cnt + 1;
713
714 if(fbi_i
715 OR
716 ((grlc_data->rd.li[grlc_data->rd.li_cnt-1])
717 AND (grlc_data->rd.m[grlc_data->rd.li_cnt-1] EQ 0)))
718 grlc_data->rd.data_array[bsn_i & WIN_MOD].pdu_complete = TRUE;
719 else
720 grlc_data->rd.data_array[bsn_i & WIN_MOD].pdu_complete = FALSE;
721
722 }
723
724 } /* rd_save_block() */
725
726
727
728 /*
729 +------------------------------------------------------------------------------
730 | Function : rd_comp_rec_par
731 +------------------------------------------------------------------------------
732 | Description : The function rd_comp_rec_par() ....
733 |
734 | Parameters : dummy - description of parameter dummy
735 |
736 +------------------------------------------------------------------------------
737 */
738 GLOBAL void rd_comp_rec_par ( UBYTE bsn_i )
739 {
740 UBYTE vq_help;
741 TRACE_FUNCTION( "rd_comp_rec_par" );
742
743 if(grlc_data->rd.rlc_mode EQ CGRLC_RLC_MODE_ACK)
744 {
745 if( ( grlc_data->rd.vr >= grlc_data->rd.ssn) &&
746 ( (bsn_i >= grlc_data->rd.vr ) ||
747 (bsn_i < grlc_data->rd.ssn) ) )
748 grlc_data->rd.vr = (bsn_i+1) & 0x7F;
749 else if( ( grlc_data->rd.vr < grlc_data->rd.ssn) &&
750 ( (bsn_i >= grlc_data->rd.vr ) &&
751 (bsn_i < grlc_data->rd.ssn) ) )
752 grlc_data->rd.vr = (bsn_i+1) & 0x7F;
753
754 grlc_data->rd.vn[bsn_i & WIN_MOD] = VN_RECEIVED;
755 vq_help = grlc_data->rd.vq;
756 while( (grlc_data->rd.vn[vq_help & WIN_MOD] EQ VN_RECEIVED) AND
757 vq_help NEQ grlc_data->rd.vr)
758 {
759 vq_help = (vq_help+1) & 0x7F;
760 }
761 grlc_data->rd.vq = vq_help;
762 }
763 else if(grlc_data->rd.rlc_mode EQ CGRLC_RLC_MODE_UACK)
764 {
765 if(grlc_data->rd.vr EQ bsn_i)
766 {
767 grlc_data->rd.vr = (1+grlc_data->rd.vr) % 128;
768 grlc_data->rd.vq = (1+grlc_data->rd.vq) % 128;
769 grlc_data->rd.inSequence = TRUE;
770 }
771 else
772 {
773 grlc_data->rd.vr = bsn_i;
774 grlc_data->rd.inSequence = FALSE;
775 }
776 }
777 else
778 TRACE_ERROR(" unknown RLC Mode during dl tbf in rd_comp_rec_par");
779
780
781
782 } /* rd_comp_rec_par() */
783
784
785
786
787 /*
788 +------------------------------------------------------------------------------
789 | Function : rd_check_fbi
790 +------------------------------------------------------------------------------
791 | Description : The function rd_check_fbi() ....
792 |
793 | Parameters : dummy - description of parameter dummy
794 |
795 +------------------------------------------------------------------------------
796 */
797 GLOBAL UBYTE rd_check_fbi ( UBYTE fbi_i, UBYTE sp , ULONG fn , UBYTE rrbp )
798 {
799 TRACE_FUNCTION( "rd_check_fbi" );
800
801 /*
802 * mark the bsn with fbi=1
803 */
804 if(fbi_i)
805 {
806 grlc_data->rd.last_bsn = grlc_data->rd.vr;
807 if(!sp)
808 {
809 TRACE_EVENT_P1("NO SP BUT FINAL DATA BLOCK t3192=%d",grlc_data->downlink_tbf.t3192_val);
810 }
811 }
812
813
814 /*
815 * if last bsn is left window element, than tbf is going to be released
816 */
817 if(grlc_data->rd.last_bsn EQ grlc_data->rd.vq AND
818 !grlc_data->rd.f_ack_ind) /* to avoid retransmission */
819 {
820 PALLOC(prim,CGRLC_T3192_STARTED_IND);
821 PSEND(hCommGRR,prim);
822 if(grlc_data->rd.rlc_mode EQ CGRLC_RLC_MODE_ACK )
823 {
824 SET_STATE(RD,RD_REL_ACK);
825 }
826 else
827 {
828 SET_STATE(RD,RD_REL_UACK);
829 }
830
831 grlc_data->tbf_ctrl[grlc_data->dl_index].fbi = 1;
832
833 if(sp)
834 {
835 grlc_data->rd.fn_p_tbf_rel = grlc_decode_tbf_start_rel(fn,(USHORT)(rrbp+3));
836 }
837 return 1;
838 }
839 else
840 {
841 return 0;
842 }
843 }/* rd_check_fbi() */
844
845
846
847
848 /*
849 +------------------------------------------------------------------------------
850 | Function : rd_set_acknack
851 +------------------------------------------------------------------------------
852 | Description : The function rd_set_acknack() ....
853 |
854 | Parameters : dummy - description of parameter dummy
855 |
856 +------------------------------------------------------------------------------
857 */
858 GLOBAL UBYTE* rd_set_acknack ( void )
859 {
860 MCAST (u_dl_ack,U_GRLC_DL_ACK);
861 UBYTE * ptr_block;
862 UBYTE i;
863 UBYTE index;
864 UBYTE help,neg_ack=0;
865 ULONG rbb1=0,rbb2=0,dummy1=0,dummy2=0;
866
867 TRACE_FUNCTION( "rd_set_acknack" );
868
869
870 if(grlc_data->rd.channel_req AND (grlc_data->tbf_type EQ TBF_TYPE_DL))
871 {
872 u_dl_ack->v_chan_req_des = 1;
873 u_dl_ack->chan_req_des = grlc_data->chan_req_des;
874 grlc_data->rd.channel_req = 0;
875 grlc_data->rd.ch_req_in_ack_prog = TRUE;
876 /* TRACE_EVENT_P6("channel req des in dl ack nack:ptp=%d,rp=%d,rlc_mode=%d,llc_pt=%d,rlc_oc=%d, pst=%d",
877 grlc_data->chan_req_des.peak_thr_class,
878 grlc_data->chan_req_des.radio_prio,
879 grlc_data->chan_req_des.rlc_mode,
880 grlc_data->chan_req_des.llc_pdu_type,
881 grlc_data->chan_req_des.rlc_octet_cnt,
882 grlc_data->prim_start_tbf);*/
883 if(grlc_data->prim_start_tbf >= PRIM_QUEUE_SIZE_TOTAL)
884 {
885 TRACE_EVENT_P3("PST=%d PSF=%d PDU=%d: rd_set_acknack"
886 ,grlc_data->prim_start_tbf
887 ,grlc_data->prim_start_free
888 ,grlc_data->grlc_data_req_cnt);
889 }
890
891 }
892 else
893 {
894 u_dl_ack->v_chan_req_des = 0;
895 grlc_data->rd.channel_req = 0;
896 }
897
898 u_dl_ack->msg_type = U_GRLC_DL_ACK_c;
899 u_dl_ack->dl_tfi = grlc_data->dl_tfi;
900 u_dl_ack->ack_nack_des.f_ack_ind = grlc_data->rd.f_ack_ind;
901 u_dl_ack->ack_nack_des.ssn = grlc_data->rd.vr;
902 memset(u_dl_ack->ack_nack_des.rbb, 1, WIN_SIZE );
903 for(i=0; i< WIN_SIZE; i++)
904 {
905 if(grlc_data->rd.vr EQ grlc_data->rd.ssn OR grlc_data->rd.rlc_mode EQ CGRLC_RLC_MODE_UACK)
906 break;
907 index = (grlc_data->rd.vr-1-i) & 0x7F;
908 if(grlc_data->rd.vn[index & WIN_MOD] NEQ VN_RECEIVED)
909 {
910 u_dl_ack->ack_nack_des.rbb[WIN_SIZE-1-i] = 0;
911 neg_ack++;
912 }
913 if(grlc_data->rd.ssn EQ index )
914 {
915 help = grlc_data->rd.ssn;
916 while(help NEQ grlc_data->rd.vq)
917 {
918 grlc_data->rd.vn[help & WIN_MOD] = VN_INVALID;
919 help = (help + 1) & 0x7F;
920 }
921 break;
922 }
923 }
924
925 /* TRACE ONLY if there is channel desc or negative ack or the final ack*/
926 if(u_dl_ack->v_chan_req_des OR
927 u_dl_ack->ack_nack_des.f_ack_ind OR
928 neg_ack)
929 {
930 if(neg_ack AND !u_dl_ack->ack_nack_des.f_ack_ind)
931 {
932 for(i=0; i<32;i++)
933 {
934 dummy1 = u_dl_ack->ack_nack_des.rbb[WIN_SIZE-1-i];
935 dummy2 = u_dl_ack->ack_nack_des.rbb[WIN_SIZE-1-i-32];
936 rbb1 += dummy1 <<i;
937 rbb2 += dummy2 <<i;
938 }
939 TRACE_EVENT_P7("dl_ack:p_fn=%ld,CD=%d ssn=%d nacks=%d vq=%d rbb2=%lx rbb1=%lx",
940 grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn,
941 u_dl_ack->v_chan_req_des,
942 u_dl_ack->ack_nack_des.ssn,
943 neg_ack,
944 grlc_data->rd.vq,
945 rbb2,
946 rbb1);
947 }
948 else
949 {
950 rbb1 = 0xFFFFFFFF;
951 rbb2 = 0xFFFFFFFF;
952 TRACE_EVENT_P6("dl_ack:p_fn=%ld,CD=%d fbi=%d ssn=%d nacks=%d vq=%d",
953 grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn,
954 u_dl_ack->v_chan_req_des,
955 u_dl_ack->ack_nack_des.f_ack_ind,
956 u_dl_ack->ack_nack_des.ssn,
957 neg_ack,
958 grlc_data->rd.vq);
959 }
960 }
961 else
962 {
963 rbb1 = 0xFFFFFFFF;
964 rbb2 = 0xFFFFFFFF;
965 }
966
967 u_dl_ack->chan_qual_rep.c_value = 0;
968 u_dl_ack->chan_qual_rep.rxqual = 0;
969 u_dl_ack->chan_qual_rep.signvar = 0;
970
971 {
972 /* processing channel quality report */
973
974 /* processing of C value */
975 u_dl_ack->chan_qual_rep.c_value = meas_grlc_c_get_value( );
976
977 /* processing of RXQUAL value */
978 u_dl_ack->chan_qual_rep.rxqual = meas_sq_get_rxqual_value( );
979
980 /* processing of signal variance */
981 u_dl_ack->chan_qual_rep.signvar = meas_sv_get_value( );
982
983 /* processing of relative interference levels */
984 meas_int_get_rel_i_level( &u_dl_ack->chan_qual_rep.ilev );
985 }
986
987 #if !defined (NTRACE)
988
989 if( grlc_data->meas.v_im_trace NEQ 0 )
990 {
991 TRACE_EVENT_P3( "rd_set_acknack: %d %d %d",
992 u_dl_ack->chan_qual_rep.c_value,
993 u_dl_ack->chan_qual_rep.rxqual,
994 u_dl_ack->chan_qual_rep.signvar );
995 }
996
997 #endif /* #if !defined (NTRACE) */
998
999 #ifdef REL99
1000
1001 u_dl_ack->v_release_99_str_u_grlc_dl_ack = 1;
1002
1003 if (grlc_data->pfi_support AND u_dl_ack->v_chan_req_des )
1004 {
1005 u_dl_ack->release_99_str_u_grlc_dl_ack.v_pfi = 1;
1006 u_dl_ack->release_99_str_u_grlc_dl_ack.pfi = grlc_data->pfi_value;
1007 }
1008 else
1009 {
1010 u_dl_ack->release_99_str_u_grlc_dl_ack.v_pfi = 0;
1011 }
1012
1013 #endif
1014
1015
1016 grlc_data->rd.ssn = grlc_data->rd.vq;
1017 ptr_block = (_decodedMsg);
1018
1019
1020 return ptr_block;
1021 } /* rd_set_acknack() */
1022
1023
1024 /*
1025 +------------------------------------------------------------------------------
1026 | Function : rd_calc_rlc_data_len
1027 +------------------------------------------------------------------------------
1028 | Description : The function rd_calc_rlc_data_len() calculates the Data size of
1029 | an RLC data block depending on coding scheme.
1030 | The size is described in bytes.
1031 |
1032 | Parameters : block_status_i - includes the Coding scheme which
1033 | determines the size of an RLC data block
1034 |
1035 +------------------------------------------------------------------------------
1036 */
1037 GLOBAL UBYTE rd_calc_rlc_data_len ( USHORT block_status_i )
1038 {
1039 UBYTE result=0;
1040 TRACE_FUNCTION( "rd_calc_rlc_data_len" );
1041
1042 /*
1043 * the coding scheme is only in the first four bits
1044 */
1045 block_status_i = block_status_i & 0x000F;
1046
1047 switch( block_status_i)
1048 {
1049 case 2:
1050 grlc_data->rd.cs_type = CS_1;
1051 break;
1052 case 4:
1053 grlc_data->rd.cs_type = CS_2;
1054 break;
1055 case 5:
1056 grlc_data->rd.cs_type = CS_3;
1057 break;
1058 case 6:
1059 grlc_data->rd.cs_type = CS_4;
1060 break;
1061 default:
1062 TRACE_EVENT("No Coding Scheme in RLC data block defined, old CS is used");
1063 break;
1064 }
1065
1066
1067 switch( grlc_data->rd.cs_type)
1068 {
1069 /*
1070 * NO CS defined in all previously received RLC data blocks,
1071 * therefore default CS_1 is used
1072 */
1073 case CS_ZERO:
1074 case CS_1:
1075 result = 20;
1076 break;
1077 case CS_2:
1078 result = 30;
1079 break;
1080 case CS_3:
1081 result = 36;
1082 break;
1083 case CS_4:
1084 result = 50;
1085 break;
1086 default:
1087 TRACE_ERROR("unknown Coding Scheme");
1088 break;
1089 }
1090
1091 return result;
1092 } /* rd_calc_rlc_data_len() */
1093
1094
1095
1096 /*
1097 +------------------------------------------------------------------------------
1098 | Function : rd_fill_blocks
1099 +------------------------------------------------------------------------------
1100 | Description : The function rd_fill_blocks() fills not received but needed
1101 | RLC data blocks with the value Zero.
1102 |
1103 | Parameters : bsn_i - bsn value of the recently received RLC data block,
1104 | which is not inSequence(not equal VR at receiving the block)
1105 |
1106 +------------------------------------------------------------------------------
1107 */
1108 GLOBAL void rd_fill_blocks ( UBYTE bsn_i )
1109 {
1110 T_NEXT_ARRAY * ptr_temp=NULL;
1111 TRACE_FUNCTION( "rd_fill_blocks" );
1112
1113 do
1114 {
1115 MALLOC(ptr_temp, sizeof(T_NEXT_ARRAY));
1116 ptr_temp->next = NULL;
1117 ptr_temp->len = grlc_data->rd.rlc_data_len;
1118 memset(ptr_temp->data,0,ptr_temp->len);
1119 grlc_data->rd.data_array[grlc_data->rd.vq & WIN_MOD].first = ptr_temp;
1120 grlc_data->rd.data_array[grlc_data->rd.vq & WIN_MOD].pdu_cnt = 0;
1121 grlc_data->rd.data_array[grlc_data->rd.vq & WIN_MOD].pdu_complete =FALSE;
1122 rd_send_grlc_data_ind(grlc_data->rd.vq);
1123 grlc_data->rd.vq = (1+grlc_data->rd.vq) % 128; /*modulo 128*/
1124 }
1125 while(grlc_data->rd.vq NEQ bsn_i);
1126
1127 grlc_data->rd.vq = (1+grlc_data->rd.vq) % 128; /*modulo 128*/
1128 grlc_data->rd.vr = grlc_data->rd.vq;
1129 grlc_data->rd.inSequence = TRUE;
1130
1131
1132
1133 } /* rd_fill_blocks() */
1134
1135
1136
1137
1138 /*
1139 +------------------------------------------------------------------------------
1140 | Function : rd_calc_delta_fn
1141 +------------------------------------------------------------------------------
1142 | Description : The function rd_calc_delta_fn() calculates delta_fn. It is
1143 | needed at receiving mac_ready_ind to send a poll block.
1144 | In Target Enviroment, the poll block(Ack/nack or Control block)
1145 | must be calculated one radio block earlier then the send time.
1146 | This is needed due to the functional interface.
1147 | Parameters : fn_i - framenumber for the uplink call
1148 |
1149 |
1150 +------------------------------------------------------------------------------
1151 */
1152 GLOBAL ULONG rd_calc_delta_fn ( ULONG fn_i )
1153 {
1154 ULONG result;
1155 TRACE_FUNCTION( "rd_calc_delta_fn" );
1156
1157 #ifdef _TARGET_
1158 {
1159 if(fn_i EQ FN_MAX-5)
1160 result = grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn + 5;
1161 else
1162 result = grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn - fn_i;
1163 }
1164 #endif
1165
1166 #ifdef _SIMULATION_
1167 {
1168 if(fn_i EQ grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn)
1169 result = 4; /*valid: send block*/
1170 else
1171 result = 0; /*no poll sending*/
1172 }
1173 #endif
1174
1175 return result;
1176
1177
1178 } /* rd_calc_delta_fn() */
1179
1180 /*
1181 +------------------------------------------------------------------------------
1182 | Function : rd_free_desc_list_partions
1183 +------------------------------------------------------------------------------
1184 | Description : The function rd_free_desc_list_partions() frees the partions,
1185 | which are linked for a candidate LLC pdu. PDU is stored as a
1186 | description list, but not passed to LLC because of incomplete.
1187 | Parameters :
1188 |
1189 +------------------------------------------------------------------------------
1190 */
1191 GLOBAL void rd_free_desc_list_partions ( void )
1192 {
1193 UBYTE cnt = 0;
1194 T_NEXT_ARRAY *help = NULL;
1195
1196 TRACE_FUNCTION( "rd_free_desc_list_partions" );
1197
1198 help = (T_NEXT_ARRAY*)grlc_data->rd.grlc_data_ind.desc_list.first;
1199
1200 grlc_data->rd.grlc_data_ind.desc_list.first = NULL;
1201
1202 while(help != NULL)
1203 {
1204 T_NEXT_ARRAY *ptr = (T_NEXT_ARRAY*) help->next;
1205 MFREE(help);
1206 help = ptr;
1207 cnt++;
1208 }
1209
1210
1211 #ifdef _SIMULATION_
1212 TRACE_EVENT_P1("freed partion (linked) : cnt=%d",cnt);
1213 #endif /* _SIMULATION_*/
1214
1215
1216 grlc_data->rd.pdu_complete = TRUE;
1217 grlc_data->rd.pdu_len = 0;
1218
1219
1220 } /* rd_free_desc_list_partions() */
1221
1222 /*
1223 +------------------------------------------------------------------------------
1224 | Function : rd_free_database_partions
1225 +------------------------------------------------------------------------------
1226 | Description : The function rd_free_database_partions() frees the partions,
1227 | which are stored in the RD database. They are not linked to a
1228 | LLC pdu because data blocks are not received in sequence.
1229 | Partions are removed from left window size (vq) up to the
1230 | right window size (vr).
1231 | Parameters :
1232 |
1233 +------------------------------------------------------------------------------
1234 */
1235 GLOBAL void rd_free_database_partions ( void )
1236 {
1237 USHORT bsn;
1238
1239 UBYTE cnt=0;
1240
1241 T_NEXT_ARRAY *help = NULL;
1242
1243 TRACE_FUNCTION( "rd_free_database_partions" );
1244
1245 bsn = grlc_data->rd.vq;
1246
1247 while (bsn NEQ grlc_data->rd.vr)
1248 {
1249 help = grlc_data->rd.data_array[bsn & WIN_MOD].first;
1250 #ifdef _SIMULATION_
1251 TRACE_EVENT_P2("candiate bsn=%d vn=%d",bsn,grlc_data->rd.vn[bsn & WIN_MOD]);
1252 #endif /* _SIMULATION_*/
1253
1254 while (help != NULL)
1255 {
1256 grlc_data->rd.data_array[bsn & WIN_MOD].first =
1257 (T_NEXT_ARRAY *)grlc_data->rd.data_array[bsn & WIN_MOD].first->next;
1258
1259 MFREE(help);
1260
1261 cnt++;
1262 #ifdef _SIMULATION_
1263 TRACE_EVENT_P1("element free : bsn=%d",bsn);
1264 #endif /* _SIMULATION_*/
1265 if(grlc_data->rd.data_array[bsn & WIN_MOD].pdu_cnt)
1266 help = grlc_data->rd.data_array[bsn & WIN_MOD].first;
1267 else
1268 help = NULL;
1269 }
1270 grlc_data->rd.data_array[bsn & WIN_MOD].pdu_complete = FALSE;
1271 grlc_data->rd.data_array[bsn & WIN_MOD].pdu_cnt = 0xFF;
1272 grlc_data->rd.data_array[bsn & WIN_MOD].first = NULL;
1273
1274 bsn = (bsn + 1) & 0x7F;
1275 }
1276 TRACE_EVENT_P2("rd_free_database_partions after: bsn=%d cnt=%d ", bsn, cnt);
1277
1278
1279 } /* rd_free_database_partions() */
1280
1281
1282 /*
1283 +------------------------------------------------------------------------------
1284 | Function : rd_cgrlc_st_time_ind
1285 +------------------------------------------------------------------------------
1286 | Description : The function rd_cgrlc_st_time_ind () informs higher layers
1287 | that the starting time is elapsed
1288 |
1289 | Parameters : -
1290 |
1291 +------------------------------------------------------------------------------
1292 */
1293 GLOBAL void rd_cgrlc_st_time_ind ( void )
1294 {
1295 PALLOC(cgrlc_starting_time_ind,CGRLC_STARTING_TIME_IND); /* T_CGRLC_STARTING_TIME_IND */
1296
1297 TRACE_FUNCTION( "rd_cgrlc_st_time_ind " );
1298
1299 cgrlc_starting_time_ind->tbf_mode = CGRLC_TBF_MODE_DL;
1300 cgrlc_starting_time_ind->tfi = grlc_data->dl_tfi;
1301
1302 PSEND(hCommGRR,cgrlc_starting_time_ind);
1303
1304 grlc_data->dl_tn_mask = grlc_data->downlink_tbf.ts_mask;
1305
1306
1307 } /* rd_cgrlc_st_time_ind () */