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