462b3d95489f388b04bc657d3b07fef523061ec9
[mfp/cedev.git] / packages / ti / sdo / ce / ipc / dsplink / Processor_dsplink.c
1 /*
2  * Copyright (c) 2013, 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  *  ======== Processor_dsplink.c ========
35  */
37 /* This define must precede inclusion of any xdc header files */
38 #define Registry_CURDESC ti_sdo_ce_ipc_processor_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 <ti/sdo/ce/osal/Memory.h>
47 #include <ti/sdo/ce/osal/Global.h>
48 #include <xdc/runtime/knl/Thread.h>
49 #include <xdc/runtime/Gate.h>
50 #include <xdc/runtime/knl/GateThread.h>
51 #include <xdc/runtime/knl/SemThread.h>
53 #include <ti/sdo/ce/global/CESettings.h>
55 #include <ti/sdo/linuxutils/cmem/include/cmem.h>
57 #include <ti/sdo/ce/ipc/Comm.h>
58 #include <ti/sdo/ce/ipc/Processor.h>
60 #include <ti/ipc/HeapBufMP.h>
61 #include <ti/ipc/Ipc.h>
62 #include <ti/ipc/MessageQ.h>
63 #include <ti/ipc/MultiProc.h>
64 #include <ti/ipc/SharedRegion.h>
65 #include <ti/syslink/ProcMgr.h>
66 #include <ti/syslink/IpcHost.h>    /* For SysLink-specific Ipc_control() */
67 #include <ti/syslink/SysLink.h>
69 #undef Processor_Handle
71 #include <stdio.h>  /* for printf() and getchar() */
72 #include <string.h>
73 #include <stdlib.h>
74 #include <sys/types.h>
75 #include <sys/stat.h>
77 #include <errno.h>
80 #define Processor_defaultSharedRegionId ti_sdo_ce_ipc_dsplink__Processor_defaultSharedRegionId
81 #define Processor_defaultHeapId ti_sdo_ce_ipc_dsplink__Processor_defaultHeapId
82 #define Processor_defaultNumMsgs ti_sdo_ce_ipc_dsplink__Processor_defaultNumMsgs
83 #define Processor_defaultMsgSize ti_sdo_ce_ipc_dsplink__Processor_defaultMsgSize
84 #define Processor_commDescs ti_sdo_ce_ipc_dsplink__Processor_commDescs
85 #define Processor_numCommDescs ti_sdo_ce_ipc_dsplink__Processor_numCommDescs
86 #define Processor_loadSlave ti_sdo_ce_ipc_dsplink__Processor_loadSlave
88 /* Generated by .xdt file */
89 extern Int16 Processor_defaultSharedRegionId;
90 extern Int16 Processor_defaultHeapId;
91 extern Int32 Processor_defaultNumMsgs;
92 extern Int32 Processor_defaultMsgSize;
93 extern Processor_CommDesc Processor_commDescs[];
94 extern UInt32 Processor_numCommDescs;
95 extern Bool Processor_loadSlave;
98 /*
99  *  ======== Processor_Obj ========
100  */
101 typedef struct Processor_Obj {
102     Int               cpuId;
103     UInt16            heapId;
104     String            imageName;
105     String            memMapName;
106     Bool              loaded;
107     Processor_Attrs   attrs;
108     ProcMgr_Handle    procMgrH;
109     HeapBufMP_Handle  heapH;
110     UInt32            fileId;
111     Int32             loadCallBackStatus;
112     Int32             startCallBackStatus;
113     Bool              useExtLoader;
114 } Processor_Obj;
116 /*
117  *  ======== Processor_ATTRS ========
118  */
119 Processor_Attrs Processor_ATTRS = {
120     "dsp0",     /* cpu ID */
121     0,          /* argc */
122     NULL,       /* argv */
123     FALSE,      /* useExtLoader */
124 };
126 #define NONE    0
127 #define CREATE  1
128 #define DELETE  2
129 #define EXIT    3
131 #define SUCCESS 1
132 #define FAILURE 2
134 /*
135  *  ======== CmdObj ========
136  */
137 typedef struct CmdObj {
138     Thread_Handle     dproc;
139     Processor_Handle  proc;
140     Int               cmdId;
141     Int               reply;
143     SemThread_Handle  cmdPresent;
144     SemThread_Handle  replyPresent;
145     GateThread_Handle gate;
146 } CmdObj;
149 /*
150  *  Memory map entry format in map text file.
151  */
152 typedef struct MapStruct {
153     UInt32 slaveVirt;
154     UInt32 slavePhys;
155     UInt32 masterPhys;
156     UInt32 size;
157     UInt32 mapMask;
158     int isCached;
159 } MapStruct;
161 /* REMINDER: if you add an initialized static var, reinitialize it at cleanup */
163 static CmdObj dcmd = {NULL, NULL, NONE, NONE, NULL, NULL, NULL};
165 static Bool mapByFile(ProcMgr_Handle handle, String mapFile, UInt16 procId,
166         int mapFlag);
167 static int initFromLine(char *line, MapStruct *mapStruct);
168 static int isMapLine(char *line, UInt16 procId);
170 static Void cleanup(Void);
171 static Int daemon(Void);
172 static Int doCmd(Int cmdId, Processor_Handle proc);
173 static Int getCmd(Processor_Handle *proc);
174 static Bool procCreate(Processor_Handle proc);
175 static Void procDelete(Processor_Handle proc);
176 static Void putReply(Int status);
178 static Int16 perCoreHeapId(UInt32 coreId);
179 static Int32 perCoreNumMsgs(UInt32 coreId);
180 static Int32 perCoreMsgSize(UInt32 coreId);
181 static Int16 perCoreSharedRegionId(UInt32 coreId);
182 static Bool perCoreUserCreatedHeapFlag(UInt32 coreId);
184 Registry_Desc ti_sdo_ce_ipc_processor_desc;
186 static Int regInit = 0;     /* Registry_addModule() called */
187 static Int curInit = 0;     /* module init counter */
189 static HeapBufMP_Handle defaultHeapH = NULL;
190 static Int defaultHeapRefCount = 0;
192 /*
193  *  ======== Processor_create ========
194  */
195 Processor_Handle Processor_create(String imageName, String memMap,
196     Processor_Attrs *attrs)
198     Processor_Handle proc = NULL;
199     struct stat statBuf;
201     Assert_isTrue(curInit == TRUE, (Assert_Id)NULL);
203     Log_print3(Diags_ENTRY, "[+E] Processor_create> "
204             "Enter(imageName='%s', memMap='%s', attrs=0x%x)",
205             (IArg)imageName, (IArg)memMap, (IArg)attrs);
207     if (attrs == NULL) {
208         attrs = &Processor_ATTRS;
209     }
211     if (stat(imageName, &statBuf) != 0) {
212         Log_print1(Diags_USER7, "[+7] Processor_create> "
213                 "ERROR: cannot access file %s", (IArg)imageName);
214         return (NULL);
215     }
217     proc = Memory_alloc(sizeof(Processor_Obj), NULL);
218     if (proc == NULL) {
219         Log_print0(Diags_USER7, "[+7] Processor_create> "
220                 "ERROR: Memory_alloc failed");
221         return (NULL);
222     }
224     proc->attrs = *attrs;
225     proc->imageName = imageName;
226     proc->memMapName = memMap;
227     proc->loaded = FALSE;
228     proc->fileId = 0xffffffff;
229     proc->heapH = NULL;
230     proc->procMgrH = NULL;
231     proc->heapId = Processor_INVALID;
232     proc->loadCallBackStatus = -1;
233     proc->startCallBackStatus = -1;
234     proc->useExtLoader = attrs->useExtLoader;
236     if (doCmd(CREATE, proc) != SUCCESS) {
237         Processor_delete(proc);
238         return (NULL);
239     }
240     proc->loaded = TRUE;
242     Log_print1(Diags_EXIT, "[+X] Processor_create> return (0x%x)", (IArg)proc);
244     return (proc);
248 /*
249  *  ======== Processor_delete ========
250  */
251 Void Processor_delete(Processor_Handle proc)
253     Assert_isTrue(curInit == TRUE, (Assert_Id)NULL);
255     Log_print1(Diags_ENTRY, "[+E] Processor_delete> Enter(proc=0x%x)",
256             (IArg)proc);
258     if (proc != NULL) {
259         if (proc->loaded == TRUE && dcmd.dproc != NULL) {
260             doCmd(DELETE, proc);
261         }
263         Log_print1(Diags_USER1,
264                 "[+1] Processor_delete(0x%x) freeing object ...", (IArg)proc);
265         Memory_free(proc, sizeof(Processor_Obj), NULL);
266     }
268     Log_print0(Diags_EXIT, "[+X] Processor_delete> return");
272 /*
273  *  ======== Processor_init ========
274  */
275 Void Processor_init(Void)
277     GateThread_Params params;
278     Registry_Result   result;
280     /*
281      *  No need to reference count for Registry_addModule(), since there
282      *  is no way to remove the module.
283      */
284     if (regInit == 0) {
285         /* Register this module for logging */
286         result = Registry_addModule(&ti_sdo_ce_ipc_processor_desc,
287                 Processor_MODNAME);
288         Assert_isTrue(result == Registry_SUCCESS, (Assert_Id)NULL);
290         if (result == Registry_SUCCESS) {
291             /* Set the diags mask to the CE default */
292             CESettings_init();
293             CESettings_setDiags(Processor_MODNAME);
294         }
295         regInit = 1;
296     }
298     if (curInit != TRUE) {
299         curInit = TRUE;
301         /* Semaphore with count 0, will be posted when a command is present */
302         dcmd.cmdPresent = SemThread_create(0, NULL, NULL);
304         /* Semaphore with count 0, will be posted when reply is ready */
305         dcmd.replyPresent = SemThread_create(0, NULL, NULL);
307         /*
308          *  Create lock to allow only one thread at a time to send command
309          *  to the daemon.
310          */
311         GateThread_Params_init(&params);
312         dcmd.gate = GateThread_create(&params, NULL);
314         if ((dcmd.cmdPresent == NULL) || (dcmd.replyPresent == NULL) ||
315                 (dcmd.gate == NULL)) {
316             // TODO: Shouldn't we abort?
317             Log_print0(Diags_USER7, "[+7] Processor_init> ERROR: cannot"
318                     " create semaphores or lock");
319         }
321         Log_print0(Diags_USER2, "[+2] Processor_init> SysLink_setup()...");
323         SysLink_setup();
324         Log_print0(Diags_USER2, "[+2] Processor_init> "
325                 "... SysLink_setup() done");
327         if ((dcmd.dproc = Thread_create((Thread_RunFxn)daemon, NULL, NULL))
328                 == NULL) {
329             Log_print0(Diags_USER7, "[+7] Processor_init> "
330                     "ERROR: cannot create DSP daemon");
331         }
333         if (Thread_start(NULL) != TRUE) {
334             Log_print0(Diags_USER7, "[+7] Processor_init> "
335                     "ERROR: cannot start threads");
336         }
338         Global_atexit((Fxn)cleanup);
339     }
342 /*
343  *  ======== Processor_getCoreName ========
344  */
345 String Processor_getCoreName(UInt32 id)
347     UInt16 mpId = (UInt16)id;
349     return(MultiProc_getName(mpId));
353 /*
354  *  ======== Processor_getCoreId ========
355  */
356 UInt32 Processor_getCoreId(String name)
358     UInt16 coreId = MultiProc_getId(name);
360     if (coreId == MultiProc_INVALIDID) {
361         return (Processor_INVALIDID);
362     }
363     else {
364         return ((UInt32)coreId);
365     }
368 /*
369  *  ======== Processor_getNumProcs ========
370  */
371 UInt32 Processor_getNumProcs(Void)
373     return(MultiProc_getNumProcessors());
376 /*
377  *  ======== Processor_myCoreId ========
378  */
379 UInt32 Processor_myCoreId(Void)
381     return(MultiProc_self());
384 /*
385  *  ======== Processor_getHeapId ========
386  */
387 UInt16 Processor_getHeapId(UInt32 coreId)
389     Int16 heapId;
391     heapId = perCoreHeapId(coreId);
392     if (heapId == Processor_INVALID) {
393         heapId = Processor_defaultHeapId;
394     }
396     return(heapId);
399 /*
400  *  ======== Processor_getMsgSize ========
401  */
402 UInt32 Processor_getMsgSize(UInt32 coreId)
404     Int32 msgSize;
406     msgSize = perCoreMsgSize(coreId);
407     if (msgSize == Processor_INVALID) {
408         msgSize = Processor_defaultMsgSize;
409     }
411     return(msgSize);
414 /*
415  *  ======== Processor_getNumMsgs ========
416  */
417 UInt32 Processor_getNumMsgs(UInt32 coreId)
419     Int32 numMsgs;
421     numMsgs = perCoreNumMsgs(coreId);
422     if (numMsgs == Processor_INVALID) {
423         numMsgs = Processor_defaultNumMsgs;
424     }
426     return(numMsgs);
429 /*
430  *  ======== Processor_getSharedRegionId ========
431  */
432 UInt16 Processor_getSharedRegionId(UInt32 coreId)
434     Int16 sharedRegionId;
436     sharedRegionId = perCoreSharedRegionId(coreId);
437     if (sharedRegionId == Processor_INVALID) {
438         sharedRegionId = Processor_defaultSharedRegionId;
439     }
441     return(sharedRegionId);
444 /*
445  *  ======== Processor_getUserCreatedHeapFlag ========
446  */
447 Bool Processor_getUserCreatedHeapFlag(UInt32 coreId)
449     return(perCoreUserCreatedHeapFlag(coreId));
452 static Int16 perCoreHeapId(UInt32 coreId)
454     if (coreId == MultiProc_INVALIDID ||
455         coreId >= Processor_numCommDescs) {
457         return(Processor_INVALID);
458     }
460     return(Processor_commDescs[coreId].heapId);
463 static Int32 perCoreMsgSize(UInt32 coreId)
465     if (coreId == MultiProc_INVALIDID ||
466         coreId >= Processor_numCommDescs) {
468         return(Processor_INVALID);
469     }
471     return(Processor_commDescs[coreId].msgSize);
474 static Int32 perCoreNumMsgs(UInt32 coreId)
476     if (coreId == MultiProc_INVALIDID ||
477         coreId >= Processor_numCommDescs) {
479         return(Processor_INVALID);
480     }
482     return(Processor_commDescs[coreId].numMsgs);
485 static Int16 perCoreSharedRegionId(UInt32 coreId)
487     if (coreId == MultiProc_INVALIDID ||
488         coreId >= Processor_numCommDescs) {
490         return(Processor_INVALID);
491     }
493     return(Processor_commDescs[coreId].sharedRegionId);
496 static Bool perCoreUserCreatedHeapFlag(UInt32 coreId)
498     if (coreId == MultiProc_INVALIDID ||
499         coreId >= Processor_numCommDescs) {
501         return(FALSE);
502     }
504     return(Processor_commDescs[coreId].userCreatedHeap);
509 /*
510  *  ======== Processor_wait ========
511  */
512 Int Processor_wait(Processor_Handle proc)
514     return(-1);
517 /*
518  *  ======== cleanup ========
519  */
520 static Void cleanup(Void)
522     static CmdObj dcmdInit = {NULL, NULL, NONE, NONE, NULL, NULL, NULL};
524     if (curInit != FALSE) {
525         curInit = FALSE;
526         if (dcmd.dproc != NULL) {
527             doCmd(EXIT, NULL);
528             // Thread_join(dcmd.dproc);
529             Thread_delete(&dcmd.dproc); /* will do join first? */
530             dcmd.dproc = NULL;
531         }
533         Log_print0(Diags_USER2, "[+2] Processor cleanup()> "
534                 "SysLink_destroy()...");
535         SysLink_destroy();
536         Log_print0(Diags_USER2, "[+2] Processor cleanup()> "
537                 "... SysLink_destroy() complete");
539         if (dcmd.cmdPresent != NULL) {
540             SemThread_delete(&dcmd.cmdPresent);
541             dcmd.cmdPresent = NULL;
542         }
544         if (dcmd.replyPresent != NULL) {
545             SemThread_delete(&dcmd.replyPresent);
546             dcmd.replyPresent = NULL;
547         }
549         if (dcmd.gate != NULL) {
550             GateThread_delete(&dcmd.gate);
551             dcmd.gate = NULL;
552         }
554         dcmd = dcmdInit;
555     }
558 /*
559  *  ======== procCreate ========
560  */
561 static Bool procCreate(Processor_Handle proc)
563     Int status = 0;
564     Bool retVal;
565     ProcMgr_AttachParams attachParams;
566     ProcMgr_StartParams  startParams;
567     ProcMgr_State        state;
568     ProcMgr_AddrInfo     CMEMAddrInfo;
569     HeapBufMP_Params heapP;
570     CMEM_BlockAttrs cmemBlockAttrs;
571     Int blockNum;
572     Int nCMEMBlocks;
573     Bool createAndRegisterHeap;
574     Int16 heapId;
575     UInt16 regionId;
576     UInt32 numMsgs;
577     UInt32 msgSize;
578     Char heapName[32];
580     Log_print1(Diags_ENTRY, "[+E] Processor_create_d> Enter(proc=0x%x)",
581             (IArg)proc);
583     /* Create and initialize the PROC object */
584     Log_print1(Diags_USER2, "[+2] Processor_create_d> "
585     "Retrieving CPU ID for '%s'...", (IArg)(proc->attrs.cpuId));
587     proc->cpuId = Processor_getCoreId(proc->attrs.cpuId);
588     if (proc->cpuId < 0) {
589         Log_print1(Diags_USER7, "[+7] Processor_create_d> "
590                "Processor_getCoreId() failed: %d", proc->cpuId);
591         goto fail;
592     }
594     /* Open DSP ProcMgr */
595     Log_print2(Diags_USER2, "[+2] Processor_create_d> "
596            "Opening %s ProcMgr for cpuId %d...",
597            (IArg)proc->attrs.cpuId, proc->cpuId);
598     status = ProcMgr_open(&proc->procMgrH, proc->cpuId);
600     if (status < 0) {
601         Log_print1(Diags_USER7, "[+7] Processor_create_d> "
602                "ProcMgr_open() failed: %d", (IArg)status);
603         goto fail;
604     }
606     /* Attach the DSP */
607     Log_print1(Diags_USER2, "[+2] Processor_create_d> "
608            "Attaching to %s...", (IArg)proc->attrs.cpuId);
610     if (proc->useExtLoader == FALSE) {
611         /* We load the slave */
612         ProcMgr_getAttachParams(NULL, &attachParams);
613         status = ProcMgr_attach(proc->procMgrH, &attachParams);
614         if (status < 0) {
615             Log_print1(Diags_USER7, "[+7] Processor_create_d> "
616                     "ProcMgr_attach() failed: %d", (IArg)status);
617             goto fail;
618         }
620         /* Map slave memory */
621         if (!mapByFile(proc->procMgrH, proc->memMapName, proc->cpuId, TRUE)) {
622             Log_print0(Diags_USER6, "Processor_create_d> mapByFile() failed!");
623         }
625         /* Load the executable on the DSP */
626         Log_print3(Diags_USER2, "[+2] Processor_create_d> "
627                 "Loading %s on %s (%d args)...",
628                 (IArg)(proc->imageName), (IArg)(proc->attrs.cpuId),
629                 (IArg)(proc->attrs.argc));
631         status = ProcMgr_load(proc->procMgrH, proc->imageName,
632                 proc->attrs.argc, proc->attrs.argv, NULL, &proc->fileId);
633         if (status < 0) {
634             Log_print1(Diags_USER7, "[+7] Processor_create_d> "
635                     "ProcMgr_load() failed: %d", status);
636             goto fail;
637         }
639         /* temporary: to be done by SysLink in the future */
640         Log_print0(Diags_USER1, "[+2] Processor_create_d> "
641                 "calling Ipc_control(LOADCALLBACK)...");
642         status = Ipc_control(proc->cpuId, Ipc_CONTROLCMD_LOADCALLBACK, NULL);
643         Log_print1(Diags_USER1, "[+2] Processor_create_d> "
644                 "Ipc_control(LOADCALLBACK) status: %d", (IArg)status);
646         /* Start execution on DSP */
647         Log_print1(Diags_USER2, "[+2] Processor_create_d> Starting %s ...",
648                 (IArg)proc->attrs.cpuId);
650         ProcMgr_getStartParams(proc->procMgrH, &startParams);
651         status = ProcMgr_start(proc->procMgrH, &startParams);
652         if (status < 0) {
653             Log_print1(Diags_USER7, "Processor_create_d> "
654                     "ProcMgr_start() failed: %d", status);
655             goto fail;
656         }
657     } // if (proc->useExtLoader == FALSE)
658     else {
659         /* Check the state of the processor to make sure it's really running */
660         state = ProcMgr_getState(proc->procMgrH);
661         if (state != ProcMgr_State_Running) {
662             Log_print1(Diags_USER7, "Processor_create_d> Invalid processor "
663                     "state [%d].", state);
664             goto fail;
665         }
667         Log_print0(Diags_USER1, "[+2] Processor_create_d> "
668                 "calling Ipc_control(LOADCALLBACK)...");
669         status = Ipc_control(proc->cpuId, Ipc_CONTROLCMD_LOADCALLBACK, NULL);
670         proc->loadCallBackStatus = status;
671         Log_print1(Diags_USER1, "[+2] Processor_create_d> "
672                 "Ipc_control(LOADCALLBACK) status: %d", (IArg)status);
674         if (status < 0) {
675             Log_print1(Diags_USER7, "Processor_create_d> "
676                     "Ipc_control(LOADCALLBACK) failed: %d", status);
677             goto fail;
678         }
679     }
681     status = Ipc_control(proc->cpuId, Ipc_CONTROLCMD_STARTCALLBACK, NULL);
682     proc->startCallBackStatus = status;
683     Log_print1(Diags_USER1, "[+2] Processor_create_d> "
684             "Ipc_control(STARTCALLBACK) status: %d", (IArg)status);
685     if (status < 0) {
686         Log_print1(Diags_USER7, "Processor_create_d> "
687                 "Ipc_control(STARTCALLBACK) failed: %d", status);
688         goto fail;
689     }
692     /* get user-specified heapId */
693     heapId = perCoreHeapId(proc->cpuId);
694     createAndRegisterHeap = FALSE;
696     if (heapId == Processor_INVALID) {
697         /* runtime validation of user configuration */
698         if (perCoreUserCreatedHeapFlag(proc->cpuId) == TRUE ||
699                 perCoreNumMsgs(proc->cpuId) != Processor_INVALID ||
700                 perCoreMsgSize(proc->cpuId) != Processor_INVALID ||
701                 perCoreSharedRegionId(proc->cpuId) != Processor_INVALID) {
703             Log_print1(Diags_USER7, "[+7] Processor_create_d> "
704                     "Invalid heap configuration for core %d: "
705                     "attempting to set other Processor_CommDesc "
706                     "elements while Processor_CommDesc.heapId is "
707                     "undefined",
708                     proc->cpuId);
710             goto fail;
711         }
713         /* will return default heapId since user didn't specify */
714         heapId = Processor_getHeapId(proc->cpuId);
716         if (defaultHeapRefCount++ == 0) {
717             createAndRegisterHeap = TRUE;
719             /* tell code below to record heapH in defaultHeapH */
720             defaultHeapH = (HeapBufMP_Handle)-1;
721         }
722     }
723     else {
724         if (perCoreUserCreatedHeapFlag(proc->cpuId) == FALSE) {
725             createAndRegisterHeap = TRUE;
726         }
727     }
729     if (createAndRegisterHeap) {
730         /* create a heap for message queue usage */
732         /* get either user-config'ed or module default */
733         numMsgs = Processor_getNumMsgs(proc->cpuId);
734         msgSize = Processor_getMsgSize(proc->cpuId);
735         regionId = Processor_getSharedRegionId(proc->cpuId);
737         HeapBufMP_Params_init(&heapP);
738         heapP.numBlocks = numMsgs;
739         heapP.blockSize = msgSize;
740         heapP.sharedAddr = NULL;
741         heapP.regionId = regionId;
742         if (defaultHeapH == (HeapBufMP_Handle)-1) {
743             sprintf(heapName, "CE-default");
744         }
745         else {
746             sprintf(heapName, "CE<->Svr%d", proc->cpuId);
747         }
748         heapP.name = heapName;
750         Log_print2(Diags_USER1, "[+2] Processor_create_d> "
751                 "calling HeapBufMP_create(): nblocks %d, blocksize 0x%x",
752                 heapP.numBlocks, heapP.blockSize);
754         proc->heapH = HeapBufMP_create(&heapP);
756         if (proc->heapH == NULL) {
757             Log_print0(Diags_USER7, "[+7] Processor_create_d> "
758                     "HeapBufMP_create failed");
759             goto fail;
760         }
762         if (defaultHeapH == (HeapBufMP_Handle)-1) {
763             /* we've just created the module default heap singleton */
764             defaultHeapH = proc->heapH;
765         }
767         /* register this heap with MessageQ */
768         Log_print2(Diags_USER1, "[+2] Processor_create_d> "
769                 "MessageQ_registerHeap(heapH: 0x%x, heapId: %d)",
770                 (IArg)(proc->heapH), (IArg)heapId);
772         if (MessageQ_registerHeap((Ptr)(proc->heapH), heapId) !=
773                     MessageQ_S_SUCCESS) {
774         Log_print1(Diags_USER7, "[+7] Processor_create_d> "
775                 "MessageQ_registerHeap() failed for heapId %d", heapId);
777         goto fail;
778         }
779     }
780     else {
781         /*
782          *  createAndRegisterHeap == FASLE
783          *  If using the default heap, need to set proc->heapH for use by
784          *  procDelete().
785          */
786         if (heapId == Processor_defaultHeapId) {
787             proc->heapH = defaultHeapH;
788         }
789     }
791     proc->heapId = heapId;
793     blockNum = 0;
794     nCMEMBlocks = 0;
795     status = CMEM_getNumBlocks(&nCMEMBlocks);
796     if (status != 0) {
797         Log_print1(Diags_USER2, "[+2] Processor_create_d> "
798                 "CMEM_getNumBlocks() failed, not registering: %d",
799                 status);
800     }
802     while (blockNum < nCMEMBlocks) {
803         status = CMEM_getBlockAttrs(blockNum, &cmemBlockAttrs);
804         if (status != 0) {
805             Log_print2(Diags_USER7, "[+7] Processor_create_d> "
806                     "CMEM_getBlockAttrs(%d) failed: %d",
807                     blockNum, status);
809             goto fail;
810         }
812         CMEMAddrInfo.addr[ProcMgr_AddrType_MasterPhys] =
813                 cmemBlockAttrs.phys_base;
814         CMEMAddrInfo.addr[ProcMgr_AddrType_SlaveVirt] =
815                 cmemBlockAttrs.phys_base;
816         CMEMAddrInfo.size = cmemBlockAttrs.size;
817         CMEMAddrInfo.isCached = FALSE;
819         Log_print3(Diags_USER1, "[+1] Processor_create_d> CMEM block "
820                 "#%d found, doing ProcMgr_map(0x%x, 0x%x)...", blockNum,
821                 (IArg)cmemBlockAttrs.phys_base,
822                 (IArg)cmemBlockAttrs.size);
824         status = ProcMgr_map(proc->procMgrH, ProcMgr_SLAVEVIRT, &CMEMAddrInfo,
825                 ProcMgr_AddrType_MasterPhys);
826         if (status < 0) {
827             Log_print1(Diags_USER7, "[+7] Processor_create_d> "
828                     "ProcMgr_map() failed: %d", status);
829             goto fail;
830         }
832         if (CMEMAddrInfo.addr[ProcMgr_AddrType_SlaveVirt] !=
833                 cmemBlockAttrs.phys_base) {
834             Log_print2(Diags_USER1, "[+2] Processor_create_d> "
835                     "mapped CMEM slave virtual address 0x%x doesn't "
836                     "match expected value 0x%x",
837                     CMEMAddrInfo.addr[ProcMgr_AddrType_SlaveVirt],
838                     cmemBlockAttrs.phys_base);
839         }
841         blockNum++;
842     }
844     if (Global_getenv("CE_DSPDEBUG") != NULL) {
845         printf("Codec Engine system message (b/c CE_DSPDEBUG=1) : %s image "
846                "loaded and started, press Enter to continue: ",
847                proc->attrs.cpuId);
848         getchar();
849     }
851     retVal = TRUE;
852     goto procCreate_return;
854     /* TODO:[4] should try those asyncErrorHandlers that link supports?
855      * (MSGQ_SetErrorHandler)
856      */
858 fail:
859     Log_print3(Diags_USER7, "[+7] Processor_create_d> "
860             "Loading and starting %s server '%s' FAILED, status=[0x%x]",
861             (IArg)proc->attrs.cpuId, (IArg)proc->imageName, status);
863     procDelete(proc);
865     retVal = FALSE;
867 procCreate_return:
869     Log_print1(Diags_USER2, "[+2] Processor_create_d> return (%d)",
870             (IArg)retVal);
872     return (retVal);
875 /*
876  *  ======== procDelete ========
877  */
878 static Void procDelete(Processor_Handle proc)
880     Int status = 0;
881     Int16 heapId;
882     Bool unregisterAndDeleteHeap;
883     ProcMgr_AddrInfo CMEMAddrInfo;
884     CMEM_BlockAttrs cmemBlockAttrs;
885     Int blockNum;
886     Int nCMEMBlocks;
888     Log_print1(Diags_ENTRY, "[+E] Processor_delete_d> Enter (proc=0x%x)",
889             (IArg)proc);
891     if (proc == NULL) {
892         goto procDelete_return;
893     }
895     /* close tranport and stop DSP, detach, destroy */
896     /* unregister this heap with MessageQ */
898     if (proc->startCallBackStatus >= 0) {
899         blockNum = 0;
900         nCMEMBlocks = 0;
901         status = CMEM_getNumBlocks(&nCMEMBlocks);
902         if (status != 0) {
903             Log_print1(Diags_USER2, "[+2] Processor_delete_d> "
904                     "CMEM_getNumBlocks() failed: %d",
905                     status);
906         }
908         while (blockNum < nCMEMBlocks) {
909             status = CMEM_getBlockAttrs(blockNum, &cmemBlockAttrs);
910             if (status != 0) {
911                 Log_print2(Diags_USER7, "[+7] Processor_delete_d> "
912                         "CMEM_getBlockAttrs(%d) failed: %d",
913                         blockNum, status);
915                 goto cmemDone;
916             }
918             CMEMAddrInfo.addr[ProcMgr_AddrType_MasterPhys] =
919                 cmemBlockAttrs.phys_base;
920             CMEMAddrInfo.addr[ProcMgr_AddrType_SlaveVirt] =
921                 cmemBlockAttrs.phys_base;
922             CMEMAddrInfo.size = cmemBlockAttrs.size;
923             CMEMAddrInfo.isCached = FALSE;
925             Log_print3(Diags_USER1, "[+1] Processor_delete_d> CMEM block "
926                     "#%d found, doing ProcMgr_unmap(0x%x, 0x%x)...", blockNum,
927                     (IArg)cmemBlockAttrs.phys_base,
928                     (IArg)cmemBlockAttrs.size);
930             status = ProcMgr_unmap(proc->procMgrH, ProcMgr_SLAVEVIRT,
931                     &CMEMAddrInfo,
932                     ProcMgr_AddrType_MasterPhys);
933             if (status < 0) {
934                 Log_print1(Diags_USER7, "[+7] Processor_delete_d> "
935                         "ProcMgr_unmap() failed: %d", status);
936                 goto cmemDone;
937             }
939             blockNum++;
940         }
942 cmemDone:
943         Log_print2(Diags_USER7, "[+2] Processor_delete_d> "
944                 "defaultHeapH: 0x%x, proc->heapH: 0x%x", (IArg)defaultHeapH,
945                 (IArg)proc->heapH);
946         if (proc->heapH != NULL) {
947             unregisterAndDeleteHeap = FALSE;
948             if (proc->heapH == defaultHeapH) {
949                 Log_print1(Diags_USER1, "[+1] Processor_delete_d> "
950                         "defaultHeapRefCount = %d",
951                         (IArg)defaultHeapRefCount);
952                 if (--defaultHeapRefCount == 0) {
953                     /* this is the last one using the default heap */
954                     unregisterAndDeleteHeap = TRUE;
955                 }
956             }
957             else {
958                 unregisterAndDeleteHeap = TRUE;
959             }
961             if (unregisterAndDeleteHeap) {
962                 heapId = proc->heapId;
963                 Log_print1(Diags_USER1, "[+1] Processor_delete_d> "
964                         "unregisterAndDeleteHeap, heapId = %d", (IArg)heapId);
965                 if (heapId != Processor_INVALID) {
966                     Log_print1(Diags_USER1, "[+1] Processor_delete_d> "
967                             "MessageQ_unregisterHeap(heapId: %d)",
968                             (IArg)heapId);
970                     if (MessageQ_unregisterHeap(heapId) !=MessageQ_S_SUCCESS) {
971                         Log_print1(Diags_USER7, "[+7] Processor_delete_d> "
972                                 "MessageQ_unregisterHeap(heapId: %d) failed",
973                                 heapId);
974                     }
975                 }
977                 /* delete heap used by message queue */
978                 Log_print1(Diags_USER1, "[+1] Processor_delete_d> "
979                         "calling HeapBufMP_delete(heapH: 0x%x)",
980                         (IArg)(proc->heapH));
982                 HeapBufMP_delete(&proc->heapH);
983             }
984         }
986         /* Stop execution on DSP */
987         Log_print0(Diags_USER1, "[+2] Processor_delete_d> "
988                 "calling Ipc_control(STOPCALLBACK)...");
989         status = Ipc_control(proc->cpuId, Ipc_CONTROLCMD_STOPCALLBACK, NULL);
991         Log_print2(Diags_USER2, "[+2] Processor_delete_d> "
992                 "Ipc_control(STOPCALLBACK) status: 0x%x [%d]", (IArg)status,
993                 (IArg)status);
994     }
995     else {
996         Log_print2(Diags_USER2, "[+2] Processor_delete_d> Not calling "
997                 "Ipc_control(STOPCALLBACK) because startCallBackStatus =  "
998                 "0x%x [%d]", (IArg)proc->startCallBackStatus,
999                 (IArg)proc->startCallBackStatus);
1000     }
1002     if (proc->useExtLoader == FALSE) {
1003         /* We unload the slave processor */
1004         Log_print0(Diags_USER2, "[+2] Processor_delete_d> Stopping DSP...");
1006         status = ProcMgr_stop(proc->procMgrH);
1007         if (status < 0) {
1008             Log_print1(Diags_USER6, "[+6] Processor_delete_d> "
1009                     "Stopping DSP FAILED, status=0x%x", (IArg)status);
1010         }
1012         if (proc->fileId != 0xffffffff) {
1013             Log_print0(Diags_USER2, "[+2] Processor_delete_d> "
1014                     "Unloading DSP...");
1015             status = ProcMgr_unload(proc->procMgrH, proc->fileId);
1016             if (status < 0) {
1017                 Log_print1(Diags_USER6, "[+6] Processor_delete_d> "
1018                         "Unloading DSP FAILED, status=0x%x", (IArg)status);
1019             }
1020         }
1022         /* Unmap slave memory */
1023         if (!mapByFile(proc->procMgrH, proc->memMapName, proc->cpuId, FALSE)) {
1024             Log_print0(Diags_USER6, "Processor_delete_d> mapByFile() failed!");
1025         }
1027         /* Detach from the processor */
1028         Log_print0(Diags_USER1, "[+1] Processor_delete_d> "
1029                 "calling ProcMgr_detach()...");
1031         status = ProcMgr_detach(proc->procMgrH);
1032         if (status < 0) {
1033             Log_print1(Diags_USER6, "[+6] Processor_delete_d> "
1034                     "Detaching from DSP FAILED, status=0x%x", (IArg)status);
1035         }
1036     } // proc->useExtLoader == FALSE
1038     Log_print0(Diags_USER1, "[+1] Processor_delete_d> "
1039             "calling ProcMgr_close()...");
1041     status = ProcMgr_close(&proc->procMgrH);
1042     if (status < 0) {
1043         Log_print1(Diags_USER6, "[+6] Processor_delete_d> "
1044                 "Closing ProcMgr FAILED, status=0x%x", (IArg)status);
1045     }
1047 procDelete_return:
1049     Log_print0(Diags_EXIT, "[+X] Processor_delete_d> return");
1052 /*
1053  *  ======== doCmd ========
1054  */
1055 static Int doCmd(Int cmdId, Processor_Handle proc)
1057     Int result;
1058     IArg key;
1060     Log_print2(Diags_ENTRY, "[+E] doCmd> Enter (cmdId=%d, proc=0x%x)",
1061             (IArg)cmdId, (IArg)proc);
1063     //pthread_mutex_lock(&dcmd.gate);
1064     key = GateThread_enter(dcmd.gate);
1066     dcmd.proc = proc;
1067     dcmd.cmdId = cmdId;
1068     //pthread_cond_signal(&dcmd.cmdPresent);
1069     SemThread_post(dcmd.cmdPresent, NULL);
1071     //while (dcmd.reply == NONE) {
1072     //    pthread_cond_wait(&dcmd.replyPresent, &dcmd.gate);
1073     //}
1074     SemThread_pend(dcmd.replyPresent, SemThread_FOREVER, NULL);
1076     result = dcmd.reply;
1077     dcmd.reply = NONE;
1079     //pthread_mutex_unlock(&dcmd.gate);
1080     GateThread_leave(dcmd.gate, key);
1082     Log_print1(Diags_EXIT, "[+X] doCmd> Exit (result=%d)", (IArg)result);
1084     return (result);
1087 /*
1088  *  ======== getCmd ========
1089  */
1090 static Int getCmd(Processor_Handle *proc)
1092     Int result;
1094     Log_print1(Diags_ENTRY, "[+E] getCmd_d> Enter (proc=0x%x)", (IArg)proc);
1096     //pthread_mutex_lock(&dcmd.gate);
1098     //while (dcmd.cmdId == NONE) {
1099     //    pthread_cond_wait(&dcmd.cmdPresent, &dcmd.gate);
1100     //}
1101     SemThread_pend(dcmd.cmdPresent, SemThread_FOREVER, NULL);
1103     result = dcmd.cmdId;
1104     *proc = dcmd.proc;
1105     dcmd.cmdId = NONE;
1107     //pthread_mutex_unlock(&dcmd.gate);
1108     Log_print1(Diags_EXIT, "[+X] getCmd_d> Exit (result=%d)", (IArg)result);
1110     return (result);
1113 /*
1114  *  ======== putReply ========
1115  */
1116 static Void putReply(Int status)
1118     //pthread_mutex_lock(&dcmd.gate);
1120     dcmd.reply = status;
1122     //pthread_cond_signal(&dcmd.replyPresent);
1123     SemThread_post(dcmd.replyPresent, NULL);
1125     //Log_print2(Diags_USER1, "putReply(0x%x): proc = 0x%lx",
1126     //        (IArg)status, (IArg)(dcmd.proc));
1128     //pthread_mutex_unlock(&dcmd.gate);
1131 /*
1132  *  ======== daemon ========
1133  */
1134 static Int daemon(Void)
1137     Log_print0(Diags_USER1, "[+1] daemon> thread created.");
1139     for (;;) {
1140         Processor_Handle proc;
1142         switch (getCmd(&proc)) {
1143             case CREATE: {
1144                 putReply(procCreate(proc) ? SUCCESS : FAILURE);
1145                 break;
1146             }
1148             case DELETE: {
1149                 /* Log_print1(Diags_USER1, "daemon(0x%x) deleting ...",
1150                  *   (IArg)proc);
1151                  */
1152                 procDelete(proc);
1153                 /* Log_print1(Diags_USER1, "daemon(0x%x) replying ...",
1154                  *   (IArg)proc);
1155                  */
1156                 putReply(SUCCESS);
1158                 break;
1159             }
1161             case EXIT: {
1162                 //Log_print0(Diags_USER1, "daemon> thread terminating");
1163                 putReply(SUCCESS);
1164                 return (0);
1165             }
1167             default: {
1168                 break;
1169             }
1170         }
1171     }
1174 /*
1175  *  Code below is temporary, until ProcMgr has an API to map by file.
1176  */
1178 #define MUV ProcMgr_AddrType_MasterUsrVirt
1179 #define MKV ProcMgr_AddrType_MasterKnlVirt
1180 #define MP ProcMgr_AddrType_MasterPhys
1181 #define MAXLINE 100
1183 /*
1184  *  ======== mapByFile ========
1185  */
1186 Bool mapByFile(ProcMgr_Handle handle, String mapFile, UInt16 procId,
1187         int mapFlag)
1189     FILE *f;
1190     char line[MAXLINE];
1191     MapStruct mapStruct;
1192     ProcMgr_AddrInfo addrInfo;
1193     Int status = 0;
1194     ProcMgr_ProcInfo *procInfo;
1195     Int procInfoSize;
1196     UInt32 maxMemoryRegions;
1197     int j;
1199     if (mapFile == NULL) {
1200         return (TRUE);
1201     }
1203     f = fopen(mapFile, "r");
1205     if (!f) {
1206         Log_print1(Diags_USER5, "[+5] mapByFile: Unable to open %s "
1207                 "skipping....", (IArg)mapFile);
1209         /* regardless, we return 'success'.  Malformed lines are skipped */
1210         return (TRUE);
1211     }
1213     while (fgets(line, MAXLINE, f)) {
1214         if (!isMapLine(line, procId)) {
1215             Log_print1(Diags_USER5, "malformed line, skipping:\n   %s",
1216                     (IArg)line);
1217             continue;
1218         }
1220         /* Parse line, if not applicable, continue */
1221         if (!initFromLine(line, &mapStruct)) {
1222             continue;
1223         }
1225         /* applicable line */
1226         if (mapFlag) {
1227             /* map! */
1228             Log_print6(Diags_USER2,
1229                     "[+2] mapByFile: Mapping SV: 0x%x, SP: 0x%x, "
1230                     "MP: 0x%x,\n  size 0x%x, mask 0x%x, cached %d",
1231                     (IArg)mapStruct.slaveVirt, (IArg)mapStruct.slavePhys,
1232                     (IArg)mapStruct.masterPhys, (IArg)mapStruct.size,
1233                     (IArg)mapStruct.mapMask, (IArg)mapStruct.isCached);
1235             addrInfo.addr[MKV] = -1u;
1236             addrInfo.addr[ProcMgr_AddrType_MasterUsrVirt] = -1u;
1237             addrInfo.addr[MP] = mapStruct.masterPhys;
1238             addrInfo.addr[ProcMgr_AddrType_SlaveVirt] = mapStruct.slaveVirt;
1239             addrInfo.addr[ProcMgr_AddrType_SlavePhys] = -1u;
1240             addrInfo.size = mapStruct.size;
1241             addrInfo.isCached = mapStruct.isCached;
1243             status = ProcMgr_map(handle, mapStruct.mapMask, &addrInfo, MP);
1244             if (status < 0) {
1245                 Log_print1(Diags_USER6, "[+6] mapByFile: ProcMgr_map "
1246                         "failed [0x%x]", (IArg)status);
1247             }
1248             else {
1249                 Log_print0(Diags_USER2, "[+2] mapByFile: mapping succeeded");
1250             }
1251         }
1252         else {
1253             /* unmap! */
1254             Log_print6(Diags_USER2, "[+2]Unmapping SV: 0x%x, SP: 0x%x, "
1255                     "MP: 0x%x,\n  size 0x%x, mask 0x%x, cached %d",
1256                     (IArg)mapStruct.slaveVirt, (IArg)mapStruct.slavePhys,
1257                     (IArg)mapStruct.masterPhys, (IArg)mapStruct.size,
1258                     (IArg)mapStruct.mapMask, (IArg)mapStruct.isCached);
1260             addrInfo.addr[MKV] = -1u;
1262             /* if unmapping MasterKnlVirt, need to look it up */
1263             if (mapStruct.mapMask & ProcMgr_MASTERKNLVIRT) {
1265                 maxMemoryRegions = ProcMgr_getMaxMemoryRegions(handle);
1266                 procInfoSize = sizeof(ProcMgr_ProcInfo) +
1267                            (maxMemoryRegions * sizeof(ProcMgr_MappedMemEntry));
1268                 procInfo = Memory_alloc(procInfoSize, NULL);
1270                 status = ProcMgr_getProcInfo(handle, procInfo);
1271                 if (status < 0) {
1272                     Log_print0(Diags_USER6, "[+6] Unable to find MKV entry");
1273                 }
1274                 else {
1275                     for (j = 0; j < procInfo->maxMemoryRegions; j++) {
1276                         if ((procInfo->memEntries[j].inUse) &&
1277                                 (procInfo->memEntries[j].info.addr[MP]
1278                                         == mapStruct.masterPhys) &&
1279                                 (procInfo->memEntries[j].info.size ==
1280                                         mapStruct.size) &&
1281                                 (procInfo->memEntries[j].info.isCached
1282                                         == mapStruct.isCached)) {
1283                             /* found it */
1284                             addrInfo.addr[MKV] =
1285                                 procInfo->memEntries[j].info.addr[MKV];
1286                             Log_print1(Diags_USER2,
1287                                     "[+2] Found MKV entry (0x%x)",
1288                                     (IArg)addrInfo.addr[MKV]);
1289                             break;
1290                         }
1291                     }
1292                 }
1294                 Memory_free(procInfo, procInfoSize, NULL);
1295             }
1297             addrInfo.addr[ProcMgr_AddrType_MasterUsrVirt] = -1u;
1298             addrInfo.addr[MP] = mapStruct.masterPhys;
1299             addrInfo.addr[ProcMgr_AddrType_SlaveVirt] =
1300                 mapStruct.slaveVirt;
1301             addrInfo.addr[ProcMgr_AddrType_SlavePhys] = -1u;
1302             addrInfo.size = mapStruct.size;
1303             addrInfo.isCached = mapStruct.isCached;
1305             status = ProcMgr_unmap(handle, mapStruct.mapMask, &addrInfo, MP);
1306             if (status < 0) {
1307                 Log_print1(Diags_USER6, "[+6] ProcMgr_unmap failed [0x%x]",
1308                         status);
1309             }
1310             else {
1311                 Log_print0(Diags_USER2, "[+2] ProcMgr_unmap succeeded");
1312             }
1313         }
1314     }
1316     fclose(f);
1318     /* regardless, we return 'success'.  Malformed lines are skipped */
1319     return (TRUE);
1322 /*
1323  *  ======== initFromLine ========
1324  */
1325 int initFromLine(char *line, MapStruct *mapStruct)
1327     int retval = FALSE;
1328     char *p;
1330     mapStruct->slaveVirt = 0;
1331     mapStruct->slavePhys = 0;
1332     mapStruct->masterPhys = 0;
1333     mapStruct->size = 0;
1334     mapStruct->mapMask = 0;
1335     mapStruct->isCached = FALSE;
1337     p = strtok(line, " ,");
1338     if (p) {
1339         /* procName */
1340         p = strtok(NULL, " ,");
1341         if (p) {
1342             /* slaveVirt, in hex */
1343             mapStruct->slaveVirt = strtoul(p, NULL, 16);
1344             if (mapStruct->slaveVirt == 0) {
1345                 /* error, exit */
1346                 Log_print0(Diags_USER6, "[+6] Error parsing slaveVirt");
1347                 p = NULL;
1348             }
1349             else {
1350                 p = strtok(NULL, " ,");
1351             }
1352         }
1353         if (p) {
1354             /* slavePhys, in hex */
1355             mapStruct->slavePhys = strtoul(p, NULL, 16);
1356             if (mapStruct->slavePhys == 0) {
1357                 /* error, exit */
1358                 Log_print0(Diags_USER6, "[+6] Error parsing slavePhys");
1359                 p = NULL;
1360             }
1361             else {
1362                 p = strtok(NULL, " ,");
1363             }
1364         }
1365         if (p) {
1366             /* masterPhys, in hex */
1367             mapStruct->masterPhys = strtoul(p, NULL, 16);
1368             if (mapStruct->masterPhys == 0) {
1369                 /* error, exit */
1370                 Log_print0(Diags_USER6, "[+6] Error parsing masterPhys");
1371                 p = NULL;
1372             }
1373             else {
1374                 p = strtok(NULL, " ,");
1375             }
1376         }
1377         if (p) {
1378             /* size, in hex */
1379             mapStruct->size = strtoul(p, NULL, 16);
1380             if (mapStruct->size == 0) {
1381                 /* error, exit */
1382                 Log_print0(Diags_USER6, "[+6] Error parsing size");
1383                 p = NULL;
1384             }
1385             else {
1386                 p = strtok(NULL, " ,");
1387             }
1388         }
1389         if (p) {
1390             /* Mask */
1391             mapStruct->mapMask = strtoul(p, NULL, 16);
1392             if (mapStruct->mapMask == 0) {
1393                 /* error, exit */
1394                 Log_print0(Diags_USER6, "[+6] Error parsing mask");
1395                 p = NULL;
1396             }
1397             else {
1398                 p = strtok(NULL, " ,");
1399             }
1400         }
1401         if (p) {
1402             /* cached */
1403             errno = 0;
1404             mapStruct->isCached = strtoul(p, NULL, 16);
1405             if ((errno != 0) ||
1406                     ((mapStruct->isCached != 0) && mapStruct->isCached != 1)) {
1407                 /* error, exit */
1408                 Log_print0(Diags_USER6, "[+6] Error parsing cached");
1409                 p = NULL;
1410             }
1411             else {
1412                 /* that's it! */
1413                 retval = TRUE;
1414             }
1415         }
1416     }
1418     return (retval);
1421 /*
1422  *  ======== isMapLine ========
1423  */
1424 int isMapLine(char *line, UInt16 procId)
1426     int  retval = FALSE;
1427     char procName[32];
1429     if (line[0] != '#') {
1430         strncpy(procName, MultiProc_getName(procId), 32);
1431         if (strncmp(procName, line, strlen(procName)) == 0) {
1432             retval = TRUE;
1433         }
1434     }
1436     return (retval);