OMAP54XX: Add remote codec support
[mfp/cedev.git] / packages / ti / sdo / ce / ipc / dsplink / Processor_dsplink.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  *  ======== 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 <sys/types.h>
56 #include <ti/cmem.h>
58 #include <ti/sdo/ce/ipc/Comm.h>
59 #include <ti/sdo/ce/ipc/Processor.h>
61 //#include <ti/ipc/HeapBufMP.h>
62 #include <ti/ipc/Ipc.h>
63 #include <ti/ipc/MessageQ.h>
64 #include <ti/ipc/MultiProc.h>
66 #include <stdio.h>  /* for printf() and getchar() */
67 #include <string.h>
68 #include <stdlib.h>
69 #include <sys/stat.h>
71 #include <errno.h>
74 #define Processor_defaultSharedRegionId ti_sdo_ce_ipc_dsplink__Processor_defaultSharedRegionId
75 #define Processor_defaultHeapId ti_sdo_ce_ipc_dsplink__Processor_defaultHeapId
76 #define Processor_defaultNumMsgs ti_sdo_ce_ipc_dsplink__Processor_defaultNumMsgs
77 #define Processor_defaultMsgSize ti_sdo_ce_ipc_dsplink__Processor_defaultMsgSize
78 #define Processor_commDescs ti_sdo_ce_ipc_dsplink__Processor_commDescs
79 #define Processor_numCommDescs ti_sdo_ce_ipc_dsplink__Processor_numCommDescs
80 #define Processor_loadSlave ti_sdo_ce_ipc_dsplink__Processor_loadSlave
82 /* Generated by .xdt file */
83 extern Int16 Processor_defaultSharedRegionId;
84 extern Int16 Processor_defaultHeapId;
85 extern Int32 Processor_defaultNumMsgs;
86 extern Int32 Processor_defaultMsgSize;
87 extern Processor_CommDesc Processor_commDescs[];
88 extern UInt32 Processor_numCommDescs;
89 extern Bool Processor_loadSlave;
92 /*
93  *  ======== Processor_Obj ========
94  */
95 typedef struct Processor_Obj {
96     Int               cpuId;
97     UInt16            heapId;
98     String            imageName;
99     String            memMapName;
100     Bool              loaded;
101     Processor_Attrs   attrs;
102     UInt32            fileId;
103     Int32             loadCallBackStatus;
104     Int32             startCallBackStatus;
105     Bool              useExtLoader;
106 } Processor_Obj;
108 /*
109  *  ======== Processor_ATTRS ========
110  */
111 Processor_Attrs Processor_ATTRS = {
112     "dsp0",     /* cpu ID */
113     0,          /* argc */
114     NULL,       /* argv */
115     FALSE,      /* useExtLoader */
116 };
118 #define NONE    0
119 #define CREATE  1
120 #define DELETE  2
121 #define EXIT    3
123 #define SUCCESS 1
124 #define FAILURE 2
126 /*
127  *  ======== CmdObj ========
128  */
129 typedef struct CmdObj {
130     Thread_Handle     dproc;
131     Processor_Handle  proc;
132     Int               cmdId;
133     Int               reply;
135     SemThread_Handle  cmdPresent;
136     SemThread_Handle  replyPresent;
137     GateThread_Handle gate;
138 } CmdObj;
141 /*
142  *  Memory map entry format in map text file.
143  */
144 typedef struct MapStruct {
145     UInt32 slaveVirt;
146     UInt32 slavePhys;
147     UInt32 masterPhys;
148     UInt32 size;
149     UInt32 mapMask;
150     int isCached;
151 } MapStruct;
153 /* REMINDER: if you add an initialized static var, reinitialize it at cleanup */
155 static CmdObj dcmd = {NULL, NULL, NONE, NONE, NULL, NULL, NULL};
157 static Void cleanup(Void);
158 static Int daemon(Void);
159 static Int doCmd(Int cmdId, Processor_Handle proc);
160 static Int getCmd(Processor_Handle *proc);
161 static Bool procCreate(Processor_Handle proc);
162 static Void procDelete(Processor_Handle proc);
163 static Void putReply(Int status);
165 static Int16 perCoreHeapId(UInt32 coreId);
166 static Int32 perCoreNumMsgs(UInt32 coreId);
167 static Int32 perCoreMsgSize(UInt32 coreId);
168 static Int16 perCoreSharedRegionId(UInt32 coreId);
169 static Bool perCoreUserCreatedHeapFlag(UInt32 coreId);
171 Registry_Desc ti_sdo_ce_ipc_processor_desc;
173 static Int regInit = 0;     /* Registry_addModule() called */
174 static Int curInit = 0;     /* module init counter */
176 /*
177  *  ======== Processor_create ========
178  */
179 Processor_Handle Processor_create(String imageName, String memMap,
180     Processor_Attrs *attrs)
182     Processor_Handle proc = NULL;
183     struct stat statBuf;
185     Assert_isTrue(curInit == TRUE, (Assert_Id)NULL);
187     Log_print3(Diags_ENTRY, "[+E] Processor_create> "
188             "Enter(imageName='%s', memMap='%s', attrs=0x%x)",
189             (IArg)imageName, (IArg)memMap, (IArg)attrs);
191     if (attrs == NULL) {
192         attrs = &Processor_ATTRS;
193     }
195     if (stat(imageName, &statBuf) != 0) {
196         Log_print1(Diags_USER7, "[+7] Processor_create> "
197                 "ERROR: cannot access file %s", (IArg)imageName);
198         return (NULL);
199     }
201     proc = Memory_alloc(sizeof(Processor_Obj), NULL);
202     if (proc == NULL) {
203         Log_print0(Diags_USER7, "[+7] Processor_create> "
204                 "ERROR: Memory_alloc failed");
205         return (NULL);
206     }
208     proc->attrs = *attrs;
209     proc->imageName = imageName;
210     proc->memMapName = memMap;
211     proc->loaded = FALSE;
212     proc->fileId = 0xffffffff;
213     proc->loadCallBackStatus = -1;
214     proc->startCallBackStatus = -1;
215     proc->useExtLoader = attrs->useExtLoader;
217     if (doCmd(CREATE, proc) != SUCCESS) {
218         Processor_delete(proc);
219         return (NULL);
220     }
221     proc->loaded = TRUE;
223     Log_print1(Diags_EXIT, "[+X] Processor_create> return (0x%x)", (IArg)proc);
225     return (proc);
229 /*
230  *  ======== Processor_delete ========
231  */
232 Void Processor_delete(Processor_Handle proc)
234     Assert_isTrue(curInit == TRUE, (Assert_Id)NULL);
236     Log_print1(Diags_ENTRY, "[+E] Processor_delete> Enter(proc=0x%x)",
237             (IArg)proc);
239     if (proc != NULL) {
240         if (proc->loaded == TRUE && dcmd.dproc != NULL) {
241             doCmd(DELETE, proc);
242         }
244         Log_print1(Diags_USER1,
245                 "[+1] Processor_delete(0x%x) freeing object ...", (IArg)proc);
246         Memory_free(proc, sizeof(Processor_Obj), NULL);
247     }
249     Log_print0(Diags_EXIT, "[+X] Processor_delete> return");
253 /*
254  *  ======== Processor_init ========
255  */
256 Void Processor_init(Void)
258     GateThread_Params params;
259     Registry_Result   result;
261     /*
262      *  No need to reference count for Registry_addModule(), since there
263      *  is no way to remove the module.
264      */
265     if (regInit == 0) {
266         /* Register this module for logging */
267         result = Registry_addModule(&ti_sdo_ce_ipc_processor_desc,
268                 Processor_MODNAME);
269         Assert_isTrue(result == Registry_SUCCESS, (Assert_Id)NULL);
271         if (result == Registry_SUCCESS) {
272             /* Set the diags mask to the CE default */
273             CESettings_init();
274             CESettings_setDiags(Processor_MODNAME);
275         }
276         regInit = 1;
277     }
279     if (curInit != TRUE) {
280         curInit = TRUE;
282         /* Semaphore with count 0, will be posted when a command is present */
283         dcmd.cmdPresent = SemThread_create(0, NULL, NULL);
285         /* Semaphore with count 0, will be posted when reply is ready */
286         dcmd.replyPresent = SemThread_create(0, NULL, NULL);
288         /*
289          *  Create lock to allow only one thread at a time to send command
290          *  to the daemon.
291          */
292         GateThread_Params_init(&params);
293         dcmd.gate = GateThread_create(&params, NULL);
295         if ((dcmd.cmdPresent == NULL) || (dcmd.replyPresent == NULL) ||
296                 (dcmd.gate == NULL)) {
297             // TODO: Shouldn't we abort?
298             Log_print0(Diags_USER7, "[+7] Processor_init> ERROR: cannot"
299                     " create semaphores or lock");
300         }
302         Log_print0(Diags_USER2, "[+2] Processor_init> Ipc_start()...");
304         Ipc_start();
305         Log_print0(Diags_USER2, "[+2] Processor_init> "
306                 "... Ipc_start() done");
308         if ((dcmd.dproc = Thread_create((Thread_RunFxn)daemon, NULL, NULL))
309                 == NULL) {
310             Log_print0(Diags_USER7, "[+7] Processor_init> "
311                     "ERROR: cannot create DSP daemon");
312         }
314         if (Thread_start(NULL) != TRUE) {
315             Log_print0(Diags_USER7, "[+7] Processor_init> "
316                     "ERROR: cannot start threads");
317         }
319         Global_atexit((Fxn)cleanup);
320     }
323 /*
324  *  ======== Processor_getCoreName ========
325  */
326 String Processor_getCoreName(UInt32 id)
328     UInt16 mpId = (UInt16)id;
330     return(MultiProc_getName(mpId));
334 /*
335  *  ======== Processor_getCoreId ========
336  */
337 UInt32 Processor_getCoreId(String name)
339     UInt16 coreId = MultiProc_getId(name);
341     if (coreId == MultiProc_INVALIDID) {
342         return (Processor_INVALIDID);
343     }
344     else {
345         return ((UInt32)coreId);
346     }
349 /*
350  *  ======== Processor_getNumProcs ========
351  */
352 UInt32 Processor_getNumProcs(Void)
354     return(MultiProc_getNumProcessors());
357 /*
358  *  ======== Processor_myCoreId ========
359  */
360 UInt32 Processor_myCoreId(Void)
362     return(MultiProc_self());
365 /*
366  *  ======== Processor_getHeapId ========
367  */
368 UInt16 Processor_getHeapId(UInt32 coreId)
370     Int16 heapId;
372     heapId = perCoreHeapId(coreId);
373     if (heapId == Processor_INVALID) {
374         heapId = Processor_defaultHeapId;
375     }
377     return(heapId);
380 /*
381  *  ======== Processor_getMsgSize ========
382  */
383 UInt32 Processor_getMsgSize(UInt32 coreId)
385     Int32 msgSize;
387     msgSize = perCoreMsgSize(coreId);
388     if (msgSize == Processor_INVALID) {
389         msgSize = Processor_defaultMsgSize;
390     }
392     return(msgSize);
395 /*
396  *  ======== Processor_getNumMsgs ========
397  */
398 UInt32 Processor_getNumMsgs(UInt32 coreId)
400     Int32 numMsgs;
402     numMsgs = perCoreNumMsgs(coreId);
403     if (numMsgs == Processor_INVALID) {
404         numMsgs = Processor_defaultNumMsgs;
405     }
407     return(numMsgs);
410 /*
411  *  ======== Processor_getSharedRegionId ========
412  */
413 UInt16 Processor_getSharedRegionId(UInt32 coreId)
415     Int16 sharedRegionId;
417     sharedRegionId = perCoreSharedRegionId(coreId);
418     if (sharedRegionId == Processor_INVALID) {
419         sharedRegionId = Processor_defaultSharedRegionId;
420     }
422     return(sharedRegionId);
425 /*
426  *  ======== Processor_getUserCreatedHeapFlag ========
427  */
428 Bool Processor_getUserCreatedHeapFlag(UInt32 coreId)
430     return(perCoreUserCreatedHeapFlag(coreId));
433 static Int16 perCoreHeapId(UInt32 coreId)
435     if (coreId == MultiProc_INVALIDID ||
436         coreId >= Processor_numCommDescs) {
438         return(Processor_INVALID);
439     }
441     return(Processor_commDescs[coreId].heapId);
444 static Int32 perCoreMsgSize(UInt32 coreId)
446     if (coreId == MultiProc_INVALIDID ||
447         coreId >= Processor_numCommDescs) {
449         return(Processor_INVALID);
450     }
452     return(Processor_commDescs[coreId].msgSize);
455 static Int32 perCoreNumMsgs(UInt32 coreId)
457     if (coreId == MultiProc_INVALIDID ||
458         coreId >= Processor_numCommDescs) {
460         return(Processor_INVALID);
461     }
463     return(Processor_commDescs[coreId].numMsgs);
466 static Int16 perCoreSharedRegionId(UInt32 coreId)
468     if (coreId == MultiProc_INVALIDID ||
469         coreId >= Processor_numCommDescs) {
471         return(Processor_INVALID);
472     }
474     return(Processor_commDescs[coreId].sharedRegionId);
477 static Bool perCoreUserCreatedHeapFlag(UInt32 coreId)
479     if (coreId == MultiProc_INVALIDID ||
480         coreId >= Processor_numCommDescs) {
482         return(FALSE);
483     }
485     return(Processor_commDescs[coreId].userCreatedHeap);
490 /*
491  *  ======== Processor_wait ========
492  */
493 Int Processor_wait(Processor_Handle proc)
495     return(-1);
498 /*
499  *  ======== cleanup ========
500  */
501 static Void cleanup(Void)
503     static CmdObj dcmdInit = {NULL, NULL, NONE, NONE, NULL, NULL, NULL};
505     if (curInit != FALSE) {
506         curInit = FALSE;
507         if (dcmd.dproc != NULL) {
508             doCmd(EXIT, NULL);
509             // Thread_join(dcmd.dproc);
510             Thread_delete(&dcmd.dproc); /* will do join first? */
511             dcmd.dproc = NULL;
512         }
514         Log_print0(Diags_USER2, "[+2] Processor cleanup()> "
515                 "Ipc_stop()...");
516         Ipc_stop();
517         Log_print0(Diags_USER2, "[+2] Processor cleanup()> "
518                 "... Ipc_stop() complete");
520         if (dcmd.cmdPresent != NULL) {
521             SemThread_delete(&dcmd.cmdPresent);
522             dcmd.cmdPresent = NULL;
523         }
525         if (dcmd.replyPresent != NULL) {
526             SemThread_delete(&dcmd.replyPresent);
527             dcmd.replyPresent = NULL;
528         }
530         if (dcmd.gate != NULL) {
531             GateThread_delete(&dcmd.gate);
532             dcmd.gate = NULL;
533         }
535         dcmd = dcmdInit;
536     }
539 /*
540  *  ======== procCreate ========
541  */
542 static Bool procCreate(Processor_Handle proc)
544     Int status = 0;
545     Bool retVal;
547     Log_print1(Diags_ENTRY, "[+E] Processor_create_d> Enter(proc=0x%x)",
548             (IArg)proc);
550     /* Create and initialize the PROC object */
551     Log_print1(Diags_USER2, "[+2] Processor_create_d> "
552     "Retrieving CPU ID for '%s'...", (IArg)(proc->attrs.cpuId));
554     proc->cpuId = Processor_getCoreId(proc->attrs.cpuId);
555     if (proc->cpuId < 0) {
556         Log_print1(Diags_USER7, "[+7] Processor_create_d> "
557                "Processor_getCoreId() failed: %d", proc->cpuId);
558         goto fail;
559     }
561     retVal = TRUE;
562     goto procCreate_return;
564     /* TODO:[4] should try those asyncErrorHandlers that link supports?
565      * (MSGQ_SetErrorHandler)
566      */
568 fail:
569     Log_print3(Diags_USER7, "[+7] Processor_create_d> "
570             "Loading and starting %s server '%s' FAILED, status=[0x%x]",
571             (IArg)proc->attrs.cpuId, (IArg)proc->imageName, status);
573     procDelete(proc);
575     retVal = FALSE;
577 procCreate_return:
579     Log_print1(Diags_USER2, "[+2] Processor_create_d> return (%d)",
580             (IArg)retVal);
582     return (retVal);
585 /*
586  *  ======== procDelete ========
587  */
588 static Void procDelete(Processor_Handle proc)
590     Log_print1(Diags_ENTRY, "[+E] Processor_delete_d> Enter (proc=0x%x)",
591             (IArg)proc);
593     Log_print0(Diags_EXIT, "[+X] Processor_delete_d> return");
596 /*
597  *  ======== doCmd ========
598  */
599 static Int doCmd(Int cmdId, Processor_Handle proc)
601     Int result;
602     IArg key;
604     Log_print2(Diags_ENTRY, "[+E] doCmd> Enter (cmdId=%d, proc=0x%x)",
605             (IArg)cmdId, (IArg)proc);
607     //pthread_mutex_lock(&dcmd.gate);
608     key = GateThread_enter(dcmd.gate);
610     dcmd.proc = proc;
611     dcmd.cmdId = cmdId;
612     //pthread_cond_signal(&dcmd.cmdPresent);
613     SemThread_post(dcmd.cmdPresent, NULL);
615     //while (dcmd.reply == NONE) {
616     //    pthread_cond_wait(&dcmd.replyPresent, &dcmd.gate);
617     //}
618     SemThread_pend(dcmd.replyPresent, SemThread_FOREVER, NULL);
620     result = dcmd.reply;
621     dcmd.reply = NONE;
623     //pthread_mutex_unlock(&dcmd.gate);
624     GateThread_leave(dcmd.gate, key);
626     Log_print1(Diags_EXIT, "[+X] doCmd> Exit (result=%d)", (IArg)result);
628     return (result);
631 /*
632  *  ======== getCmd ========
633  */
634 static Int getCmd(Processor_Handle *proc)
636     Int result;
638     Log_print1(Diags_ENTRY, "[+E] getCmd_d> Enter (proc=0x%x)", (IArg)proc);
640     //pthread_mutex_lock(&dcmd.gate);
642     //while (dcmd.cmdId == NONE) {
643     //    pthread_cond_wait(&dcmd.cmdPresent, &dcmd.gate);
644     //}
645     SemThread_pend(dcmd.cmdPresent, SemThread_FOREVER, NULL);
647     result = dcmd.cmdId;
648     *proc = dcmd.proc;
649     dcmd.cmdId = NONE;
651     //pthread_mutex_unlock(&dcmd.gate);
652     Log_print1(Diags_EXIT, "[+X] getCmd_d> Exit (result=%d)", (IArg)result);
654     return (result);
657 /*
658  *  ======== putReply ========
659  */
660 static Void putReply(Int status)
662     //pthread_mutex_lock(&dcmd.gate);
664     dcmd.reply = status;
666     //pthread_cond_signal(&dcmd.replyPresent);
667     SemThread_post(dcmd.replyPresent, NULL);
669     //Log_print2(Diags_USER1, "putReply(0x%x): proc = 0x%lx",
670     //        (IArg)status, (IArg)(dcmd.proc));
672     //pthread_mutex_unlock(&dcmd.gate);
675 /*
676  *  ======== daemon ========
677  */
678 static Int daemon(Void)
681     Log_print0(Diags_USER1, "[+1] daemon> thread created.");
683     for (;;) {
684         Processor_Handle proc;
686         switch (getCmd(&proc)) {
687             case CREATE: {
688                 putReply(procCreate(proc) ? SUCCESS : FAILURE);
689                 break;
690             }
692             case DELETE: {
693                 /* Log_print1(Diags_USER1, "daemon(0x%x) deleting ...",
694                  *   (IArg)proc);
695                  */
696                 procDelete(proc);
697                 /* Log_print1(Diags_USER1, "daemon(0x%x) replying ...",
698                  *   (IArg)proc);
699                  */
700                 putReply(SUCCESS);
702                 break;
703             }
705             case EXIT: {
706                 //Log_print0(Diags_USER1, "daemon> thread terminating");
707                 putReply(SUCCESS);
708                 return (0);
709             }
711             default: {
712                 break;
713             }
714         }
715     }