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