OMAP54XX: Add remote codec support
[mfp/cedev.git] / packages / ti / sdo / ce / rms.c
1 /*
2  * Copyright (c) 2013-2014, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  */
33 /*
34  *  ======== rms.c ========
35  */
37 /* This define must precede inclusion of any xdc header files */
38 #define Registry_CURDESC ti_sdo_ce_rms_desc
40 #include <xdc/std.h>
41 #include <xdc/runtime/Assert.h>
42 #include <xdc/runtime/Diags.h>
43 #include <xdc/runtime/Log.h>
44 #include <xdc/runtime/Registry.h>
46 #include <xdc/runtime/knl/Thread.h>
48 #include <string.h>
49 #include <assert.h>
50 #include <stdio.h>
51 #include <ctype.h>
53 #include <ti/sdo/ce/global/CESettings.h>
54 #include <ti/sdo/ce/osal/Global.h>
55 #include <ti/sdo/ce/osal/Memory.h>
56 #include <ti/sdo/ce/osal/Trace.h>
57 #include <ti/sdo/ce/ipc/Comm.h>
58 #include <ti/sdo/ce/ipc/Processor.h>
60 #include <ti/sdo/ce/rms.h>
61 #include <ti/sdo/ce/alg/Algorithm.h>
62 #include <ti/sdo/ce/node/node.h>
63 #include <ti/sdo/ce/node/_node.h>  /* RMS is a "friend" of NODE */
64 #include <ti/sdo/ce/Server.h>
65 #include <ti/sdo/ce/_Server.h>
66 #include <ti/sdo/ce/skel.h>
68 #include <ti/xdais/ialg.h>
71 #define MAXNUMLEN   8
72 #define MAXNUMSEGS  1024        /* Maximum number of heaps checked for */
74 /*
75  *  Heap must be large enough to hold HeapMem_Header. Don't allow heaps to
76  *  be re-defined to a size of 0 to avoid extra maintenance. Will check that
77  *  the size is at least MINHEAPSIZE.
78  */
79 #define MINHEAPSIZE 16
81 #define MODNAME "ti.sdo.ce.rms"
83 /*
84  *  Maximum length of codec name (Should be the same as in visa.c)
85  */
86 #define MAXNAMELEN 127          /* Maximum length of codec name */
88 #define HEADERSIZE  ( \
89     (Char *)&(((RMS_RmsMsg *)0)->cmdBuf) - (Char *)0  \
90 )
92 /* this function is for internal use only */
93 #define RMS_checkUuid(uuid1, uuid2) \
94     ( ((uuid1).data) == ((uuid2).data) )
96 /* internal description of a created node instance */
97 typedef struct RMS_Obj {
98     NODE_Handle     node;       /* NULL means free */
99     NODE_Desc       *nodeDesc;  /* ptr to entry in node database */
100     Comm_Handle     nodeQueue;  /* node's input message queue */
101     Comm_Id         gppQueue;   /* gpp's (client's) message queue */
102     Int             instanceId; /* unique instance ID */
103     String          name;       /* node's instance name */
104 } RMS_Obj;
107 static Int           initCount = 0;
109 static Comm_Handle   rmsMsgQueue = Comm_INVALIDHANDLE;
110 static RMS_RmsMsg    *rmsMsg = NULL;
111 static Thread_Handle rmsTsk = NULL;
112 static Bool traceTokenAvailable = TRUE;
114 /* default RMS configuration data set */
115 RMS_Config RMS_CONFIG = RMS_CONFIGDEFAULT;
117 Void RMS_run(IArg arg); /* RMS task entry function prototype */
119 static Void RMS_exec(Void);
121 static RMS_Status addAlg(RMS_CmdSetAddAlgIn *cmdIn,
122         RMS_CmdSetAddAlgOut *cmdOut);
123 static Char *formatNum(Char *ptr, UInt32 un);
124 static Void freeInst(RMS_Obj *inst);
125 static RMS_Status getAlg(RMS_CmdSetGetAlgIn *cmdIn,
126         RMS_CmdSetGetAlgOut *cmdOut);
127 static RMS_Status getMemRecs(RMS_CmdSetGetMemRecsIn *cmdIn,
128         RMS_CmdSetGetMemRecsOut *cmdOut);
129 static RMS_Status getNumAlgs(RMS_CmdSetGetNumAlgsOut *cmdOut);
130 static RMS_Status getNumRecs(RMS_CmdSetGetNumRecsIn *cmdIn,
131         RMS_CmdSetGetNumRecsOut *cmdOut);
132 static RMS_Status getSegStat(Int segId, RMS_CmdSetGetSegStatOut *out);
133 static RMS_Obj *mkInst(String nodeName, Int id);
135 static RMS_Status processRmsCmd(RMS_CmdBuf *cmdBuf, Int size);
136 static RMS_Status redefineHeap(String name, Int segId, Uint32 base,
137         Uint32 size);
138 static RMS_Status restoreHeap(String name);
140 extern Void IPC_threadGeneratedInit(Void);
141 extern Void IPC_threadGeneratedReset(Void);
143 Registry_Desc ti_sdo_ce_rms_desc;
145 static Int regInit = 0;     /* Registry_addModule() called */
147 static Int detachFlag = 0;  /* Set to 1 when we need to detatch */
148 static Int exitFlag = 0;    /* Set to 1 when we need the rms thread to exit */
150 /*
151  *  ======== RMS_init ========
152  *  Calls to RMS_init() must be serialized.
153  */
154 Void RMS_init(Void)
156 #ifndef xdc_target__os_undefined
157     Thread_Priority   threadPri;
158     Int               pri;
159 #endif
160     Registry_Result   result;
162     /*
163      *  No need to reference count for Registry_addModule(), since there
164      *  is no way to remove the module.
165      */
166     if (regInit == 0) {
167         /* Register this module for logging */
168         result = Registry_addModule(&ti_sdo_ce_rms_desc, MODNAME);
169         Assert_isTrue(result == Registry_SUCCESS, (Assert_Id)NULL);
171         if (result == Registry_SUCCESS) {
172             /* Set the diags mask to the CE default */
173             CESettings_init();
174             CESettings_setDiags(MODNAME);
175         }
176         regInit = 1;
177     }
179     if (initCount++ == 0) {
180         Thread_Params rmsTskAttrs;
181         Comm_Attrs commAttrs;
182         static char rmsCommName[32];  /* MessageQ_max length(?) */
184         NODE_init();
185         Comm_init();
188         /* HACK: we set callFxn in advance in case we run with an
189          * OSAL that does not support separate Thread threads
190          */
191         commAttrs = Comm_ATTRS;
192         commAttrs.callFxn = (Comm_CallFxn)RMS_exec;
194         /* create core-specific RMS's MSGQ for msg exchange with clients */
195         sprintf(rmsCommName, RMS_CMDQNAME ":%s",
196                 Processor_getCoreName(Processor_myCoreId()));
197         rmsMsgQueue = Comm_create(rmsCommName, &commAttrs);
198         assert(rmsMsgQueue != NULL);
200         /* now, create the RMS task that acts on the server's behalf */
201         Thread_Params_init(&rmsTskAttrs);
202 #ifdef xdc_target__os_undefined
203         rmsTskAttrs.osPriority  = RMS_config.tskPriority;
204 #else
205         pri = RMS_config.tskPriority;
206         threadPri = (pri <= RMS_LOWESTPRI) ? Thread_Priority_LOWEST :
207             (pri <= RMS_LOWPRI) ? Thread_Priority_BELOW_NORMAL :
208             (pri <= RMS_NORMALPRI) ? Thread_Priority_NORMAL :
209             (pri <= RMS_HIGHPRI) ? Thread_Priority_ABOVE_NORMAL :
210             Thread_Priority_HIGHEST;
212         rmsTskAttrs.priority  = threadPri;
213 #endif
214         rmsTskAttrs.stackSize = RMS_config.tskStacksize;
215         rmsTsk = Thread_create((Thread_RunFxn)RMS_run, &rmsTskAttrs, NULL);
216         assert(rmsTsk != NULL);
217     }
218     Log_print0(Diags_USER5, "[+5] RMS_init> exit");
222 /*
223  *  ======== RMS_exit ========
224  */
225 Void RMS_exit(Void)
227     Comm_Id rmsMsgQueueId;
228     RMS_RmsMsg msg;
230     if (initCount-- <= 1) {
231         initCount = 0;
233         if ((rmsTsk != NULL) && (rmsMsgQueue != Comm_INVALIDHANDLE)) {
234             rmsMsgQueueId = Comm_getId(rmsMsgQueue);
235             Comm_staticMsgInit((Comm_Msg)&msg, sizeof(RMS_RmsMsg));
236             msg.cmdBuf.cmd = RMS_QUIT;
238             Comm_put(rmsMsgQueueId, (Comm_Msg)&msg);
240             /* Wait for RMS thread to terminate */
241             Thread_join(rmsTsk, NULL);
242         }
244         if (rmsMsgQueue != NULL) {
245             Comm_delete(rmsMsgQueue);
246             rmsMsgQueue = NULL;
247         }
248         rmsMsgQueue = Comm_INVALIDHANDLE;
250         if (rmsTsk != NULL) {
251             Thread_delete(&rmsTsk);
252             rmsTsk = NULL;
253         }
255         traceTokenAvailable = TRUE;
256     }
260 /*
261  *  ======== RMS_run ========
262  */
263 Void RMS_run(IArg arg)
265     for (;;) {
266         /* Note, we do any deferred thread level init here. */
268         /*
269          *  When ipc.bios.Ipc.manageIpc = TRUE, this function calls
270          *  Ipc_attach().
271          */
272         IPC_threadGeneratedInit();
274         /* and finally, the RMS_exec() loop can run */
275         for (;;) {
276             RMS_exec();
277             if (detachFlag) {
278                 detachFlag = FALSE;
279                 break;
280             }
281             if (exitFlag) {
282                 /*
283                  *  CERuntime_exit has been called.  We shouldn't get
284                  *  here unless IPC_threadGeneratedInit and exit are NOPs
285                  *  (ipc.bios.Ipc.manageIpc == FALSE, ie the app is
286                  *  responsible for calling Ipc_attach() / Ipc_detatch()).
287                  */
288                 exitFlag = FALSE;
289                 return;
290             }
291         }
293         /*
294          *  Calls Ipc_detatch(), Ipc_stop(), and Ipc_start(), when manageIpc
295          *  is TRUE.
296          */
297         IPC_threadGeneratedReset();
298     }
301 /*
302  *  ======== RMS_exec ========
303  */
304 static Void RMS_exec(Void)
306     RMS_CmdBuf  *cmdBuf;
307     Int         commStatus;
308     Comm_Id     sendersMsgQueue;
309     RMS_Status  status;
311     /* get something to do */
312     commStatus = Comm_get(rmsMsgQueue, (Comm_Msg *)&rmsMsg, Comm_FOREVER);
314     Log_print1(Diags_USER4, "[+4] RMS_exec> got msg. status = %d",
315             (IArg)commStatus);
317     if (commStatus == Comm_EOK) {
318         Int msgSize = Comm_getMsgSize((Comm_Msg)rmsMsg);
320         /* we assume message recieved is at least as large as we require */
321         assert(msgSize >= sizeof (RMS_RmsMsg));
323         /* do it */
324         cmdBuf = (RMS_CmdBuf *)&(rmsMsg->cmdBuf);
325         status = processRmsCmd(cmdBuf, msgSize - HEADERSIZE);
326         cmdBuf->status = status;
328         if (!exitFlag) {
329             /* find out who the sender was */
330             commStatus = Comm_getSendersId((Comm_Msg)rmsMsg, &sendersMsgQueue);
331             assert(commStatus == Comm_EOK);
333             /* then send the message back */
334             commStatus = Comm_put(sendersMsgQueue, (Comm_Msg)rmsMsg);
335             assert(commStatus == Comm_EOK);
336         }
337     }
338     else {
339 #if 0
340         /* In some cases (like shutdown) this is expected */
341         Log_print1(Diags_USER7, "[+7] RMS_exec> Comm_get failed (0x%x)",
342                 (IArg)commStatus);
343 #endif
344     }
347 /*
348  *  ======== addAlg ========
349  */
350 static RMS_Status addAlg(RMS_CmdSetAddAlgIn *cmdIn,
351         RMS_CmdSetAddAlgOut *cmdOut)
353     Server_AlgDesc  algDesc;
354     Server_Status   status;
356     /* Set fields to defaults */
357     Server_initAlgDesc(&algDesc);
359     /* Server will make a copy of the name */
360     algDesc.name = (String)cmdIn->name;
362     Log_print1(Diags_USER4, "[+4] RMS addAlg> Name: %s", (IArg)algDesc.name);
364     algDesc.fxns = (IALG_Fxns *)cmdIn->fxns;
365     algDesc.idmaFxns = (Ptr)cmdIn->idmaFxns;
366     algDesc.iresFxns = (Ptr)cmdIn->iresFxns;
367     algDesc.isLocal = TRUE;
368     algDesc.groupId = (Int)cmdIn->groupId;
369     algDesc.memType = (Engine_CachedMemType)cmdIn->memType;
371     algDesc.types = (String)cmdIn->typeTab;
372     algDesc.stubFxnsName = (String)cmdIn->stubFxnsName;
373     algDesc.skelFxns = (SKEL_Fxns *)cmdIn->skelFxns;
375     Log_print1(Diags_USER4, "[+4] RMS addAlg> fxns: 0x%x",
376             (IArg)algDesc.fxns);
377     Log_print1(Diags_USER6, "[+4] RMS addAlg> skel: 0x%x",
378             (IArg)algDesc.skelFxns);
380     Log_print1(Diags_USER4, "[+4] RMS addAlg> idmaFxns: 0x%x",
381             (IArg)algDesc.idmaFxns);
382     Log_print1(Diags_USER4, "[+4] RMS addAlg> iresFxns: 0x%x",
383             (IArg)algDesc.iresFxns);
384     Log_print1(Diags_USER4, "[+4] RMS addAlg> groupId: %d",
385             (IArg)algDesc.groupId);
386     Log_print1(Diags_USER4, "[+4] RMS addAlg> memType: %d",
387             (IArg)algDesc.memType);
389     Log_print1(Diags_USER4, "[+4] RMS addAlg> Types: %s", (IArg)algDesc.types);
390     Log_print1(Diags_USER4, "[+4] RMS addAlg> Stubs: %s",
391             (IArg)algDesc.stubFxnsName);
393     algDesc.priority = (Int)cmdIn->priority;
394     algDesc.stackSize = (UInt32)cmdIn->stackSize;
395     algDesc.stackSeg = (UInt32)cmdIn->stackSeg;
396     algDesc.codecClassConfig = (Void *)cmdIn->codecClassConfig;
398     Log_print1(Diags_USER4, "[+4] RMS addAlg> isLocal: %d",
399             (IArg)algDesc.isLocal);
400     Log_print1(Diags_USER4, "[+4] RMS addAlg> priority: %d",
401             (IArg)algDesc.priority);
402     Log_print1(Diags_USER4, "[+4] RMS addAlg> stackSize: 0x%x",
403             (IArg)algDesc.stackSize);
404     Log_print1(Diags_USER4, "[+4] RMS addAlg> codecClassConfig: 0x%x",
405             (IArg)algDesc.codecClassConfig);
407     status = Server_addAlg(NULL, NULL, &algDesc);
409     if (status != Server_EOK) {
410         Log_print1(Diags_USER7, "App-> ERROR: can't add Alg (0x%x)\n",
411                 (IArg)status);
412         /* TODO: Convert Server_Status to RMS error */
413         cmdOut->serverError = (RMS_Word)status;
414         return (RMS_EFAIL);
415     }
417     /* Get the uuid assigned to the node to pass back to the host */
418     status = Server_getNodeUuid(algDesc.name, &(cmdOut->uuid));
420     if (status != Server_EOK) {
421         Log_print1(Diags_USER7, "App-> ERROR: can't find alg uuid (0x%x)\n",
422                 (IArg)status);
423         /* TODO: Convert Server_Status to RMS error */
424         cmdOut->serverError = (RMS_Word)status;
426         return (RMS_EFAIL);
427     }
429     cmdOut->serverError = (RMS_Word)status;
430     return (RMS_EOK);
433 /*
434  *  ======== checkStack ========
435  */
436 static Void checkStack(Void)
438     Bits16 classId = Diags_USER5;
439     Int headroom = 100;
440     Thread_Stat buf;
442     Thread_stat(Thread_self(NULL), &buf, NULL);
444     /* check stack size to see if we are close to overrun */
445     if (buf.stackSize != 0) {
446         headroom = (buf.stackSize > buf.stackUsed)
447             ? ((buf.stackSize - buf.stackUsed) * 100) / buf.stackSize : 0;
448     }
450     if (headroom < 10) {
451         classId |= Diags_USER6; /* less than 10%, generate warning */
452     }
453     Log_print3(classId, "RMS: stack size = %d, stack used = %d(%d%%)",
454             (IArg)(buf.stackSize), (IArg)(buf.stackUsed),
455             (IArg)(100 - headroom));
458 /*
459  *  ======== createNode ========
460  */
461 static RMS_Status createNode(RMS_CmdSetCreateNodeIn  *cmdIn,
462                               RMS_CmdSetCreateNodeOut *cmdOut)
464     RMS_Obj     *rmsInst;
465     NODE_Desc   *nodeDesc = NULL;
466     NODE_Desc   desc;
467     NODE_Attrs  nodeAttrs;
468     NODE_Handle node;
469     Int         numDynNodes;
470     Int         i;
471     Int         priority;
472     RMS_Status  status;
473     Char        tmpName[MAXNAMELEN + 1];
474     String      createArgBuf;
475     Int         createArgLen;
477     /* instance ID -- unique across all instances */
478     static Int          instanceId = 0;
480     Log_print2(Diags_USER5, "[+5] RMS createNode> Enter(0x%x, 0x%x)",
481             (IArg)cmdIn, (IArg)cmdOut);
483     /* search the database of nodes for the given uuid       */
484     for (nodeDesc = RMS_nodeTab; nodeDesc->name != NULL; nodeDesc++) {
485         if (RMS_checkUuid(cmdIn->uuid, nodeDesc->uuid)) {
486             break;  /* found it */
487         }
488     }
489     numDynNodes = Server_getNumNodes();
490     Log_print1(Diags_USER5, "[+5]RMS createNode> Num dynamic nodes: %d",
491             (IArg)numDynNodes);
493     if (nodeDesc->name == NULL) {
494         /* Search in list of dynamically added nodes */
495         numDynNodes = Server_getNumNodes();
497         Log_print1(Diags_USER5, "[+5] RMS createNode> Searching dynamic "
498                 "nodes.  num nodes = %d",
499                 (IArg)numDynNodes);
501         for (i = 0; i < numDynNodes; i++) {
502             nodeDesc = Server_getNode(i);
503             if ((nodeDesc != NULL) &&
504                     (RMS_checkUuid(cmdIn->uuid, nodeDesc->uuid))) {
505                 break;  /* found it */
506             }
507         }
508     }
510     if ((nodeDesc == NULL) || (nodeDesc->name == NULL)) {
511         return (RMS_EINVUUID);
512     }
514     Log_print2(Diags_USER5, "[+5] RMS createNode> Found match: "
515             "name = %s, uuid = 0x%x",
516             (IArg)nodeDesc->name, (IArg)nodeDesc->uuid.data);
519     if (nodeDesc->rpcProtocolVersion != cmdIn->rpcProtocolVersion) {
520         return (RMS_EINVPROT);
521     }
523     /* create an RMS node instance */
524     rmsInst = mkInst(nodeDesc->name, instanceId);
525     if (rmsInst == NULL) {
526         return (RMS_ERESOURCE);
527     }
529     /* point to the args buffer of the in structure */
530     createArgLen = cmdIn->argLength;
531     if (createArgLen > 0) {
532         createArgBuf = (String)(cmdIn->argBuffer);
533     }
534     else {
535         createArgBuf = NULL;
536     }
538     /* Initilize desc with configured values. */
539     desc = *nodeDesc;
540     nodeAttrs = *(nodeDesc->nodeAttrs);
541     desc.nodeAttrs = &nodeAttrs;
543     /*
544      *  If create parameters have priority set to -1, use configured priority,
545      *  otherwise override the configured priority with the value passed in
546      *  the create args.
547      */
548     priority = (Int)(cmdIn->nodePriority);
549     if (priority != -1) {
550         // TODO: (jeh) Thread_MINPRI and Thread_MAXPRI no longer exist.
551         //if ((priority < Thread_MINPRI) || (priority > Thread_MAXPRI)) {
552         //    return (RMS_EINVAL);
553         //}
554         nodeAttrs.initPriority = priority;
555     }
557     /*
558      *  Create new name combining nodeDesc->name and ::1 if cmdIn->useExtHeap
559      *  is TRUE. We need to do this because NODE_create() calls the codec's
560      *  create function (which only takes its own attributes arg).
561      */
562     if (cmdIn->useExtHeap) {
563         desc.name = tmpName;
564         strncpy(tmpName, nodeDesc->name, MAXNAMELEN - strlen("::1"));
565         tmpName[MAXNAMELEN - strlen("::1")] = '\0';
567         strcpy(tmpName + strlen(tmpName), "::1");
568         tmpName[MAXNAMELEN] = '\0';
569     }
571     status = NODE_create(
572         &desc,                          /* in: */
573         createArgLen,                   /* in: */
574         createArgBuf,                   /* in: */
575         cmdIn->gppQueue,                /* in:  sendQueue (to gpp msgq) */
576         rmsInst->name,                  /* in:  node instance name */
577         &node                           /* out: node handle */
578     );
580     if (status != NODE_EOK) {
581         freeInst(rmsInst);
582         status = (status == NODE_EOUTOFMEMORY) ? RMS_EOUTOFMEMORY :
583             (status == NODE_ETASK) ? RMS_ETASK : RMS_EFAIL;
584         return (status);
585     }
587     /* record the node instance data */
588     rmsInst->node       = node;
589     rmsInst->nodeDesc   = nodeDesc;
590     rmsInst->nodeQueue  = NODE_getRecvQueue(node);
591     rmsInst->gppQueue   = cmdIn->gppQueue;
592     rmsInst->instanceId = instanceId;
593     instanceId++;
595     /* prepare command output  */
596     cmdOut->node       = (RMS_Word)rmsInst;
597     cmdOut->nodeQueue  = Comm_getId(rmsInst->nodeQueue);
598     cmdOut->remoteVisa = (RMS_Word)NODE_getEnv(node);
600     return (RMS_EOK);
603 /*
604  *  ======== deleteNode ========
605  */
606 static RMS_Status deleteNode(RMS_CmdSetDeleteNodeIn *cmdIn, RMS_CmdSetDeleteNodeOut *cmdOut)
608     RMS_Obj     *rmsInst = (RMS_Obj *)cmdIn->node;
609     RMS_Status  status = RMS_EOK;
610     NODE_Stat   buf;
612     Log_print2(Diags_USER5, "[+5] RMS deleteNode> Enter(0x%x, 0x%x)",
613             (IArg)cmdIn, (IArg)cmdOut);
615     /* get current stack info before deleting node */
616     if (NODE_stat(rmsInst->node, &buf) == 0) {
617         cmdOut->stackSize = buf.stackSize;
618         cmdOut->stackUsed = buf.stackUsed;
619     }
620     else {
621         cmdOut->stackSize = 0;
622         cmdOut->stackUsed = 0;
623     }
625     /* delete the node object itself */
626     if (NODE_delete(rmsInst->node) != NODE_EOK) {
627         status = RMS_EFAIL;
628     }
630     freeInst(rmsInst);
632     return (status);
635 /*
636  *  ======== startNode ========
637  */
638 static RMS_Status startNode(RMS_CmdSetExecuteNodeIn *cmdIn)
640     RMS_Obj     *rmsInst = (RMS_Obj *)cmdIn->node;
641     RMS_Status  status = RMS_EOK;
643     Log_print1(Diags_USER5, "[+5] RMS startNode> Enter(0x%x)", (IArg)cmdIn);
645     if (NODE_start(rmsInst->node) != NODE_EOK) {
646         status = RMS_EFAIL;
647     }
649     return (status);
652 /*
653  *  ======== formatNum ========
654  */
655 static Char *formatNum(Char *ptr, UInt32 un)
657     Int i = 0;
658     UInt32 n = un;
659     static const Char digtohex[] = "0123456789abcdef";
661     /* compute digits in number from right to left */
662     do {
663         *(--ptr) = digtohex[n & 0xf];
664         n = n >> 4;
665         ++i;
666     } while (n);
668     return (ptr);
671 /*
672  *  ======== freeInst ========
673  */
674 static Void freeInst(RMS_Obj *inst)
676     if (inst->name != NULL) {
677         Memory_free(inst->name, strlen(inst->name) + 1, NULL);
678     }
679     Memory_free(inst, sizeof (RMS_Obj), NULL);
682 /*
683  *  ======== getAlg ========
684  */
685 static RMS_Status getAlg(RMS_CmdSetGetAlgIn *cmdIn,
686         RMS_CmdSetGetAlgOut *cmdOut)
688     NODE_Desc *desc;
689     Int        len;
690     Int        nodeTabLen = 0;
691     Int        index = (Int)cmdIn->index;
693     Log_print2(Diags_USER5, "[+5] RMS getAlg> Enter(0x%x, 0x%x)",
694             (IArg)cmdIn, (IArg)cmdOut);
696     /* search the database of nodes for the given uuid       */
697     for (desc = RMS_nodeTab, nodeTabLen = 0; desc->name != NULL;
698          desc++, nodeTabLen++) {
699     }
701     if (index < nodeTabLen) {
702         desc = RMS_nodeTab + index;
703     }
704     else {
705         desc = Server_getNode(index - nodeTabLen);
706     }
708     if (desc == NULL) {
709         /* Can't find node with this index */
710         Log_print3(Diags_USER6, "[+6] RMS getAlg> Failed to find node [%d]. "
711                 "RMS_nodeTab len = [%d], number of dynamically added "
712                 "nodes = [%d]", (IArg)index, (IArg)nodeTabLen,
713                 (IArg)Server_getNumNodes());
714         return (RMS_EFAIL);
715     }
717     /* Copy alg name */
718     len = strlen(desc->name);
719     if (len >= RMS_MAXSTRLEN) {
720         /* Name is too big to copy */
721         Log_print1(Diags_USER7, "[+7] RMS getAlg> Length of alg name [%d] "
722                 "is too big to copy!", len);
723         return (RMS_EFAIL);
724     }
725     strncpy((Char *)cmdOut->name, desc->name, RMS_MAXSTRLEN);
727     /* Copy stub functions name */
728     len = strlen(desc->stubFxnsName);
729     if (len >= RMS_MAXSTRLEN) {
730         /* Name is too big to copy */
731         Log_print1(Diags_USER7, "[+7] RMS getAlg> Length of alg's stub "
732                 "functions name [%d] is too big to copy!", len);
733         return (RMS_EFAIL);
734     }
735     strncpy((Char *)cmdOut->stubFxns, desc->stubFxnsName, RMS_MAXSTRLEN);
737     /* Copy the typetab string */
738     len = strlen(desc->typeTab);
739     if (len >= RMS_MAXSTRLEN) {
740         /* Name is too big to copy */
741         Log_print1(Diags_USER7, "[+7] RMS getAlg> Length of alg's typeTab "
742                 "string [%d] is too big to copy!", len);
743         return (RMS_EFAIL);
744     }
745     strncpy((Char *)cmdOut->typeTab, desc->typeTab, RMS_MAXSTRLEN);
747     /* Copy the rest of the stuff */
748     cmdOut->uuid = desc->uuid;
749     cmdOut->rpcProtocolVersion = desc->rpcProtocolVersion;
751     return (RMS_EOK);
755 /*
756  *  ======== getMemStat ========
757  */
758 static RMS_Status getMemStat(RMS_CmdSetGetMemStatOut *out)
760     Int i;
761     ti_sdo_ce_osal_Memory_Stat statBuf;
762     UInt32 total = 0;
764     for (i = 0; i < MAXNUMSEGS; i++) {
765         if (Memory_segStat(i, &statBuf) != TRUE) {
766             break;
767         }
768         total += statBuf.used;
769     }
771     if (i == MAXNUMSEGS) {
772         /* Memory may be corrupted, print warning */
773         Log_print1(Diags_USER6, "[+6] RMS> getMemStat() finding > %d heaps!!!",
774                 (IArg)MAXNUMSEGS);
775     }
776     out->used = total;
778     checkStack();
780     return (RMS_EOK);
783 /*
784  *  ======== getMemRecs ========
785  */
786 static RMS_Status getMemRecs(RMS_CmdSetGetMemRecsIn *cmdIn,
787         RMS_CmdSetGetMemRecsOut *cmdOut)
789     RMS_Obj         *rmsInst = (RMS_Obj *)cmdIn->node;
790     Algorithm_Handle alg;
791     VISA_Handle      visa;
792     Int              maxRecs = cmdIn->numRecs;
793     IALG_MemRec     *memTab = (IALG_MemRec *)(cmdOut->memRecs);
794     RMS_Status       status = RMS_EOK;
796     visa = (VISA_Handle)NODE_getEnv(rmsInst->node);
797     alg = (Algorithm_Handle)VISA_getAlgorithmHandle(visa);
799     cmdOut->numRecs = Algorithm_getMemRecs(alg, memTab, maxRecs);
801     return (status);
804 /*
805  *  ======== getNumAlgs ========
806  */
807 static RMS_Status getNumAlgs(RMS_CmdSetGetNumAlgsOut *cmdOut)
809     NODE_Desc   *desc;
810     Int          numAlgs = 0;
812     Log_print1(Diags_USER5, "[+5] RMS getNumAlgs> Enter(0x%x)", (IArg)cmdOut);
814     /* Count the number of nodes in the database */
815     for (desc = RMS_nodeTab; desc->name != NULL; desc++, numAlgs++) {
816     }
818     /* Get the number of dynamically addes algs */
819     numAlgs += Server_getNumNodes();
821     cmdOut->numAlgs = numAlgs;
822     return (RMS_EOK);
825 /*
826  *  ======== getNumRecs ========
827  */
828 static RMS_Status getNumRecs(RMS_CmdSetGetNumRecsIn *cmdIn,
829         RMS_CmdSetGetNumRecsOut *cmdOut)
831     RMS_Obj         *rmsInst = (RMS_Obj *)cmdIn->node;
832     Algorithm_Handle alg;
833     VISA_Handle      visa;
834     RMS_Status       status = RMS_EOK;
836     visa = (VISA_Handle)NODE_getEnv(rmsInst->node);
837     alg = (Algorithm_Handle)VISA_getAlgorithmHandle(visa);
839     cmdOut->numRecs = Algorithm_getNumRecs(alg);
841     return (status);
844 /*
845  *  ======== getSegStat ========
846  */
847 static RMS_Status getSegStat(Int segId, RMS_CmdSetGetSegStatOut *out)
849     Memory_Stat statBuf;
851     if (Memory_segStat(segId, &statBuf) != TRUE) {
852         /* segId is out of range */
853         Log_print1(Diags_USER6,
854                 "[+6] RMS> getSegStat() segment [%d] not found", (IArg)segId);
855         return (RMS_ENOTFOUND);
856     }
857     else {
858         /* Copy to out */
859         out->base = statBuf.base;
860         out->size = statBuf.size;
861         out->used = statBuf.used;
862         out->maxBlockLen = statBuf.length;
864         /* Copy memory segment name */
865         // TODO: Find a way to get segment name.
866         if (statBuf.name != NULL) {
867             strncpy((Char *)out->name, statBuf.name, RMS_MAXSEGNAMELENGTH);
868             ((Char *)(out->name))[RMS_MAXSEGNAMELENGTH] = '\0';
869         }
870         else {
871             ((Char *)(out->name))[0] = 0;
872         }
873     }
875     return (RMS_EOK);
878 /*
879  *  ======== getCpuStat ========
880  */
881 static RMS_Status getCpuStat(RMS_CmdSetGetCpuStatOut *out)
883     out->cpuLoad = Global_getCpuLoad();
884     return (RMS_EOK);
887 #if 0
888 /*
889  *  ======== getTrace ========
890  */
891 static RMS_Status getTrace(RMS_CmdSetGetTraceOut *out, Int size)
893     UInt32  avail;
894     UInt32  lost;
896     Log_print2(Diags_USER5, "[+5] RMS getTrace> Enter(0x%x, 0x%x)",
897             (IArg)out, (IArg)size);
899     out->max = Trace_getSize();
900     out->size = Trace_fillBuf((Char *)out->buf, size, &avail, &lost);
901     out->avail = avail;
902     out->lost = lost;
904     return (RMS_EOK);
906 #endif
908 /*
909  *  ======== setTraceMask ========
910  */
911 static RMS_Status setTraceMask(RMS_CmdSetSetTraceMaskIn *in)
913     String mask = (String)in->traceMask;
915     mask[RMS_MAXTRACEMASKSIZE + 1] = '\0';
917     Log_print1(Diags_ENTRY, "[+E] setting trace mask to %s", (IArg)mask);
919     Diags_setMask(mask);
921     Global_setSpecialTrace(mask);
923     return (RMS_EOK);
926 /*
927  *  ======== getVers ========
928  */
929 static RMS_Status getVers(RMS_CmdSetGetVersOut *out)
931     extern String ti_sdo_ce__versionString;
933     if (ti_sdo_ce__versionString != NULL) {
934         /* The CE version */
935         strncpy((Char *)out->vers, ti_sdo_ce__versionString,
936             RMS_READBUFSIZE - 1);
937         ((Char *)out->vers)[RMS_READBUFSIZE - 1] = '\0';
939         /* The RMS Protocol version */
940         out->rpcMajor = RMS_VERSION_MAJOR;
941         out->rpcSource = RMS_VERSION_SOURCE;
942         out->rpcMinor = RMS_VERSION_MINOR;
944         return (RMS_EOK);
945     }
947     return (RMS_EFAIL);
950 /*
951  *  ======== mkInst ========
952  */
953 static RMS_Obj *mkInst(String nodeName, Int id)
955     Char idBuf[MAXNUMLEN + 1];  /* +1 for terminating '\0' */
956     String idString;
957     Int len;
958     RMS_Obj *inst;
960     inst = Memory_alloc(sizeof (RMS_Obj), NULL);
961     if (inst == NULL) {
962         return (NULL);
963     }
965     idBuf[MAXNUMLEN] = '\0';
966     idString = formatNum(idBuf + MAXNUMLEN, id);
968     len = strlen(nodeName) + strlen(idString) + 2;  /* +2 for '\0' and '#' */
969     inst->name = (String)Memory_alloc(len, NULL);
970     if (inst->name == NULL) {
971         freeInst(inst);
972         return (NULL);
973     }
975     strcpy(inst->name, nodeName);
976     strcat(inst->name, "#");
977     strcat(inst->name, idString);
979     return (inst);
982 /*
983  *  ======== processRmsCmd ========
984  */
985 static RMS_Status processRmsCmd(RMS_CmdBuf *cmdBuf, Int cmdBufSize)
987     Log_print3(Diags_ENTRY, "[+E] processRmsCmd(0x%x, %d): cmd = %d",
988             (IArg)cmdBuf, (IArg)cmdBufSize, (IArg)(cmdBuf->cmd));
990     switch (cmdBuf->cmd) {
991         case RMS_CREATENODE:
992             return createNode(&cmdBuf->data.createNodeIn,
993                                &cmdBuf->data.createNodeOut);
994         case RMS_STARTNODE:
995             return startNode(&cmdBuf->data.startNodeIn);
997         case RMS_DELETENODE:
998             return deleteNode(&cmdBuf->data.deleteNodeIn,
999                 &cmdBuf->data.deleteNodeOut);
1001         case RMS_GETMEMSTAT:
1002             return getMemStat(&cmdBuf->data.getMemStatOut);
1004         case RMS_GETNUMSEGS:
1005             cmdBuf->data.getNumSegsOut.numSegs = Memory_getNumHeaps();
1006             return (RMS_EOK);
1008         case RMS_GETSEGSTAT:
1009             return getSegStat((Int)(cmdBuf->data.getSegStatIn.segId),
1010                     &cmdBuf->data.getSegStatOut);
1012         case RMS_GETCPUSTAT:
1013             return getCpuStat(&cmdBuf->data.getCpuStatOut);
1015 #if 0
1016         case RMS_GETTRACE: {
1017             Int traceSize = cmdBufSize - (
1018                 (Char *)cmdBuf->data.getTraceOut.buf - (Char *)cmdBuf
1019             );
1020             Log_print2(Diags_ENTRY,
1021                     "[+E] remote time = 0x%x, trace buffer size = %d",
1022                     (IArg)(cmdBuf->data.getTraceIn.curTime), (IArg)traceSize);
1023             return getTrace(&cmdBuf->data.getTraceOut, traceSize);
1024         }
1025 #endif
1027         case RMS_SETTRACEMASK:
1028             return setTraceMask(&cmdBuf->data.setTraceMaskIn);
1030         case RMS_GETVERS:
1031             return getVers(&cmdBuf->data.getVersOut);
1033         case RMS_REDEFINEHEAP:
1034             return redefineHeap((String)(cmdBuf->data.redefineHeapIn.name),
1035                     -1, /* Redefine heap by name, not segid */
1036                     cmdBuf->data.redefineHeapIn.base,
1037                     cmdBuf->data.redefineHeapIn.size);
1039         case RMS_RELTRACETOKEN:
1040             traceTokenAvailable = TRUE;
1041             return (RMS_EOK);
1043         case RMS_REQTRACETOKEN:
1044             if (traceTokenAvailable == TRUE) {
1045                 traceTokenAvailable = FALSE;
1046                 return (RMS_EOK);
1047             }
1048             else {
1049                 return (RMS_ERESOURCE);
1050             }
1052         case RMS_RESTOREHEAP:
1053             return restoreHeap((String)(cmdBuf->data.redefineHeapIn.name));
1055         case RMS_WRITEWORD:
1056             *(Int *)(cmdBuf->data.writeWordIn.addr) =
1057                 (Int)cmdBuf->data.writeWordIn.value;
1058             return (RMS_EOK);
1060         case RMS_GETNUMMEMRECS:
1061             return getNumRecs(&cmdBuf->data.getNumRecsIn,
1062                                &cmdBuf->data.getNumRecsOut);
1064         case RMS_GETMEMRECS:
1065             return getMemRecs(&cmdBuf->data.getMemRecsIn,
1066                                &cmdBuf->data.getMemRecsOut);
1067         case RMS_GETALG:
1068             return (getAlg(&cmdBuf->data.getAlgIn, &cmdBuf->data.getAlgOut));
1070         case RMS_ADDALG:
1071             return (addAlg(&cmdBuf->data.addAlgIn, &cmdBuf->data.addAlgOut));
1073         case RMS_GETNUMALGS:
1074             return (getNumAlgs(&cmdBuf->data.getNumAlgsOut));
1076        case RMS_DETACH:
1077            detachFlag = 1;
1078            return (RMS_EOK);
1080        case RMS_QUIT:
1081            exitFlag = 1;
1082            return (RMS_EOK);
1084         default:
1085             return (RMS_EFAIL);
1086     }
1089 /*
1090  *  ======== redefineHeap ========
1091  *  Redefine the heap defined by either name (if not NULL), or by segId
1092  *  (if name is NULL).
1093  */
1094 static RMS_Status redefineHeap(String name, Int segId, UInt32 base,
1095         UInt32 size)
1097     Memory_Stat stat;
1098     Uint32      end = base + size - 1;
1099     Int         i;
1101     if (name != NULL) {
1102         if ((segId = Memory_getHeapId(name)) < 0) {
1103             Log_print1(Diags_USER6, "[+6] RMS> redefineHeap() heap %s not "
1104                     "found.", (IArg)name);
1105             return (RMS_ENOTFOUND);
1106         }
1107     }
1109     Assert_isTrue(Memory_segStat(segId, &stat), (Assert_Id)NULL);
1111     /*
1112      *  Check for memory overlap with another heap, if size > 0.
1113      *  (This check still does not guarentee that [base, base + size - 1]
1114      *  is a valid memory segment.)
1115      */
1116     if (size > MINHEAPSIZE) {
1117         for (i = 0; Memory_segStat(i, &stat); i++) {
1118             if (i == segId) {
1119                 continue;
1120             }
1122             if (((stat.base <= base) && (base < stat.base + stat.size)) ||
1123                     ((base <= stat.base) && (stat.base <= end))) {
1124                 /* Memory overlap */
1125                 Log_print2(Diags_USER6, "[+6] RMS> redefineHeap() cannot "
1126                         "redefine heap %s, since this would cause overlap "
1127                         "with heap %s", (IArg)name, (IArg)stat.name);
1128                 return (RMS_EINVAL);
1129             }
1130         }
1131     }
1132     else {
1133         Log_print3(Diags_USER6, "[+6] RMS> redefineHeap() cannot redefine "
1134                 "heap %s, since new size (0x%x) is too small. Size should "
1135                 "be at least %d.",
1136                 (IArg)name, (IArg)size, (IArg)MINHEAPSIZE);
1137         return (RMS_EINVAL);
1138     }
1140     if (!Memory_redefine(segId, base, size)) {
1141         /*
1142          *  Should not get here unless memory is in use, since we've
1143          *  already checked that segment exists.
1144          */
1145         return (RMS_EFREE);
1146     }
1148     return (RMS_EOK);
1151 /*
1152  *  ======== restoreHeap ========
1153  */
1154 static RMS_Status restoreHeap(String name)
1156     Int         segId;
1158     if ((segId = Memory_getHeapId(name)) < 0) {
1159         Log_print1(Diags_USER6, "[+6] RMS> restoreHeap() heap %s not found",
1160                 (IArg)name);
1161         return (RMS_ENOTFOUND);
1162     }
1164     if (!Memory_restoreHeap(segId)) {
1165         /*
1166          *  Should not get here unless memory is in use, since we've
1167          *  already checked that segment exists.
1168          */
1169         return (RMS_EFREE);
1170     }
1172     return (RMS_EOK);