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