comparison src/gpf/frame/route.c @ 5:1ea54a97e831

src/gpf: import of Magnetite src/gpf3
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 15 Jul 2018 08:11:07 +0000
parents
children
comparison
equal deleted inserted replaced
4:6e457872f745 5:1ea54a97e831
1 /*
2 +------------------------------------------------------------------------------
3 | File: route.c
4 +------------------------------------------------------------------------------
5 | Copyright 2004 Texas Instruments Deutschland, AG
6 | All rights reserved.
7 |
8 | This file is confidential and a trade secret of Texas
9 | Instruments Berlin, AG
10 | The receipt of or possession of this file does not convey
11 | any rights to reproduce or disclose its contents or to
12 | manufacture, use, or sell anything it may describe, in
13 | whole, or in part, without the specific written consent of
14 | Texas Instruments Deutschland, AG.
15 +-----------------------------------------------------------------------------
16 | Purpose : This Modul performs the filtering and routing of
17 | primitives for testing capabilities of the protocol stack.
18 +-----------------------------------------------------------------------------
19 */
20
21 #ifndef __ROUTE_C__
22 #define __ROUTE_C__
23 #endif
24
25 /*==== INCLUDES ===================================================*/
26
27 #include <stdio.h>
28 #include <string.h>
29
30 #include "typedefs.h"
31 #include "os.h"
32 #include "vsi.h"
33 #include "frame.h"
34 #include "tools.h"
35 #include "frm_defs.h"
36 #include "frm_types.h"
37 #include "frm_glob.h"
38 #include "p_mem.h"
39 #include "route.h"
40 #include "frm_ext.h"
41
42 /*==== CONSTANTS ==================================================*/
43
44 /*==== TYPES ======================================================*/
45
46 /*==== CONSTANTS ====================================================*/
47
48 /*==== EXTERNALS =====================================================*/
49
50 /* -------------- S H A R E D - BEGIN ---------------- */
51 #ifdef _TOOLS_
52 #pragma data_seg("FRAME_SHARED")
53 #endif
54
55 extern OS_HANDLE ext_data_pool_handle;
56 extern T_HANDLE TestGroupHandle;
57 extern T_FRM_ROUTING_TABLE_ENTRY *Routing[];
58 extern char TaskName[];
59 #ifndef _TOOLS_
60 extern T_lemu_SendToQueue lemu_SendToQueue_func;
61 #endif
62 /*==== VARIABLES ==================================================*/
63
64 #ifndef RUN_INT_RAM
65 T_HANDLE rt_tst_handle = VSI_ERROR;
66 #else
67 extern int rt_tst_handle;
68 #endif
69
70 #ifdef _TOOLS_
71 #pragma data_seg()
72 #endif
73 /* -------------- S H A R E D - END ---------------- */
74
75 #ifndef _TOOLS_
76 extern const T_MEM_PROPERTIES *mem;
77 #endif
78
79 /*==== FUNCTIONS ==================================================*/
80
81 #ifndef RUN_INT_RAM
82 /*
83 +--------------------------------------------------------------------+
84 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
85 | STATE : code ROUTINE : rt_Init |
86 +--------------------------------------------------------------------+
87
88 PURPOSE : initialize the routing table.
89 */
90
91 GLOBAL SHORT rt_Init (void)
92 {
93 USHORT i;
94 /*
95 * Initialize the routingTable
96 */
97 for ( i = 0; i <= MaxEntities; i++ )
98 Routing[i] = NULL;
99
100 return OS_OK;
101 }
102 #endif
103
104
105 #ifndef RUN_INT_RAM
106 /*
107 +--------------------------------------------------------------------+
108 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
109 | STATE : code ROUTINE : rt_CvrtOpcMask |
110 +--------------------------------------------------------------------+
111
112 PURPOSE : convert "1010101" mask to opcMask and opcStatus
113 */
114
115 LOCAL SHORT rt_CvrtToOpcMask ( char *OpcString, ULONG *opcMask, ULONG *opcStatus )
116 {
117 unsigned int len;
118 unsigned int i;
119 char *p;
120
121 len = strlen ( OpcString );
122 p = OpcString + len;
123
124 for ( i = 0; i < len; i++ )
125 {
126 switch (*--p)
127 {
128 case '1':
129 *opcMask |= (1<<i);
130 *opcStatus |= (1<<i);
131 break;
132 case '0':
133 *opcMask |= (1<<i);
134 *opcStatus &= ~((unsigned int)1<<i);
135 break;
136 case '*': /* wildcard matches */
137 *opcMask &= ~((unsigned int)1<<i);
138 *opcStatus &= ~((unsigned int)1<<i);
139 break;
140 default:
141 break;
142 }
143 }
144 return OS_OK;
145 }
146 #endif
147
148 #ifndef RUN_INT_RAM
149 /*
150 +--------------------------------------------------------------------+
151 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
152 | STATE : code ROUTINE : rt_CvrtOpcMask |
153 +--------------------------------------------------------------------+
154
155 PURPOSE : convert opcMask and opcStatus to "1010101"
156 */
157 LOCAL SHORT rt_CvrtFromOpcMask ( char *OpcString, ULONG opcMask, ULONG opcStatus )
158 {
159 signed char i;
160 char len;
161
162 if ( opcMask >> 16 )
163 len = 32;
164 else
165 len = 16;
166 for ( i = len-1; i >= 0; i-- )
167 {
168 if ( opcMask & (1<<i) )
169 {
170 if ( opcStatus & (1<<i) )
171 *OpcString = '1';
172 else
173 *OpcString = '0';
174 }
175 else
176 *OpcString = '*';
177 OpcString++;
178 }
179 *(OpcString++) = ' ';
180 *(OpcString++) = 0;
181
182 return OS_OK;
183 }
184 #endif
185
186 #ifndef RUN_INT_RAM
187 /*
188 +--------------------------------------------------------------------+
189 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
190 | STATE : code ROUTINE : rt_ReadRouting |
191 +--------------------------------------------------------------------+
192
193 PURPOSE : reads all routings of the routing table of the task.
194 */
195
196 GLOBAL SHORT rt_RouteRead ( T_HANDLE Handle, char *Buffer )
197 {
198 T_HANDLE TstComHandle;
199 static T_FRM_ROUTING_TABLE_ENTRY *pEntry;
200 char OrgReceiver[ RESOURCE_NAMELEN ];
201 char NewReceiver[ RESOURCE_NAMELEN ];
202 char OpcString [18];
203 char const *pCmd;
204 static UBYTE FirstRead = 1;
205
206 if ( FirstRead )
207 {
208 FirstRead = 0;
209 pEntry = Routing[Handle];
210 }
211 if ( pEntry )
212 {
213 if ( pEntry->OldDestComHandle == ROUTE_ALL )
214 strcpy ( OrgReceiver, RT_ALL_TOKEN );
215 else
216 strcpy ( OrgReceiver, pf_TaskTable[pEntry->OldDestComHandle].Name );
217 TstComHandle = vsi_c_open ( Handle, FRM_TST_NAME );
218 if ( pEntry->NewDestComHandle == TstComHandle )
219 strcpy ( NewReceiver, pEntry->ExtDest );
220 else
221 {
222 if ( pEntry->NewDestComHandle != 0 )
223 strcpy ( NewReceiver, pf_TaskTable[pEntry->NewDestComHandle].Name );
224 }
225 if ( pEntry->opcMask )
226 rt_CvrtFromOpcMask ( OpcString, pEntry->opcMask, pEntry->opcStatus );
227 else
228 OpcString[0] = 0;
229
230 switch (pEntry->Command & RT_COMMAND_MASK)
231 {
232 case RT_DUPLICATE: pCmd = SYSPRIM_DUPLICATE_TOKEN;
233 break;
234 case RT_REDIRECT: pCmd = SYSPRIM_REDIRECT_TOKEN;
235 break;
236 case RT_DESTROY: pCmd = SYSPRIM_REDIRECT_TOKEN;
237 strcpy ( NewReceiver, SYSPRIM_NULL_TOKEN );
238 break;
239 default: pCmd = NULL;
240 break;
241 }
242 sprintf ( Buffer, "%s %s %s %s%s", pf_TaskTable[Handle].Name, pCmd, OrgReceiver, OpcString, NewReceiver );
243 pEntry = pEntry->pNextEntry;
244 return RT_OK;
245 }
246 else
247 {
248 FirstRead = 1;
249 pEntry = Routing[Handle];
250 return RT_ERROR;
251 }
252 }
253 #endif
254
255 #ifndef RUN_INT_RAM
256 /*
257 +--------------------------------------------------------------------+
258 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
259 | STATE : code ROUTINE : rt_RoutingEntry |
260 +--------------------------------------------------------------------+
261
262 PURPOSE : adds a new routing to the routing table of the task.
263 routings with duplicates are stored in the beginning
264 of the table because if the primitive is redirected and
265 send it can not be duplicated.
266 */
267
268 LOCAL SHORT rt_RoutingEntry ( T_HANDLE SndTaskHandle, T_FRM_ROUTING_TABLE_ENTRY *pNewEntry, RT_ENTRY Status )
269 {
270 T_FRM_ROUTING_TABLE_ENTRY *pEntry, *pNextEntry, *pPrevEntry;
271
272 /*
273 * delete all entries with same OldDestComHandle if a destroy command is stored
274 */
275 if ( pNewEntry->Command & RT_DESTROY )
276 {
277 if ( ( pEntry = Routing[SndTaskHandle] ) != NULL )
278 {
279 do
280 {
281 if ( pEntry->OldDestComHandle == pNewEntry->OldDestComHandle )
282 {
283 if ( pEntry == Routing[SndTaskHandle] )
284 {
285 if ( pEntry->pNextEntry )
286 {
287 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = NULL;
288 }
289 Routing[SndTaskHandle] = pEntry->pNextEntry;
290 }
291 else
292 {
293 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pPrevEntry)->pNextEntry = pEntry->pNextEntry;
294 if ( pEntry->pNextEntry )
295 {
296 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = pEntry->pPrevEntry;
297 }
298 }
299 pNextEntry = pEntry->pNextEntry;
300 os_DeallocateMemory ( SndTaskHandle, (T_VOID_STRUCT*)pEntry );
301 }
302 else
303 pNextEntry = pEntry->pNextEntry;
304
305 pEntry = pNextEntry;
306 }
307 while ( pEntry );
308 }
309 }
310 else
311 {
312 /*
313 * delete destroy command for OldDestComHandle if a new command is stored
314 */
315 if ( ( pEntry = Routing[SndTaskHandle] ) != NULL )
316 {
317 do
318 {
319 if ( pEntry->OldDestComHandle == pNewEntry->OldDestComHandle )
320 {
321 if ( pEntry->Command == RT_DESTROY )
322 {
323 if ( pEntry == Routing[SndTaskHandle] )
324 {
325 if ( pEntry->pNextEntry )
326 {
327 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = NULL;
328 }
329 Routing[SndTaskHandle] = pEntry->pNextEntry;
330 }
331 else
332 {
333 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pPrevEntry)->pNextEntry = pEntry->pNextEntry;
334 if ( pEntry->pNextEntry )
335 {
336 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = pEntry->pPrevEntry;
337 }
338 }
339 pNextEntry = pEntry->pNextEntry;
340 os_DeallocateMemory ( SndTaskHandle, (T_VOID_STRUCT*)pEntry );
341 }
342 break;
343 }
344 else
345 pNextEntry = pEntry->pNextEntry;
346
347 pEntry = pNextEntry;
348 }
349 while ( pEntry );
350 }
351 }
352
353
354 if ( (pEntry = Routing[SndTaskHandle]) != NULL )
355 {
356 do
357 {
358 if ( pEntry->SndTaskHandle == SndTaskHandle
359 && pEntry->NewDestComHandle == pNewEntry->NewDestComHandle
360 && pEntry->OldDestComHandle == pNewEntry->OldDestComHandle
361 && pEntry->MsgType == pNewEntry->MsgType )
362 {
363 if ( !strcmp (pEntry->ExtDest, pNewEntry->ExtDest) )
364 {
365 if ( Status == RT_DELETE )
366 {
367 if ( pEntry == Routing[SndTaskHandle] )
368 {
369 Routing[SndTaskHandle] = pEntry->pNextEntry;
370 if ( pEntry->pNextEntry )
371 {
372 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = NULL;
373 }
374 }
375 else
376 {
377 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pPrevEntry)->pNextEntry = pEntry->pNextEntry;
378 if ( pEntry->pNextEntry )
379 {
380 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = pEntry->pPrevEntry;
381 }
382 }
383 pNextEntry = pEntry->pNextEntry;
384 os_DeallocateMemory ( SndTaskHandle, (T_VOID_STRUCT*)pEntry );
385 return RT_OK;
386 }
387 #ifndef _TOOLS_
388 else
389 {
390 pEntry->Command = pNewEntry->Command; /* modify command for old routing entry */
391 pEntry->opcMask = pNewEntry->opcMask; /* set new opcMask in old routing entry */
392 pEntry->opcStatus = pNewEntry->opcStatus; /* set new opcStatus in old routing entry */
393 return RT_OK;
394 }
395 #else
396 pEntry = pEntry->pNextEntry;
397 #endif
398 }
399 else
400 {
401 #ifdef _TOOLS_
402 if ( ( pEntry->opcMask == pNewEntry->opcMask )
403 && ( pEntry->opcStatus == pNewEntry->opcStatus ) )
404 {
405 strcpy ( pEntry->ExtDest, pNewEntry->ExtDest );
406 return RT_OK;
407 }
408 else
409 #endif
410 pEntry = pEntry->pNextEntry;
411 }
412 }
413 else
414 pEntry = pEntry->pNextEntry;
415 } while ( pEntry );
416 }
417
418 pPrevEntry = NULL;
419 if ( ( pEntry = Routing[SndTaskHandle] ) != NULL )
420 {
421 do
422 {
423 pPrevEntry = pEntry;
424 if ( pNewEntry->Command & RT_DUPLICATE )/* put Duplications at the end of Duplications */
425 {
426 if ( pEntry->Command & RT_DUPLICATE )
427 pEntry = pEntry->pNextEntry;
428 else
429 {
430 if ( pPrevEntry == Routing[SndTaskHandle] )
431 pPrevEntry = NULL;
432 else
433 pPrevEntry = pEntry->pPrevEntry;
434 break;
435 }
436 }
437 else
438 pEntry = pEntry->pNextEntry;
439 }
440 while ( pEntry );
441 }
442 if ( os_AllocateMemory ( SndTaskHandle, (T_VOID_STRUCT**)&pNextEntry, sizeof(T_FRM_ROUTING_TABLE_ENTRY), OS_NO_SUSPEND, ext_data_pool_handle ) == OS_TIMEOUT )
443 return RT_NO_MEM;
444 pNextEntry->SndTaskHandle = SndTaskHandle;
445 pNextEntry->OldDestComHandle = pNewEntry->OldDestComHandle;
446 pNextEntry->NewDestComHandle = pNewEntry->NewDestComHandle;
447 pNextEntry->OldDestTaskHandle = pNewEntry->OldDestTaskHandle;
448 pNextEntry->Command = pNewEntry->Command;
449 pNextEntry->MsgType = pNewEntry->MsgType;
450 pNextEntry->opcMask = pNewEntry->opcMask;
451 pNextEntry->opcStatus = pNewEntry->opcStatus;
452 strcpy ( pNextEntry->ExtDest, pNewEntry->ExtDest );
453
454 if ( pEntry )
455 {
456 pEntry->pPrevEntry = pNextEntry; /* store at the beginning/in the list */
457 }
458 else
459 pNextEntry->pNextEntry = NULL; /* append to the list */
460
461 if ( pPrevEntry )
462 {
463 pPrevEntry->pNextEntry = pNextEntry; /* store in the list */
464 pNextEntry->pPrevEntry = pPrevEntry;
465 pNextEntry->pNextEntry = pEntry;
466 }
467 else
468 {
469 Routing[SndTaskHandle] = pNextEntry; /* store at the beginning */
470 pNextEntry->pNextEntry = pEntry;
471 }
472 return RT_OK;
473 }
474 #endif
475
476 #if 0
477 /* not needed -> temporarily removed */
478 #ifndef RUN_INT_RAM
479 /*
480 +--------------------------------------------------------------------+
481 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
482 | STATE : code ROUTINE : rt_ModifyRouting |
483 +--------------------------------------------------------------------+
484
485 PURPOSE : handle the contents of the redirection or duplicate
486 system primitive
487
488 */
489 GLOBAL SHORT rt_isolate_entity ( T_HANDLE caller, char *entity )
490 {
491 T_FRM_ROUTING_TABLE_ENTRY entry;
492 T_HANDLE snd;
493 T_HANDLE rcv;
494 int read_entry = FIRST_ENTRY;
495
496 if ( (rcv = vsi_e_handle ( caller, entity )) == VSI_ERROR )
497 return RT_ERROR;
498 else
499 {
500 while ( vsi_c_get_entity_com_entry ( read_entry, rcv, &snd ) == VSI_OK )
501 {
502 read_entry = NEXT_ENTRY;
503 entry.SndTaskHandle = snd;
504 entry.OldDestComHandle = rcv;
505 entry.NewDestComHandle = 0;
506 entry.opcMask = 0;
507 entry.MsgType = RT_PRIMITIVE_TYPE;
508 entry.Command = RT_DESTROY;
509 rt_RoutingEntry ( snd, &entry, RT_STORE );
510 }
511
512 entry.SndTaskHandle = rcv;
513 entry.OldDestComHandle = ROUTE_ALL;
514 entry.NewDestComHandle = 0;
515 entry.opcMask = 0;
516 entry.MsgType = RT_PRIMITIVE_TYPE;
517 entry.Command = RT_DESTROY;
518 rt_RoutingEntry ( rcv, &entry, RT_STORE );
519
520 return RT_OK;
521 }
522 }
523 #endif
524 #endif
525
526 #ifndef RUN_INT_RAM
527 /*
528 +--------------------------------------------------------------------+
529 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
530 | STATE : code ROUTINE : rt_ModifyRouting |
531 +--------------------------------------------------------------------+
532
533 PURPOSE : handle the contents of the redirection or duplicate
534 system primitive
535
536 */
537 GLOBAL SHORT rt_RoutingModify ( T_HANDLE SndTaskHandle, char *Command, char *RoutingString)
538 {
539 char Token[81];
540 char *pChar = RoutingString;
541 T_FRM_ROUTING_TABLE_ENTRY Entry = { 0 };
542 unsigned int len;
543 T_FRM_ROUTING_TABLE_ENTRY *pEntry, *pNextEntry;
544
545 if ( !strcmp (Command, SYSPRIM_DUPLICATE_TOKEN) )
546 Entry.Command = RT_DUPLICATE;
547
548 if ( !strcmp (Command, SYSPRIM_REDIRECT_TOKEN) )
549 Entry.Command = RT_REDIRECT;
550
551 if ( (len = GetNextToken (pChar, Token, " #")) == 0 )
552 return RT_ERROR;
553 else
554 pChar += (len+1);
555
556 if ( !strcmp (Token, RT_CLEAR_TOKEN) )
557 Entry.Command |= RT_CLEAR_ENTRY;
558
559 if ( !strcmp (Token, RT_ALL_TOKEN) )
560 Entry.Command |= RT_ALL_DESTINATION;
561
562 if ( Entry.Command & RT_CLEAR_ENTRY )
563 {
564 if ( (pEntry = Routing[SndTaskHandle]) != NULL )
565 {
566 do
567 {
568 pNextEntry = (T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry;
569 os_DeallocateMemory ( SndTaskHandle, (T_VOID_STRUCT*)pEntry );
570 pEntry = pNextEntry;
571 }
572 while ( pEntry );
573 Routing[SndTaskHandle] = NULL;
574 }
575 return RT_OK;
576 }
577
578 if ( Entry.Command & RT_ALL_DESTINATION )
579 {
580 Entry.OldDestComHandle = ROUTE_ALL;
581 Entry.OldDestTaskHandle = ROUTE_ALL;
582 }
583 else
584 {
585 if ( ( Entry.OldDestComHandle = vsi_c_open (SndTaskHandle, Token ) ) == VSI_ERROR )
586 return RT_ERROR;
587 Entry.OldDestTaskHandle = Entry.OldDestComHandle;
588 }
589
590 if ( (len = GetNextToken (pChar, Token, " #")) == 0 )
591 return RT_ERROR;
592 else
593 pChar += (len+1);
594
595 if ( !strcmp (Token, RT_TIMEOUT_TOKEN) )
596 {
597 Entry.MsgType = RT_TIMEOUT_TYPE;
598 if ( (len = GetNextToken (pChar, Token, " #")) == 0 )
599 return RT_ERROR;
600 else
601 pChar += (len+1);
602
603 }
604 else
605 {
606 if ( !strcmp (Token, RT_SIGNAL_TOKEN) )
607 {
608 Entry.MsgType = RT_SIGNAL_TYPE;
609 if ( (len = GetNextToken (pChar, Token, " #")) == 0 )
610 return RT_ERROR;
611 else
612 pChar += (len+1);
613 }
614 else
615 Entry.MsgType = RT_PRIMITIVE_TYPE;
616 }
617
618 if ( (Token[0] == '1') || (Token[0] == '0') || (Token[0] == '*') )
619 {
620 rt_CvrtToOpcMask(Token, &Entry.opcMask, &Entry.opcStatus);
621 if ( (len = GetNextToken (pChar, Token, " #")) == 0 )
622 return RT_ERROR;
623 else
624 pChar += (len+1);
625 }
626 /* else */
627 {
628 if (!strcmp (Token, SYSPRIM_NULL_TOKEN))
629 {
630 if ( Entry.Command & RT_REDIRECT )
631 {
632 Entry.Command |= RT_DESTROY; /* destroy the primitive */
633 Entry.Command &= ~RT_REDIRECT;
634 }
635 else
636 return RT_ERROR;
637 }
638 else
639 {
640 if ( ( Entry.NewDestComHandle = vsi_c_open (SndTaskHandle, Token ) ) == VSI_ERROR )
641 {
642 #ifdef _TOOLS_
643 if ( !strcmp ( FRM_PCO_NAME, Token ) )
644 return RT_ERROR;
645 #endif
646 if ( ( Entry.NewDestComHandle = vsi_c_open (SndTaskHandle, FRM_TST_NAME ) ) != VSI_ERROR )
647 {
648 rt_tst_handle = Entry.NewDestComHandle;
649 if ( len < RESOURCE_NAMELEN )
650 {
651 strncpy( Entry.ExtDest, Token, RESOURCE_NAMELEN );
652 Entry.ExtDest[RESOURCE_NAMELEN-1] = 0;
653 }
654 else
655 return RT_ERROR;
656 }
657 }
658 }
659
660 if ( Entry.Command & RT_ALL_DESTINATION )
661 {
662 if ( (pEntry = Routing[SndTaskHandle]) != NULL )
663 {
664 int all_cleared = 1;
665 do
666 {
667 pNextEntry = (T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry;
668 if ( (pEntry->NewDestComHandle == Entry.NewDestComHandle )
669 && !strcmp(pEntry->ExtDest, Entry.ExtDest) )
670 {
671 if ( pEntry == Routing[SndTaskHandle] )
672 {
673 Routing[SndTaskHandle] = pEntry->pNextEntry;
674 if ( pEntry->pNextEntry != NULL )
675 {
676 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = NULL;
677 }
678 }
679 else
680 {
681 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pPrevEntry)->pNextEntry = pEntry->pNextEntry;
682 if ( pEntry->pNextEntry != NULL )
683 {
684 ((T_FRM_ROUTING_TABLE_ENTRY*)pEntry->pNextEntry)->pPrevEntry = pEntry->pPrevEntry;
685 }
686 }
687 os_DeallocateMemory ( SndTaskHandle, (T_VOID_STRUCT*)pEntry );
688 }
689 else
690 {
691 all_cleared = 0;
692 }
693 pEntry = pNextEntry;
694 }
695 while ( pEntry );
696 if ( all_cleared == 1 )
697 Routing[SndTaskHandle] = NULL;
698 }
699 }
700
701 if ( (pChar >= RoutingString+ strlen (RoutingString))
702 || ((len = GetNextToken (pChar, Token, " #")) == 0) )
703 return ( rt_RoutingEntry(SndTaskHandle, &Entry, RT_STORE) );
704 else
705 pChar += (len+1);
706
707 if ( Entry.Command & RT_CLEAR_ENTRY )
708 return ( rt_RoutingEntry(SndTaskHandle, &Entry, RT_DELETE) );
709 return RT_ERROR;
710 }
711
712 }
713 #endif
714
715 #ifndef RUN_FLASH
716 /*
717 +--------------------------------------------------------------------+
718 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
719 | STATE : code ROUTINE : rt_routePrim |
720 +--------------------------------------------------------------------+
721
722 PURPOSE : Looks if the task have some routing rules stored and
723 perform the redirection or duplication.
724
725 */
726
727 GLOBAL SHORT rt_Route ( T_HANDLE SndTaskHandle, T_HANDLE RcvComHandle, USHORT Prio, ULONG Suspend, OS_QDATA *Msg )
728 {
729 T_FRM_ROUTING_TABLE_ENTRY *pEntry;
730
731 T_PRIM_HEADER *prim;
732 ULONG opc;
733
734 if ( ( pEntry = Routing[SndTaskHandle] ) != NULL )
735 {
736 if ( pEntry->MsgType == Msg->data16 )
737 {
738 prim = (T_PRIM_HEADER*)Msg->ptr;
739
740 #ifndef _TOOLS_
741 if (prim->opc & MEMHANDLE_OPC)
742 {
743 P_MEMHANDLE_SDU(prim)=0x00000000;
744 }
745 #endif
746
747 do
748 {
749 if ( SndTaskHandle == pEntry->SndTaskHandle
750 && ( (RcvComHandle == pEntry->OldDestComHandle) || (pEntry->OldDestComHandle == ROUTE_ALL) ) )
751 {
752 /*
753 * a route for the receiver is defined. Now
754 * check the filter conditions
755 */
756 opc = ((T_PRIM_HEADER*)Msg->ptr)->opc;
757 if ( (opc & pEntry->opcMask) == (pEntry->opcStatus & pEntry->opcMask) )
758 {
759 /*
760 * filter matched -> redirect, duplicate or destroy
761 * the primitive.
762 */
763 switch (pEntry->Command & RT_COMMAND_MASK)
764 {
765 case RT_DESTROY:
766 /* add VSI_PPM_FREE(Msg->ptr) just to avoid the PPM warning of freeing a primitive in a queue */
767 VSI_PPM_RCV(Msg->ptr);
768 VSI_PPM_FREE(Msg->ptr);
769 os_DeallocatePartition (SndTaskHandle, Msg->ptr-PPM_OFFSET );
770 return RT_OK;
771
772 case RT_REDIRECT:
773 #ifndef _TOOLS_
774 if (pEntry->NewDestComHandle != rt_tst_handle)
775 {
776 /* if not on tool side and not sending via TST -> send directly */
777 Msg->e_id = pEntry->NewDestComHandle;
778 return ( (SHORT)os_SendToQueue ( SndTaskHandle, pf_TaskTable[pEntry->NewDestComHandle].QueueHandle, OS_NORMAL, OS_SUSPEND, Msg ) );
779 }
780 #endif
781 /*lint -fallthrough */
782 case RT_DUPLICATE:
783 if (pEntry->NewDestComHandle != OS_ERROR)
784 {
785 OS_QDATA QData;
786 #ifdef _TOOLS_
787 QData.len = (USHORT)(PSIZE(P2D(Msg->ptr))-sizeof(T_PRIM_HEADER));
788 #else
789 /* QData.len = 4; not needed if per reference */
790 T_DP_HEADER *dp_hdr;
791 #if 0
792 P_ATTACH(P2D(prim)); /* recursivly increase use counters */
793 #else
794 prim->use_cnt++;
795 if ( prim->dph_offset != 0 )
796 {
797 dp_hdr = (T_DP_HEADER*)((ULONG*)prim + prim->dph_offset);
798 /* only increment use_cnt for dynamic primitives - not for DTI primitives */
799 if ( dp_hdr->magic_nr == GUARD_PATTERN )
800 {
801 do
802 {
803 dp_hdr->use_cnt++;
804 } while ( (dp_hdr = (T_DP_HEADER*)dp_hdr->next) != NULL );
805 }
806 }
807 #endif /* 0 */
808
809 #endif
810 QData.data16 = MSG_PRIMITIVE;
811 QData.ptr = Msg->ptr;
812
813 #ifndef _TOOLS_
814 if (pEntry->NewDestComHandle != rt_tst_handle)
815 {
816 Msg->e_id = pEntry->NewDestComHandle;
817 os_SendToQueue ( SndTaskHandle, pf_TaskTable[pEntry->NewDestComHandle].QueueHandle, OS_NORMAL, OS_SUSPEND, Msg );
818 }
819 else
820 #endif
821 {
822 /* if on tool side or sending via TST -> send with sys header a.s.o */
823 rt_ExtPrimitive ( SndTaskHandle, pEntry->NewDestComHandle, RcvComHandle, pEntry->ExtDest, &QData );
824 }
825 }
826 if ( pEntry->Command & RT_REDIRECT )
827 {
828 T_VOID_STRUCT *free_ptr = (T_VOID_STRUCT*)P2D(prim);
829
830 #ifndef _TOOLS_
831 if ((prim->opc & MEMHANDLE_OPC) && (mem!=NULL))
832 {
833 if (P_MEMHANDLE(prim)!=0)
834 {
835 mem->dealloc(P_MEMHANDLE(prim));
836 }
837 }
838 #endif /* !_TOOLS_ */
839
840 vsi_free ((T_VOID_STRUCT**)&free_ptr FILE_LINE_MACRO);
841 return RT_OK;
842 }
843 break;
844 default:
845 break;
846 }
847 }
848 }
849 pEntry = pEntry->pNextEntry;
850 } while ( pEntry );
851 }
852 }
853
854 /*
855 * send original
856 */
857
858 #ifdef _TOOLS_
859 return ( (SHORT)os_SendToQueue ( SndTaskHandle, RcvComHandle, Prio, Suspend, Msg ) );
860 #else
861 if((pf_TaskTable[RcvComHandle].Flags & USE_LEMU_QUEUE) AND
862 (lemu_SendToQueue_func.magic_nr == LEMU_SENDTOQUEUE_INITIALIZED))
863 {
864 if(lemu_SendToQueue_func.plemu_SendToQueue( SndTaskHandle, RcvComHandle,
865 pf_TaskTable[RcvComHandle].QueueHandle, Prio, Suspend, Msg )
866 != lemu_SendToQueue_func.ret_ok )
867 {
868 return OS_ERROR;
869 }
870 return OS_OK;
871 }
872 else
873 {
874 return ( (SHORT)os_SendToQueue ( SndTaskHandle, pf_TaskTable[RcvComHandle].QueueHandle, Prio, Suspend, Msg ) );
875 }
876 #endif
877 }
878 #endif
879
880 #ifndef RUN_INT_RAM
881 /*
882 +--------------------------------------------------------------------+
883 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
884 | STATE : code ROUTINE : rt_ExtPrimitive |
885 +--------------------------------------------------------------------+
886
887 PURPOSE : formats duplicated primitive to be sent to TST
888
889 */
890 void rt_ExtPrimitive ( T_HANDLE TaskHandle, T_HANDLE DestComHandle, T_HANDLE OrgDestTaskHandle, char *ExtDest, OS_QDATA *Msg )
891 {
892 T_PRIM_HEADER *prim;
893 #ifndef _TOOLS_
894 T_PRIM_HEADER *sdu_prim;
895 #endif /* not _TOOLS_ */
896 T_PRIM_HEADER *ptr;
897 T_S_HEADER *s_hdr;
898 OS_QDATA DMsg;
899 ULONG AllocSize;
900 LONG Status;
901 ULONG suspend;
902 #ifdef _TOOLS_
903 T_S_HEADER *prim_s_hdr;
904 unsigned int i;
905 #endif
906
907 prim = (T_PRIM_HEADER*)Msg->ptr;
908 #ifdef _TOOLS_
909 AllocSize = S_ALLOC_SIZE(Msg->len + 1); /* +1 To add LF in TIF */
910 #else
911 if ( prim->dph_offset != 0 )
912 {
913 T_DP_HEADER *dp_hdr;
914
915 dp_hdr = (T_DP_HEADER*)((ULONG*)prim + prim->dph_offset);
916 if ( dp_hdr->magic_nr != GUARD_PATTERN
917 #ifdef _TARGET_
918 && route_desclist[TaskHandle] == TRUE
919 #endif
920 )
921 {
922 rt_desclist_to_sdu ( TaskHandle, DestComHandle, prim, &sdu_prim );
923 prim = sdu_prim;
924 }
925 }
926
927 AllocSize = S_ALLOC_SIZE(4 + 1); /* only ptr to primitive */
928 #endif /* _TOOLS_ */
929 suspend = get_suspend_state(TaskHandle,CHECK_PRIM_SUSPEND);
930 Status = os_AllocatePartition ( TaskHandle, (T_VOID_STRUCT**)&ptr, AllocSize, suspend, TestGroupHandle );
931 if ( Status == OS_OK || Status == OS_WAITED || Status == OS_ALLOCATED_BIGGER )
932 {
933 DMsg.data16 = MSG_PRIMITIVE;
934 DMsg.data32 = Msg->data32;
935 #ifdef _TOOLS_
936 DMsg.len = AllocSize;
937 #endif
938 DMsg.ptr = (T_VOID_STRUCT*)ptr;
939
940 ptr->opc = prim->opc;
941 ptr->len = AllocSize;
942 ptr->sh_offset = S_HDR_OFFSET(AllocSize - sizeof(T_S_HEADER));
943 s_hdr = (T_S_HEADER*)((ULONG*)ptr + ptr->sh_offset);
944 #ifdef _TOOLS_
945 if ( prim->sh_offset == 0 )
946 {
947 /*
948 if the primitive is sent via the TAP REDIRECT TAP ... mechanism, then the prim->sh_offset
949 is zero and the org_rcv is filled corresponding to the original addressed entity name.
950 */
951 vsi_e_name ( TaskHandle, OrgDestTaskHandle, TaskName );
952 strcpy (s_hdr->org_rcv, TaskName);
953 strcpy (s_hdr->rcv, ExtDest);
954 }
955 else
956 {
957 /*
958 if the primitive is sent via the TAP TPORT mechanism then the original receiver is already
959 filled by the TAP and copied to the newly allocated primitive to be routed.
960 */
961 prim_s_hdr = (T_S_HEADER*)((ULONG*)prim + prim->sh_offset);
962
963 for (i = 0; prim_s_hdr->org_rcv[i] != 0 && i < sizeof (s_hdr->org_rcv)-1; i++)
964 s_hdr->org_rcv[i] = prim_s_hdr->org_rcv[i];
965 for (i = 0; prim_s_hdr->rcv[i] != 0 && i < sizeof (s_hdr->rcv)-1; i++)
966 s_hdr->rcv[i] = prim_s_hdr->rcv[i];
967 }
968 get_local_time (&s_hdr->time);
969 os_GetTaskName ( TaskHandle, TaskHandle, TaskName );
970 strcpy (s_hdr->snd, TaskName);
971 #else
972 vsi_e_name ( TaskHandle, OrgDestTaskHandle, TaskName );
973 strcpy (s_hdr->org_rcv, TaskName);
974 strcpy (s_hdr->rcv, ExtDest);
975 os_GetTime(TaskHandle,&s_hdr->time);
976 s_hdr->snd[0] = (char)(TaskHandle | HANDLE_BIT);
977 #endif
978 #ifdef _TOOLS_
979 memcpy ( (char*)P2D(ptr), P2D(Msg->ptr), Msg->len );
980 #else
981 ((T_PRIM_X*)(ptr))->prim_ptr = prim;
982 #endif
983 DMsg.e_id = DestComHandle;
984 #ifdef _TOOLS_
985 os_SendToQueue ( TaskHandle, DestComHandle, OS_NORMAL, OS_SUSPEND, &DMsg );
986 #else
987 if ((prim->opc & MEMHANDLE_OPC) && (mem!=NULL))
988 {
989 if (P_MEMHANDLE_SDU(prim)==0x00000000)
990 {
991 /* copy MEM-handle content into new sdu */
992 U8 *user_data;
993 U16 ptr_length;
994 user_data=mem->get_user_data(P_MEMHANDLE(prim), &ptr_length);
995
996 if (user_data)
997 {
998 T_sdu *sdu=(T_sdu *)M_ALLOC(ptr_length+2*sizeof(U16));
999
1000 sdu->l_buf=ptr_length*8;
1001 sdu->o_buf=0;
1002 memcpy(sdu->buf,user_data,ptr_length);
1003
1004 P_MEMHANDLE_SDU(prim)=(U32)sdu;
1005 }
1006 }
1007 else
1008 {
1009 M_ATTACH((void*)P_MEMHANDLE_SDU(prim));
1010 }
1011 }
1012
1013 if ( PrimAborted[TaskHandle] > 0 )
1014 {
1015 if ( vsi_o_ttrace ( 0, TC_SYSTEM, "%d %s primitive routings aborted",PrimAborted[TaskHandle], pf_TaskTable[TaskHandle].Name ) == VSI_OK )
1016 PrimAborted[TaskHandle] = 0;
1017 }
1018 if ( os_SendToQueue ( TaskHandle, pf_TaskTable[DestComHandle].QueueHandle, OS_NORMAL, suspend, &DMsg ) == OS_TIMEOUT )
1019 {
1020 T_VOID_STRUCT *free_ptr = (T_VOID_STRUCT*)P2D(prim);
1021 vsi_free ((T_VOID_STRUCT**)&free_ptr FILE_LINE_MACRO);
1022 vsi_trc_free (0, (T_VOID_STRUCT**)&ptr);
1023 PrimAborted[TaskHandle]++;
1024 }
1025 #endif
1026 }
1027 else
1028 {
1029 T_VOID_STRUCT *free_ptr = (T_VOID_STRUCT*)P2D(prim);
1030 vsi_free ((T_VOID_STRUCT**)&free_ptr FILE_LINE_MACRO);
1031 PrimAborted[TaskHandle]++;
1032 }
1033 }
1034 #endif
1035
1036 #ifndef RUN_INT_RAM
1037 /*
1038 +--------------------------------------------------------------------+
1039 | PROJECT : GSM-PS (6147) MODULE : PF_ROUTE |
1040 | STATE : code ROUTINE : rt_desclist_to_sdu |
1041 +--------------------------------------------------------------------+
1042
1043 PURPOSE : formats duplicated primitive with descriptor list into a
1044 primitive with SDU
1045
1046 */
1047 int rt_desclist_to_sdu ( T_HANDLE caller, T_HANDLE dst, T_PRIM_HEADER *prim, T_PRIM_HEADER **sdu_prim )
1048 {
1049 T_PRIM_HEADER *ptr;
1050 T_DP_HEADER *dp_hdr;
1051 T_M_HEADER *m_hdr;
1052 T_desc3 *desc3;
1053 T_desc2 *desc2;
1054 T_desc *desc;
1055 int len = 0;
1056 int sdu_prim_size = 0;
1057 char *fill_ptr;
1058 USHORT *l_buf_ptr;
1059 USHORT *o_buf_ptr;
1060 char *sdu_data_ptr;
1061 T_sdu *sdu = NULL;
1062 unsigned int new_opc;
1063 int desc_type = 0;
1064
1065 dp_hdr = (T_DP_HEADER*)((ULONG*)prim + prim->dph_offset);
1066 /* primitive contains descriptor list */
1067
1068 /*
1069 START OF NON GENERIC CODE
1070 This code is for the phase 1 routing of primitives containing descriptor lists.
1071 It is non-generic and depends on the primitive ids defined in SAP docs.
1072 It should be removed as soon as the generic descriptor list routing is ready
1073 */
1074 switch ( prim->opc )
1075 {
1076 case 0x7754: /* DTI2_DATA_IND */
1077 new_opc = 0x7755; /* DTI2_DATA_TEST_IND */
1078 desc_type = VSI_DESC_TYPE2 >> 16;
1079 break;
1080 case 0x3754: /* DTI2_DATA_REQ */
1081 new_opc = 0x3755; /* DTI2_DATA_TEST_REQ */
1082 desc_type = VSI_DESC_TYPE2 >> 16;
1083 break;
1084 case 0x6800: /* SN_DATA_IND */
1085 new_opc = 0x6806; /* SN_DATA_TEST_IND */
1086 desc_type = VSI_DESC_TYPE2 >> 16;
1087 break;
1088 case 0x2800: /* SN_DATA_REQ */
1089 new_opc = 0x2806; /* SN_DATA_TEST_REQ */
1090 desc_type = VSI_DESC_TYPE2 >> 16;
1091 break;
1092 case 0x6801: /* SN_UNITDATA_IND */
1093 new_opc = 0x6807; /* SN_DATA_TEST_IND */
1094 desc_type = VSI_DESC_TYPE2 >> 16;
1095 break;
1096 case 0x2801: /* SN_UNITDATA_REQ */
1097 new_opc = 0x2807; /* SN_DATA_TEST_REQ */
1098 desc_type = VSI_DESC_TYPE2 >> 16;
1099 break;
1100 case 0x7701: /* DTI_DATA_IND */
1101 new_opc = 0x7702; /* DTI_DATA_TEST_IND */
1102 desc_type = VSI_DESC_TYPE1 >> 16;
1103 break;
1104 case 0x3701: /* DTI_DATA_REQ */
1105 new_opc = 0x3702; /* DTI_DATA_TEST_REQ */
1106 desc_type = VSI_DESC_TYPE1 >> 16;
1107 break;
1108 case 0x80004097: /* GRLC_DATA_IND */
1109 new_opc = 0x80014097; /* GRLC_DATA_IND_TEST */
1110 desc_type = VSI_DESC_TYPE1 >> 16;
1111 break;
1112 case 0x80024097: /* GRLC_UNITDATA_IND */
1113 new_opc = 0x80034097; /* GRLC_UNITDATA_IND_TEST */
1114 desc_type = VSI_DESC_TYPE1 >> 16;
1115 break;
1116 default:
1117 new_opc = prim->opc;
1118 break;
1119 }
1120 /* END OF NON GENERIC CODE */
1121
1122 /*
1123 it has to be distinguished between T_desc, T_desc2 and T_desc3 because to length information
1124 is located at different places inside the structure
1125 */
1126 m_hdr = (T_M_HEADER*)(((T_desc_list*)dp_hdr)->first) - 1;
1127 if ( m_hdr->desc_type != 0 )
1128 {
1129 desc_type = m_hdr->desc_type;
1130 }
1131 if ( desc_type == (VSI_DESC_TYPE2 >> 16) )
1132 {
1133 desc2 = (T_desc2*)(((T_desc_list2*)dp_hdr)->first);
1134 while (desc2 != NULL)
1135 {
1136 len = len + desc2->len;
1137 desc2 = (T_desc2 *)desc2->next;
1138 }
1139 /* the size to be allocated for the primitive containing the sdu needs to be
1140 root prim length + data length + sdu size minus data buffer - desc list2 size */
1141 sdu_prim_size = prim->len + len + sizeof(sdu->l_buf) + sizeof(sdu->o_buf) - sizeof(T_desc_list2);
1142 }
1143 else if ( desc_type == (VSI_DESC_TYPE1 >> 16) )
1144 {
1145 desc = (T_desc*)(((T_desc_list*)dp_hdr)->first);
1146 while (desc != NULL)
1147 {
1148 len = len + desc->len;
1149 desc = (T_desc *)desc->next;
1150 }
1151 /* the size to be allocated for the primitive containing the sdu needs to be
1152 root prim length + data length + sdu size minus data buffer - desc list size */
1153 sdu_prim_size = prim->len + len + sizeof(sdu->l_buf) + sizeof(sdu->o_buf) - sizeof(T_desc_list);
1154 }
1155 else if ( desc_type == (VSI_DESC_TYPE3 >> 16) )
1156 {
1157 /* it is assumed that type 3 is valid if not 1 or 2 */
1158 desc3 = (T_desc3*)(((T_desc_list3*)dp_hdr)->first);
1159 while (desc3 != NULL)
1160 {
1161 len = len + desc3->len;
1162 desc3 = (T_desc3 *)desc3->next;
1163 }
1164 /* the size to be allocated for the primitive containing the sdu needs to be
1165 root prim length + data length + sdu size minus data buffer - desc list3 size */
1166 sdu_prim_size = prim->len + len + sizeof(sdu->l_buf) + sizeof(sdu->o_buf) - sizeof(T_desc_list3);
1167 }
1168 else
1169 {
1170 vsi_o_ttrace ( 0, TC_SYSTEM, "unknown desc type in 0x%x, routing aborted", prim->opc );
1171 vsi_c_free ( caller, (T_VOID_STRUCT**)&prim FILE_LINE_MACRO );
1172 return RT_ERROR;
1173 }
1174
1175 if ( sdu_prim_size < (int)MaxPrimPartSize )
1176 {
1177 ptr = (T_PRIM_HEADER*)vsi_c_new ( caller, sdu_prim_size, new_opc FILE_LINE_MACRO );
1178 }
1179 else
1180 {
1181 vsi_o_ttrace ( 0, TC_SYSTEM, "desclist in 0x%x too long, routing aborted", prim->opc );
1182 vsi_c_free ( caller, (T_VOID_STRUCT**)&prim FILE_LINE_MACRO );
1183 return RT_ERROR;
1184 }
1185 #ifdef MEMORY_SUPERVISION
1186 vsi_ppm_send ( caller, dst, (T_PRIM_HEADER*)ptr FILE_LINE_MACRO );
1187 #endif /* MEMORY_SUPERVISION */
1188
1189 fill_ptr = (char*)ptr;
1190 l_buf_ptr = &((T_sdu*)((int*)fill_ptr + prim->dph_offset))->l_buf;
1191 o_buf_ptr = &((T_sdu*)((int*)fill_ptr + prim->dph_offset))->o_buf;
1192 sdu_data_ptr = (char*)&((T_sdu*)((int*)fill_ptr + prim->dph_offset))->buf;
1193
1194 memcpy ( (char*)P2D(fill_ptr), (char*)P2D(prim), prim->len-sizeof(T_PRIM_HEADER) );
1195
1196 *l_buf_ptr = 0;
1197 *o_buf_ptr = 0;
1198
1199 fill_ptr = sdu_data_ptr;
1200
1201 if ( desc_type == (VSI_DESC_TYPE2 >> 16) )
1202 {
1203 desc2 = (T_desc2*)(((T_desc_list2*)dp_hdr)->first);
1204 while (desc2 != NULL)
1205 {
1206 *l_buf_ptr += (desc2->len*8);
1207 memcpy ( fill_ptr, (char*)(&desc2->buffer)+desc2->offset, desc2->len );
1208 fill_ptr += desc2->len;
1209 desc2 = (T_desc2 *)desc2->next;
1210 }
1211 }
1212 else if ( desc_type == (VSI_DESC_TYPE1 >> 16) )
1213 {
1214 desc = (T_desc*)(((T_desc_list*)dp_hdr)->first);
1215 while (desc != NULL)
1216 {
1217 *l_buf_ptr += (desc->len*8);
1218 memcpy ( fill_ptr, (char*)(&desc->buffer), desc->len );
1219 fill_ptr += desc->len;
1220 desc = (T_desc *)desc->next;
1221 }
1222 }
1223 else if ( desc_type == (VSI_DESC_TYPE3 >>16) )
1224 {
1225 desc3 = (T_desc3*)(((T_desc_list3*)dp_hdr)->first);
1226 while (desc3 != NULL)
1227 {
1228 *l_buf_ptr += (desc3->len*8);
1229 memcpy ( fill_ptr, (char*)(desc3->buffer)+desc3->offset, desc3->len );
1230 fill_ptr += desc3->len;
1231 desc3 = (T_desc3 *)desc3->next;
1232 }
1233 }
1234 vsi_c_free ( caller, (T_VOID_STRUCT**)&prim FILE_LINE_MACRO );
1235 *sdu_prim = ptr;
1236 return RT_OK;
1237 }
1238 #endif
1239
1240