comparison src/g23m-fad/l2r/l2r_upf.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 : CSD (8411)
4 | Modul : L2r_upf.c
5 +-----------------------------------------------------------------------------
6 | Copyright 2002 Texas Instruments Berlin, AG
7 | All rights reserved.
8 |
9 | This file is confidential and a trade secret of Texas
10 | Instruments Berlin, AG
11 | The receipt of or possession of this file does not convey
12 | any rights to reproduce or disclose its contents or to
13 | manufacture, use, or sell anything it may describe, in
14 | whole, or in part, without the specific written consent of
15 | Texas Instruments Berlin, AG.
16 +-----------------------------------------------------------------------------
17 | Purpose : This Modul defines the procedures and functions for
18 | the component L2R of the base station
19 +-----------------------------------------------------------------------------
20 */
21
22 #ifndef L2R_UPF_C
23 #define L2R_UPF_C
24 #endif
25
26 #define ENTITY_L2R
27
28 /*==== INCLUDES ===================================================*/
29
30 #include <string.h>
31 #include "typedefs.h"
32 #include "pconst.cdg"
33 #include "vsi.h"
34 #include "macdef.h"
35 #include "custom.h"
36 #include "gsm.h"
37 #include "cus_l2r.h"
38 #include "cnf_l2r.h"
39 #include "mon_l2r.h"
40 #include "prim.h"
41 #include "pei.h"
42 #include "tok.h"
43 #include "dti.h" /* functionality of the dti library */
44
45 #include "cl_ribu.h"
46 #include "l2r.h"
47
48 /*==== CONST =======================================================*/
49
50 /*==== TYPES =======================================================*/
51
52 /*==== VAR EXPORT ==================================================*/
53
54 /*==== VAR LOCAL ===================================================*/
55
56 /*==== FUNCTIONS ===================================================*/
57
58 /*
59 +------------------------------------------------------------------------------
60 | Function : up_init
61 +------------------------------------------------------------------------------
62 | Description : initialise the l2r data for the uplink process
63 |
64 | Parameters : -
65 |
66 |
67 | Return : -
68 +------------------------------------------------------------------------------
69 */
70
71 GLOBAL void up_init(T_UP *dup)
72 {
73 register ULONG i;
74
75 TRACE_FUNCTION ("up_init()");
76
77 dup->FlowCtrlUsed = FALSE;
78 dup->DnFlow = FL_INACTIVE;
79 dup->UpFlow = FL_INACTIVE;
80 dup->ULFlow = FL_INACTIVE;
81 dup->LLFlow = FL_INACTIVE;
82 dup->MrgFlow = FL_INACTIVE;
83 dup->FlowThreshLo = MAX_UPRIM_RIBU_SIZE/2;
84 dup->FlowThreshHi = 3*MAX_UPRIM_RIBU_SIZE/4;
85 dup->DataSize = 0;
86 dup->FrameSize = 0;
87 dup->OldFrameSize = 0;
88 dup->FramesPerPrim = L2R_FRAMES_PER_PRIM_MAX;
89 dup->LastRcvdSa = 0;
90 dup->LastRcvdSb = 0;
91 dup->LastSentSa = 0;
92 dup->LastSentSb = 0;
93 dup->LastSentFlow = FL_INACTIVE;
94 dup->StoreDataActive = FALSE;
95 dup->UrgentMsg = FALSE;
96 dup->DiscardRemapData = FALSE;
97 dup->QRemapRead = 0;
98 dup->QRemapWrite = 0;
99 dup->BRemapAdr = NULL;
100 dup->BRemapLen = 0;
101 dup->BRemapSa = 0;
102 dup->BRemapSb = 0;
103 dup->BRemapLastState = 0;
104 dup->QRemapPrimDesc.prim = NULL;
105
106 for (i = 0; i < MAX_UP_REMAP_QUEUE_SIZE; i++)
107 {
108 dup->QRemap[i] = NULL;
109 }
110
111 for (i = 0; i < UP_REMAP_BUFFER_SIZE; i++)
112 {
113 dup->BRemap[i] = 0;
114 }
115
116 dup->RiBu.idx.depth = MAX_UPRIM_RIBU_SIZE;
117
118 INIT_STATE (UP_UL, IW_IDLE);
119 INIT_STATE (UP_LL, ISW_IDLE);
120 INIT_STATE (UP, UP_DISCONNECTED);
121 }
122
123 /*
124 +------------------------------------------------------------------------------
125 | Function : up_alloc_prim
126 +------------------------------------------------------------------------------
127 | Description :
128 |
129 | Parameters : -
130 |
131 |
132 | Return : -
133 +------------------------------------------------------------------------------
134 */
135
136
137 LOCAL void up_alloc_prim(void)
138 {
139 T_UP *dup = &l2r_data->up;
140
141 T_PRIM_INDEX m;
142 T_P_UPRIM_DESCRIPTOR primDesc;
143 USHORT sduSize;
144
145 TRACE_FUNCTION ("up_alloc_prim()");
146
147 sduSize = dup->FramesPerPrim * dup->FrameSize * 8;
148 primDesc = dup->RiBu.primDesc[dup->RiBu.alloc];
149 {
150 PALLOC_SDU(data_req, RLP_DATA_REQ, sduSize);
151 primDesc->prim = data_req;
152 }
153
154 #ifdef _SIMULATION_
155 /* Clear SDU for test environment */
156 {
157 UBYTE *p;
158 UBYTE *pend;
159 p = &primDesc->prim->sdu.buf[0];
160 pend = p + (sduSize >> 3);
161 while (p < pend)
162 {
163 *p++ = 0;
164 }
165 }
166 #endif
167
168 primDesc->prim->sdu.o_buf = 0;
169 primDesc->prim->sdu.l_buf = sduSize;
170 primDesc->nFr = dup->FramesPerPrim;
171 primDesc->index = 0;
172 primDesc->offset = 0;
173 primDesc->off_status = 0;
174 primDesc->full = FALSE;
175 primDesc->sa = FL_INACTIVE;
176 primDesc->sb = FL_INACTIVE;
177 /*lint -e416 (Warning -- Likely creation of out-of-bounds) */
178 for (m = 0; m != dup->FramesPerPrim; m++)
179 {
180 (*primDesc->adr)[m] = (T_P_L2R_FRAME)(primDesc->prim->sdu.buf +L2R_ENCODING_OFFSET + m * dup->FrameSize);
181 }
182 /*lint +e416 (Warning -- Likely creation of out-of-bounds) */
183 dup->RiBu.alloc++;
184 if (dup->RiBu.alloc EQ dup->RiBu.idx.depth)
185 {
186 dup->RiBu.alloc = 0;
187 }
188 }
189
190 /*
191 +------------------------------------------------------------------------------
192 | Function : up_send_prim_timeout
193 +------------------------------------------------------------------------------
194 | Description :
195 |
196 | Parameters : -
197 |
198 |
199 | Return : -
200 +------------------------------------------------------------------------------
201 */
202
203
204 GLOBAL void up_send_prim_timeout(void)
205 {
206 T_UP *dup = &l2r_data->up;
207
208 TRACE_FUNCTION ("up_send_prim_timeout()");
209
210 if (!dup->RiBu.idx.filled)
211 {
212 if (dup->RiBu.alloc EQ dup->RiBu.idx.wi)
213 {
214 /* No primitive is there, so we allocate one */
215 up_alloc_prim();
216 }
217
218 /*
219 No primitive is ready, so we take one away from the relay entity
220 */
221 cl_ribu_write_index(&dup->RiBu.idx); /* point to next primitive */
222 }
223 up_send_current_prim();
224 }
225
226 /*
227 +------------------------------------------------------------------------------
228 | Function : up_next_remap_frame
229 +------------------------------------------------------------------------------
230 | Description : Local function, which is used by up_copy_data_from_l2r
231 | to advance to the next frame in the primitive.
232 | The variable primDesc of the calling function is updated.
233 |
234 | Parameters : primDesc -
235 |
236 | Return : 1 -
237 | 0 -
238 +------------------------------------------------------------------------------
239 */
240
241 LOCAL UBYTE up_next_remap_frame(T_RPRIM_DESCRIPTOR *primDesc)
242 {
243 T_UP *dup = &l2r_data->up;
244
245 U8 i;
246 T_P_RLP_REMAP_DATA_IND prim;
247
248 /* next frame */
249 primDesc->index++;
250
251 if (primDesc->index >= primDesc->nFr)
252 {
253 /* primitive is completely read out */
254 PFREE(dup->QRemap [dup->QRemapRead]);
255
256 /* next primitive */
257 (dup->QRemapRead)++;
258 if (dup->QRemapRead >= MAX_UP_REMAP_QUEUE_SIZE)
259 {
260 dup->QRemapRead = 0;
261 }
262 if (dup->QRemapRead EQ dup->QRemapWrite)
263 {
264 /* no primitive is ready */
265 primDesc->prim = NULL;
266 return (1);
267 }
268
269 /* point to next primitive descriptor */
270
271 prim = dup->QRemap[dup->QRemapRead];
272 primDesc->prim = prim;
273 primDesc->nFr = prim->sdu.l_buf / (8 * prim->data_size + HT_LEN);
274 primDesc->index = 0;
275
276 for (i = 0; i < primDesc->nFr; i++)
277 {
278 primDesc->adr[i] = (T_P_L2R_FRAME)(prim->sdu.buf + (prim->sdu.o_buf>>3)
279 + HEADER_LEN + i * (prim->data_size + HT_LEN));
280 }
281 }
282 primDesc->offset = 0;
283 primDesc->off_status = 0;
284 return (0);
285 }
286
287 /*
288 +------------------------------------------------------------------------------
289 | Function : up_copy_data_from_rq
290 +------------------------------------------------------------------------------
291 | Description :
292 |
293 | Parameters : buf -
294 | len -
295 | sa -
296 | sb -
297 | bytesCopied -
298 |
299 | Return : -
300 +------------------------------------------------------------------------------
301 */
302
303 LOCAL void up_copy_data_from_rq(U8 *buf, U16 len, U8 *sa, U8 *sb, U16 *bytesCopied)
304 {
305 T_UP *dup = &l2r_data->up;
306
307 register ULONG i;
308 register T_P_UBYTE pFrame;
309 register T_P_UBYTE pBuf;
310 register T_P_UBYTE pStat;
311 T_P_RLP_REMAP_DATA_IND prim;
312 T_P_L2R_FRAME frame;
313 T_P_UBYTE pEnd;
314 USHORT bytesToCopy;
315 USHORT blocklen;
316 UBYTE statOct;
317 UBYTE lastState;
318
319 T_RPRIM_DESCRIPTOR *primDesc = &dup->QRemapPrimDesc;
320
321 #ifdef _SIMULATION_
322 TRACE_FUNCTION ("up_copy_data_from_rq()");
323 #endif
324
325 bytesToCopy = len;
326
327 if (primDesc->prim EQ NULL)
328 {
329 prim = dup->QRemap[dup->QRemapRead];
330 primDesc->prim = prim;
331 primDesc->nFr = prim->sdu.l_buf / ((prim->data_size<<3) + HT_LEN);
332 primDesc->index = 0;
333 primDesc->offset = 0;
334 primDesc->off_status = 0;
335
336 for (i = 0; i < primDesc->nFr; i++)
337 {
338 primDesc->adr[i] = (T_P_L2R_FRAME)(prim->sdu.buf + (prim->sdu.o_buf>>3)
339 + HEADER_LEN + i * (prim->data_size + HT_LEN));
340 }
341 }
342
343 /* skip empty primitive */
344 if (primDesc->nFr EQ 0)
345 {
346 *bytesCopied = 0;
347 return;
348 }
349
350 frame = primDesc->adr[primDesc->index]; /* point to current l2r frame in primitive */
351 pBuf = buf; /* point to destination buffer */
352 pFrame = &((*frame)[primDesc->offset]);
353 pStat = &((*frame)[primDesc->off_status]);
354
355 if (pFrame EQ pStat)
356 {
357 /* current byte is status octet */
358 dup->BRemapLastState = *pFrame & SO_STATUS_BITS_MASK;
359 }
360
361 lastState = dup->BRemapLastState;
362 *sa = GET_SO_SA_BIT(lastState);
363 *sb = GET_SO_SB_BIT(lastState);
364
365 /************************************************************************************
366 * loop until either
367 * - no more data are available or
368 * - status in L2R frame changes or
369 * - buffer for data is full
370 ************************************************************************************/
371
372 for (;;)
373 {
374 #ifdef _SIMULATION_
375 TRACE_FUNCTION ("loop");
376 #endif
377
378 blocklen = pStat - pFrame;
379 if (blocklen EQ 0)
380 {
381 /*
382 * current byte is status octet
383 * (only in the first pass of the loop, there may be no status octet)
384 */
385
386 /*****************************
387 * evaluate status bits
388 *****************************/
389 statOct = *pFrame;
390 if (lastState NEQ (statOct & SO_STATUS_BITS_MASK))
391 {
392 /*
393 * status has changed. We have to stop,
394 * since only one state can be transmitted to the upper layer
395 */
396 primDesc->offset = primDesc->off_status = pFrame - (T_P_UBYTE)frame;
397
398 *bytesCopied = len - bytesToCopy;
399 return;
400 }
401
402 pFrame++;
403
404 /************************************
405 * evaluate addrss bits
406 ************************************/
407 statOct &= SO_ADR_MASK;
408
409 switch (statOct)
410 {
411 case SO_BREAK_ACK:
412 case SO_BREAK_REQ:
413 case SO_END_EMPTY:
414 /* no more data in this frame */
415 if (up_next_remap_frame(primDesc) EQ 1)
416 {
417 /* no more data available */
418 *bytesCopied = len - bytesToCopy; /* this much data could be copied */
419 return;
420 }
421
422 frame = primDesc->adr[primDesc->index];
423 pFrame = (T_P_UBYTE)frame;
424 pStat = (T_P_UBYTE)frame;
425 continue; /* continue with next frame */
426
427 case SO_END_FULL:
428 pStat = &((*frame)[primDesc->prim->data_size]);
429 blocklen = pStat - pFrame;
430 break;
431
432 case SO_TWO_OCTET:
433 blocklen = *pFrame++ & SO_ADR_MASK_TWO_OCT;
434 pStat = pFrame + blocklen;
435 break;
436
437 default:
438 blocklen = statOct;
439 pStat = pFrame + blocklen;
440 break;
441 }
442 }
443
444 if (bytesToCopy < blocklen)
445 {
446 /***************************************
447 * There is not enough space in the
448 * buffer to copy the complete block
449 ***************************************/
450
451 pEnd = pFrame + bytesToCopy;
452
453 while (pFrame < pEnd)
454 {
455 *pBuf++ = *pFrame++;
456 }
457
458 if (pFrame EQ &((*frame)[primDesc->prim->data_size]))
459 {
460 /* end of frame reached */
461 up_next_remap_frame(primDesc);
462 }
463 else
464 {
465 primDesc->offset = pFrame - (T_P_UBYTE)frame;
466 primDesc->off_status = pStat - (T_P_UBYTE)frame;
467 }
468 *bytesCopied = len; /* this much data could be copied */
469 return;
470 }
471 else
472 {
473 /***************************************
474 * Copy the complete block
475 ***************************************/
476 bytesToCopy -= blocklen;
477
478 while (pFrame < pStat)
479 {
480 *pBuf++ = *pFrame++;
481 }
482
483 if (pFrame EQ &((*frame)[primDesc->prim->data_size]))
484 {
485 /* end of frame reached */
486 if (up_next_remap_frame(primDesc) EQ 1)
487 {
488 /* no more data available */
489 *bytesCopied = len - bytesToCopy; /* this much data could be copied */
490 return;
491 }
492 frame = primDesc->adr[primDesc->index];
493 pFrame = (T_P_UBYTE)frame;
494 pStat = (T_P_UBYTE)frame;
495 }
496 if (bytesToCopy EQ 0)
497 {
498 primDesc->offset = pFrame - (T_P_UBYTE)frame;
499 primDesc->off_status = pStat - (T_P_UBYTE)frame;
500 *bytesCopied = len; /* this much data could be copied */
501 return;
502 }
503 }
504 }
505 }
506
507 /*
508 +------------------------------------------------------------------------------
509 | Function : up_fill_in_status_octet
510 +------------------------------------------------------------------------------
511 | Description : local function, which is used patch a status octet into a
512 | l2r frame. This function takes into acount the two octet
513 | format for 14400.
514 |
515 | Parameters : pFrame - points to begin of l2r frame
516 | offstat1 - offset of status octet to be patched
517 | offstat2 - offset of next status octet
518 |
519 | Return :
520 +------------------------------------------------------------------------------
521 */
522
523 LOCAL BOOL up_fill_in_status_octet(T_P_UBYTE pFrame, UBYTE offstat1, UBYTE offstat2)
524 {
525 register T_P_UBYTE pStat, pSrc, pDes, pEnd;
526 register UBYTE dataLen;
527
528 dataLen = offstat2 - offstat1 - 1; /* number of data bytes between status octets */
529 pStat = pFrame + offstat1;
530
531 if (dataLen <= DATA_SIZE_SHORT-2)
532 {
533 *pStat |= dataLen;
534 return (FALSE);
535 }
536 else
537 {
538 /* this is only possible with 14400 */
539 if (offstat2 < DATA_SIZE_LONG - 1)
540 {
541 /* a two octet status must be inserted */
542 pSrc = pFrame + offstat2;
543 pDes = pSrc + 1;
544 pEnd = pFrame + offstat1;
545 while (pSrc > pEnd)
546 {
547 *--pDes = *--pSrc;
548 }
549 *pStat |= SO_TWO_OCTET;
550 pStat++;
551 *pStat = dataLen;
552 }
553 else
554 {
555 /* a additional status octet (FULL) must be inserted somewhere in the frame */
556 pSrc = pFrame + offstat2;
557 pDes = pSrc + 1;
558 pEnd = pFrame + offstat1 + DATA_SIZE_SHORT - 1;
559 while (pSrc > pEnd)
560 {
561 *--pDes = *--pSrc;
562 }
563 *pStat |= DATA_SIZE_SHORT - 2;
564 *pEnd = *pStat & SO_STATUS_BITS_MASK | SO_END_FULL;
565 }
566 return (TRUE);
567 }
568 }
569
570 /*
571 +------------------------------------------------------------------------------
572 | Function : up_next_frame
573 +------------------------------------------------------------------------------
574 | Description : local function, which is used by up_copy_data_into_l2r to
575 | advance to the next frame in the primitive
576 | The variables primDesc, frame and pFrame of the calling function
577 | are updated. Moreover the return values of the calling function
578 | primToSend and bytesCopied are set.
579 |
580 |
581 | Parameters : primDesc -
582 | primToSend -
583 |
584 | Return :
585 +------------------------------------------------------------------------------
586 */
587
588 LOCAL UBYTE up_next_frame(T_P_UPRIM_DESCRIPTOR *primDesc, BOOL *primToSend)
589 {
590 T_UP *dup = &l2r_data->up;
591
592 TRACE_FUNCTION("up_next_frame()");
593
594 (*primDesc)->index++;
595 (*primDesc)->offset = 0;
596
597 if ((*primDesc)->index >= dup->FramesPerPrim) /* primitive is filled */
598 {
599 (*primDesc)->full = TRUE;
600 *primToSend = TRUE;
601
602 cl_ribu_write_index(&dup->RiBu.idx); /* point to next primitive */
603
604 if (dup->RiBu.alloc EQ dup->RiBu.idx.wi)
605 {
606 /* no primitive is ready */
607 return (1);
608 }
609
610 /* point to next primitive descriptor */
611 *primDesc = dup->RiBu.primDesc[dup->RiBu.idx.wi];
612 (*primDesc)->index = 0;
613 }
614 return (0);
615 }
616
617 LOCAL void up_copy_data_into_l2r(U8 *buf, U16 len, U8 sa, U8 sb, U8 x, BOOL *primToSend, U16 *bytesCopied)
618 {
619 T_UP *dup = &l2r_data->up;
620
621 T_P_UPRIM_DESCRIPTOR primDesc;
622 T_P_L2R_FRAME frame;
623 register T_P_UBYTE pFrame;
624 register T_P_UBYTE pEnd;
625 register T_P_UBYTE pBuf;
626 USHORT bytesToCopy;
627 UBYTE frameCount;
628 T_FLOW flow = FL_INVALID;
629
630 #ifdef _SIMULATION_
631 TRACE_FUNCTION ("up_copy_data_into_l2r()");
632 #endif
633
634 switch (x)
635 {
636 case DTI_FLOW_ON:
637 flow = FL_INACTIVE;
638 break;
639 case DTI_FLOW_OFF:
640 flow = FL_ACTIVE;
641 break;
642 }
643
644 #ifdef _TARGET_
645 if (dup->DataSize > DATA_SIZE_SHORT)
646 {
647 frameCount = 1;
648 }
649 else
650 {
651 frameCount = 2;
652 }
653 #else
654 {
655 frameCount = 100;
656 }
657 #endif
658
659 up_store_status(sa, sb, flow);
660
661 if (dup->LastSentFlow EQ dup->MrgFlow)
662 {
663 *primToSend = FALSE;
664 }
665 else
666 {
667 *primToSend = TRUE;
668 }
669
670 /* don't copy into primitive if no primitive is ready */
671 if (dup->RiBu.alloc EQ dup->RiBu.idx.wi)
672 {
673 *bytesCopied = 0;
674 return;
675 }
676
677 bytesToCopy = len;
678
679 primDesc = dup->RiBu.primDesc[dup->RiBu.idx.wi]; /* point to current primitive descriptor */
680 frame = (*primDesc->adr)[primDesc->index]; /* point to current l2r frame in primitive */
681 pFrame = &(*frame)[primDesc->offset]; /* point to current byte in frame */
682 pBuf = buf; /* point to source buffer */
683
684 /************************************************************************************
685 *
686 * Handle a partly filled frame, which has been written in the primitive previously
687 *
688 ************************************************************************************/
689
690 if (primDesc->offset NEQ 0)
691 {
692 /* partly filled frame is there */
693
694 if (bytesToCopy EQ 0)
695 /* no data to copy -> quit without writing status octet */
696 {
697 *bytesCopied = len;
698 return;
699 }
700
701 if (sa NEQ primDesc->sa OR sb NEQ primDesc->sb)
702 {
703 /*
704 * status has changed since last time
705 */
706
707 /* finish previous status octet */
708 if (
709 up_fill_in_status_octet(
710 (T_P_UBYTE)frame,
711 primDesc->off_status,
712 primDesc->offset
713 )
714 )
715 {
716 /* frame data has been moved to make space for two octet status */
717 pFrame++;
718 (primDesc->offset)++;
719
720 if (primDesc->offset >= (dup->DataSize))
721 {
722 /* frame is just filled by patching the previous status frame */
723
724 if (up_next_frame(&primDesc, primToSend) EQ 1)
725 {
726 /* no more space for data */
727 *bytesCopied = 0; /* no data could be copied */
728 return;
729 }
730 frameCount--;
731 #ifdef _TARGET_
732 if (frameCount EQ 0)
733 {
734 *bytesCopied = 0; /* no data could be copied */
735 return;
736 }
737 #endif
738 frame = (*primDesc->adr)[primDesc->index]; /* point to current l2r frame in primitive */
739 pFrame = &(*frame)[primDesc->offset]; /* point to current byte in frame */
740 }
741 }
742
743 if (primDesc->offset NEQ 0)
744 {
745 /* write status octet */
746 *pFrame++ = (U8)(sa << SO_SA_BIT | sb << SO_SB_BIT | 0 << SO_X_BIT); /* x is set to 0 (inactive) by default */
747
748 /* store current status for next call */
749 primDesc->sa = sa;
750 primDesc->sb = sb;
751
752 primDesc->off_status = primDesc->offset;
753 (primDesc->offset)++;
754 if (primDesc->offset >= (dup->DataSize))
755 {
756 /* frame is just filled by the status octet */
757
758 /* finish previous status octet */
759 (*frame)[primDesc->off_status] |= SO_END_EMPTY;
760
761 if (up_next_frame(&primDesc, primToSend) EQ 1)
762 {
763 /* no more space for data */
764 *bytesCopied = 0; /* no data could be copied */
765 return;
766 }
767 frameCount--;
768 if (frameCount EQ 0)
769 {
770 *bytesCopied = 0; /* no data could be copied */
771 return;
772 }
773 frame = (*primDesc->adr)[primDesc->index]; /* point to current l2r frame in primitive */
774 pFrame = &(*frame)[primDesc->offset]; /* point to current byte in frame */
775 }
776 }
777 }
778
779 /*
780 * write data into partly filled frame
781 */
782 if (primDesc->offset NEQ 0)
783 {
784 if (bytesToCopy >= dup->DataSize - primDesc->offset)
785 {
786 /* enough data to fill frame completly */
787
788 for (pEnd = pFrame + dup->DataSize - primDesc->offset; pFrame < pEnd; )
789 {
790 *pFrame++ = *pBuf++;
791 }
792
793 /* finish previous status octet */
794 (*frame)[primDesc->off_status] |= SO_END_FULL;
795
796 bytesToCopy -= dup->DataSize - primDesc->offset;
797
798 if (up_next_frame(&primDesc, primToSend) EQ 1)
799 {
800 /* no more space for data */
801 *bytesCopied = len - bytesToCopy; /* this much data could be copied */
802 return;
803 }
804 frameCount--;
805 if (frameCount EQ 0)
806 {
807 *bytesCopied = len - bytesToCopy; /* this much data could be copied */
808 return;
809 }
810 frame = (*primDesc->adr)[primDesc->index]; /* point to current l2r frame in primitive */
811 pFrame = &(*frame)[primDesc->offset]; /* point to current byte in frame */
812
813 }
814 else
815 {
816 /* not enough data to fill frame completly */
817
818 for (pEnd = pFrame + bytesToCopy; pFrame < pEnd; )
819 {
820 *pFrame++ = *pBuf++;
821 }
822 primDesc->offset += bytesToCopy;
823 *bytesCopied = len;
824 return; /* Nothing else to do */
825 }
826 }
827 }
828
829 /************************************************************************************
830 *
831 * Handle consecutive frames, which are filled starting with byte 0
832 *
833 ************************************************************************************/
834
835 while (bytesToCopy > 0)
836 {
837 if (bytesToCopy >= dup->DataSize - 1)
838 {
839 /*
840 * There are enough data to fill a frame completely
841 */
842 *pFrame++ = sa << SO_SA_BIT | sb << SO_SB_BIT | 0 << SO_X_BIT | SO_END_FULL; /* x is set to 0 (inactive) by default */
843
844 /* store current status for next call */
845 primDesc->sa = sa;
846 primDesc->sb = sb;
847
848 for (pEnd = pFrame + dup->DataSize - 1; pFrame < pEnd; )
849 {
850 *pFrame++ = *pBuf++;
851 }
852 bytesToCopy -= dup->DataSize - 1;
853
854 /* advance to next frame */
855 if (up_next_frame(&primDesc, primToSend) EQ 1)
856 {
857 /* running out of primitives */
858 *bytesCopied = len - bytesToCopy; /* this much data could be copied */
859 return;
860 }
861 frameCount--;
862 if (frameCount EQ 0)
863 {
864 *bytesCopied = len - bytesToCopy; /* this much data could be copied */
865 return;
866 }
867 frame = (*primDesc->adr)[primDesc->index]; /* point to current l2r frame in primitive */
868 pFrame = &(*frame)[primDesc->offset]; /* point to current byte in frame */
869 }
870 else
871 {
872 /*
873 * There are some data, but not enough to fill a frame completely
874 */
875 *pFrame++ = (U8)(sa << SO_SA_BIT | sb << SO_SB_BIT | 0 << SO_X_BIT); /* x is set to 0 (inactive) by default */
876
877 /* store current status for next call */
878 primDesc->sa = sa;
879 primDesc->sb = sb;
880
881 for (pEnd = pFrame + bytesToCopy; pFrame < pEnd; )
882 {
883 *pFrame++ = *pBuf++;
884 }
885 primDesc->off_status = 0;
886 primDesc->offset = bytesToCopy + 1;
887 bytesToCopy = 0;
888 }
889 }
890 *bytesCopied = len;
891 }
892
893 /*
894 +------------------------------------------------------------------------------
895 | Function : up_copy_remap_data
896 +------------------------------------------------------------------------------
897 | Description :
898 |
899 | Parameters : -
900 |
901 |
902 | Return : -
903 +------------------------------------------------------------------------------
904 */
905
906 LOCAL void up_copy_remap_data(void)
907 {
908 T_UP *dup = &l2r_data->up;
909
910 USHORT bytesCopied;
911 BOOL dummy;
912
913 #ifdef _SIMULATION_
914 TRACE_FUNCTION ("up_copy_remap_data()");
915 #endif
916
917 do
918 {
919 if (dup->BRemapLen EQ 0)
920 {
921 dup->BRemapAdr = dup->BRemap;
922 up_copy_data_from_rq
923 (
924 dup->BRemapAdr,
925 UP_REMAP_BUFFER_SIZE,
926 &dup->BRemapSa,
927 &dup->BRemapSb,
928 &dup->BRemapLen
929 );
930 if (dup->BRemapLen EQ 0)
931 {
932 up_check_flow();
933 return;
934 }
935 }
936 up_copy_data_into_l2r
937 (
938 dup->BRemapAdr,
939 dup->BRemapLen,
940 dup->BRemapSa,
941 dup->BRemapSb,
942 DTI_FLOW_OFF,
943 &dummy,
944 &bytesCopied
945 );
946 dup->BRemapAdr += bytesCopied;
947 dup->BRemapLen -= bytesCopied;
948
949 } while (bytesCopied NEQ 0);
950 }
951
952 /*
953 +------------------------------------------------------------------------------
954 | Function : up_check_alloc
955 +------------------------------------------------------------------------------
956 | Description : This procedure allocates new primitives until there are
957 | UP_RIBU_PREALLOC primitives ready.
958 |
959 | I.e.: alloc = write + UP_RIBU_PREALLOC
960 |
961 | It may be less than this, if otherwise the alloc pointer
962 | would reach the read pointer.
963 |
964 |
965 | Parameters : -
966 |
967 |
968 | Return : -
969 +------------------------------------------------------------------------------
970 */
971
972 GLOBAL void up_check_alloc(void)
973 {
974 T_UP *dup = &l2r_data->up;
975
976 S8 i_from, i_to;
977
978 TRACE_FUNCTION ("up_check_alloc()");
979
980 i_to = dup->RiBu.idx.ri - dup->RiBu.idx.wi - 1;
981
982 if (i_to < 0)
983 {
984 i_to = i_to + dup->RiBu.idx.depth;
985 }
986
987 if (i_to > UP_RIBU_PREALLOC)
988 {
989 i_to = UP_RIBU_PREALLOC;
990 }
991
992 i_from = dup->RiBu.alloc - dup->RiBu.idx.wi;
993
994 if (i_from < 0)
995 {
996 i_from = i_from + dup->RiBu.idx.depth;
997 }
998
999 if (i_from >= i_to)
1000 {
1001 return;
1002 }
1003
1004 do
1005 {
1006 up_alloc_prim();
1007 i_from++;
1008 } while (i_from < i_to);
1009
1010 if (dup->QRemapRead NEQ dup->QRemapWrite)
1011 {
1012 up_copy_remap_data();
1013 return;
1014 }
1015
1016 switch (GET_STATE (UP_UL))
1017 {
1018 case IW_WAIT:
1019 break;
1020
1021 case IW_IDLE:
1022 if (dup->StoreDataActive EQ FALSE AND dup->Prim NEQ NULL)
1023 {
1024 up_store_data();
1025 }
1026 break;
1027 }
1028 }
1029
1030 /*
1031 +------------------------------------------------------------------------------
1032 | Function : up_check_flow
1033 +------------------------------------------------------------------------------
1034 | Description :
1035 |
1036 | Parameters : -
1037 |
1038 |
1039 | Return : -
1040 +------------------------------------------------------------------------------
1041 */
1042
1043 GLOBAL void up_check_flow(void)
1044 {
1045 T_UP *dup = &l2r_data->up;
1046
1047 U8 primCount;
1048
1049 TRACE_FUNCTION ("up_check_flow()");
1050
1051 if (!dup->FlowCtrlUsed)
1052 {
1053 return;
1054 }
1055
1056 primCount = dup->RiBu.idx.filled;
1057
1058 switch (dup->UpFlow)
1059 {
1060 case FL_ACTIVE:
1061 if (primCount < dup->FlowThreshLo)
1062 {
1063 dup->UpFlow = FL_INACTIVE;
1064 }
1065 else
1066 {
1067 return;
1068 }
1069 break;
1070
1071 case FL_INACTIVE:
1072 if (primCount >= dup->FlowThreshHi)
1073 {
1074 dup->UpFlow = FL_ACTIVE;
1075 }
1076 else
1077 {
1078 return;
1079 }
1080 break;
1081 }
1082 sig_up_dn_flow(dup->UpFlow);
1083 }
1084
1085 /*
1086 +------------------------------------------------------------------------------
1087 | Function : up_store_data
1088 +------------------------------------------------------------------------------
1089 | Description : This procedure copies data from a dti_data_req primitive
1090 | into the uplink ring buffer.
1091 |
1092 |
1093 | Parameters : -
1094 |
1095 |
1096 | Return : -
1097 +------------------------------------------------------------------------------
1098 */
1099
1100 GLOBAL void up_store_data(void)
1101 {
1102 T_UP *dup = &l2r_data->up;
1103
1104 T_P_UBYTE adr;
1105 USHORT len;
1106 BOOL primToSend;
1107 USHORT bytesCopied;
1108 USHORT i, j;
1109 T_desc2 *desc;
1110
1111 TRACE_FUNCTION ("up_store_data()");
1112
1113 dup->StoreDataActive = TRUE;
1114
1115 do
1116 {
1117 desc = (T_desc2*)dup->Prim->desc_list2.first;
1118 if (desc)
1119 {
1120 len = desc->len;
1121 adr = desc->buffer;
1122 }
1123 else
1124 {
1125 len = 0;
1126 adr = NULL;
1127 }
1128
1129 up_copy_data_into_l2r (adr,
1130 len,
1131 dup->Prim->parameters.st_lines.st_line_sa,
1132 dup->Prim->parameters.st_lines.st_line_sb,
1133 dup->Prim->parameters.st_lines.st_flow,
1134 &primToSend,
1135 &bytesCopied);
1136
1137 dup->Prim->desc_list2.list_len -= bytesCopied;
1138
1139 if (desc)
1140 {
1141 if ((bytesCopied EQ len))
1142 {
1143 /*
1144 * Block has been copied successfully
1145 */
1146 dup->Prim->desc_list2.first = desc->next;
1147 MFREE (desc);
1148 }
1149 else if (bytesCopied > 0)
1150 {
1151 /*
1152 * remaining data must be copied to begin of block
1153 */
1154 /*lint -e{661} (Warning -- Likely creation of out-of-bounds) */
1155 for (i=0, j = bytesCopied; j < len; i++, j++)
1156 {
1157 desc->buffer[i] = desc->buffer[j];
1158 }
1159 desc->len -= bytesCopied;
1160 }
1161 }
1162 up_check_alloc();
1163
1164 } while (dup->Prim->desc_list2.first NEQ 0 AND dup->RiBu.alloc NEQ dup->RiBu.idx.wi);
1165
1166 if (dup->Prim->desc_list2.first EQ 0)
1167 {
1168 PFREE (dup->Prim);
1169 dup->Prim = NULL;
1170 up_send_ready();
1171 }
1172 dup->StoreDataActive = FALSE;
1173 }
1174
1175 /*
1176 +------------------------------------------------------------------------------
1177 | Function : up_send_ready
1178 +------------------------------------------------------------------------------
1179 | Description : only used in test environment
1180 |
1181 | Parameters : -
1182 |
1183 |
1184 | Return : -
1185 +------------------------------------------------------------------------------
1186 */
1187
1188 GLOBAL void up_send_ready(void)
1189 {
1190 TRACE_FUNCTION ("up_send_ready()");
1191
1192 if (GET_STATE (UP_UL) EQ IW_IDLE)
1193 {
1194 if (l2r_data->up.DtiConnected EQ FALSE)
1195 {
1196 TRACE_EVENT("DTI not connected, but up_send_ready() called -> break");
1197 return; /* jk: DTI_READY_IND primitive cannot be sent when DTI disconnected (!) */
1198 }
1199
1200 dti_start (
1201 l2r_hDTI,
1202 L2R_DTI_UP_DEF_INSTANCE,
1203 L2R_DTI_UP_INTERFACE,
1204 L2R_DTI_UP_CHANNEL
1205 );
1206 SET_STATE (UP_UL, IW_WAIT);
1207 }
1208 }
1209
1210 LOCAL void clear_primDesc(T_P_UPRIM_DESCRIPTOR primDesc)
1211 {
1212 primDesc->prim = NULL;
1213
1214 primDesc->nFr = 0;
1215 primDesc->index = 0;
1216 primDesc->offset = 0;
1217 primDesc->off_status = 0;
1218 primDesc->full = FALSE;
1219 primDesc->sa = FL_INACTIVE;
1220 primDesc->sb = FL_INACTIVE;
1221 }
1222
1223 /*
1224 +------------------------------------------------------------------------------
1225 | Function : up_free_prim
1226 +------------------------------------------------------------------------------
1227 | Description :
1228 |
1229 | Parameters : primDesc
1230 |
1231 |
1232 | Return : -
1233 +------------------------------------------------------------------------------
1234 */
1235
1236 LOCAL void up_free_prim(T_P_UPRIM_DESCRIPTOR primDesc)
1237 {
1238 TRACE_FUNCTION ("up_free_prim()");
1239
1240 if (primDesc->prim NEQ NULL)
1241 {
1242 PFREE (primDesc->prim);
1243 clear_primDesc(primDesc);
1244 }
1245 }
1246
1247 /*
1248 +------------------------------------------------------------------------------
1249 | Function : up_deinit_ribu
1250 +------------------------------------------------------------------------------
1251 | Description :
1252 |
1253 | Parameters : -
1254 |
1255 |
1256 | Return : -
1257 +------------------------------------------------------------------------------
1258 */
1259
1260 GLOBAL void up_deinit_ribu(void)
1261 {
1262 T_UP *dup = &l2r_data->up;
1263
1264 T_PRIM_DESC_RIBU_INDEX n;
1265
1266 T_P_UPRIM_DESCRIPTOR primDesc;
1267
1268 TRACE_FUNCTION ("up_deinit_ribu()");
1269
1270 for (n = 0; n < dup->RiBu.idx.depth; n++)
1271 {
1272 primDesc = dup->RiBu.primDesc[n];
1273 if (primDesc->prim NEQ NULL)
1274 {
1275 up_free_prim(primDesc);
1276 }
1277 }
1278 if (GET_STATE (UP_LL) EQ ISW_SEND)
1279 {
1280 SET_STATE (UP_LL, ISW_IDLE);
1281 }
1282 }
1283
1284 /*
1285 +------------------------------------------------------------------------------
1286 | Function : up_send_status
1287 +------------------------------------------------------------------------------
1288 | Description :
1289 |
1290 | Parameters : sa -
1291 | sb -
1292 | flow -
1293 | adr -
1294 |
1295 | Return : -
1296 +------------------------------------------------------------------------------
1297 */
1298
1299
1300
1301 GLOBAL void up_send_status
1302 (
1303 T_BIT sa,
1304 T_BIT sb,
1305 T_FLOW flow,
1306 UBYTE adr
1307 )
1308 {
1309 T_UP *dup = &l2r_data->up;
1310
1311 T_P_UPRIM_DESCRIPTOR primDesc;
1312 T_P_L2R_FRAME frame;
1313 T_BIT x = 0;
1314
1315 TRACE_FUNCTION ("up_send_status()");
1316
1317 primDesc = dup->RiBu.primDesc[dup->RiBu.idx.wi];
1318 frame = (*primDesc->adr)[0];
1319
1320 switch (flow)
1321 {
1322 case FL_ACTIVE:
1323 x = 1;
1324 break;
1325 case FL_INACTIVE:
1326 x = 0;
1327 break;
1328 }
1329 (*frame)[0] = sa << SO_SA_BIT | sb << SO_SB_BIT | x << SO_X_BIT | adr;
1330
1331 /* jk:030501 - TEST CASE 251 -
1332 new funktion parameter 'adr' was introduced
1333 in order to cancel the older function 'up_send_break(...)'
1334 */
1335 primDesc->sa = sa; /* the status has to be saved in order to be correctly stored later */
1336 primDesc->sb = sb; /* on into "dup->LastSentSa/Sb" [up_send current_prim()] */
1337
1338 primDesc->index = 1;
1339 primDesc->offset = 0;
1340
1341 cl_ribu_write_index(&dup->RiBu.idx); /* point to next primitive */
1342 }
1343
1344 /*
1345 +------------------------------------------------------------------------------
1346 | Function : up_set_flow_in_prim
1347 +------------------------------------------------------------------------------
1348 | Description :
1349 |
1350 | Parameters : prim -
1351 |
1352 |
1353 | Return : -
1354 +------------------------------------------------------------------------------
1355 */
1356
1357 LOCAL void up_set_flow_in_prim(T_P_RLP_DATA_REQ prim)
1358 {
1359 T_UP *dup = &l2r_data->up;
1360
1361 if (dup->MrgFlow EQ FL_INACTIVE)
1362 {
1363 TRACE_FUNCTION ("up_set_flow_in_prim(INACTIVE)");
1364 }
1365 else
1366 {
1367 T_PRIM_INDEX frames;
1368 T_PRIM_INDEX ind;
1369 UBYTE off;
1370 register UBYTE statOct;
1371 T_P_L2R_FRAME frame;
1372
1373 TRACE_FUNCTION ("up_set_flow_in_prim(ACTIVE)");
1374
1375 frames = prim->sdu.l_buf / (8 * dup->FrameSize);
1376 frame = (T_P_L2R_FRAME) (prim->sdu.buf + (prim->sdu.o_buf / 8) + HEADER_LEN);
1377 off = 0;
1378 ind = 0;
1379
1380 while (ind < frames)
1381 {
1382 statOct = (*frame)[off];
1383 SET_BIT(statOct, SO_X_BIT);
1384 (*frame)[off] = statOct;
1385
1386 switch (statOct & SO_ADR_MASK)
1387 {
1388 case SO_BREAK_REQ:
1389 case SO_BREAK_ACK:
1390 case SO_END_EMPTY:
1391 case SO_END_FULL:
1392 ind++;
1393 frame = (T_P_L2R_FRAME)((UBYTE*)frame + dup->FrameSize);
1394 off = 0;
1395 break;
1396
1397 case SO_TWO_OCTET:
1398 off++;
1399 off += ((*frame)[off] & SO_ADR_MASK_TWO_OCT) + 1;
1400 if (off >= dup->DataSize)
1401 {
1402 ind++;
1403 frame = (T_P_L2R_FRAME)((UBYTE*)frame + dup->FrameSize);
1404 off = 0;
1405 }
1406 break;
1407
1408 default:
1409 off += (statOct & SO_ADR_MASK) + 1;
1410 if (off >= dup->DataSize)
1411 {
1412 ind++;
1413 frame = (T_P_L2R_FRAME)((UBYTE*)frame + dup->FrameSize);
1414 off = 0;
1415 }
1416 break;
1417 }
1418 }
1419 }
1420 dup->LastSentFlow = dup->MrgFlow;
1421 }
1422
1423 /*
1424 +------------------------------------------------------------------------------
1425 | Function : up_send_current_prim
1426 +------------------------------------------------------------------------------
1427 | Description :
1428 |
1429 | Parameters : -
1430 |
1431 |
1432 | Return : -
1433 +------------------------------------------------------------------------------
1434 */
1435
1436 GLOBAL void up_send_current_prim(void)
1437 {
1438 T_UP *dup = &l2r_data->up;
1439 T_P_UPRIM_DESCRIPTOR primDesc = dup->RiBu.primDesc[dup->RiBu.idx.ri];
1440
1441 TRACE_FUNCTION ("up_send_current_prim()");
1442
1443 if (!primDesc->full AND primDesc->index < primDesc->nFr)
1444 {
1445 TRACE_FUNCTION ("prim is not full");
1446 if (primDesc->offset > 0)
1447 {
1448 if (up_fill_in_status_octet((T_P_UBYTE)(*primDesc->adr)[primDesc->index], primDesc->off_status, primDesc->offset))
1449 {
1450 primDesc->offset++;
1451 if (primDesc->offset >= dup->DataSize)
1452 {
1453 primDesc->offset = 0;
1454 primDesc->index++;
1455 }
1456 }
1457 }
1458
1459 if (primDesc->offset > 0 OR primDesc->index EQ 0)
1460 {
1461 /*
1462 * Add status octet, if there is a partly filled frame
1463 * or if status has changed since last write
1464 */
1465 (*(*primDesc->adr)[primDesc->index])[primDesc->offset] =
1466 dup->LastRcvdSa << SO_SA_BIT |
1467 dup->LastRcvdSb << SO_SB_BIT |
1468 0 << SO_X_BIT |
1469 SO_END_EMPTY;
1470 primDesc->sa = dup->LastRcvdSa;
1471 primDesc->sb = dup->LastRcvdSb;
1472 primDesc->index++;
1473 }
1474 primDesc->prim->sdu.l_buf = primDesc->index * dup->FrameSize * 8;
1475 }
1476
1477 dup->LastSentSa = primDesc->sa;
1478 dup->LastSentSb = primDesc->sb;
1479 up_set_flow_in_prim(primDesc->prim);
1480
1481 PSENDX (RLP, primDesc->prim);
1482
1483 clear_primDesc(primDesc); /* this primitive doesn't belong to us any longer */
1484
1485 cl_ribu_read_index(&dup->RiBu.idx); /* point to next primitive */
1486
1487 dup->UrgentMsg = FALSE;
1488 up_check_alloc();
1489 up_check_flow();
1490 }
1491
1492
1493 /*
1494 +------------------------------------------------------------------------------
1495 | Function : up_send_prim_cond
1496 +------------------------------------------------------------------------------
1497 | Description :
1498 |
1499 | Parameters : -
1500 |
1501 |
1502 | Return : -
1503 +------------------------------------------------------------------------------
1504 */
1505
1506 GLOBAL void up_send_prim_cond(void)
1507 {
1508 TRACE_FUNCTION ("up_send_prim_cond()");
1509
1510 switch (GET_STATE (UP_LL))
1511 {
1512 case ISW_WAIT:
1513 TIMERSTOP (TIMER_TUP_SND);
1514 up_send_current_prim();
1515 SET_STATE (UP_LL, ISW_IDLE);
1516 break;
1517
1518 default:
1519 l2r_data->up.UrgentMsg = TRUE;
1520 up_check_flow();
1521 up_check_alloc();
1522 SET_STATE (UP_LL, ISW_SEND);
1523 break;
1524 }
1525 }
1526
1527 /*
1528 +------------------------------------------------------------------------------
1529 | Function : up_init_ribu
1530 +------------------------------------------------------------------------------
1531 | Description :
1532 |
1533 | Parameters : -
1534 |
1535 |
1536 | Return : -
1537 +------------------------------------------------------------------------------
1538 */
1539
1540
1541 GLOBAL void up_init_ribu(void)
1542 {
1543 T_UP *dup = &l2r_data->up;
1544
1545 T_PRIM_DESC_RIBU_INDEX n;
1546 T_PRIM_INDEX m;
1547
1548 TRACE_FUNCTION ("up_init_ribu()");
1549
1550 dup->RiBu.alloc = 0;
1551
1552 cl_ribu_init(&dup->RiBu.idx, dup->RiBu.idx.depth);
1553
1554 for (n = 0; n < dup->RiBu.idx.depth; n++)
1555 {
1556 dup->RiBu.primDesc[n] = &(dup->PrimDesc[n]);
1557
1558 dup->PrimDesc[n].nFr = 0;
1559 dup->PrimDesc[n].adr = (T_P_ADR_VECTOR)&(dup->AdrVec[n]);
1560 dup->PrimDesc[n].index = 0;
1561 dup->PrimDesc[n].offset = 0;
1562 dup->PrimDesc[n].off_status = 0;
1563 dup->PrimDesc[n].full = FALSE;
1564 dup->PrimDesc[n].sa = FL_INACTIVE;
1565 dup->PrimDesc[n].sb = FL_INACTIVE;
1566 dup->PrimDesc[n].prim = NULL;
1567
1568 for(m = 0;m < L2R_FRAMES_PER_PRIM_MAX; m++)
1569 {
1570 dup->AdrVec[n][m] = NULL;
1571 }
1572
1573 if (dup->RiBu.alloc < UP_RIBU_PREALLOC)
1574 {
1575 up_alloc_prim();
1576 }
1577 }
1578 }
1579
1580 /*
1581 +------------------------------------------------------------------------------
1582 | Function : up_store_status
1583 +------------------------------------------------------------------------------
1584 | Description :
1585 |
1586 | Parameters : sa
1587 | sb
1588 | flow
1589 |
1590 | Return : -
1591 +------------------------------------------------------------------------------
1592 */
1593
1594
1595 GLOBAL void up_store_status
1596 (
1597 T_BIT sa,
1598 T_BIT sb,
1599 T_FLOW flow
1600 )
1601 {
1602 T_UP *dup = &l2r_data->up;
1603
1604 #ifdef _SIMULATION_
1605 TRACE_FUNCTION ("up_store_status()");
1606 #endif
1607
1608 dup->LastRcvdSa = sa;
1609 dup->LastRcvdSb = sb;
1610
1611 if (dup->FlowCtrlUsed EQ FALSE OR flow EQ dup->ULFlow)
1612 {
1613 return;
1614 }
1615
1616 dup->ULFlow = flow;
1617
1618 up_merge_flow();
1619 sig_up_dn_ul_flow(dup->ULFlow);
1620 }
1621
1622 /*
1623 +------------------------------------------------------------------------------
1624 | Function : up_send_empty_frame
1625 +------------------------------------------------------------------------------
1626 | Description :
1627 |
1628 | Parameters : sa -
1629 | sb -
1630 | flow -
1631 |
1632 | Return : -
1633 +------------------------------------------------------------------------------
1634 */
1635
1636
1637 GLOBAL void up_send_empty_frame(T_BIT sa, T_BIT sb, T_FLOW flow)
1638 {
1639 T_UP *dup = &l2r_data->up;
1640
1641 T_BIT x = 0;
1642 USHORT sduSize = dup->FrameSize << 3;
1643
1644 PALLOC_SDU(data_req, RLP_DATA_REQ, sduSize);
1645
1646 TRACE_FUNCTION ("up_send_empty_frame()");
1647
1648 #ifdef _SIMULATION_
1649 /* Clear SDU for test environment */
1650 {
1651 UBYTE *p;
1652 UBYTE *pend;
1653 p = &data_req->sdu.buf[0];
1654 pend = p + dup->FrameSize;
1655 while (p < pend)
1656 {
1657 *p++ = 0;
1658 }
1659 }
1660 #endif
1661
1662 data_req->sdu.o_buf = 0;
1663 data_req->sdu.l_buf = sduSize;
1664
1665 switch (flow)
1666 {
1667 case FL_ACTIVE:
1668 x = 1;
1669 break;
1670 case FL_INACTIVE:
1671 x = 0;
1672 break;
1673 }
1674 /*lint -e416 (Warning -- Likely creation of out-of-bounds pointer) */
1675 /*lint -e415 (Warning -- Likely access of out-of-bounds pointer) */
1676 data_req->sdu.buf[L2R_ENCODING_OFFSET] = sa << SO_SA_BIT | sb << SO_SB_BIT | x << SO_X_BIT | SO_END_EMPTY;
1677 /*lint +e416 (Warning -- Likely creation of out-of-bounds pointer) */
1678 /*lint +e415 (Warning -- Likely access of out-of-bounds pointer) */
1679
1680 dup->LastSentFlow = flow;
1681 dup->LastSentSa = sa;
1682 dup->LastSentSb = sb;
1683
1684 PSENDX (RLP, data_req);
1685 }
1686
1687 /*
1688 +------------------------------------------------------------------------------
1689 | Function : up_merge_flow
1690 +------------------------------------------------------------------------------
1691 | Description :
1692 |
1693 | Parameters : -
1694 |
1695 |
1696 | Return : -
1697 +------------------------------------------------------------------------------
1698 */
1699
1700
1701 GLOBAL void up_merge_flow(void)
1702 {
1703 T_UP *dup = &l2r_data->up;
1704
1705 #ifdef _SIMULATION_
1706 TRACE_FUNCTION ("up_merge_flow()");
1707 #endif
1708
1709 if (dup->FlowCtrlUsed AND (dup->DnFlow EQ FL_ACTIVE OR dup->ULFlow EQ FL_ACTIVE))
1710 {
1711 /* flow control active */
1712 dup->MrgFlow = FL_ACTIVE;
1713 }
1714 else
1715 {
1716 /* flow control inactive */
1717 dup->MrgFlow = FL_INACTIVE;
1718 }
1719
1720 }
1721
1722 /*
1723 +------------------------------------------------------------------------------
1724 | Function : up_rq_init
1725 +------------------------------------------------------------------------------
1726 | Description :
1727 |
1728 | Parameters : -
1729 |
1730 |
1731 | Return : -
1732 +------------------------------------------------------------------------------
1733 */
1734
1735 GLOBAL void up_rq_init(void)
1736 {
1737 #ifdef _SIMULATION_
1738 TRACE_FUNCTION ("up_rq_init()");
1739 #endif
1740
1741 l2r_data->up.QRemapWrite = 0;
1742 l2r_data->up.QRemapRead = 0;
1743 }
1744
1745 /*
1746 +------------------------------------------------------------------------------
1747 | Function : up_some_data_to_send
1748 +------------------------------------------------------------------------------
1749 | Description :
1750 |
1751 | Parameters : -
1752 |
1753 |
1754 | Return : TRUE -
1755 | FALSE -
1756 +------------------------------------------------------------------------------
1757 */
1758
1759 GLOBAL BOOL up_some_data_to_send(void)
1760 {
1761 T_UP *dup = &l2r_data->up;
1762
1763 #ifdef _SIMULATION_
1764 TRACE_EVENT ("check if any data to send");
1765 #endif
1766
1767 if (
1768 dup->RiBu.idx.filled OR
1769 (dup->RiBu.primDesc[dup->RiBu.idx.ri]->index > 0) OR
1770 (dup->RiBu.primDesc[dup->RiBu.idx.ri]->offset > 0) OR
1771 (dup->LastRcvdSa NEQ dup->LastSentSa) OR
1772 (dup->LastRcvdSb NEQ dup->LastSentSb)
1773 )
1774 {
1775 return (TRUE);
1776 }
1777 return (FALSE);
1778 }