3723e27eee5eb081022c8036c047afc8d7a61772
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)
158 {
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);
221 }
224 /* detaches from a remote processor */
225 Int Ipc_detach (UInt16 remoteProcId)
226 {
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);
260 }
262 /*
263 * ======== Ipc_getConfig ========
264 */
265 Void Ipc_getConfig (Ipc_Config * cfgParams)
266 {
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");
297 }
300 /* Sets up Ipc for this processor. */
301 Int Ipc_setup (const Ipc_Config * cfg)
302 {
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;
358 }
361 /* Destroys Ipc for this processor. */
362 Int
363 Ipc_destroy (Void)
364 {
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;
408 }
411 #if defined (__cplusplus)
412 }
413 #endif /* defined (__cplusplus) */