1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
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 #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
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 *******************************************************************************/
19 /********************************************************************20**
21 Name: LTE-RLC Layer - Upper Interface
25 Desc: C source code for the upper interface of LTE-RLC
29 *********************************************************************21*/
30 static const char* RLOG_MODULE_NAME="UIM";
31 static int RLOG_MODULE_ID=2048;
32 static int RLOG_FILE_ID=199;
35 @brief RLC Upper Interface
39 /* header (.h) include files */
40 #include "envopt.h" /* environment options */
41 #include "envdep.h" /* environment dependent */
42 #include "envind.h" /* environment independent */
44 #include "gen.h" /* general */
45 #include "ssi.h" /* system services */
46 #include "cm5.h" /* common timer defines */
47 #include "cm_tkns.h" /* common tokens defines */
48 #include "cm_mblk.h" /* common memory allocation library defines */
49 #include "cm_llist.h" /* common link list defines */
50 #include "cm_hash.h" /* common hash list defines */
51 #include "cm_lte.h" /* common LTE defines */
52 #include "lkw.h" /* LKW defines */
53 #include "ckw.h" /* CKW defines */
54 #include "kwu.h" /* KWU defines */
55 #include "rgu.h" /* RGU defines */
58 #include "kw_env.h" /* RLC environment options */
59 #include "kw.h" /* RLC defines */
61 /* extern (.x) include files */
62 #include "gen.x" /* general */
63 #include "ssi.x" /* system services */
65 #include "cm5.x" /* common timer library */
66 #include "cm_tkns.x" /* common tokens */
67 #include "cm_mblk.x" /* common memory allocation */
68 #include "cm_llist.x" /* common link list */
69 #include "cm_hash.x" /* common hash list */
70 #include "cm_lte.x" /* common LTE includes */
71 #include "cm_lib.x" /* common memory allocation library */
72 #include "lkw.x" /* LKW */
73 #include "ckw.x" /* CKW */
74 #include "kwu.x" /* KWU */
75 #include "rgu.x" /* RGU */
76 #if defined(MAC_RLC_UL_RBUF) || (defined(L2_L3_SPLIT) && defined(ICC_RECV_TSK_RBUF)) || defined(SS_RBUF)
81 #if defined(L2_L3_SPLIT) && defined(ICC_RECV_TSK_RBUF)
82 #include "mt_plat_t33.h"
83 #include "mt_plat_t33.x"
107 #endif /* __cplusplus */
110 /*********************************************************************
111 * Forward Declartion for KWU Porting Functions
112 ********************************************************************/
113 #if defined(PDCP_RLC_DL_RBUF) || defined(SS_RBUF)
114 PUBLIC S16 kwDlBatchProc ARGS ((Void));
115 PUBLIC S16 kwUtlDlFreeRlcRBuf ARGS((Void));
116 EXTERN void kwUtlDlBatchProcHqStaInd ARGS ((Void));
117 EXTERN Void kwUtlFreeDlMem ARGS((Void));
118 EXTERN SsRngBufCnt rngCb;
119 EXTERN S16 kwUtlDlBatchProcPkts ARGS((Void));
122 #if (defined(L2_L3_SPLIT) && defined(ICC_RECV_TSK_RBUF))
123 PUBLIC S16 kwDlBatchProcSplit ARGS((Void));
127 /*********************************************************************
128 * Primitives for KWU interface
129 ********************************************************************/
131 /* KWU Bind Confirm primitive */
133 PUBLIC KwuBndCfm kwUiKwuBndCfmMt[] =
136 cmPkKwuBndCfm, /* 0 - loosely coupled */
137 #endif /* LCKWUIKWU */
139 NhLiKwuBndCfm, /* 1 - tightly coupled, RRC */
143 PjLiKwuBndCfm, /* 2 - tightly coupled, PDCP */
148 cmPkKwuBndCfm, /* 3 - light weight loosely coupled */
149 #endif /* LCKWUIKWU */
153 /* KWU Data Indication primitive */
155 PUBLIC KwuDatInd kwUiKwuDatIndMt[] =
158 cmPkKwuDatInd, /* 0 - loosely coupled */
159 #endif /* LCKWUIKWU */
161 NhLiKwuDatInd, /* 1 - tightly coupled, RRC */
166 PjLiKwuDatInd, /* 2 - tightly coupled, PDCP */
170 cmPkKwuDatInd, /* 3 - light weight loosely coupled */
171 #endif /* LCKWUIKWU */
177 PUBLIC KwuDatCfm kwUiKwuDatCfmMt[] =
180 cmPkKwuDatCfm, /* 0 - loosely coupled */
181 #endif /* LCKWUIKWU */
183 PjLiKwuDatCfm, /* 2 - tightly coupled, PDCP */
187 cmPkKwuDatCfm, /* 3 - light weight loosely coupled */
188 #endif /* LCKWUIKWU */
192 /* KWU AM Status Indication primitive */
194 PUBLIC KwuStaInd kwUiKwuStaIndMt[] =
197 cmPkKwuStaInd, /* 0 - loosely coupled */
198 #endif /* LCKWUIKWU */
200 PjLiKwuStaInd, /* 2 - tightly coupled, PDCP */
204 cmPkKwuStaInd, /* 3 - light weight loosely coupled */
205 #endif /* LCKWUIKWU */
209 PUBLIC KwuReEstCmpInd kwUiKwuReEstCmpIndMt[] =
212 cmPkKwuReEstCmpInd, /* 0 - loosely coupled */
213 #endif /* LCKWUIKWU */
215 PjLiKwuReEstCmpInd, /* 2 - tightly coupled, PDCP */
220 cmPkKwuReEstCmpInd, /* 3 - light weight loosely coupled */
221 #endif /* LCKWUIKWU */
225 /* kw005.201 added support for L2 measurement */
226 PUBLIC KwuDiscSduCfm kwUiKwuDiscSduCfmMt[] =
229 cmPkKwuDiscSduCfm, /* 0 - loosely coupled */
230 #endif /* LCKWUIKWU */
232 PjLiKwuDiscSduCfm, /* 2 - tightly coupled, PDCP */
236 cmPkKwuDiscSduCfm, /* 3 - light weight loosely coupled */
240 PUBLIC KwuFlowCntrlInd kwUiKwuFlowCntrlIndMt[] =
243 cmPkKwuFlowCntrlInd, /* 0 - loosely coupled */
244 #endif /* LCKWUIKWU */
246 PjLiKwuFlowCntrlInd, /* 2 - tightly coupled, PDCP */
249 cmPkKwuFlowCntrlInd, /* 3 - light weight loosely coupled */
250 #endif /* LCKWUIKWU */
253 PUBLIC KwuDatAckInd kwUiKwuDatAckIndMt[] =
256 cmPkKwuDatAckInd, /* 0 - loosely coupled */
257 #endif /* LCKWUIKWU */
259 PjLiKwuDatAckInd, /* 2 - tightly coupled, PDCP */
263 cmPkKwuDatAckInd, /* 3 - light weight loosely coupled, portable */
267 #endif /* LTE_L2_MEAS */
268 /* KWU AM Data confirm primitive */
273 /****************************************************************************
274 * KWU Interface Mt functions
275 ***************************************************************************/
\f
280 * Handler for confirming the bind request received from KWU
285 * This function send the bind confirm primitive to the RLC user,
286 * when it receives a bind request from its service user.
288 * @param[in] pst Post structure
289 * @param[in] suId Service user SAP ID
290 * @param[in] status Status of Confirmation
297 PUBLIC S16 KwUiKwuBndCfm
299 Pst *pst, /* post structure */
300 SuId suId, /* Service User Id */
301 U8 status /* Status */
304 PUBLIC S16 KwUiKwuBndCfm(pst, suId, status)
305 Pst *pst; /* post structure */
306 SuId suId; /* Service User Id */
307 U8 status; /* Status */
312 /* jump to specific primitive depending on configured selector */
313 (*kwUiKwuBndCfmMt[pst->selector])(pst, suId, status);
317 } /* end of KwUiKwuBndCfm */
324 * Handler for sending the data(SDU) from upper layer.
328 * This function is used to transfer a SDU received from the peer
329 * RLC entity to the service user(RRC/PDCP).
331 * @param[in] pst Post structure
332 * @param[in] suId Service User SAP ID
333 * @param[in] datIndInfo Data Request Information
334 * @param[in] mBuf Data Buffer (SDU)
341 PUBLIC S16 KwUiKwuDatInd
345 KwuDatIndInfo *datInd,
349 PUBLIC S16 KwUiKwuDatInd(pst, suId, datInd, mBuf)
352 KwuDatIndInfo *datInd;
358 /* jump to specific primitive depending on configured selector */
359 (*kwUiKwuDatIndMt[pst->selector])(pst, suId, datInd, mBuf);
363 } /* end of KwUiKwuDatInd */
365 PUBLIC int rlcDatCfmsSent = 0;
372 * Handler for sending the data confirmation to upper layer.
376 * This function is used to send a confirmation to the service
377 * user about the data received by the peer RLC entity.
379 * @param[in] pst Post structure
380 * @param[in] suId Service User SAP ID
381 * @param[in] datCfmInfo Data Confirmation Information
388 PUBLIC S16 KwUiKwuDatCfm
392 KwuDatCfmInfo *datCfm
395 PUBLIC S16 KwUiKwuDatCfm(pst, suId, datCfm)
398 KwuDatCfmInfo *datCfm;
404 /* jump to specific primitive depending on configured selector */
405 (*kwUiKwuDatCfmMt[pst->selector])(pst, suId, datCfm);
409 } /* end of KwUiKwuDatCfm */
416 * Handler for sending the Status Indication to the upper layer.
420 * This function is used only by RLC AM entity.It send status
421 * indication to the upper layer about the maximum number of
422 * re-transmissions reached for a RLC AM entity.
424 * @param[in] pst Post structure
425 * @param[in] suId Service User SAP ID
426 * @param[in] staInd RLC Entity Id
433 PUBLIC S16 KwUiKwuStaInd
437 KwuStaIndInfo *staInd
440 PUBLIC S16 KwUiKwuStaInd(pst, suId, staInd)
443 KwuStaIndInfo *staInd;
448 /* jump to specific primitive depending on configured selector */
449 (*kwUiKwuStaIndMt[pst->selector])(pst, suId, staInd);
453 } /* end of KwUiKwuStaInd */
460 * Handler for sending the Status Indication to the upper layer.
464 * This function is used only by RLC AM entity.It send status
465 * indication to the upper layer about the maximum number of
466 * re-transmissions reached for a RLC AM entity.
468 * @param[in] pst Post structure
469 * @param[in] suId Service User SAP ID
470 * @param[in] staInd RLC Entity Id
477 PUBLIC S16 KwUiKwuReEstCmpInd
484 PUBLIC S16 KwUiKwuReEstCmpInd(pst, suId, rlcId)
490 TRC3(KwUiKwuReEstCmpInd)
491 RLOG0(L_DEBUG, "In KwUiKwuReEstCmpInd");
493 /* jump to specific primitive depending on configured selector */
494 (*kwUiKwuReEstCmpIndMt[pst->selector])(pst, suId, rlcId);
498 } /* end of KwUiKwuReEstCmpInd */
499 /* kw005.201 added support for L2 Measurement */
505 * Handler for sending the Sdu Disc Cfm to the upper layer.
509 * This function confirms the discard of an SDU .
511 * @param[in] pst Post structure
512 * @param[in] suId Service User SAP ID
513 * @param[in] discCfm Disc information.
520 PUBLIC S16 KwUiKwuDiscSduCfm
524 KwuDiscSduInfo *discCfm
527 PUBLIC S16 KwUiKwuDiscSduCfm(pst, suId, discCfm)
530 KwuDiscSduInfo *discCfm;
533 TRC3(KwUiKwuDiscSduCfm)
535 /* jump to specific primitive depending on configured selector */
536 (*kwUiKwuDiscSduCfmMt[pst->selector])(pst, suId, discCfm);
540 } /* end of KwUiKwuDiscSduCfm */
546 * Handler for sending Flow indication to the upper layer.
550 * This function indicates to PDCP if packets need to be stopped or
551 * started for a particular RB
553 * @param[in] pst Post structure
554 * @param[in] suId Service User SAP ID
555 * @param[in] flowCntrlIndInfo Flow control information.
562 PUBLIC S16 KwUiKwuFlowCntrlInd
566 KwuFlowCntrlIndInfo *flowCntrlIndInfo
569 PUBLIC S16 KwUiKwuFlowCntrlInd(pst, suId, flowCntrlIndInfo)
572 KwuFlowCntrlIndInfo *flowCntrlIndInfo;
575 TRC3(KwUiKwuFlowCntrlInd)
577 /* jump to specific primitive depending on configured selector */
578 (*kwUiKwuFlowCntrlIndMt[pst->selector])(pst, suId, flowCntrlIndInfo);
582 } /* end of KwUiKwuFlowCntrlInd */
589 * Handler for sending the Data ack indication to the upper layer.
593 * This function confirms the succesfull transmission of SDU
595 * @param[in] pst Post structure
596 * @param[in] suId Service User SAP ID
597 * @param[in] datAckInd DatAckInd
604 PUBLIC S16 KwUiKwuDatAckInd
608 KwuDatAckInfo *datAckInd
611 PUBLIC S16 KwUiKwuDatAckInd(pst, suId, datAckInd)
614 KwuDatAckInfo *datAckInd;
617 TRC3(KwUiKwuDatAckInd)
619 /* jump to specific primitive depending on configured selector */
620 (*kwUiKwuDatAckIndMt[pst->selector])(pst, suId, datAckInd);
624 } /* end of KwUiKwuDatAckInd */
625 #endif /* LTE_L2_MEAS */
630 /*********************************************************************
631 * Primitives for CKW interface
632 ********************************************************************/
634 /* CKW Bind Confirm primitive */
636 PUBLIC CkwBndCfm kwUiCkwBndCfmMt[] =
639 cmPkCkwBndCfm, /* 0 - loosely coupled */
640 #endif /* LCCKUICKW */
642 NhLiCkwBndCfm, /* 1 - tightly coupled, RRC */
646 /* CKW Configuration confirm primitive */
648 PUBLIC CkwCfgCfm kwUiCkwCfgCfmMt[] =
651 cmPkCkwCfgCfm, /* 0 - loosely coupled */
652 #endif /* LCKWUICKW */
654 NhLiCkwCfgCfm, /* 1 - tightly coupled, RRC */
658 PUBLIC CkwUeIdChgCfm kwUiCkwUeIdChgCfmMt[] =
661 cmPkCkwUeIdChgCfm, /* 0 - loosely coupled */
662 #endif /* LCKWUICKW */
664 NhLiCkwUeIdChgCfm, /* 1 - tightly coupled, RRC */
670 /****************************************************************************
671 * CKW Interface Mt functions
672 ***************************************************************************/
677 * Handler for confirming the bind request received from CKW
682 * This function send the bind confirm primitive to the RLC user,
683 * when it receives a bind request from its service user.
685 * @param[in] pst - Post structure
686 * @param[in] suId - Service user SAP ID
687 * @param[in] status - Status
693 PUBLIC S16 KwUiCkwBndCfm
695 Pst *pst, /* post structure */
696 SuId suId, /* Service User Id */
697 U8 status /* Status */
700 PUBLIC S16 KwUiCkwBndCfm(pst, suId, status)
701 Pst *pst; /* post structure */
702 SuId suId; /* Service User Id */
703 U8 status; /* Status */
708 /* jump to specific primitive depending on configured selector */
709 (*kwUiCkwBndCfmMt[pst->selector])(pst, suId, status);
713 } /* end of KwUiCkwBndCfm */
720 * Handler for sending a configuration confirm to RRC.
724 * This function is used by RLC user to send a configuration
725 * confirmation to RRC after configuring(add/delete/modify)
728 * @param[in] pst Post structure
729 * @param[in] transId Transaction Id
730 * @param[in] cfmInfo Config Confirmation Info
737 PUBLIC S16 KwUiCkwCfgCfm
739 Pst *pst, /* post structure */
740 SuId suId, /* Service User Id */
741 CkwCfgCfmInfo *cfmInfo /* Configuration Confirm */
744 PUBLIC S16 KwUiCkwCfgCfm(pst, suId, cfmInfo)
745 Pst *pst; /* post structure */
746 SuId suId; /* Service User Id */
747 CkwCfgCfmInfo *cfmInfo; /* Configuration Confirm */
752 /* jump to specific primitive depending on configured selector */
753 (*kwUiCkwCfgCfmMt[pst->selector])(pst, suId, cfmInfo);
757 } /* end of KwUiCkwCfgCfm */
764 * Handler for sending a configuration for UE ID change.
768 * This function is used by RLC to send a configuration
769 * confirm for UE ID change.
771 * @param[in] pst Post structure
772 * @param[in] suId Service User Id
773 * @param[in] transId Transaction Id
774 * @param[in] cfmInfo Config Confirmation Info
781 PUBLIC S16 KwUiCkwUeIdChgCfm
783 Pst *pst, /* post structure */
784 SuId suId, /* Service User Id */
790 PUBLIC S16 KwUiCkwUeIdChgCfm(pst, suId, transId,ueInfo,status)
791 Pst *pst; /* post structure */
792 SuId suId; /* Service User Id */
798 TRC3(KwUiCkwUeIdChgCfm)
800 /* jump to specific primitive depending on configured selector */
801 (*kwUiCkwUeIdChgCfmMt[pst->selector])(pst, suId, transId, ueInfo, status);
805 } /* end of KwUiCkwCfgCfm */
808 #if (defined(L2_L3_SPLIT) && defined(ICC_RECV_TSK_RBUF))
813 * kwDlBatchProcSplit- process rbug messages
819 PUBLIC S16 kwDlBatchProcSplit
824 PUBLIC S16 kwDlBatchProcSplit()
829 /* Read from Ring Buffer and process PDCP packets */
830 Void *elmIndx = NULLP;
831 RxmBufReq *datReq = NULLP;
835 U8 rngBufDeqIndx = 0;
839 rngBufDeqMaxCnt = SS_RNG_MAX_DLPDCP_TO_DLRLC_DQ_CNT;
840 #ifdef TENB_T2K3K_SPECIFIC_CHANGES
841 rngBufCurrCnt = SGetNumElemInRng(SS_RNG_BUF_RX_TO_DLRLC);
842 if ( rngBufCurrCnt > (3 * SS_RNG_MAX_DLPDCP_TO_DLRLC_DQ_CNT))
844 if ( rngBufCurrCnt > (6 * SS_RNG_MAX_DLPDCP_TO_DLRLC_DQ_CNT))
846 /* Restablishment scenario */
847 rngBufDeqMaxCnt = (4 * SS_RNG_MAX_DLPDCP_TO_DLRLC_DQ_CNT);
851 rngBufDeqMaxCnt = (3 * SS_RNG_MAX_DLPDCP_TO_DLRLC_DQ_CNT)/2;
855 elmIndx = SRngGetRIndx(SS_RNG_BUF_RX_TO_DLRLC);
856 while(NULLP != elmIndx)
858 datReq = (RxmBufReq *)elmIndx;
859 if(datReq->mBuf != NULLP)
861 cmUnpkKwuDatReq(KwUiKwuDatReq, &datReq->pst, datReq->mBuf);
865 RLOG0(L_ERROR, "mBuf is NULL");
867 cmUnpkKwuDatReq(KwUiKwuDatReq, &datReq->pst, datReq->mBuf);
870 SsRngInfoTbl[SS_RNG_BUF_RX_TO_DLRLC].nPktProc++;//Number of pkt processed in tti
871 datReq->mBuf = NULLP;
872 SRngIncrRIndx(SS_RNG_BUF_RX_TO_DLRLC);
874 if(rngBufDeqIndx >= rngBufDeqMaxCnt)
887 if((elmIndx = SRngGetRIndx(SS_RNG_BUF_RX_TO_DLRLC)) == NULLP)
897 #if defined(PDCP_RLC_DL_RBUF) || defined(SS_RBUF)
899 PUBLIC S16 kwDlBatchProc
904 PUBLIC S16 kwDlBatchProc()
908 /* Read from Ring Buffer and process PDCP packets */
910 U8 rngBufDeqIndx = 0;
912 #ifdef TENB_T2K3K_SPECIFIC_CHANGES
915 /* Memory regions different for BRCM and Intel */
916 /*dstProcId,srcProcId,dstEnt,dstInst,srcEnt,srcInst,prior,route,event,region,pool,selector*/
918 PRIVATE Pst rlcDlRbfuPst ={1,1,ENTKW,1,ENTPJ,1,PRIOR0,RTESPEC,KWU_EVT_DAT_REQ,1,1,0,0};
920 PRIVATE Pst rlcDlRbfuPst ={1,1,ENTKW,1,ENTPJ,1,PRIOR0,RTESPEC,KWU_EVT_DAT_REQ,2,1,0,0};
922 Void *elmIndx = NULLP;
923 KwuDatReqDetl *kwuDatReqDetl = NULLP;
924 KwuDatReqInfo datReq;
926 rngBufDeqMaxCnt = SS_RNG_MAX_DLPDCP_TO_DLRLC_DQ_CNT;
927 #ifdef TENB_T2K3K_SPECIFIC_CHANGES
928 rngBufCurrCnt = SGetNumElemInRng(SS_RNG_BUF_DLPDCP_TO_DLRLC);
929 if ( rngBufCurrCnt > (3 * SS_RNG_MAX_DLPDCP_TO_DLRLC_DQ_CNT))
931 if ( rngBufCurrCnt > (5 * SS_RNG_MAX_DLPDCP_TO_DLRLC_DQ_CNT))
933 /* Restablishment scenario */
934 rngBufDeqMaxCnt = (4 * SS_RNG_MAX_DLPDCP_TO_DLRLC_DQ_CNT);
938 rngBufDeqMaxCnt = (2 * SS_RNG_MAX_DLPDCP_TO_DLRLC_DQ_CNT);
942 elmIndx = SRngGetRIndx(SS_RNG_BUF_DLPDCP_TO_DLRLC);
943 while(NULLP != elmIndx)
945 kwuDatReqDetl = (KwuDatReqDetl *)elmIndx;
946 datReq.rlcId = kwuDatReqDetl->rlcId;
947 datReq.sduId = kwuDatReqDetl->sduId;
948 datReq.lcType = kwuDatReqDetl->lcType;
949 SsRngInfoTbl[SS_RNG_BUF_DLPDCP_TO_DLRLC].nPktProc++;;//Number of pkt processed in tti
950 if(kwuDatReqDetl->mBuf != NULLP)
952 KwUiKwuDatReq(&rlcDlRbfuPst, kwuDatReqDetl->spId, &datReq, kwuDatReqDetl->mBuf);
954 SRngIncrRIndx(SS_RNG_BUF_DLPDCP_TO_DLRLC);
957 if(rngBufDeqIndx >= rngBufDeqMaxCnt)
961 elmIndx = (Void *)SRngGetRIndx(SS_RNG_BUF_DLPDCP_TO_DLRLC);
969 PUBLIC S16 kwUtlDlBatchProcPkts
974 PUBLIC S16 kwUtlDlBatchProcPkts
981 kwUtlDlBatchProcHqStaInd();
990 PUBLIC S16 kwUtlDlFreeRlcRBuf
995 PUBLIC S16 kwUtlDlFreeRlcRBuf
999 /* Read from Ring Buffer and process PDCP packets */
1000 Void *elmIndx = NULLP;
1001 KwuDatReqDetl *kwuDatReqDetl = NULLP;
1002 /* Free SS_RNG_BUF_DLPDCP_TO_DLRLC */
1003 elmIndx = SRngGetRIndx(SS_RNG_BUF_DLPDCP_TO_DLRLC);
1004 while(NULLP != elmIndx)
1006 kwuDatReqDetl = (KwuDatReqDetl *)elmIndx;
1007 SRngIncrRIndx(SS_RNG_BUF_DLPDCP_TO_DLRLC);
1008 SsRngInfoTbl[SS_RNG_BUF_DLPDCP_TO_DLRLC].nPktProc++;
1009 SPutMsg(kwuDatReqDetl->mBuf);
1011 kwuDatReqDetl = NULLP;
1012 if((elmIndx = SRngGetRIndx(SS_RNG_BUF_DLPDCP_TO_DLRLC)) == NULLP)
1022 #endif /* __cplusplus */
1023 /********************************************************************30**
1025 **********************************************************************/