Set status field in fw_rsc_vdev after MessageQCopy_attach and before RscTable_update...
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / ipc / hlos / knl / Ipc.c
1 /*
2  *  Copyright (c) 2008-2013, Texas Instruments Incorporated
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions
6  *  are met:
7  *
8  *  *  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  *
11  *  *  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  *  *  Neither the name of Texas Instruments Incorporated nor the names of
16  *     its contributors may be used to endorse or promote products derived
17  *     from this software without specific prior written permission.
18  *
19  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29  *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
33 /*  ----------------------------------- Standard headers   */
34 #include <ti/syslink/Std.h>
36 /*  ----------------------------------- SysLink IPC module Headers   */
37 #include <ti/ipc/Ipc.h>
38 #include <_Ipc.h>
39 #include <IpcKnl.h>
40 #include <Platform.h>
41 #include <Bitops.h>
42 #include <RscTable.h>
43 #include <_MessageQCopy.h>
44 #include <ti/ipc/MessageQCopy.h>
46 /*  ----------------------------------- SysLink utils Headers   */
47 #include <ti/syslink/inc/_MultiProc.h>
48 #include <ti/ipc/MultiProc.h>
49 #include <ti/syslink/utils/Gate.h>
50 #include <ti/syslink/utils/Trace.h>
51 #include <ti/syslink/utils/Cache.h>
52 #include <ti/syslink/utils/Memory.h>
54 #if defined(SYSLINK_USE_IPU_PM)
55 #include <ipu_pm.h>
56 #endif
58 #if defined  (__cplusplus)
59 extern "C" {
60 #endif
63 /* =============================================================================
64  * Macros
65  * =============================================================================
66  */
67 /* Macro to make a correct module magic number with refCount */
68 #define Ipc_MAKE_MAGICSTAMP(x) ((SharedRegion_MODULEID << 16u) | (x))
71 /* =============================================================================
72  * Enums & Structures
73  * =============================================================================
74  */
76 /* The structure used for reserving memory in SharedRegion */
77 typedef struct Ipc_Reserved {
78     volatile Bits32    startedKey;
79 //    SharedRegion_SRPtr ipu_pm_sr_ptr; //Ramesh: Port from WinCe.
80 } Ipc_Reserved;
83 /*!
84  *  head of the config list
85  */
86 typedef struct Ipc_ConfigHead {
87     volatile Bits32 first;
88     /* Address of first config entry */
89 } Ipc_ConfigHead;
92 /*!
93  *   This structure captures Configuration details of a module/instance
94  *   written by a slave to synchornize with a remote slave/HOST
95  */
96 typedef struct Ipc_ConfigEntry {
97     volatile Bits32 remoteProcId;
98     /* Remote processor identifier */
99     volatile Bits32 localProcId;
100     /* Config Entry owner processor identifier */
101     volatile Bits32 tag;
102     /* Unique tag to distinguish config from other config entries */
103     volatile Bits32 size;
104     /* Size of the config pointer */
105     volatile Bits32 next;
106     /* Address of next config entry  (In SRPtr format) */
107 } Ipc_ConfigEntry;
109 /*
110  *  This structure defines the fields that are to be configured
111  *  between the executing processor and a remote processor.
112  */
113 typedef struct Ipc_Entry {
114     UInt16 remoteProcId;            /* the remote processor id   */
115     Bool    setup_ipu_pm;          //Ramesh: port from WinCE
116 } Ipc_Entry;
118 /*!
119  *   Ipc instance structure.
120  */
121 typedef struct Ipc_ProcEntry {
122     Ptr        localConfigList;
123     Ptr        remoteConfigList;
124     Ptr        userObj;
125     Bool       slave;
126     Ipc_Entry  entry;
127     Bool       isAttached;
128 } Ipc_ProcEntry;
131 /*!
132  *  Module state structure
133  */
134 typedef struct Ipc_Module_State {
135     Int32         refCount;
136     Ipc_Config    cfg;
137     Ipc_ProcEntry procEntry [MultiProc_MAXPROCESSORS];
138 } Ipc_Module_State;
141 /* =============================================================================
142  * Globals
143  * =============================================================================
144  */
145 static Ipc_Module_State Ipc_module_state = {
146                                              .refCount = 0,
147                                            };
148 static Ipc_Module_State * Ipc_module = &Ipc_module_state;
151 /* =============================================================================
152  * APIs
153  * =============================================================================
154  */
156 /* attaches to a remote processor */
157 Int Ipc_attach (UInt16 remoteProcId)
159     Int                     status = 0;
160     IArg                    key;
161     UInt32                  numVrings = 0;
162     UInt32                  vringAddr = 0;
163     ProcMgr_Handle          procHandle = NULL;
165     GT_1trace (curTrace, GT_ENTER, "Ipc_attach", remoteProcId);
167     GT_assert(curTrace,remoteProcId < MultiProc_INVALIDID);
168     GT_assert(curTrace,remoteProcId != MultiProc_self());
170     key = Gate_enterSystem ();
171    /* Make sure its not already attached */
172     if (Ipc_module->procEntry[remoteProcId].isAttached) {
173         Ipc_module->procEntry[remoteProcId].isAttached++;
174         Gate_leaveSystem (key);
175         status = Ipc_S_ALREADYSETUP;
176     }
177     else {
178         Gate_leaveSystem (key);
180         status = ProcMgr_open(&procHandle, remoteProcId);
181         if (status >= 0) {
182             /* get IPC VRING information */
183             status = RscTable_getInfo(remoteProcId, TYPE_VDEV, 0, NULL,
184                                       NULL, &numVrings);
185             if (status >= 0) {
186                 status = RscTable_getInfo(remoteProcId, TYPE_VDEV, 1,
187                                           &vringAddr, NULL, NULL);
188                 if (status >= 0) {
189                     status = MessageQCopy_attach(remoteProcId,
190                                                  (Ptr)vringAddr, 0);
191                     if (status >= 0) {
192                         status = RscTable_setStatus(remoteProcId, 7);
193                     }
194                 }
195             }
197             if (status >= 0) {
198                 status = RscTable_update(remoteProcId, procHandle);
199             }
200             ProcMgr_close(&procHandle);
201         }
203 #if defined(SYSLINK_USE_IPU_PM)
204         if (status >= 0) {
205             status = ipu_pm_attach(remoteProcId);
206             if (status < 0) {
207                 MessageQCopy_detach(remoteProcId);
208             }
209         }
210 #endif
212         if (status >= 0) {
213             key = Gate_enterSystem ();
214             Ipc_module->procEntry[remoteProcId].isAttached++;
215             Gate_leaveSystem (key);
216         }
217     }
218     GT_1trace (curTrace, GT_LEAVE, "Ipc_attach", status);
220     return  (status);
224 /* detaches from a remote processor */
225 Int Ipc_detach (UInt16 remoteProcId)
227     Int                     status = 0;
228     IArg                    key;
229     GT_1trace (curTrace, GT_ENTER, "Ipc_detach", remoteProcId);
231     key = Gate_enterSystem ();
232     if (Ipc_module->procEntry[remoteProcId].isAttached > 1) {
233         /* Only detach if attach count reaches 1 */
234         Ipc_module->procEntry[remoteProcId].isAttached--;
235         Gate_leaveSystem (key);
236         status = Ipc_S_BUSY;
237     }
238     else if (Ipc_module->procEntry[remoteProcId].isAttached == 0) {
239         /* If already detached, then return fail */
240         Gate_leaveSystem (key);
241         status = Ipc_E_FAIL;
242     }
243     else {
244         Gate_leaveSystem (key);
246 #if defined(SYSLINK_USE_IPU_PM)
247         status = ipu_pm_detach (remoteProcId);
248 #endif
250         status = MessageQCopy_detach (remoteProcId);
252         key = Gate_enterSystem ();
253         Ipc_module->procEntry[remoteProcId].isAttached--;
254         Gate_leaveSystem (key);
255     }
257     GT_1trace (curTrace, GT_LEAVE, "Ipc_detach", status);
259     return  (status);
262 /*
263  *  ======== Ipc_getConfig ========
264  */
265 Void Ipc_getConfig (Ipc_Config * cfgParams)
267     IArg key;
269     GT_1trace (curTrace, GT_ENTER, "Ipc_getConfig", cfgParams);
271     GT_assert (curTrace, (cfgParams != NULL));
273 #if !defined(SYSLINK_BUILD_OPTIMIZE)
274     if (cfgParams == NULL) {
275         /* No retVal since this is a Void function. */
276         GT_setFailureReason (curTrace,
277                              GT_4CLASS,
278                              "Ipc_getConfig",
279                              Ipc_E_INVALIDARG,
280                              "Argument of type (Ipc_Config *) passed "
281                              "is null!");
282     }
283     else {
284 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
285         key = Gate_enterSystem ();
286         if (Ipc_module->refCount != 0) {
287             Memory_copy ((Ptr) cfgParams,
288                          (Ptr) &Ipc_module->cfg,
289                          sizeof (Ipc_Config));
290         }
291         Gate_leaveSystem (key);
292 #if !defined(SYSLINK_BUILD_OPTIMIZE)
293     }
294 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
296     GT_0trace (curTrace, GT_LEAVE, "Ipc_getConfig");
300 /* Sets up Ipc for this processor. */
301 Int Ipc_setup (const Ipc_Config * cfg)
303     Int             status = Ipc_S_SUCCESS;
304     Ipc_Config      tmpCfg;
305     IArg            key;
306     Int             i;
308     GT_1trace (curTrace, GT_ENTER, "Ipc_setup", cfg);
310     key = Gate_enterSystem ();
311     Ipc_module->refCount++;
313     /* This sets the refCount variable is not initialized, upper 16 bits is
314      * written with module Id to ensure correctness of refCount variable.
315      */
316     if (Ipc_module->refCount > 1) {
317         status = Ipc_S_ALREADYSETUP;
318         GT_0trace (curTrace,
319                    GT_2CLASS,
320                    "Ipc Module already initialized!");
321         Gate_leaveSystem (key);
322     }
323     else {
324         Gate_leaveSystem (key);
325         if (cfg == NULL) {
326             Ipc_getConfig (&tmpCfg);
327             cfg = &tmpCfg;
328         }
330         /* Copy the cfg */
331         Memory_copy ((Ptr) &Ipc_module->cfg,
332                      (Ptr) cfg,
333                      sizeof (Ipc_Config));
335         status = Platform_setup ((Ipc_Config *)cfg);
336         if (status < 0) {
337             key = Gate_enterSystem ();
338             Ipc_module->refCount--;
339             Gate_leaveSystem (key);
340             status = Ipc_E_FAIL;
341             GT_setFailureReason (curTrace,
342                                  GT_4CLASS,
343                                  "Ipc_setup",
344                                  status,
345                                  "Platform_setup failed!");
346         }
348         /* Following can be done regardless of status */
349         for (i = 0; i < MultiProc_getNumProcessors (); i++) {
350             Ipc_module->procEntry [i].isAttached = FALSE;
351         }
352     }
354     GT_1trace (curTrace, GT_LEAVE, "Ipc_setup", status);
356     /*! @retval Ipc_S_SUCCESS Operation successful */
357     return status;
361 /* Destroys Ipc for this processor. */
362 Int
363 Ipc_destroy (Void)
365     Int status = Ipc_S_SUCCESS;
366     IArg  key;
368     GT_0trace (curTrace, GT_ENTER, "Ipc_destroy");
370     key = Gate_enterSystem ();
371     Ipc_module->refCount--;
372 #if !defined(SYSLINK_BUILD_OPTIMIZE)
373     if (Ipc_module->refCount < 0) {
374         Gate_leaveSystem (key);
375         /*! @retval Ipc_E_INVALIDSTATE Module was not initialized */
376         status = Ipc_E_INVALIDSTATE;
377         GT_setFailureReason (curTrace,
378                              GT_4CLASS,
379                              "Ipc_destroy",
380                              status,
381                              "Module was not initialized!");
382     }
383     else {
384 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
385         if (Ipc_module->refCount == 0) {
386             Gate_leaveSystem (key);
387             status = Platform_destroy ();
388             if (status < 0) {
389                 status = Ipc_E_FAIL;
390                 GT_setFailureReason (curTrace,
391                                      GT_4CLASS,
392                                      "Ipc_destroy",
393                                      status,
394                                      "Platform_destroy failed!");
395             }
396         }
397         else {
398             Gate_leaveSystem (key);
399         }
400 #if !defined(SYSLINK_BUILD_OPTIMIZE)
401     }
402 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
404     GT_1trace (curTrace, GT_LEAVE, "Ipc_destroy", status);
406     /*! @retval Ipc_S_SUCCESS Operation successful */
407     return status;
411 #if defined (__cplusplus)
413 #endif /* defined (__cplusplus) */