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
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