1 /*
2 * Copyright (c) 2013-2015, 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 * @file Ipc.c
34 *
35 * @brief Starts and stops user side Ipc
36 * All setup/destroy APIs on user side will be call from this
37 * module.
38 *
39 * @ver 0002
40 *
41 */
43 /* Standard headers */
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <signal.h>
47 #include <ti/ipc/Std.h>
49 /* Common IPC headers: */
50 #include <ti/ipc/Ipc.h>
51 #include <ti/ipc/NameServer.h>
53 /* User side headers */
54 #include <ti/syslink/inc/usr/Qnx/IpcDrv.h>
56 /* IPC startup/shutdown stuff: */
57 #include <ti/ipc/MultiProc.h>
58 #include <ti/ipc/MessageQ.h>
59 #include <ti/ipc/NameServer.h>
60 #include <_MessageQ.h>
61 #include <_NameServer.h>
62 #include <_GateMP.h>
63 #include <_GateMP_usr.h>
64 #include <_TiIpcFxns.h>
65 #include <ti/syslink/inc/GateHWSpinlock.h>
66 #include <ti/syslink/inc/_MultiProc.h>
68 MultiProc_Config _MultiProc_cfg;
70 static void cleanup(int arg);
72 /** ============================================================================
73 * Functions
74 * ============================================================================
75 */
76 /* Function to start Ipc */
77 Int Ipc_start (Void)
78 {
79 MessageQ_Config msgqCfg;
80 MultiProc_Config mpCfg;
81 Int32 status = Ipc_S_SUCCESS;
82 UInt16 rprocId;
84 /* Catch ctrl-C, and cleanup: */
85 (void) signal(SIGINT, cleanup);
87 if (getenv("IPC_DEBUG") != NULL) {
88 /* turn on tracing */
89 if (getenv("IPC_DEBUG")[0] == '1') {
90 /* level 1 enables typical user API tracing */
91 _MessageQ_verbose = TRUE;
92 _MultiProc_verbose = TRUE;
93 _NameServer_verbose = TRUE;
94 #if defined(GATEMP_SUPPORT)
95 _GateMP_verbose = TRUE;
97 _GateHWSpinlock_verbose = TRUE;
98 #endif
99 }
100 else if ((getenv("IPC_DEBUG")[0] == '2') ||
101 (getenv("IPC_DEBUG")[0] == '3')) {
102 /* levels 2 and 3 add TiIpcFxns tracing */
103 _MessageQ_verbose = TRUE;
104 _MultiProc_verbose = TRUE;
105 _NameServer_verbose = TRUE;
107 #if defined(GATEMP_SUPPORT)
108 _GateMP_verbose = TRUE;
110 _GateHWSpinlock_verbose = TRUE;
111 #endif
113 _TiIpcFxns_verbose = TRUE;
114 }
115 }
117 status = IpcDrv_open();
118 if (status < 0) {
119 printf("Ipc_start: IpcDrv_open() failed: %d\n", status);
120 status = Ipc_E_FAIL;
121 goto exit;
122 }
124 status = NameServer_setup();
125 if (status >= 0) {
126 MessageQ_getConfig(&msgqCfg);
127 MessageQ_setup(&msgqCfg);
129 /* Setup and get MultiProc configuration from resource manager */
130 MultiProc_getConfig(&mpCfg);
131 _MultiProc_cfg = mpCfg;
133 /* Now attach to all remote processors, assuming they are up. */
134 for (rprocId = 0;
135 (rprocId < MultiProc_getNumProcessors()) && (status >= 0);
136 rprocId++) {
137 if (0 == rprocId) {
138 /* Skip host, which should always be 0th entry. */
139 continue;
140 }
141 status = MessageQ_attach (rprocId, NULL);
142 if (status < 0) {
143 printf("Ipc_start: MessageQ_attach(%d) failed: %d\n",
144 rprocId, status);
145 status = Ipc_E_FAIL;
146 goto messageqattach_fail;
147 }
148 }
149 }
150 else {
151 printf("Ipc_start: NameServer_setup() failed: %d\n", status);
152 status = Ipc_E_FAIL;
153 goto nameserversetup_fail;
154 }
156 /* Start GateMP only if it is setup in the resource manager */
157 #if defined(GATEMP_SUPPORT)
158 if (GateMP_isSetup()) {
159 status = GateHWSpinlock_start();
160 if (status < 0) {
161 printf("Ipc_start: GateHWSpinlock_start failed: %d\n",
162 status);
163 status = Ipc_E_FAIL;
164 goto gatehwspinlockstart_fail;
165 }
166 else {
167 status = GateMP_start();
168 if (status < 0) {
169 printf("Ipc_start: GateMP_start failed: %d\n",
170 status);
171 status = Ipc_E_FAIL;
172 goto gatempstart_fail;
173 }
174 }
175 }
176 #endif
177 /* Success */
178 goto exit;
179 #if defined(GATEMP_SUPPORT)
180 gatempstart_fail:
181 GateHWSpinlock_stop();
182 gatehwspinlockstart_fail:
183 for (rprocId = rprocId - 1; (rprocId > 0) && (status >= 0); rprocId--) {
184 MessageQ_detach(rprocId);
185 }
186 #endif
187 messageqattach_fail:
188 MessageQ_destroy();
189 NameServer_destroy();
190 nameserversetup_fail:
191 IpcDrv_close();
193 exit:
194 return (status);
195 }
198 /* Function to stop Ipc */
199 Int Ipc_stop (Void)
200 {
201 Int32 status = Ipc_S_SUCCESS;
202 UInt16 rprocId;
203 #if defined(GATEMP_SUPPORT)
204 if (GateMP_isSetup()) {
205 /* Stop GateMP */
206 status = GateMP_stop();
207 if (status < 0) {
208 printf("Ipc_stop: GateMP_stop() failed: %d\n", status);
209 status = Ipc_E_FAIL;
210 goto exit;
211 }
213 /* Finalize GateHWSpinlock */
214 status = GateHWSpinlock_stop();
215 if (status < 0) {
216 printf("Ipc_stop: GateHWSpinlock_stop() failed: %d\n", status);
217 status = Ipc_E_FAIL;
218 goto exit;
219 }
220 }
221 #endif
222 /* Now detach from all remote processors, assuming they are up. */
223 for (rprocId = 0;
224 (rprocId < MultiProc_getNumProcessors()) && (status >= 0);
225 rprocId++) {
226 if (0 == rprocId) {
227 /* Skip host, which should always be 0th entry. */
228 continue;
229 }
230 status = MessageQ_detach(rprocId);
231 if (status < 0) {
232 printf("Ipc_stop: MessageQ_detach(%d) failed: %d\n",
233 rprocId, status);
234 status = Ipc_E_FAIL;
235 goto exit;
236 }
237 }
239 status = MessageQ_destroy();
240 if (status < 0) {
241 printf("Ipc_stop: MessageQ_destroy() failed: %d\n", status);
242 status = Ipc_E_FAIL;
243 goto exit;
244 }
246 status = NameServer_destroy();
247 if (status < 0) {
248 printf("Ipc_stop: NameServer_destroy() failed: %d\n", status);
249 status = Ipc_E_FAIL;
250 goto exit;
251 }
253 IpcDrv_close();
255 exit:
256 return (status);
257 }
259 static void cleanup(int arg)
260 {
261 printf("Ipc: Caught SIGINT, calling Ipc_stop...\n");
262 Ipc_stop();
263 exit(0);
264 }