Added Call flow debug print for all the layer
[o-du/l2.git] / src / 5gnrmac / mac_msg_router.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
5 #   Licensed under the Apache License, Version 2.0 (the "License");            #
6 #   you may not use this file except in compliance with the License.           #
7 #   You may obtain a copy of the License at                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
11 #   Unless required by applicable law or agreed to in writing, software        #
12 #   distributed under the License is distributed on an "AS IS" BASIS,          #
13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
14 #   See the License for the specific language governing permissions and        #
15 #   limitations under the License.                                             #
16 ################################################################################
17 *******************************************************************************/
18
19 /************************************************************************
20  
21      Name:     LTE-MAC layer
22   
23      Type:     C source file
24   
25      Desc:     C source code SSI Interface Implementation
26   
27      File:     mac_msg_router.c
28   
29 **********************************************************************/
30
31 /** @file mac_msg_router.c
32 @brief This file contains the implementation of callback functions 
33 registered with SSI during the LTE MAC Task initialization.
34 */
35 /* header include files -- defines (.h) */
36 #include "common_def.h"
37 #include "rgu.h"           /* RGU defines */
38 #include "tfu.h"           /* RGU defines */
39 #include "lrg.h"           /* layer management defines for LTE-MAC */
40 #include "rgr.h"           /* layer management defines for LTE-MAC */
41 #include "crg.h"           /* CRG interface includes */
42 #include "rg_sch_inf.h"    /* SCH interface includes */
43 #include "rg_prg.h"        /* PRG interface includes */
44 #include "rg_env.h"        /* customisable defines and macros for LTE-MAC */
45 #include "rg.h"            /* defines and macros for MAC */
46 #include "rgr.h"            /* defines and macros for SCH */
47
48
49 /* header/extern include files (.x) */
50 #include "rgu.x"           /* RGU types */
51 #include "tfu.x"           /* RGU types */
52 #include "lrg.x"           /* layer management typedefs for MAC */
53 #include "rgr.x"           /* layer management typedefs for MAC */
54 #include "crg.x"           /* CRG interface typedes */
55 #include "rg_sch_inf.x"    /* SCH interface typedefs */
56 #include "rg_prg.x"        /*PRG interface includes*/
57 #include "du_app_mac_inf.h"
58 #include "rg.x"            /* typedefs for MAC */
59 #include "rlc_mac_inf.h"
60 #include "lwr_mac_upr_inf.h"
61
62 /**
63  * @brief Task Activation callback function Entity SM. 
64  *
65  * @details
66  *
67  *     Function : rgHdlSMEvents
68  *     
69  *     Process Messages received from Entity SM
70  *     
71  *  @param[in]  Pst     *pst, Post structure of the primitive.     
72  *  @param[in]  Buffer *mBuf, Packed primitive parameters in the buffer.
73  *  @param[in]  Reason reason.
74  *  @return  void
75  **/
76 static inline void rgHdlSMEvents
77 (
78 Pst     *pst,                       /* post structure       */
79 Buffer  *mBuf                       /* message buffer       */
80 )
81 {
82    switch(pst->event)
83    {
84 #ifdef LCRGMILRG
85       case EVTLRGCFGREQ:
86          /* Process a config. request */
87          cmUnpkLrgCfgReq(RgMiLrgCfgReq, pst, mBuf);
88          break;
89       case EVTMACSCHGENCFGREQ:
90          /* Process a config. request */
91          cmUnpkLrgSchCfgReq(MacSchGenCfgReq, pst, mBuf);
92          break;
93       case EVTLRGCNTRLREQ:
94          /* Process a control request */
95          cmUnpkLrgCntrlReq(RgMiLrgCntrlReq, pst, mBuf);
96          break;
97       case EVTLRGSSTAREQ:
98          /* Process a status request  */
99          cmUnpkLrgStaReq(RgMiLrgStaReq, pst, mBuf);
100          break;
101       case EVTLRGSTSREQ:
102          /* Process a statistics request */
103          cmUnpkLrgStsReq(RgMiLrgStsReq, pst, mBuf);
104          break;
105 #endif /* LCRGMILRG */
106       case EVENT_MAC_CELL_CONFIG_REQ:
107          /* Process MAC cell config */
108          unpackDuMacCellCfg(MacProcCellCfgReq, pst, mBuf);
109          break;
110       case EVENT_MAC_CELL_START:
111          /* Process MAC cell start request */
112          unpackMacCellStart(MacProcCellStart, pst, mBuf);
113          break;
114       case EVENT_MAC_CELL_STOP:
115          /* Process MAC cell stop request */
116          unpackMacCellStop(MacProcCellStop, pst, mBuf);
117          break;
118       case EVENT_MAC_DL_CCCH_IND:
119          /* Process DL CCCH Ind */
120          unpackMacDlCcchInd(MacProcDlCcchInd, pst, mBuf);
121          break;
122       case EVENT_MAC_UE_CREATE_REQ:
123          /* Process Ue Create Request */
124          unpackMacUeCreateReq(MacProcUeCreateReq, pst, mBuf);
125          break;
126       case EVENT_MAC_UE_RECONFIG_REQ:
127          /* Process Ue Reconfig Request */
128          unpackMacUeReconfigReq(MacProcUeReconfigReq, pst, mBuf);
129          break;
130     case EVENT_MAC_UE_DELETE_REQ:
131     {
132        unpackMacUeDeleteReq(MacProcUeDeleteReq, pst, mBuf);
133        break;
134     }
135     case EVENT_MAC_CELL_DELETE_REQ:
136     {
137        unpackMacCellDeleteReq(MacProcCellDeleteReq, pst, mBuf);
138        break;
139     }
140     default:
141          RG_FREE_MSG(mBuf);
142          break;
143    }
144 }
145
146
147 /**
148  * @brief Task Activation callback function Entity NH. 
149  *
150  * @details
151  *
152  *     Function : rgHdlNHEvents
153  *     
154  *     Process Messages received from Entity NH
155  *     
156  *  @param[in]  Pst     *pst, Post structure of the primitive.     
157  *  @param[in]  Buffer *mBuf, Packed primitive parameters in the buffer.
158  *  @param[in]  Reason reason.
159  *  @return  void
160  **/
161 static inline void rgHdlNHEvents
162 (
163 Pst     *pst,                       /* post structure       */
164 Buffer  *mBuf                       /* message buffer       */
165 )
166 {
167    switch(pst->event)
168    {
169 #ifdef LCRGUICRG
170       case EVTCRGBNDREQ:
171          cmUnpkCrgBndReq(RgUiCrgBndReq, pst, mBuf);
172          break;
173       case EVTCRGUBNDREQ:
174          cmUnpkCrgUbndReq(RgUiCrgUbndReq, pst, mBuf);
175          break;
176       case EVTCRGCFGREQ:
177          cmUnpkCrgCfgReq(RgUiCrgCfgReq, pst, mBuf);
178          break;
179 #endif            
180       default:
181          RG_FREE_MSG(mBuf);
182          break;
183    }
184 }
185
186 /**
187  * @brief Task Activation callback function Entity KW. 
188  *
189  * @details
190  *
191  *     Function : rgHdlKWEvents
192  *     
193  *     Process Messages received from Entity KW
194  *     
195  *  @param[in]  Pst     *pst, Post structure of the primitive.     
196  *  @param[in]  Buffer *mBuf, Packed primitive parameters in the buffer.
197  *  @param[in]  Reason reason.
198  *  @return  void
199  **/
200 static inline void rgHdlKWEvents
201 (
202 Pst     *pst,                       /* post structure       */
203 Buffer  *mBuf                       /* message buffer       */
204 )
205 {
206    switch(pst->event)
207    {
208 #ifdef LCRGUIRGU
209       case EVTRGUBNDREQ:
210          cmUnpkRguBndReq(RgUiRguBndReq, pst, mBuf);
211          break;
212       case EVTRGUUBNDREQ:
213          cmUnpkRguUbndReq(RgUiRguUbndReq, pst, mBuf);
214          break;
215       case EVENT_DL_DATA_TO_MAC:
216          unpackRlcDlData(MacProcRlcDlData, pst, mBuf);
217          break;
218       case EVENT_BO_STATUS_TO_MAC:
219          unpackRlcBoStatus(MacProcRlcBoStatus, pst, mBuf);
220          break;
221 #ifdef LTE_L2_MEAS
222
223       case EVTRGUL2MULTHRPMEASREQ:
224          cmUnpkRguL2MUlThrpMeasReq(RgUiRguL2MUlThrpMeasReq, pst,mBuf);
225          break;
226
227 #endif
228 #endif            
229       default:
230          RG_FREE_MSG(mBuf);
231          break;
232    }
233 }
234
235 /**
236  * @brief Task Activation callback function Entity TF. 
237  *
238  * @details
239  *
240  *     Function : rgHdlTFEvents
241  *     
242  *     Process Messages received from Entity TF
243  *     
244  *  @param[in]  Pst     *pst, Post structure of the primitive.     
245  *  @param[in]  Buffer *mBuf, Packed primitive parameters in the buffer.
246  *  @param[in]  Reason reason.
247  *  @return  void
248  **/
249 static inline void rgHdlTFEvents
250 (
251 Pst     *pst,                       /* post structure       */
252 Buffer  *mBuf                       /* message buffer       */
253 )
254 {
255    switch(pst->event)
256    {
257       case EVENT_SLOT_IND_TO_MAC:
258          unpackSlotInd(fapiMacSlotInd, pst, mBuf);
259          break;
260       case EVENT_STOP_IND_TO_MAC:
261          unpackStopInd(fapiMacStopInd, pst, mBuf);
262          break;
263       case EVENT_RACH_IND_TO_MAC:
264          unpackRachInd(fapiMacRachInd, pst, mBuf);
265          break;
266       case EVENT_CRC_IND_TO_MAC:
267          unpackCrcInd(fapiMacCrcInd, pst, mBuf);
268          break;
269       case EVENT_RX_DATA_IND_TO_MAC:
270          unpackRxDataInd(fapiMacRxDataInd, pst, mBuf);
271          break;
272       case EVENT_UCI_IND_TO_MAC:
273          unpackUciInd(FapiMacUciInd, pst, mBuf);
274          break;
275       default:
276          RG_FREE_MSG(mBuf);
277          break;
278    }
279 }
280
281
282 /**
283  * @brief Task Activation callback function Entity RG SCH. 
284  *
285  * @details
286  *
287  *     Function : rgHdlRGEvents
288  *     
289  *     Process Messages received from Entity RG SCH
290  *     
291  *  @param[in]  Pst     *pst, Post structure of the primitive.     
292  *  @param[in]  Buffer *mBuf, Packed primitive parameters in the buffer.
293  *  @param[in]  Reason reason.
294  *  @return  void
295  **/
296 static inline void rgHdlRGEvents
297 (
298 Pst     *pst,                       /* post structure       */
299 Buffer  *mBuf                       /* message buffer       */
300 )
301 {
302    switch(pst->event)
303    {
304 #ifdef LCRG
305       case EVTINFCELLREGREQ:
306          cmUnpkSchMacCellRegReq(RgSchMacCellRegReq, pst, mBuf);
307          break;
308       case EVTINFSFALLOCREQ:
309          cmUnpkSchMacSfAllocReq(RgSchMacSfAllocReq, pst, mBuf);
310          break;
311       case EVTINFRLSHQREQ:
312          cmUnpkSchMacRlsHqReq(RgSchMacRlsHqReq, pst, mBuf);
313          break;
314       case EVTINFHQENTRESET:
315          cmUnpkSchMacRstHqEntReq(RgSchMacRstHqEntReq, pst, mBuf);
316          break;
317       case EVTINFRLSRNTIREQ:
318          cmUnpkSchMacRlsRntiReq(RgSchMacRlsRntiReq, pst, mBuf);
319          break;
320 #ifdef LTEMAC_SPS
321       case EVTINFSPSLCREG:
322          cmUnpkSchMacSpsLcRegReq(RgSchMacSpsLcRegReq, pst, mBuf);
323          break;
324       case EVTINFSPSLCDEREG:
325          cmUnpkSchMacSpsLcDeregReq(RgSchMacSpsLcDeregReq, pst, mBuf);
326          break;
327       case EVTINFSPSRESET:
328          cmUnpkSchMacUlSpsResetReq(RgSchMacUlSpsResetReq, pst, mBuf);
329          break;
330 #endif /* LTEMAC_SPS */
331 #ifdef LTE_L2_MEAS
332       case EVTINFL2MEASREQ:
333          cmUnpkSchMacL2MeasReq(RgSchMacL2MeasReq, pst, mBuf);
334          break;
335       case EVTINFL2MEASSENDREQ :
336          cmUnpkSchMacL2MeasSendReq(RgSchMacL2MeasSendReq, pst , mBuf);
337          break;
338       case EVTINFL2MEASSTOPREQ:
339          cmUnpkSchMacL2MeasStopReq(RgSchMacL2MeasStopReq, pst , mBuf);
340          break;
341 #endif/* LTE_L2_MEAS */
342       case EVTINFLCGREG:
343          cmUnpkSchMacLcgRegReq(RgSchMacLcgRegReq, pst, mBuf);
344          break;
345 #endif            
346 #if defined(LTE_ADV) && defined(LCPRG)
347       case EVTPRGUESCELLCFGREQ:
348       {
349          cmUnpkPrgPMacSMacUeSCellCfgReq(RgPrgPMacSMacUeSCellCfgReq, pst, mBuf);
350       }
351       break;
352       case EVTPRGUESCELLCFGCFM:
353       case EVTPRGUESCELLLCHMODCFM:
354       case EVTPRGUESCELLLCHDELCFMDEL:
355       case EVTPRGUESCELLLCHADDCFM:
356       {
357          cmUnpkPrgSMacPMacCfgCfm(RgPrgSMacPMacCfgCfm, pst, mBuf);
358       }
359       break;
360       case EVTPRGUESCELLDELREQ:
361       {
362          cmUnpkPrgPMacSMacUeSCellDelReq(RgPrgPMacSMacUeSCellDelReq, pst, mBuf);
363       }
364       break;
365       case EVTPRGUESCELLLCHMODREQ:
366       {
367          cmUnpkPrgPMacSMacUeSCellLchModReq(RgPrgPMacSMacUeSCellLchModReq, pst,
368                                            mBuf);
369       }
370       break;
371       case EVTPRGUESCELLLCHDELREQ:
372       {
373          cmUnpkPrgPMacSMacUeSCellLchDelReq(RgPrgPMacSMacUeSCellLchDelReq, pst,
374                                            mBuf);
375       }
376       break;
377       case EVTPRGUESCELLLCHADDREQ:
378       {
379          cmUnpkPrgPMacSMacUeSCellLchAddReq(RgPrgPMacSMacUeSCellLchAddReq, pst,
380                                            mBuf);
381       }
382       break;
383
384 #endif
385       default:
386       {
387          RG_FREE_MSG(mBuf);
388          break;
389       }
390
391    }
392 }
393
394 /**
395 * @brief Function prints src, dest, msg infor about all the msgs that received.
396 *
397 * @details
398 *
399 *     Function : callFlowRgActvTsk 
400 *
401 *     Function prints src, dest, msg infor about all the msgs that received
402 *
403 *  @param[in]  Pst     *pst, Post structure of the primitive.
404 *
405 *  @return  void
406 **/
407
408 void callFlowRgActvTsk(Pst *pst)
409 {
410    char sourceTask[50];
411    char destTask[50]="ENTMAC";
412    char message[100];
413
414    switch(pst->srcEnt)
415    {
416       case ENTDUAPP:
417          {
418             strcpy(sourceTask,"ENTDUAPP");
419             switch(pst->event)
420             {
421 #ifdef LCRGMILRG
422                case EVTLRGCFGREQ:
423                   strcpy(message,"EVTLRGCFGREQ");
424                   break;
425                case EVTMACSCHGENCFGREQ:
426                   strcpy(message,"EVTMACSCHGENCFGREQ");
427                   break;
428                case EVTLRGCNTRLREQ:
429                   strcpy(message,"EVTLRGCNTRLREQ");
430                   break;
431                case EVTLRGSSTAREQ:
432                   strcpy(message,"EVTLRGSSTAREQ");
433                   break;
434                case EVTLRGSTSREQ:
435                   strcpy(message,"EVTLRGSTSREQ");
436                   break;
437 #endif /* LCRGMILRG */
438                case EVENT_MAC_CELL_CONFIG_REQ:
439                   strcpy(message,"EVENT_MAC_CELL_CONFIG_REQ");
440                   break;
441                case EVENT_MAC_CELL_START:
442                   strcpy(message,"EVENT_MAC_CELL_START");
443                   break;
444                case EVENT_MAC_CELL_STOP:
445                   strcpy(message,"EVENT_MAC_CELL_STOP");
446                   break;
447                case EVENT_MAC_DL_CCCH_IND:
448                   strcpy(message,"EVENT_MAC_DL_CCCH_IND");
449                   break;
450                case EVENT_MAC_UE_CREATE_REQ:
451                   strcpy(message,"EVENT_MAC_UE_CREATE_REQ");
452                   break;
453                case EVENT_MAC_UE_RECONFIG_REQ:
454                   strcpy(message,"EVENT_MAC_UE_RECONFIG_REQ");
455                   break;
456                case EVENT_MAC_UE_DELETE_REQ:
457                   strcpy(message,"EVENT_MAC_UE_DELETE_REQ");
458                   break;
459                case EVENT_MAC_CELL_DELETE_REQ:
460                   strcpy(message,"EVENT_MAC_CELL_DELETE_REQ");
461                   break;
462                default:
463                   strcpy(message,"Invalid Event");
464                   break;
465             }
466             break;
467          }
468       case ENTRLC:
469          { 
470             strcpy(sourceTask,"ENTRLC");
471             switch(pst->event)
472             {
473 #ifdef LCRGUIRGU
474                case EVTRGUBNDREQ:
475                   strcpy(message,"EVTRGUBNDREQ");
476                   break;
477                case EVTRGUUBNDREQ:
478                   strcpy(message,"EVTRGUUBNDREQ");
479                   break;
480                case EVENT_DL_DATA_TO_MAC:
481                   strcpy(message,"EVENT_DL_DATA_TO_MAC");
482                   break;
483                case EVENT_BO_STATUS_TO_MAC:
484                   strcpy(message,"EVENT_BO_STATUS_TO_MAC");
485                   break;
486 #endif
487                default:
488                   strcpy(message,"Invalid Event");
489                   break;
490             }
491
492             break;
493          }
494       case ENTLWRMAC:
495          {
496             strcpy(sourceTask,"ENTLWRMAC");
497             switch(pst->event)
498             {
499                case EVENT_SLOT_IND_TO_MAC:
500                   strcpy(message,"EVENT_SLOT_IND_TO_MAC");
501                   break;
502                case EVENT_STOP_IND_TO_MAC:
503                   strcpy(message,"EVENT_STOP_IND_TO_MAC");
504                   break;
505                case EVENT_RACH_IND_TO_MAC:
506                   strcpy(message,"EVENT_RACH_IND_TO_MAC");
507                   break;
508                case EVENT_CRC_IND_TO_MAC:
509                   strcpy(message,"EVENT_CRC_IND_TO_MAC");
510                   break;
511                case EVENT_RX_DATA_IND_TO_MAC:
512                   strcpy(message,"EVENT_RX_DATA_IND_TO_MAC");
513                   break;
514                case EVENT_UCI_IND_TO_MAC:
515                   strcpy(message,"EVENT_UCI_IND_TO_MAC");
516                   break;
517                default:
518                   strcpy(message,"Invalid Event");
519                   break;
520             }
521
522             break;
523          }
524       case ENTMAC: /* When scheduler instance sends msg to MAC */
525          {
526             strcpy(sourceTask,"ENTMAC");
527             switch(pst->event)
528             {
529 #ifdef LCRG
530                case EVTINFCELLREGREQ:
531                   strcpy(message,"EVTINFCELLREGREQ");
532                   break;
533                case EVTINFSFALLOCREQ:
534                   strcpy(message,"EVTINFSFALLOCREQ");
535                   break;
536                case EVTINFRLSHQREQ:
537                   strcpy(message,"EVTINFRLSHQREQ");
538                   break;
539                case EVTINFHQENTRESET:
540                   strcpy(message,"EVTINFHQENTRESET");
541                   break;
542                case EVTINFRLSRNTIREQ:
543                   strcpy(message,"EVTINFRLSRNTIREQ");
544                   break;
545 #ifdef LTEMAC_SPS
546                case EVTINFSPSLCREG:
547                   strcpy(message,"EVTINFSPSLCREG");
548                   break;
549                case EVTINFSPSLCDEREG:
550                   strcpy(message,"EVTINFSPSLCDEREG");
551                   break;
552                case EVTINFSPSRESET:
553                   strcpy(message,"EVTINFSPSRESET");
554                   break;
555 #endif /* LTEMAC_SPS */
556                case EVTINFLCGREG:
557                   strcpy(message,"EVTINFLCGREG");
558                   break;
559 #endif            
560 #if defined(LTE_ADV) && defined(LCPRG)
561                case EVTPRGUESCELLCFGREQ:
562                   strcpy(message,"EVTPRGUESCELLCFGREQ");
563                   break;
564                case EVTPRGUESCELLCFGCFM:
565                   strcpy(message,"EVTPRGUESCELLCFGCFM");
566                   break;
567                case EVTPRGUESCELLLCHMODCFM:
568                   strcpy(message,"EVTPRGUESCELLLCHMODCFM");
569                   break;
570                case EVTPRGUESCELLLCHDELCFMDEL:
571                   strcpy(message,"EVTPRGUESCELLLCHDELCFMDEL");
572                   break;
573                case EVTPRGUESCELLLCHADDCFM:
574                   strcpy(message,"EVTPRGUESCELLLCHADDCFM");
575                   break;
576                case EVTPRGUESCELLDELREQ:
577                   strcpy(message,"EVTPRGUESCELLDELREQ");
578                   break;
579                case EVTPRGUESCELLLCHMODREQ:
580                   strcpy(message,"EVTPRGUESCELLLCHMODREQ");
581                   break;
582                case EVTPRGUESCELLLCHDELREQ:
583                   strcpy(message,"EVTPRGUESCELLLCHDELREQ");
584                   break;
585                case EVTPRGUESCELLLCHADDREQ:
586                   strcpy(message,"EVTPRGUESCELLLCHADDREQ");
587                   break;
588
589 #endif
590                default:
591                   strcpy(message,"Invalid Event");
592                   break;
593             }
594             break;
595          }
596
597       default:
598          {
599             strcpy(sourceTask,"Invalid Source Entity Id");
600             break;
601          }
602    }
603    DU_LOG("\nCall Flow: %s -> %s : %s\n", sourceTask, destTask, message);
604 }
605
606 \f
607 /**********************************************************************
608 \f
609 /**
610  * @brief Task Activation callback function. 
611  *
612  * @details
613  *
614  *     Function : rgActvTsk
615  *     
616  *     Primitives invoked by MAC's users/providers through
617  *     a loosely coupled interface arrive here by means of 
618  *     SSI's message handling. This API is registered with
619  *     SSI during the Task Registration of MAC.
620  *     
621  *  @param[in]  Pst     *pst, Post structure of the primitive.     
622  *  @param[in]  Buffer *mBuf, Packed primitive parameters in the buffer.
623  *  @param[in]  Reason reason.
624  *  @return  S16
625  *      -# ROK
626  **/
627 S16 rgActvTsk
628 (
629 Pst     *pst,                       /* post structure       */
630 Buffer  *mBuf                       /* message buffer       */
631 )
632 {
633
634 #ifdef CALL_FLOW_DEBUG_LOG
635    callFlowRgActvTsk(pst);
636 #endif
637
638    switch(pst->srcEnt)
639    {
640       /* The originator of this message is the stack manager,
641        * unpack and go to the respective primitive processing function */
642       case ENTDUAPP:
643           rgHdlSMEvents(pst, mBuf);
644            break;
645       case ENTNH:
646           rgHdlNHEvents(pst, mBuf);
647           break;
648       case ENTRLC:
649           rgHdlKWEvents(pst, mBuf);
650           break;
651       case ENTLWRMAC:
652           rgHdlTFEvents(pst, mBuf);
653           break;
654       case ENTMAC: /* When scheduler instance sends msg to MAC */
655           rgHdlRGEvents(pst, mBuf);
656           break;
657        default:
658           RG_FREE_MSG(mBuf);
659           break;
660    }
661    ODU_EXIT_TASK();
662    return ROK;
663 }/* end of rgActvTsk */
664
665 \f
666 /**********************************************************************
667  
668          End of file
669 **********************************************************************/