50d4ec2304f196837d334df572ecc1eff3b8dd54
[keystone-rtos/rm-lld.git] / src / rm_transport.c
1 /**\r
2  *   @file  rm.c\r
3  *\r
4  *   @brief   \r
5  *      This is the Resource Manager source.\r
6  *\r
7  *  \par\r
8  *  ============================================================================\r
9  *  @n   (C) Copyright 2012-2013, Texas Instruments, Inc.\r
10  * \r
11  *  Redistribution and use in source and binary forms, with or without \r
12  *  modification, are permitted provided that the following conditions \r
13  *  are met:\r
14  *\r
15  *    Redistributions of source code must retain the above copyright \r
16  *    notice, this list of conditions and the following disclaimer.\r
17  *\r
18  *    Redistributions in binary form must reproduce the above copyright\r
19  *    notice, this list of conditions and the following disclaimer in the \r
20  *    documentation and/or other materials provided with the   \r
21  *    distribution.\r
22  *\r
23  *    Neither the name of Texas Instruments Incorporated nor the names of\r
24  *    its contributors may be used to endorse or promote products derived\r
25  *    from this software without specific prior written permission.\r
26  *\r
27  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
28  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
29  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
30  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
31  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
32  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
33  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
34  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
35  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
36  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
37  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
38  *\r
39  *  \par\r
40 */\r
41 \r
42 /* Standard includes */\r
43 #include <string.h>\r
44 \r
45 /* RM external includes */\r
46 #include <ti/drv/rm/rm.h>\r
47 #include <ti/drv/rm/rm_transport.h>\r
48 \r
49 /* RM internal includes */\r
50 #include <ti/drv/rm/include/rm_loc.h>\r
51 #include <ti/drv/rm/include/rm_transportloc.h>\r
52 \r
53 /* RM OSAL layer */\r
54 #include <rm_osal.h>\r
55 \r
56 /**********************************************************************\r
57  ********************** Internal Functions ****************************\r
58  **********************************************************************/\r
59 \r
60 static Rm_Transport *transportAdd(Rm_TransportCfg *transportCfg)\r
61 {\r
62     Rm_Inst      *rmInst = (Rm_Inst *) transportCfg->rmHandle;\r
63     Rm_Transport *transports = rmInst->transports;\r
64     Rm_Transport *newTransport = NULL;\r
65 \r
66     newTransport = Rm_osalMalloc (sizeof(Rm_Transport));\r
67     memset((void *)newTransport, 0, sizeof(Rm_Transport));\r
68 \r
69     if (newTransport) {\r
70         newTransport->rmHandle = transportCfg->rmHandle;\r
71         newTransport->appTransportHandle = transportCfg->appTransportHandle;\r
72         newTransport->remoteInstType = transportCfg->remoteInstType;\r
73         strncpy(newTransport->remoteInstName, transportCfg->remoteInstName, RM_NAME_MAX_CHARS);\r
74         newTransport->nextTransport = NULL;\r
75 \r
76         if (transports) {\r
77             while (transports->nextTransport) {\r
78                 transports = transports->nextTransport;\r
79             }\r
80             transports->nextTransport = newTransport;\r
81         }\r
82         else {\r
83             rmInst->transports = (void *)newTransport;\r
84         }\r
85     }\r
86     return (newTransport);\r
87 }\r
88 \r
89 static bool transportIsTransportRegistered(Rm_Handle rmHandle, Rm_Transport *transport)\r
90 {\r
91     Rm_Inst      *rmInst = (Rm_Inst *)rmHandle;\r
92     Rm_Transport *transportList = (Rm_Transport *)rmInst->transports;\r
93     \r
94     while (transportList) {\r
95         if (transportList == transport) {\r
96             return(TRUE);             \r
97         }\r
98         transportList = transportList->nextTransport;\r
99     }\r
100     return (FALSE);\r
101 }\r
102 \r
103 static void transportDelete(Rm_Transport *transport)\r
104 {\r
105     Rm_Inst      *rmInst = (Rm_Inst *)transport->rmHandle;\r
106     Rm_Transport *transportList = (Rm_Transport *)rmInst->transports;\r
107     Rm_Transport *prevTransport = NULL;\r
108 \r
109     /* Get previous transport in list */\r
110     while (transportList) {\r
111         if (transportList == transport) {\r
112             break;             \r
113         }\r
114         prevTransport = transportList;\r
115         transportList = transportList->nextTransport;\r
116     }\r
117 \r
118     if (prevTransport == NULL) {\r
119          rmInst->transports = (void *)transport->nextTransport;\r
120     }\r
121     else {\r
122          prevTransport->nextTransport = transport->nextTransport;\r
123     }\r
124     Rm_osalFree((void *)transport, sizeof(Rm_Transport));\r
125 }\r
126 \r
127 Rm_Transport *rmTransportFindRemoteName(Rm_Transport *transports, char *remoteName)\r
128 {\r
129     while (transports) {\r
130         if (strncmp(transports->remoteInstName, remoteName, RM_NAME_MAX_CHARS) == 0) {\r
131             break;             \r
132         }\r
133         transports = transports->nextTransport;\r
134     }\r
135     return (transports);\r
136 }\r
137 \r
138 Rm_Transport *rmTransportFindRemoteInstType(Rm_Transport *transports, Rm_InstType remoteInstType)\r
139 {\r
140     while (transports) {\r
141         if (transports->remoteInstType == remoteInstType) {\r
142             break;             \r
143         }\r
144         transports = transports->nextTransport;\r
145     }\r
146     return (transports);\r
147 }\r
148 \r
149 Rm_PacketHandle rmTransportCreateResourceReqPkt(Rm_Inst *rmInst, Rm_AppTransportHandle appTransport,\r
150                                                 Rm_Transaction *transaction)\r
151 {\r
152     Rm_Packet             *rmPkt = NULL;\r
153     Rm_PacketHandle        pktHandle = NULL;\r
154     Rm_ResourceRequestPkt *resourceReqPkt = NULL;\r
155 \r
156     if ((rmPkt = rmInst->transportCallouts.rmAllocPkt(appTransport, \r
157                                                       sizeof(Rm_Packet),\r
158                                                       &pktHandle)) == NULL) {\r
159         transaction->state = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
160         return (NULL);\r
161     }\r
162    \r
163     rmPkt->pktType = Rm_pktType_RESOURCE_REQUEST;\r
164     resourceReqPkt = (Rm_ResourceRequestPkt *) rmPkt->data;\r
165     resourceReqPkt->requestId = transaction->localId;\r
166     if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {\r
167         resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_INIT;\r
168     }\r
169     else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {\r
170         resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_USE;\r
171     }    \r
172     else if (transaction->type == Rm_service_RESOURCE_FREE) {\r
173         resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE;\r
174     }\r
175     else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {\r
176         resourceReqPkt->resourceReqType = Rm_resReqPktType_GET_NAMED;\r
177     }\r
178     strncpy(resourceReqPkt->pktSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);\r
179     strncpy(resourceReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
180     memcpy ((void *)&(resourceReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
181             sizeof(Rm_ResourceInfo));\r
182     \r
183     return (pktHandle);\r
184 }\r
185 \r
186 Rm_PacketHandle rmTransportCreateResourceResponsePkt(Rm_Inst *rmInst, Rm_AppTransportHandle appTransport,\r
187                                                      Rm_Transaction *transaction)\r
188 {\r
189     Rm_Packet              *rmPkt = NULL;\r
190     Rm_PacketHandle         pktHandle = NULL;\r
191     Rm_ResourceResponsePkt *resourceRespPkt = NULL;\r
192 \r
193     if ((rmPkt = rmInst->transportCallouts.rmAllocPkt(appTransport, \r
194                                                       sizeof(Rm_Packet),\r
195                                                       &pktHandle)) == NULL) {\r
196         transaction->state = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
197         return (NULL);\r
198     }\r
199  \r
200     rmPkt->pktType = Rm_pktType_RESOURCE_RESPONSE;                 \r
201     resourceRespPkt = (Rm_ResourceResponsePkt *)rmPkt->data;\r
202     resourceRespPkt->responseId = transaction->remoteOriginatingId;\r
203     resourceRespPkt->requestState = transaction->state;\r
204     memcpy ((void *)&(resourceRespPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
205             sizeof(Rm_ResourceInfo));\r
206 \r
207     return (pktHandle);\r
208 }\r
209 \r
210 Rm_PacketHandle rmTransportCreateNsRequestPkt(Rm_Inst *rmInst, Rm_AppTransportHandle appTransport,\r
211                                               Rm_Transaction *transaction)\r
212 {\r
213     Rm_Packet       *rmPkt = NULL;\r
214     Rm_PacketHandle  pktHandle = NULL;    \r
215     Rm_NsRequestPkt *nsReqPkt = NULL;\r
216 \r
217     if ((rmPkt = rmInst->transportCallouts.rmAllocPkt(appTransport, \r
218                                                       sizeof(Rm_Packet),\r
219                                                       &pktHandle)) == NULL) {\r
220         transaction->state = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
221         return (NULL);\r
222     }\r
223 \r
224     rmPkt->pktType = Rm_pktType_NAMESERVER_REQUEST;                   \r
225     nsReqPkt = (Rm_NsRequestPkt *)rmPkt->data;\r
226     nsReqPkt->requestId = transaction->localId;\r
227     if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {\r
228         nsReqPkt->nsRequestType = Rm_nsReqPktType_MAP_RESOURCE;\r
229     }\r
230     else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {\r
231         nsReqPkt->nsRequestType = Rm_nsReqPktType_UNMAP_RESOURCE;\r
232     }\r
233     strncpy(nsReqPkt->pktSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);\r
234     strncpy(nsReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
235     memcpy ((void *)&(nsReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
236             sizeof(Rm_ResourceInfo));\r
237     \r
238     return (pktHandle);\r
239 }\r
240 \r
241 Rm_PacketHandle rmTransportCreateNsResponsePkt(Rm_Inst *rmInst, Rm_AppTransportHandle appTransport,\r
242                                                Rm_Transaction *transaction)\r
243 {\r
244     Rm_Packet        *rmPkt = NULL;\r
245     Rm_PacketHandle   pktHandle = NULL;\r
246     Rm_NsResponsePkt *nsRespPkt = NULL;\r
247 \r
248     if ((rmPkt = rmInst->transportCallouts.rmAllocPkt(appTransport, \r
249                                                       sizeof(Rm_Packet),\r
250                                                       &pktHandle)) == NULL) {\r
251         transaction->state = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
252         return (NULL);\r
253     }\r
254  \r
255     rmPkt->pktType = Rm_pktType_NAMESERVER_RESPONSE;                \r
256     nsRespPkt = (Rm_NsResponsePkt *)rmPkt->data;\r
257     nsRespPkt->responseId = transaction->remoteOriginatingId;\r
258     nsRespPkt->requestState = transaction->state;\r
259 \r
260     return (pktHandle);\r
261 }\r
262 \r
263 /**********************************************************************\r
264  ********************* Application visible APIs ***********************\r
265  **********************************************************************/\r
266 \r
267 Rm_TransportHandle Rm_transportRegister (Rm_TransportCfg *transportCfg, int32_t *result)\r
268 {\r
269     Rm_Inst      *rmInst = (Rm_Inst *) transportCfg->rmHandle;\r
270     Rm_Transport *transport = NULL;\r
271 \r
272     /* RM Servers cannot connect to other Servers.  RM Client Delegates cannot\r
273      * connect to other Client Delegates. */\r
274     if (((rmInst->instType == Rm_instType_SERVER) &&\r
275          (transportCfg->remoteInstType == Rm_instType_SERVER)) ||\r
276         ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
277          (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE))) {\r
278         *result = RM_TRANSPORT_ERROR_INVALID_REMOTE_INST_TYPE;\r
279         return(NULL);\r
280     }\r
281 \r
282     /* Verify Clients are not registering with more than one Client Delegate or Server. And\r
283      * that Client Delegate is not registering with more than one Server. */\r
284     if (rmInst->registeredWithDelegateOrServer &&\r
285         (((rmInst->instType == Rm_instType_CLIENT) &&\r
286           (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)) || \r
287          ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
288           (transportCfg->remoteInstType == Rm_instType_SERVER)))) {\r
289         *result = RM_TRANSPORT_ERROR_REGISTERING_WITH_MORE_THAN_ONE_SERVER_OR_CD;\r
290         return(NULL);\r
291     }         \r
292     \r
293     if (transportCfg->transportCalloutsValid &&\r
294         ((transportCfg->transportCallouts.rmAllocPkt == NULL) ||\r
295          (transportCfg->transportCallouts.rmSendPkt == NULL))) {\r
296         *result = RM_TRANSPORT_ERROR_CALLOUTS_VALID_BUT_NULL_PROVIDED;\r
297         return(NULL);\r
298     }\r
299     else {\r
300         rmInst->transportCallouts.rmAllocPkt = transportCfg->transportCallouts.rmAllocPkt;\r
301         rmInst->transportCallouts.rmSendPkt = transportCfg->transportCallouts.rmSendPkt;\r
302     }\r
303 \r
304     transport = transportAdd(transportCfg);\r
305 \r
306     if ((transport->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
307         (transport->remoteInstType == Rm_instType_SERVER)) {\r
308         rmInst->registeredWithDelegateOrServer = true;\r
309     }\r
310 \r
311     *result = RM_INIT_OK;\r
312     return ((Rm_TransportHandle) transport);\r
313 }\r
314 \r
315 int32_t Rm_transportUnregister(Rm_TransportHandle transportHandle)\r
316 {\r
317     Rm_Transport *transport = (Rm_Transport *)transportHandle;\r
318     Rm_Inst      *rmInst = (Rm_Inst *)transport->rmHandle;\r
319     int32_t       retVal = RM_TRANSPORT_SUCCESSFUL;  \r
320 \r
321     if (transportIsTransportRegistered(transport->rmHandle, transport)) {\r
322         if ((transport->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
323             (transport->remoteInstType == Rm_instType_SERVER)) {\r
324             rmInst->registeredWithDelegateOrServer = false;\r
325         }\r
326         transportDelete(transport);\r
327     }\r
328     else {\r
329         retVal = RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED;\r
330     }\r
331     return (retVal);\r
332 }\r
333 \r
334 /* Used by the application to pass RM packets received from a transport to RM.\r
335  * Function can be called from polling or ISR context. */\r
336 int32_t Rm_receivePacket(Rm_TransportHandle transportHandle, Rm_Packet *pkt)\r
337 {\r\r\r
338     Rm_Transport   *transport = (Rm_Transport *)transportHandle;\r
339     Rm_Inst        *rmInst = (Rm_Inst *)transport->rmHandle;\r
340     Rm_Transaction *transaction;\r
341 \r
342     if (!transportIsTransportRegistered(transport->rmHandle, transport)) {\r
343         return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
344     }\r
345 \r
346     switch (pkt->pktType) {\r
347         case Rm_pktType_RESOURCE_REQUEST:\r
348         {\r
349             Rm_ResourceRequestPkt *resourceReqPkt = (Rm_ResourceRequestPkt *)pkt->data;\r
350 \r
351             transaction = rmTransactionQueueAdd(rmInst);\r
352             transaction->remoteOriginatingId = resourceReqPkt->requestId;\r
353             if (resourceReqPkt->resourceReqType == Rm_resReqPktType_ALLOCATE_INIT) {\r
354                 transaction->type = Rm_service_RESOURCE_ALLOCATE_INIT;\r
355             }\r
356             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_ALLOCATE_USE) {\r
357                 transaction->type = Rm_service_RESOURCE_ALLOCATE_USE;\r
358             }            \r
359             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_FREE) {\r
360                 transaction->type = Rm_service_RESOURCE_FREE;\r
361             }\r
362             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_GET_NAMED) {\r
363                 transaction->type = Rm_service_RESOURCE_GET_BY_NAME;\r
364             }            \r
365             strncpy(transaction->pktSrcInstName, resourceReqPkt->pktSrcInstName, RM_NAME_MAX_CHARS);\r
366             strncpy(transaction->serviceSrcInstName, resourceReqPkt->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
367             transaction->state = RM_SERVICE_PROCESSING;\r
368             memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceReqPkt->resourceInfo),\r
369                     sizeof(Rm_ResourceInfo));\r
370             rmTransactionProcessor(rmInst, transaction);\r
371             break;\r
372         }\r
373         case Rm_pktType_RESOURCE_RESPONSE:\r
374         {\r
375             Rm_ResourceResponsePkt *resourceRespPkt = (Rm_ResourceResponsePkt *)pkt->data;\r
376 \r
377             if (transaction = rmTransactionQueueFind(rmInst,resourceRespPkt->responseId)) {\r
378                 transaction->state = resourceRespPkt->requestState;\r
379 \r
380                 if ((transaction->state == RM_SERVICE_APPROVED_AND_COMPLETED) &&\r
381                     ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||\r
382                      (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||\r
383                      (transaction->type == Rm_service_RESOURCE_GET_BY_NAME))) {\r
384                     memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceRespPkt->resourceInfo),\r
385                             sizeof(Rm_ResourceInfo));\r
386                 }\r
387                 rmTransactionProcessor(rmInst, transaction);\r
388             }\r
389             else {\r
390                 return (RM_TRANSPORT_ERROR_MATCHING_RESOURCE_REQUEST_NOT_FOUND);\r
391             }\r
392             break;\r
393         }\r
394         case Rm_pktType_NAMESERVER_REQUEST:\r
395         {\r
396             Rm_NsRequestPkt *nsRequestPkt = (Rm_NsRequestPkt *)pkt->data;\r
397 \r
398             transaction = rmTransactionQueueAdd(rmInst);\r
399             transaction->remoteOriginatingId = nsRequestPkt->requestId;\r
400 \r
401             if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_MAP_RESOURCE) {\r
402                 transaction->type = Rm_service_RESOURCE_MAP_TO_NAME;\r
403             }\r
404             else if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_UNMAP_RESOURCE) {\r
405                 transaction->type = Rm_service_RESOURCE_UNMAP_NAME;\r
406             }\r
407 \r
408             strncpy(transaction->pktSrcInstName, nsRequestPkt->pktSrcInstName, RM_NAME_MAX_CHARS);\r
409             strncpy(transaction->serviceSrcInstName, nsRequestPkt->serviceSrcInstName, RM_NAME_MAX_CHARS);\r
410             transaction->state = RM_SERVICE_PROCESSING;\r
411             memcpy ((void *)&(transaction->resourceInfo), (void *)&(nsRequestPkt->resourceInfo),\r
412                     sizeof(Rm_ResourceInfo));\r
413             rmTransactionProcessor(rmInst, transaction);            \r
414             break;\r
415         }\r
416         case Rm_pktType_NAMESERVER_RESPONSE:\r
417         {\r
418             Rm_NsResponsePkt *nsResponsePkt = (Rm_NsResponsePkt *)pkt->data;\r
419 \r
420             if (transaction = rmTransactionQueueFind(rmInst, nsResponsePkt->responseId)) {\r
421                 transaction->state = nsResponsePkt->requestState;            \r
422                 rmTransactionProcessor(rmInst, transaction);\r
423             }\r
424             else {\r
425                 return (RM_TRANSPORT_ERROR_MATCHING_NAME_SERVER_REQUEST_NOT_FOUND);\r
426             }\r
427             break;\r
428         }\r
429         default:\r
430             return (RM_TRANSPORT_ERROR_INVALID_PACKET_TYPE);\r
431       }\r
432 \r
433     return (RM_TRANSPORT_SUCCESSFUL);\r
434 }\r
435 \r