Basic infrastructure coded. All compiler errors resolved
[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, 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 /* RM Types */\r
43 #include <ti/drv/rm/rm_types.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 Rm_TransportNode *Rm_transportNodeAdd(Rm_Inst *rmInst, Rm_TransportCfg *transportCfg)\r
61 {\r
62     Rm_TransportNode *routeMap = (Rm_TransportNode *)rmInst->routeMap;\r
63     Rm_TransportNode *newTransportNode = NULL;\r
64     void *key;\r
65 \r
66     /* Lock access to the RM instance's route map */\r
67     key = Rm_osalLocalCsEnter();\r
68 \r
69     /* Get memory for a new transport node from local memory */\r
70     newTransportNode = Rm_osalMalloc (sizeof(Rm_TransportNode), false);\r
71 \r
72     /* Return if the memory allocated for the transport node is NULL */\r
73     if (newTransportNode != NULL)\r
74     {\r
75         /* Populate the new entry. */\r
76         newTransportNode->remoteInstType = transportCfg->remoteInstType;\r
77         strcpy(&(newTransportNode->remoteInstName)[0], transportCfg->remoteInstName);\r
78         newTransportNode->nextNode = NULL;  /* New node will always be NULL */\r
79 \r
80         /* Check if there are any nodes in the transport routing map */\r
81         if (routeMap)\r
82         {\r
83             /* At least one node in the routing map.  Add the new node to the end of the\r
84              * routing map */\r
85             while (routeMap->nextNode != NULL)\r
86             {\r
87                 /* Traverse the list until arriving at the last node */\r
88                 routeMap = (Rm_TransportNode *)routeMap->nextNode;\r
89             }\r
90 \r
91             /* Add the new node to the end of the list */\r
92             routeMap->nextNode = (void *)newTransportNode;\r
93         }\r
94         else\r
95         {\r
96             /* The transport routing map does not currently exist.  The new node is the first node */\r
97             rmInst->routeMap = (void *)newTransportNode;\r
98         }\r
99     }\r
100    \r
101     Rm_osalLocalCsExit(key);\r
102 \r
103     return (newTransportNode);\r
104 }\r
105 \r
106 Rm_TransportNode *Rm_transportNodeFindTransportHandle(Rm_Inst *rmInst, \r
107                                                       Rm_TransportHandle transportHandle)\r
108 {\r
109     Rm_TransportNode *transportNode = (Rm_TransportNode *)rmInst->routeMap;\r
110 \r
111     /* Make sure there is at least one node in the route map */\r
112     if (transportNode != NULL)\r
113     {\r
114         /* Find the transport node with the transport handle within the RM instance's\r
115          * route map.  If the end of the route map is reached without finding the node the \r
116          * node pointer will be NULL */\r
117         while (transportNode != NULL)\r
118         {\r
119             /* The transport handle is the address of the transport node */\r
120             if (transportNode == ((Rm_TransportNode *)transportHandle))\r
121             {\r
122                 /* Match: break out of loop and return the node */\r
123                 break;             \r
124             }\r
125             transportNode = (Rm_TransportNode *)transportNode->nextNode;\r
126         }\r
127     }\r
128 \r
129     return (transportNode);\r
130 }\r
131 \r
132 Rm_TransportNode *Rm_transportNodeFindRemoteName(Rm_Inst *rmInst, char *remoteName)\r
133 {\r
134     Rm_TransportNode *transportNode = (Rm_TransportNode *)rmInst->routeMap;\r
135 \r
136     /* Make sure there is at least one node in the route map */\r
137     if (transportNode != NULL)\r
138     {\r
139         /* Find the transport node with the provided remote instance name.\r
140          * If the end of the route map is reached without finding the node the \r
141          * node pointer will be NULL */\r
142         while (transportNode != NULL)\r
143         {\r
144             /* The transport handle is the address of the transport node */\r
145             if (strcmp(&(transportNode->remoteInstName)[0], remoteName) == 0)\r
146             {\r
147                 /* Match: break out of loop and return the node */\r
148                 break;             \r
149             }\r
150             transportNode = (Rm_TransportNode *)transportNode->nextNode;\r
151         }\r
152     }\r
153 \r
154     return (transportNode);\r
155 }\r
156 \r
157 Rm_TransportNode *Rm_transportNodeFindRemoteInstType(Rm_Inst *rmInst,\r
158                                                      Rm_InstType remoteInstType)\r
159 {\r
160     Rm_TransportNode *transportNode = (Rm_TransportNode *)rmInst->routeMap;\r
161 \r
162     /* Make sure there is at least one node in the route map */\r
163     if (transportNode != NULL)\r
164     {\r
165         /* Find the transport node with the provided remote instance type.\r
166          * If the end of the route map is reached without finding the node the \r
167          * node pointer will be NULL */\r
168         while (transportNode != NULL)\r
169         {\r
170             if (transportNode->remoteInstType == remoteInstType)\r
171             {\r
172                 /* Match: break out of loop and return the node */\r
173                 break;             \r
174             }\r
175             transportNode = (Rm_TransportNode *)transportNode->nextNode;\r
176         }\r
177     }\r
178 \r
179     return (transportNode);\r
180 }\r
181 \r
182 Rm_TransportResult Rm_transportNodeDelete(Rm_Inst *rmInst, Rm_TransportHandle transportHandle)\r
183 {\r
184     Rm_TransportNode *transportNode = (Rm_TransportNode *)rmInst->routeMap;\r
185     Rm_TransportNode *prevNode = NULL;\r
186     void *key;\r
187 \r
188     /* Lock access to the RM instance's route map */\r
189     key = Rm_osalLocalCsEnter();\r
190 \r
191     /* Make sure there is at least one entry in the transaction queue */\r
192     if (transportNode == NULL)\r
193     {\r
194         Rm_osalLocalCsExit(key);\r
195         return (RM_TRANSPORT_ERROR_NO_TRANSPORTS_REGISTERED);\r
196     }\r
197 \r
198     /* Find the transport handle within the RM instance's route map. */\r
199     while (transportNode != NULL)\r
200     {\r
201         if (transportNode == (Rm_TransportNode *) transportHandle)\r
202         {\r
203             /* Match: break out of loop and delete the entry */\r
204             break;             \r
205         }\r
206 \r
207         prevNode = transportNode;\r
208         transportNode = (Rm_TransportNode *)transportNode->nextNode;\r
209     }\r
210 \r
211     /* Traversed entire queue but did not find transaction */\r
212     if (transportNode == NULL)\r
213     {\r
214         Rm_osalLocalCsExit(key);\r
215         return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
216     }\r
217     else\r
218     {\r
219         /* Delete the transport node */\r
220         if ((prevNode == NULL) && transportNode->nextNode)\r
221         {\r
222             /* Node to be deleted exists at start of route map.  Map second\r
223              * node to be start of route map as long as there are more than\r
224              * one nodes */\r
225             rmInst->routeMap = transportNode->nextNode;\r
226         }\r
227         else\r
228         {\r
229             /* Node to be deleted is in the middle or at end of the route map.  Adjust adjacent\r
230              * node pointers.  This covers the case where the node to be removed is at the\r
231              * end of the route map. */\r
232             prevNode->nextNode = transportNode->nextNode;\r
233         }\r
234 \r
235         /* Free the memory associated with the node. */\r
236         Rm_osalFree((void *) transportNode, sizeof(Rm_TransportNode), false);\r
237     }\r
238 \r
239     Rm_osalLocalCsExit(key);\r
240     return (RM_TRANSPORT_SUCCESSFUL);\r
241 }\r
242 \r
243 Rm_Packet *Rm_transportCreateResourceReqPkt(Rm_Inst *rmInst, Rm_TransportNode *dstTransportNode,\r
244                                             Rm_Transaction *transaction, Rm_TransactionReceipt *receipt)\r
245 {\r
246     Rm_Packet *rmPkt = NULL;\r
247     Rm_ResourceRequestPkt *resourceReqPkt = NULL;\r
248 \r
249     /* Make sure a buffer for the packet was allocated  */\r
250     if ((rmPkt = rmInst->transport.rmAllocPkt((Rm_TransportHandle)dstTransportNode, sizeof(Rm_Packet))) ==\r
251         NULL)\r
252     {\r
253         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
254         return (NULL);\r
255     }\r
256 \r
257     /* Make sure allocated buffer is large enough to fit the request packet plus the \r
258      * rmPktLen and Rm_PktType fields */\r
259     if (rmPkt->pktLenBytes < (sizeof(Rm_ResourceRequestPkt) + sizeof(uint32_t) + sizeof(Rm_pktType)))\r
260     {   \r
261         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;\r
262         return (NULL);\r
263     }\r
264 \r
265     /* Set the Rm Packet type */    \r
266     rmPkt->pktType = Rm_pktType_RESOURCE_REQUEST;\r
267                           \r
268     /* Assign the packet's data field to be the start of the resource request packet */\r
269     resourceReqPkt = (Rm_ResourceRequestPkt *) rmPkt->data;\r
270     /* Populate the resource request packet using the transaction information */\r
271     resourceReqPkt->requestId = transaction->id;\r
272     if (transaction->type == Rm_service_RESOURCE_ALLOCATE)\r
273     {\r
274         resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE;\r
275     }\r
276     else if (transaction->type == Rm_service_RESOURCE_BLOCK_ALLOCATE)\r
277     {\r
278         resourceReqPkt->resourceReqType = Rm_resReqPktType_BLOCK_ALLOCATE;\r
279     }\r
280     else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_BY_NAME)\r
281     {\r
282         resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_NAMED;\r
283     }\r
284     else if (transaction->type == Rm_service_RESOURCE_FREE)\r
285     {\r
286         resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE;\r
287     }\r
288     else if (transaction->type == Rm_service_RESOURCE_BLOCK_FREE)\r
289     {\r
290         resourceReqPkt->resourceReqType = Rm_resReqPktType_BLOCK_FREE;\r
291     }\r
292     else if (transaction->type == Rm_service_RESOURCE_FREE_BY_NAME)\r
293     {\r
294         resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE_NAMED;\r
295     }\r
296     strcpy(&(resourceReqPkt->instName)[0], rmInst->name);\r
297     /* Copy the resource data */\r
298     memcpy ((void *)&(resourceReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
299             sizeof(Rm_ResourceInfo));\r
300 \r
301     return (rmPkt);\r
302 }\r
303 \r
304 Rm_Packet *Rm_transportCreateResourceResponsePkt(Rm_Inst *rmInst, Rm_TransportNode *dstTransportNode,\r
305                                                  Rm_Transaction *transaction, Rm_TransactionReceipt *receipt)\r
306 {\r
307     Rm_Packet *rmPkt = NULL;\r
308     Rm_ResourceResponsePkt *resourceRespPkt = NULL;\r
309 \r
310     /* Make sure a buffer for the packet was allocated  */\r
311     if ((rmPkt = rmInst->transport.rmAllocPkt((Rm_TransportHandle)dstTransportNode, sizeof(Rm_Packet))) ==\r
312         NULL)\r
313     {\r
314         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
315         return (NULL);\r
316     }\r
317 \r
318     /* Make sure allocated buffer is large enough to fit the request packet plus the \r
319      * rmPktLen and Rm_PktType fields */\r
320     if (rmPkt->pktLenBytes < (sizeof(Rm_ResourceResponsePkt) + sizeof(uint32_t) + sizeof(Rm_pktType)))\r
321     {   \r
322         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;\r
323         return (NULL);\r
324     }\r
325 \r
326     /* Set the Rm Packet type */    \r
327     rmPkt->pktType = Rm_pktType_RESOURCE_RESPONSE;\r
328                           \r
329     /* Assign the packet's data field to be the start of the resource response packet */\r
330     resourceRespPkt = (Rm_ResourceResponsePkt *)rmPkt->data;\r
331     /* Populate the resource response packet using the transaction information */\r
332     resourceRespPkt->responseId = transaction->id;\r
333     resourceRespPkt->requestResult = transaction->details;\r
334     /* Copy the resource data */\r
335     memcpy ((void *)&(resourceRespPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
336             sizeof(Rm_ResourceInfo));\r
337 \r
338     return (rmPkt);\r
339 }\r
340 \r
341 Rm_Packet *Rm_transportCreateNsRequestPkt(Rm_Inst *rmInst, Rm_TransportNode *dstTransportNode,\r
342                                           Rm_Transaction *transaction, Rm_TransactionReceipt *receipt)\r
343 {\r
344     Rm_Packet *rmPkt = NULL;\r
345     Rm_NsRequestPkt *nsReqPkt = NULL;\r
346 \r
347     /* Make sure a buffer for the packet was allocated  */\r
348     if ((rmPkt = rmInst->transport.rmAllocPkt((Rm_TransportHandle)dstTransportNode, sizeof(Rm_Packet))) ==\r
349         NULL)\r
350     {\r
351         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
352         return (NULL);\r
353     }\r
354 \r
355     /* Make sure allocated buffer is large enough to fit the request packet plus the \r
356      * rmPktLen and Rm_PktType fields */\r
357     if (rmPkt->pktLenBytes < (sizeof(Rm_NsRequestPkt) + sizeof(uint32_t) + sizeof(Rm_pktType)))\r
358     {   \r
359         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;\r
360         return (NULL);\r
361     }\r
362 \r
363     /* Set the Rm Packet type */    \r
364     rmPkt->pktType = Rm_pktType_NAMESERVER_REQUEST;\r
365                           \r
366     /* Assign the packet's data field to be the start of the NameServer request packet */\r
367     nsReqPkt = (Rm_NsRequestPkt *)rmPkt->data;\r
368     /* Populate the NameServer request packet using the transaction information */\r
369     nsReqPkt->requestId = transaction->id;\r
370     if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME)\r
371     {\r
372         nsReqPkt->nsRequestType = Rm_nsReqPktType_MAP_RESOURCE;\r
373     }\r
374     else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)\r
375     {\r
376         nsReqPkt->nsRequestType = Rm_nsReqPktType_UNMAP_RESOURCE;\r
377     }\r
378     strcpy(&(nsReqPkt->instName)[0], rmInst->name);\r
379     /* Copy the NameServer request data */\r
380     memcpy ((void *)&(nsReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),\r
381             sizeof(Rm_ResourceInfo));\r
382 \r
383     return (rmPkt);\r
384 }\r
385 \r
386 Rm_Packet *Rm_transportCreateNsResponsePkt(Rm_Inst *rmInst, Rm_TransportNode *dstTransportNode,\r
387                                            Rm_Transaction *transaction, Rm_TransactionReceipt *receipt)\r
388 {\r
389     Rm_Packet *rmPkt = NULL;\r
390     Rm_NsResponsePkt *nsRespPkt = NULL;\r
391 \r
392     /* Make sure a buffer for the packet was allocated  */\r
393     if ((rmPkt = rmInst->transport.rmAllocPkt((Rm_TransportHandle)dstTransportNode, sizeof(Rm_Packet))) ==\r
394         NULL)\r
395     {\r
396         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_ALLOC_PKT_ERROR;\r
397         return (NULL);\r
398     }\r
399 \r
400     /* Make sure allocated buffer is large enough to fit the response packet plus the \r
401      * rmPktLen and Rm_PktType fields */\r
402     if (rmPkt->pktLenBytes < (sizeof(Rm_NsResponsePkt) + sizeof(uint32_t) + sizeof(Rm_pktType)))\r
403     {   \r
404         receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;\r
405         return (NULL);\r
406     }\r
407 \r
408     /* Set the Rm Packet type */    \r
409     rmPkt->pktType = Rm_pktType_NAMESERVER_RESPONSE;\r
410                           \r
411     /* Assign the packet's data field to be the start of the NameServer response packet */\r
412     nsRespPkt = (Rm_NsResponsePkt *)rmPkt->data;\r
413     /* Populate the NameServer response packet using the transaction information */\r
414     nsRespPkt->responseId = transaction->id;\r
415     nsRespPkt->requestResult = transaction->details;\r
416 \r
417     return (rmPkt);\r
418 }\r
419 \r
420 /**********************************************************************\r
421  ********************* Application visible APIs ***********************\r
422  **********************************************************************/\r
423 \r
424 Rm_TransportHandle Rm_transportRegister (Rm_Handle rmHandle, Rm_TransportCfg *transportCfg)\r
425 {\r
426     Rm_Inst *rmInst = (Rm_Inst *) rmHandle;\r
427     Rm_TransportNode *transportNode = NULL;\r
428     void *key;\r
429 \r
430     /* Lock access to the RM instance */\r
431     key = Rm_osalLocalCsEnter();\r
432 \r
433     /* RM Servers cannot connect to other Servers.  RM Client Delegates cannot\r
434      * connect to other Client Delegates. */\r
435     if (((rmInst->instType == Rm_instType_SERVER) &&\r
436          (transportCfg->remoteInstType == Rm_instType_SERVER)) ||\r
437         ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
438          (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)))\r
439     {\r
440         Rm_osalLocalCsExit(key);\r
441         return (NULL); /* Error - return null */\r
442     }\r
443 \r
444     /* Verify Clients and Client Delegates are not registering with more than one \r
445      * Client Delegate or Server. Assuming a Client Delegate can register with another \r
446      * Client Delegate that can "act" as a server */\r
447     if (((rmInst->instType == Rm_instType_CLIENT) &&\r
448          (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)) || \r
449         ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
450          (transportCfg->remoteInstType == Rm_instType_SERVER)) &&\r
451         rmInst->registeredWithDelegateOrServer)\r
452     {\r
453         Rm_osalLocalCsExit(key);\r
454         return (NULL); /* Error - return null */\r
455     }         \r
456 \r
457     /* Copy the transport callout function pointers into the RM instance as long as they're\r
458      * valid or not NULL */\r
459     if (transportCfg->transportCalloutsValid)\r
460     {\r
461         /* The transport APIs must not be NULL */\r
462         if ((transportCfg->transportCallouts.rmAllocPkt == NULL) ||\r
463             (transportCfg->transportCallouts.rmFreePkt == NULL) ||\r
464             (transportCfg->transportCallouts.rmSend == NULL) ||\r
465             (transportCfg->transportCallouts.rmReceive == NULL) ||\r
466             (transportCfg->transportCallouts.rmNumPktsReceived == NULL))\r
467         {\r
468             Rm_osalLocalCsExit(key);\r
469             return (NULL); /* Error - return null */\r
470         }\r
471             \r
472         /* Populate the instance transport callouts */\r
473         rmInst->transport.rmAllocPkt = transportCfg->transportCallouts.rmAllocPkt;\r
474         rmInst->transport.rmFreePkt = transportCfg->transportCallouts.rmFreePkt;\r
475         rmInst->transport.rmSend = transportCfg->transportCallouts.rmSend;\r
476         rmInst->transport.rmReceive = transportCfg->transportCallouts.rmReceive;\r
477         rmInst->transport.rmNumPktsReceived = transportCfg->transportCallouts.rmNumPktsReceived;\r
478     }\r
479 \r
480     /* Error checks passed - Create a new transport handle for the specified RM instance and\r
481      * create a new node in the RM instance's routing map. */\r
482     transportNode = Rm_transportNodeAdd(rmInst, transportCfg);\r
483 \r
484     /* Specify RM instance has registered with a higher level agent */\r
485     if ((transportNode->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
486         (transportNode->remoteInstType == Rm_instType_SERVER))\r
487     {\r
488         rmInst->registeredWithDelegateOrServer = true;\r
489     }\r
490 \r
491     Rm_osalLocalCsExit(key);\r
492     return ((Rm_TransportHandle) transportNode);\r
493 }\r
494 \r
495 Rm_TransportResult Rm_transportUnregister (Rm_Handle rmHandle, Rm_TransportHandle transportHandle)\r
496 {\r
497     Rm_Inst *rmInst = (Rm_Inst *) rmHandle;\r
498     Rm_TransportNode *transportNode = NULL;\r
499     Rm_TransportResult retVal = RM_TRANSPORT_SUCCESSFUL;\r
500     void *key;\r
501 \r
502     /* Lock access to the RM instance */\r
503     key = Rm_osalLocalCsEnter();    \r
504 \r
505     /* Check if the transportHandle exists in the RM instance's route map */\r
506     transportNode = Rm_transportNodeFindTransportHandle(rmInst, transportHandle);\r
507 \r
508     if (transportNode == NULL)\r
509     {\r
510         /* Error - transport node does not exist in RM instance route map */\r
511         Rm_osalLocalCsExit(key);\r
512         return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
513     }\r
514 \r
515     /* Remove specification that RM instance has been connected to an upper level agent\r
516      * if the node to be deleted has a remote instance type of Client Delegate or Server */\r
517     if ((transportNode->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
518         (transportNode->remoteInstType == Rm_instType_SERVER))\r
519     {\r
520         rmInst->registeredWithDelegateOrServer = false;\r
521     }\r
522 \r
523     /* Delete the transport node */\r
524     retVal = Rm_transportNodeDelete(rmInst, transportHandle);\r
525 \r
526     Rm_osalLocalCsExit(key);\r
527 \r
528     return (retVal);\r
529 }\r
530 \r
531 /* Used by the application to pass RM packets received from a transport to RM.\r
532  * CODE THE FUNCTION SUCH THAT IT CAN BE CALLED DIRECTLY BY APP OR BE PLUGGED\r
533  * AS PART OF AN ISR HANDLER FOR THE TRANSACTION RECEIVE */\r
534 int32_t Rm_receivePktIsr(Rm_Handle rmHandle, Rm_TransportHandle transportHandle, Rm_Packet *pkt)\r
535 {\r\r\r
536     Rm_Inst *rmInst = (Rm_Inst *)rmHandle;\r
537     Rm_Transaction *transaction;\r
538     Rm_TransactionReceipt receipt;\r
539 \r
540     /* Make sure the transport handle is registered with the provided RM instance */\r
541     if (Rm_transportNodeFindTransportHandle(rmInst, transportHandle) == NULL)\r
542     {\r
543         /* Transport is not registered with the RM instance.  Return an error.\r
544          * The packet cannot be freed since the transport handle is not valid. */\r
545         return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
546     }\r
547 \r
548     /* Clear the transaction receipt */\r
549     memset((void *)&receipt, 0, sizeof(Rm_TransactionReceipt));\r
550 \r
551     /* Based on packet type transfer the data to a transaction or a policy structure */\r
552     switch (pkt->pktType)\r
553     {\r
554         case Rm_pktType_RESOURCE_REQUEST:\r
555         {\r
556             Rm_ResourceRequestPkt *resourceReqPkt = (Rm_ResourceRequestPkt *)pkt->data;\r
557 \r
558             /* The transaction ID will be the request ID.  The request ID\r
559              * will become the response packet's ID so the requesting RM instance\r
560              * can filter received resource responses */\r
561             transaction = Rm_transactionQueueAdd(rmInst, resourceReqPkt->requestId);\r
562 \r
563             /* Transfer the rest of the data into the transaction */\r
564             if (resourceReqPkt->resourceReqType == Rm_resReqPktType_ALLOCATE)\r
565             {\r
566                 transaction->type = Rm_service_RESOURCE_ALLOCATE;\r
567             }\r
568             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_BLOCK_ALLOCATE)\r
569             {\r
570                 transaction->type = Rm_service_RESOURCE_BLOCK_ALLOCATE;\r
571             }\r
572             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_ALLOCATE_NAMED)\r
573             {\r
574                 transaction->type = Rm_service_RESOURCE_ALLOCATE_BY_NAME;\r
575             }\r
576             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_FREE)\r
577             {\r
578                 transaction->type = Rm_service_RESOURCE_FREE;\r
579             }\r
580             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_BLOCK_FREE)\r
581             {\r
582                 transaction->type = Rm_service_RESOURCE_BLOCK_FREE;\r
583             }\r
584             else if (resourceReqPkt->resourceReqType == Rm_resReqPktType_FREE_NAMED)\r
585             {\r
586                 transaction->type = Rm_service_RESOURCE_FREE_BY_NAME;\r
587             }\r
588 \r
589             strcpy(transaction->sourceInstName, resourceReqPkt->instName);\r
590             transaction->state = Rm_transactionState_PROCESSING;\r
591             memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceReqPkt->resourceInfo),\r
592                     sizeof(Rm_ResourceInfo));\r
593 \r
594             /* Process the transaction */\r
595             Rm_transactionProcessor(rmInst, transaction, &receipt);\r
596             break;\r
597         }\r
598         case Rm_pktType_RESOURCE_RESPONSE:\r
599         {\r
600             Rm_ResourceResponsePkt *resourceRespPkt = (Rm_ResourceResponsePkt *)pkt->data;\r
601 \r
602             /* If the packet is a response packet the transaction ID should match a queued \r
603              * request transaction's ID  */\r
604             transaction = Rm_transactionQueueAdd(rmInst, resourceRespPkt->responseId);\r
605 \r
606             if (resourceRespPkt->requestResult == RM_SERVICE_APPROVED)\r
607             {\r
608                 transaction->state = Rm_transactionState_RESOURCE_APPROVED;\r
609             }\r
610             else if ((resourceRespPkt->requestResult >= RM_SERVICE_DENIED_BEGIN) &&\r
611                      (resourceRespPkt->requestResult <= RM_SERVICE_DENIED_END))\r
612             {\r
613                 transaction->state = Rm_transactionState_RESOURCE_DENIED;\r
614             }            \r
615             /* The result of the request should be placed in the details field of the \r
616              * response transaction */\r
617             transaction->details = resourceRespPkt->requestResult;\r
618             memcpy ((void *)&(transaction->resourceInfo), (void *)&(resourceRespPkt->resourceInfo),\r
619                     sizeof(Rm_ResourceInfo));\r
620             \r
621             /* Process the transaction */\r
622             Rm_transactionProcessor(rmInst, transaction, &receipt);\r
623             break;\r
624         }\r
625         case Rm_pktType_NAMESERVER_REQUEST:\r
626         {\r
627             Rm_NsRequestPkt *nsRequestPkt = (Rm_NsRequestPkt *)pkt->data;\r
628 \r
629             transaction = Rm_transactionQueueAdd(rmInst, nsRequestPkt->requestId);\r
630 \r
631             if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_MAP_RESOURCE)\r
632             {\r
633                 transaction->type = Rm_service_RESOURCE_MAP_TO_NAME;\r
634             }\r
635             else if (nsRequestPkt->nsRequestType == Rm_nsReqPktType_UNMAP_RESOURCE)\r
636             {\r
637                 transaction->type = Rm_service_RESOURCE_UNMAP_NAME;\r
638             }\r
639 \r
640             strcpy(transaction->sourceInstName, nsRequestPkt->instName);\r
641             transaction->state = Rm_transactionState_PROCESSING;\r
642             memcpy ((void *)&(transaction->resourceInfo), (void *)&(nsRequestPkt->resourceInfo),\r
643                     sizeof(Rm_ResourceInfo));\r
644 \r
645             /* Process the transaction */\r
646             Rm_transactionProcessor(rmInst, transaction, &receipt);            \r
647             break;\r
648         }\r
649         case Rm_pktType_NAMESERVER_RESPONSE:\r
650         {\r
651             Rm_NsResponsePkt *nsResponsePkt = (Rm_NsResponsePkt *)pkt->data;\r
652 \r
653             transaction = Rm_transactionQueueAdd(rmInst, nsResponsePkt->responseId);\r
654             transaction->details = nsResponsePkt->requestResult;\r
655 \r
656             if (nsResponsePkt->requestResult == RM_SERVICE_APPROVED)\r
657             {\r
658                 transaction->state = Rm_transactionState_RESOURCE_APPROVED;\r
659             }\r
660             else if ((nsResponsePkt->requestResult >= RM_SERVICE_DENIED_BEGIN) &&\r
661                      (nsResponsePkt->requestResult <= RM_SERVICE_DENIED_END))\r
662             {\r
663                 transaction->state = Rm_transactionState_RESOURCE_DENIED;\r
664             }\r
665 \r
666             /* Process the transaction */\r
667             Rm_transactionProcessor(rmInst, transaction, &receipt);\r
668             break;\r
669         }\r
670         case Rm_pktType_POLICY_REQUEST:\r
671         {\r
672             Rm_PolicyRequestPkt *policyRequestPkt = (Rm_PolicyRequestPkt *)pkt->data;\r
673 \r
674             /* FILL IN POLICY API INFORMATION */\r
675             break;  \r
676         }\r
677         case Rm_pktType_POLICY_CHANGE:\r
678         {\r
679             Rm_PolicyChangePkt *policyChangePkt = (Rm_PolicyChangePkt *)pkt->data;\r
680 \r
681             /* FILL IN POLICY API INFORMATION */\r
682             break;\r
683         }\r
684         case Rm_pktType_RESOURCE_POOL_MODIFICATION_REQUEST:\r
685         {\r
686             Rm_ResourcePoolModRequestPkt *resPoolModReqPkt = (Rm_ResourcePoolModRequestPkt *)pkt->data;\r
687 \r
688             /* FILL IN RESOURCE POOL MODIFICATION API */\r
689             /* Rm_resourcePoolModRequestHandler(...); Server only - needs to allocate resources to\r
690              * the Client Delegate based on the policy and return those resources to the Client Delegate */\r
691             break;\r
692         }\r
693         case Rm_pktType_RESOURCE_POOL_MODIFICATION_RESPONSE:\r
694         {\r
695             Rm_ResourcePoolModResponsePkt *resPoolModRespPkt = (Rm_ResourcePoolModResponsePkt *)pkt->data;\r
696 \r
697             /* FILL IN RESOURCE POOL MODIFICAITON API */\r
698             /* Rm_resourcePoolModResponseHandler(...);  Handler needs to populate allocator with\r
699              * new resources provided in the response and then handle any request transactions waiting on\r
700              * the resource pool modification */\r
701             break;\r
702         }\r
703         default:\r
704             /* Invalid packet type.  Free the packet and return */\r
705             rmInst->transport.rmFreePkt(transportHandle, pkt);\r
706             return (RM_TRANSPORT_ERROR_INVALID_PACKET_TYPE);\r
707       }\r
708 \r
709     /* Free the packet after it has been processed */\r
710     rmInst->transport.rmFreePkt(transportHandle, pkt);\r
711 \r
712     /* Return the receipt's service result which contains the result return code\r
713      * for the receive packet */\r
714     return (receipt.serviceResult);\r
715 }\r
716 \r
717 /* Application can call this API so that RM handles reception of packets based on\r
718  * the RM handle and transport handle provided */\r
719 int32_t Rm_receivePktPolling(Rm_Handle rmHandle, Rm_TransportHandle transportHandle)\r
720 {\r
721     Rm_Inst *rmInst = (Rm_Inst *)rmHandle;\r
722     Rm_Packet *pkt = NULL;\r
723     int32_t retVal = RM_SERVICE_ACTION_BASE;\r
724 \r
725     /* Make sure the transport handle is registered with the provided RM instance */\r
726     if (Rm_transportNodeFindTransportHandle(rmInst, transportHandle) == NULL)\r
727     {\r
728         /* Transport is not registered with the RM instance.  Return an error.\r
729          * The packet cannot be freed since the transport handle is not valid. */\r
730         return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
731     }\r
732 \r
733     /* Check to see if any RM packets are available.  Process any available packets. */\r
734     while (rmInst->transport.rmNumPktsReceived(transportHandle))\r
735     {\r
736         pkt = rmInst->transport.rmReceive(transportHandle);\r
737 \r
738         if (pkt == NULL)\r
739         {\r
740             return (RM_TRANSPORT_ERROR_PACKET_RECEPTION_ERROR);\r
741         }\r
742 \r
743         /* Pass the packet to RM.  The packet will be freed within the PktIsr API */\r
744         if (retVal = Rm_receivePktIsr(rmHandle, transportHandle, pkt) <= RM_SERVICE_ERROR_BASE)\r
745         {\r
746             /* Return if an error is encountered */\r
747             return (retVal);\r
748         }\r
749     }\r
750     return (retVal); \r
751 }\r
752 \r
753 /**\r
754 @}\r
755 */\r