Initial MessageQ transport implementation
[ipc/ipcdev.git] / linux / src / api / Ipc.c
1 /*
2  * Copyright (c) 2012-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  *  @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  */
40 /* Standard headers */
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <signal.h>
45 /* Common IPC headers: */
46 #include <ti/ipc/Std.h>
47 #include <ti/ipc/Ipc.h>
48 #include <ti/ipc/NameServer.h>
49 #include <IMessageQTransport.h>
50 #include <TransportRpmsg.h>
52 /* User side headers */
53 #include <ladclient.h>
55 /* IPC startup/shutdown stuff: */
56 #include <ti/ipc/MultiProc.h>
57 #include <GateHWSpinlock.h>
58 #include <_GateMP.h>
59 #include <_MultiProc.h>
60 #include <_MessageQ.h>
61 #include <_NameServer.h>
63 GateHWSpinlock_Config _GateHWSpinlock_cfgParams;
65 static LAD_ClientHandle ladHandle;
67 static void cleanup(int arg);
69 /** ============================================================================
70  *  Functions
71  *  ============================================================================
72  */
73 /* Function to start Ipc */
74 Int Ipc_start (Void)
75 {
76     TransportRpmsg_Handle  transport;
77     TransportRpmsg_Params  params;
78     IMessageQTransport_Handle iMsgQTrans;
79     MessageQ_Config        msgqCfg;
80     MultiProc_Config       mpCfg;
81 #if defined(GATEMP_SUPPORT)
82     GateHWSpinlock_Config  gateHWCfg;
83 #endif
84     Int                    attachStatus;
85     Int32                  status;
86     LAD_Status             ladStatus;
87     UInt16                 rprocId;
88     Int32                  attachedAny;
90     /* Catch ctrl-C, and cleanup: */
91     (void) signal(SIGINT, cleanup);
93     if (getenv("IPC_DEBUG") != NULL) {
94         /* turn on tracing */
95         if (getenv("IPC_DEBUG")[0] == '1') {
96             /* level 1 enables typical user API tracing */
97             _MessageQ_verbose = TRUE;
98             _MultiProc_verbose = TRUE;
99             _NameServer_verbose = TRUE;
100 #if defined(GATEMP_SUPPORT)
101             _GateMP_verbose = TRUE;
103             _GateHWSpinlock_verbose = TRUE;
104 #endif
105         }
106         else if ((getenv("IPC_DEBUG")[0] == '2') ||
107                 (getenv("IPC_DEBUG")[0] == '3')) {
108             /* levels 2 and 3 add socket and LAD client tracing */
109             _MessageQ_verbose = TRUE;
110             _MultiProc_verbose = TRUE;
111             _NameServer_verbose = TRUE;
113 #if defined(GATEMP_SUPPORT)
114             _GateMP_verbose = TRUE;
116             _GateHWSpinlock_verbose = TRUE;
117 #endif
119             /* internals - should be declared in respective _*.h files */
120             extern Bool _SocketFxns_verbose;
121             extern Bool _LAD_Client_verbose;
123             _SocketFxns_verbose = TRUE;
124             _LAD_Client_verbose = TRUE;
125         }
126     }
128     ladStatus = LAD_connect(&ladHandle);
129     if (ladStatus != LAD_SUCCESS) {
130         printf("Ipc_start: LAD_connect() failed: %d\n", ladStatus);
131         status = Ipc_E_FAIL;
132         goto exit;
133     }
135     /*
136      * Get MultiProc configuration from LAD and initialize local MultiProc
137      * config structure.
138      */
139     MultiProc_getConfig(&mpCfg);
140     _MultiProc_initCfg(&mpCfg);
142     status = NameServer_setup();
143     if (status >= 0) {
144         MessageQ_getConfig(&msgqCfg);
145         MessageQ_setup(&msgqCfg);
147         /*
148          * Attach to all remote processors.  We need to attach to
149          * at least one, so tolerate MessageQ_E_RESOURCE failures for
150          * now.
151          */
152         status = Ipc_S_SUCCESS;
153         attachedAny = FALSE;
155         for (rprocId = 0; rprocId < MultiProc_getNumProcessors(); rprocId++) {
156             if (0 == rprocId) {
157                 /* Skip host, which should always be 0th entry. */
158                 continue;
159             }
161             params.rprocId = rprocId;
162             transport = TransportRpmsg_create(&params, &attachStatus);
164             if (transport) {
165                 iMsgQTrans = TransportRpmsg_upCast(transport);
166                 MessageQ_registerTransport(iMsgQTrans, rprocId, 0);
168                 attachedAny = TRUE;
169             }
170             else {
171                 if (attachStatus == MessageQ_E_RESOURCE) {
172                     continue;
173                 }
175                 printf("Ipc_start: failed to attach to %d: %d\n",
176                        rprocId, attachStatus);
178                 status = Ipc_E_FAIL;
180                 break;
181             }
182         }
183         if (!attachedAny) {
184             status = Ipc_E_FAIL;
185         }
186     }
187     else {
188         printf("Ipc_start: NameServer_setup() failed: %d\n", status);
189         status = Ipc_E_FAIL;
190     }
192     /* Start GateMP only if device has support */
193 #if defined(GATEMP_SUPPORT)
194     if (GateMP_isSetup()) {
195         /*
196          * Get HWSpinlock base address and size from LAD and
197          * initialize the local config structure.
198          */
199         GateHWSpinlock_getConfig(&gateHWCfg);
200         _GateHWSpinlock_cfgParams = gateHWCfg;
202         status = GateHWSpinlock_start();
203         if (status < 0) {
204             printf("Ipc_start: GateHWSpinlock_start failed: %d\n",
205                 status);
206             status = Ipc_E_FAIL;
207             goto gatehwspinlockstart_fail;
208         }
209         else {
210             status = GateMP_start();
211             if (status < 0) {
212                 printf("Ipc_start: GateMP_start failed: %d\n",
213                 status);
214                 status = Ipc_E_FAIL;
215                 goto gatempstart_fail;
216             }
217         }
218     }
219 #endif
220     /* Success */
221     goto exit;
222 #if defined(GATEMP_SUPPORT)
223 gatempstart_fail:
224     GateHWSpinlock_stop();
225 gatehwspinlockstart_fail:
226 #if 0
227     for (rprocId = rprocId - 1; (rprocId > 0) && (status >= 0); rprocId--) {
228         MessageQ_detach(rprocId);
229     }
230 #endif
231 #endif
233 exit:
234     return (status);
238 /* Function to stop Ipc */
239 Int Ipc_stop (Void)
241     Int32             status = Ipc_S_SUCCESS;
242     LAD_Status        ladStatus;
243     UInt16            rprocId;
245     /* Now detach from all remote processors, assuming they are up. */
246     for (rprocId = 0;
247          (rprocId < MultiProc_getNumProcessors()) && (status >= 0);
248          rprocId++) {
249         if (0 == rprocId) {
250           /* Skip host, which should always be 0th entry. */
251           continue;
252         }
253 #if 0
254         status = MessageQ_detach(rprocId);
255         if (status < 0) {
256             printf("Ipc_stop: MessageQ_detach(%d) failed: %d\n",
257                 rprocId, status);
258             status = Ipc_E_FAIL;
259             goto exit;
260        }
261 #endif
262     }
264     status = MessageQ_destroy();
265     if (status < 0) {
266         printf("Ipc_stop: MessageQ_destroy() failed: %d\n", status);
267         status = Ipc_E_FAIL;
268         goto exit;
269     }
271     status = NameServer_destroy();
272     if (status < 0) {
273         printf("Ipc_stop: NameServer_destroy() failed: %d\n", status);
274         status = Ipc_E_FAIL;
275         goto exit;
276     }
278     ladStatus = LAD_disconnect(ladHandle);
279     if (ladStatus != LAD_SUCCESS) {
280         printf("LAD_disconnect() failed: %d\n", ladStatus);
281         status = Ipc_E_FAIL;
282         goto exit;
283     }
285 exit:
286     return (status);
289 static void cleanup(int arg)
291     printf("Ipc: Caught SIGINT, calling Ipc_stop...\n");
292     Ipc_stop();
293     exit(0);