2f99160d23698914c46af4a60bbb1dec93d4cea9
[keystone-rtos/rm-lld.git] / src / rm.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_services.h>\r
48 #include <ti/drv/rm/rm_transport.h>\r
49 #include <ti/drv/rm/rm_policy.h>\r
50 \r
51 /* RM internal includes */\r
52 #include <ti/drv/rm/include/rm_loc.h>\r
53 #include <ti/drv/rm/include/rm_transportloc.h>\r
54 #include <ti/drv/rm/include/rm_servicesloc.h>\r
55 #include <ti/drv/rm/include/rm_nameserverloc.h>\r
56 #include <ti/drv/rm/include/rm_dtb_utilloc.h>\r
57 \r
58 /* RM LIBFDT includes */\r
59 #include <ti/drv/rm/src/libfdt/libfdt.h>\r
60 \r
61 /* AVL BBST includes */\r
62 #include <ti/drv/rm/include/tree.h>\r
63 \r
64 /* RM OSAL layer */\r
65 #include <rm_osal.h>\r
66 \r
67 /**********************************************************************\r
68  ************************** Globals ***********************************\r
69  **********************************************************************/\r
70 extern char rmDtbStartingNode[];\r
71 \r
72 /** @brief Global Variable which describes the RM Version Information */\r
73 const char   rmVersionStr[] = RM_VERSION_STR ":" __DATE__  ":" __TIME__;\r
74 \r
75 /**********************************************************************\r
76  ************** Red-Black BBST Tree Allocator Functions ***************\r
77  **********************************************************************/\r
78 \r
79 /* Prototype for function that allocates new tree nodes */\r
80 Rm_ResourceNode *Rm_newResourceNode(uint32_t resourceBase, uint32_t resourceLength, \r
81                                     char *allocatedTo)\r
82 {\r
83     Rm_ResourceNode *newNode = NULL;\r
84 \r
85     newNode = Rm_osalMalloc(sizeof(Rm_ResourceNode));\r
86 \r
87     /* Populate the RM relevant fields */\r
88     newNode->base = resourceBase;\r
89     newNode->length = resourceLength;\r
90     strcpy(newNode->allocatedTo, allocatedTo);\r
91 \r
92     return(newNode);\r
93 }\r
94 \r
95 /* Prototype for function that frees new tree nodes */\r
96 void Rm_freeResourceNode(Rm_ResourceNode *node)\r
97 {\r
98     /* Free the memory associated with the tree node. */\r
99     Rm_osalFree((void *)node, sizeof(Rm_ResourceNode));\r
100 }\r
101 \r
102 /* Prototype for tree node comparison function\r
103  * element1 < element2 --> return < 0\r
104  * element1 = element2 --> return 0\r
105  * element1 > element2 --> return > 0 */\r
106 int Rm_ResourceNodeCompare(Rm_ResourceNode *element1, Rm_ResourceNode *element2)\r
107 {\r
108     uint32_t element1End = element1->base + element1->length - 1;\r
109     uint32_t element2End = element2->base + element2->length - 1;\r
110 \r
111     if (element1End < element2->base)\r
112     {\r
113         /* End of element1 range is less than the start of element2's range.  Return a negative\r
114          * value */\r
115         return (-1);\r
116     }\r
117     else if (element1->base > element2End)\r
118     {\r
119         /* Start of element1 range is after end of element2's range.  Return a positive value */\r
120         return (1);\r
121     }\r
122     else\r
123     {\r
124         /* If neither of the latter conditions were satisfied there is some overlap between\r
125          * element1 and element2.  Return 0 since the application must handle this overlap. */\r
126         return (0);\r
127     }\r
128 }\r
129 \r
130 /* Generate the red-black tree manipulation functions */\r
131 RB_GENERATE(_Rm_ResourceTree, _Rm_ResourceNode, linkage, Rm_ResourceNodeCompare);\r
132 \r
133 /**********************************************************************\r
134  ********************** Internal Functions ****************************\r
135  **********************************************************************/\r
136 \r
137 Rm_Transaction *Rm_transactionQueueAdd(Rm_Inst *rmInst)\r
138 {\r
139     Rm_Transaction *transactionQueue = (Rm_Transaction *)rmInst->transactionQueue;\r
140     Rm_Transaction *newTransaction = NULL;\r
141     void *key;\r
142 \r
143     /* Lock access to the RM instance's transaction queue */\r
144     key = Rm_osalMtCsEnter();\r
145 \r
146     /* Get memory for a new transaction from local memory */\r
147     newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));\r
148 \r
149     /* Return if the memory allocated for the transaction entry is NULL */\r
150     if (newTransaction != NULL)\r
151     {\r
152         /* Clear the transaction */\r
153         memset((void *)newTransaction, 0, sizeof(Rm_Transaction));\r
154 \r
155         /* Create an ID for the new transaction.  The ID will be used for two purposes:\r
156          * 1) Matching responses from higher level RM agents to requests\r
157          * 2) Provided to the component that requested the service so that it can match its\r
158          *    request with the response it receives via its callback function it provided */\r
159         newTransaction->localId = Rm_transactionGetSequenceNum(rmInst);\r
160         /* New transaction's nextTransaction pointer will always be NULL */\r
161         newTransaction->nextTransaction = NULL;  \r
162 \r
163         /* Check if there are any transactions in the transaction queue */\r
164         if (transactionQueue)\r
165         {\r
166             /* At least one transaction in the transaction queue.  Add the new entry to the \r
167              * end of the transaction queue */\r
168             while (transactionQueue->nextTransaction != NULL)\r
169             {\r
170                 /* Traverse the list until arriving at the last transaction */\r
171                 transactionQueue = transactionQueue->nextTransaction;\r
172             }\r
173 \r
174             /* Add the new transaction to the end of the queue */\r
175             transactionQueue->nextTransaction = newTransaction;\r
176         }\r
177         else\r
178         {\r
179             /* The transaction queue does not currently exist.  The new transaction is the \r
180              * first transaction */\r
181             rmInst->transactionQueue = newTransaction;\r
182         }\r
183     }\r
184 \r
185     Rm_osalMtCsExit(key);\r
186     return (newTransaction);\r
187 }\r
188 \r
189 Rm_Transaction *Rm_transactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)\r
190 {\r
191     Rm_Transaction *transaction = (Rm_Transaction *)rmInst->transactionQueue;\r
192 \r
193     /* Make sure there is at least one transaction in the transaction queue */\r
194     if (transaction != NULL)\r
195     {\r
196         /* Find the transaction ID within the specified RM instance's transaction queue.\r
197          * If the end of the transaction queue is reached without finding the transaction the \r
198          * transaction pointer will be NULL */\r
199         while (transaction != NULL)\r
200         {\r
201             if (transaction->localId == transactionId)\r
202             {\r
203                 /* Match: break out of loop and return the transaction */\r
204                 break;             \r
205             }\r
206             transaction = transaction->nextTransaction;\r
207         }\r
208     }\r
209 \r
210     return (transaction);\r
211 }\r
212 \r
213 int32_t Rm_transactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)\r
214 {\r
215     Rm_Transaction *transaction = (Rm_Transaction *) rmInst->transactionQueue;\r
216     Rm_Transaction *prevTransaction = NULL;\r
217     int32_t retVal = RM_SERVICE_STATE_OKAY;\r
218     void *key;\r
219 \r
220     /* Lock access to the RM instance's transaction queue */\r
221     key = Rm_osalMtCsEnter();\r
222 \r
223     /* Find the transaction ID within the specified RM instance's transaction queue. */\r
224     while (transaction != NULL)\r
225     {\r
226         if (transaction->localId == transactionId)\r
227         {\r
228             /* Match: break out of loop and delete the transaction */\r
229             break;             \r
230         }\r
231 \r
232         prevTransaction = transaction;\r
233         transaction = transaction->nextTransaction;\r
234     }\r
235 \r
236     /* Traversed entire queue but did not find transaction */\r
237     if (transaction == NULL)\r
238     {\r
239         retVal = RM_SERVICE_ERROR_SERVICE_TRANSACTION_DOES_NOT_EXIST;\r
240     }\r
241     else\r
242     {\r
243         /* Delete the transaction */\r
244         if (prevTransaction == NULL)\r
245         {\r
246             /* Transaction to be deleted exists at start of transaction queue.  Map second\r
247              * transaction to be start of transaction queue as long as there are more than\r
248              * one transactions. */\r
249             rmInst->transactionQueue = transaction->nextTransaction;\r
250         }\r
251         else\r
252         {\r
253             /* Transaction to be deleted is in the middle or at end of the queue.  Adjust \r
254              * adjacent transaction pointers.  This covers the case where the transaction to be \r
255              * removed is at the end of the queue. */\r
256             prevTransaction->nextTransaction = transaction->nextTransaction;\r
257         }\r
258 \r
259         /* Free the memory associated with the transaction. */\r
260         Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));\r
261     }\r
262 \r
263     Rm_osalMtCsExit(key);\r
264     return (retVal);\r
265 }\r
266 \r
267 uint32_t Rm_transactionInitSequenceNum(void)\r
268 {\r
269     /* Sequence number can never have a value of zero so that there are no conflicts\r
270      * with transactions that have a remoteOriginatingId of zero */\r
271     return (1);\r
272 }\r
273 \r
274 uint32_t Rm_transactionGetSequenceNum(Rm_Inst *rmInst)\r
275 {\r
276     uint32_t sequenceNum = 0;\r
277 \r
278     /* Get the next sequence number and then increment.  If there's an overflow\r
279      * assign the initial value instead of incrementing. */\r
280     if (rmInst->transactionSeqNum + 1 < rmInst->transactionSeqNum)\r
281     {\r
282         /* Overflow */\r
283         sequenceNum = rmInst->transactionSeqNum;\r
284         rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
285     }\r
286     else\r
287     {\r
288         sequenceNum = rmInst->transactionSeqNum++;\r
289     }    \r
290 \r
291     return (sequenceNum);\r
292 }\r
293 \r
294 Rm_Allocator *Rm_allocatorAdd(Rm_Inst *rmInst, const char *resourceName)\r
295 {\r
296     Rm_Allocator *allocators = (Rm_Allocator *)rmInst->allocators;\r
297     Rm_Allocator *newAllocator = NULL;\r
298     void *key;\r
299 \r
300     /* Lock access to the RM instance's allocator list */\r
301     key = Rm_osalMtCsEnter();\r
302 \r
303     /* Get memory for a new allocator from local memory */\r
304     newAllocator = Rm_osalMalloc(sizeof(Rm_Allocator));\r
305 \r
306     /* Return if the memory allocated for the allocator is NULL */\r
307     if (newAllocator != NULL)\r
308     {\r
309         /* Clear the allocator */\r
310         memset((void *)newAllocator, 0, sizeof(Rm_Allocator));\r
311 \r
312         /* Populate the allocator */\r
313         strcpy(newAllocator->resourceName, resourceName);\r
314         /* allocator's root entry will be created by the invoking function */\r
315         newAllocator->allocatorRootEntry = NULL;\r
316         /* New allocator's nextAllocator pointer will always be NULL */\r
317         newAllocator->nextAllocator = NULL;  \r
318 \r
319         /* Check if there are any allocators in the allocator list */\r
320         if (allocators)\r
321         {\r
322             /* At least one allocator in the allocator list.  Add the new allocator to the \r
323              * end of the allocator list */\r
324             while (allocators->nextAllocator != NULL)\r
325             {\r
326                 /* Traverse the list until arriving at the last allocator */\r
327                 allocators = allocators->nextAllocator;\r
328             }\r
329 \r
330             /* Add the new allocator to the end of the list */\r
331             allocators->nextAllocator = newAllocator;\r
332         }\r
333         else\r
334         {\r
335             /* The allocator list does not currently exist.  The new allocator is the \r
336              * first allocator */\r
337             rmInst->allocators = newAllocator;\r
338         }\r
339     }\r
340 \r
341     Rm_osalMtCsExit(key);\r
342     return (newAllocator);\r
343 }\r
344 \r
345 Rm_Allocator *Rm_allocatorFind(Rm_Inst *rmInst, char *resourceName)\r
346 {\r
347     Rm_Allocator *allocator = (Rm_Allocator *)rmInst->allocators;\r
348 \r
349     /* Make sure there is at least one allocator in the allocator list */\r
350     if (allocator != NULL)\r
351     {\r
352         /* Find the resource name within the allocator list.  If the end of the\r
353          * allocator list is reached without finding the resource name the \r
354          * allocator pointer will be NULL */\r
355         while (allocator != NULL)\r
356         {\r
357             if (strcmp(allocator->resourceName, resourceName) == 0)\r
358             {\r
359                 /* Match: break out of loop and return the allocator */\r
360                 break;             \r
361             }\r
362             allocator = allocator->nextAllocator;\r
363         }\r
364     }\r
365 \r
366     return (allocator);\r
367 }\r
368 \r
369 int32_t Rm_allocatorDelete(Rm_Inst *rmInst, char *resourceName)\r
370 {\r
371     Rm_Allocator *allocator = (Rm_Allocator *) rmInst->allocators;\r
372     Rm_Allocator *prevAllocator = NULL;\r
373     int32_t retVal = RM_SERVICE_STATE_OKAY;\r
374     void *key;\r
375 \r
376     /* Lock access to the RM instance's allocator list */\r
377     key = Rm_osalMtCsEnter();\r
378 \r
379     /* Find the resource within the specified RM instance's allocator list. */\r
380     while (allocator != NULL)\r
381     {\r
382         if (strcmp(allocator->resourceName, resourceName) == 0)\r
383         {\r
384             /* Match: break out of loop and delete the transaction */\r
385             break;             \r
386         }\r
387 \r
388         prevAllocator = allocator;\r
389         allocator = allocator->nextAllocator;\r
390     }\r
391 \r
392     /* Traversed entire list but did not find allocator. */\r
393     if (allocator == NULL)\r
394     {\r
395         retVal = -22; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
396     }\r
397     else\r
398     {\r
399         /* Delete the allocator */\r
400         if (prevAllocator == NULL)\r
401         {\r
402             /* Allocator to be deleted exists at start of allocator list.  Map second\r
403              * allocator to be start of allocator list as long as there are more than\r
404              * one allocators. */\r
405             rmInst->allocators = allocator->nextAllocator;\r
406         }\r
407         else\r
408         {\r
409             /* Allocator to be deleted is in the middle or at end of the list.  Adjust \r
410              * adjacent allocator pointers.  This covers the case where the allocator to be \r
411              * removed is at the end of the list. */\r
412             prevAllocator->nextAllocator = allocator->nextAllocator;\r
413         }\r
414 \r
415         /* Free the memory associated with the allocator. */\r
416         Rm_osalFree((void *)allocator, sizeof(Rm_Allocator));\r
417     }\r
418 \r
419     Rm_osalMtCsExit(key);\r
420     return (retVal);\r
421 }\r
422 \r
423 int32_t Rm_createTreeAllocator(Rm_Inst *rmInst, const char *resourceName, Rm_ResourceRange *range)\r
424 {\r
425     Rm_Allocator *allocator = NULL;\r
426     Rm_ResourceTree *treeRootEntry = NULL;\r
427     Rm_ResourceNode *treeNode = NULL;\r
428     Rm_ResourceNode *collidingNode = NULL;\r
429 \r
430     /* Create the new base integer allocator */\r
431     allocator = Rm_allocatorAdd(rmInst, resourceName);\r
432 \r
433     /* Create the tree root entry and initialize it */\r
434     treeRootEntry = Rm_osalMalloc(sizeof(Rm_ResourceTree));\r
435     RB_INIT(treeRootEntry);\r
436 \r
437     /* Create a node in the tree for resource range and insert them into the tree. */\r
438     while (range != NULL)\r
439     {\r
440         treeNode = Rm_newResourceNode(range->base, range->length, RM_NOT_ALLOCATED_STRING);\r
441 \r
442         /* Insert the node into the tree */\r
443         collidingNode = RB_INSERT(_Rm_ResourceTree, treeRootEntry, treeNode);\r
444 \r
445         if (collidingNode)\r
446         {\r
447             Rm_ResourceNode *nextNode = NULL;\r
448             \r
449             /* Node that was inserted colliding with an existing node.  Clean up the tree\r
450              * that's been allocated thus far and return an error since there should be no\r
451              * collisions */\r
452             for (treeNode = RB_MIN(_Rm_ResourceTree, treeRootEntry); treeNode != NULL; treeNode = nextNode)\r
453             {\r
454                         nextNode = RB_NEXT(_Rm_ResourceTree, treeRootEntry, treeNode);\r
455                         RB_REMOVE(_Rm_ResourceTree, treeRootEntry, nextNode);\r
456                 Rm_freeResourceNode(treeNode);\r
457                 }\r
458             /* Delete the tree root entry and the allocator */\r
459             Rm_osalFree((void *)treeRootEntry, sizeof(Rm_ResourceTree));\r
460             Rm_allocatorDelete(rmInst, allocator->resourceName);\r
461             return (-24); /* TODO FIX RETURN */\r
462         }\r
463 \r
464         range = range->nextRange;\r
465     }\r
466 \r
467     /* Assign the tree's root to the allocator */\r
468     allocator->allocatorRootEntry = treeRootEntry;\r
469 \r
470     return(0);   /* TODO: FIX THIS RETURN */\r
471 }\r
472 \r
473 /* Called when an allocate request is made but the base is unspecified.  RM must preallocate\r
474  * resources which then must be checked against the RM policy for the instance.  If the\r
475  * policy does not agree another resource(s) must be preallocated and tested against the \r
476  * policy.  Policy will provide initialize the preallocate with the base that it allows\r
477  * for the rm instance for the specified resource. */\r
478 int32_t Rm_treePreAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
479 {\r
480     Rm_ResourceNode findNode;\r
481     Rm_ResourceNode *matchingNode = NULL;\r
482     uint32_t matchingEnd;\r
483     uint32_t rangeIndex;\r
484     bool resourceFound = FALSE;\r
485     int32_t retVal = RM_SERVICE_PROCESSING;\r
486 \r
487     /* Initialize the findNode parameters to the starting preallocation parameters */\r
488     if (opInfo->resourceInfo->base)\r
489     {\r
490         findNode.base = opInfo->resourceInfo->base;\r
491     }\r
492     else\r
493     {\r
494         /* Otherwise use the first resource value in the tree */\r
495         matchingNode = RB_MIN(_Rm_ResourceTree, allocator->allocatorRootEntry);\r
496         findNode.base = matchingNode->base;\r
497     }\r
498     findNode.length = opInfo->resourceInfo->length;\r
499 \r
500     do\r
501     {\r
502         matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
503         \r
504         if (matchingNode != NULL)\r
505         {\r
506             /* Is the matchingNode free? */\r
507             if (strcmp(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0)\r
508             {\r
509                 matchingEnd = matchingNode->base + matchingNode->length - 1;\r
510                 /* Initialize the indexer to be the first resource base value that \r
511                  * satisfies the alignment property */\r
512                 rangeIndex = findNode.base;\r
513                 if (rangeIndex % opInfo->resourceInfo->alignment)\r
514                 {\r
515                     rangeIndex += (opInfo->resourceInfo->alignment -\r
516                               (rangeIndex % opInfo->resourceInfo->alignment));\r
517                 }\r
518                 \r
519                 /*Is there a block of unallocated resources within the matchingNode\r
520                  * that satisfies the allocate properties? */\r
521                 if ((rangeIndex + opInfo->resourceInfo->length - 1) <= matchingEnd)\r
522                 {\r
523                     opInfo->resourceInfo->base = rangeIndex;\r
524                     resourceFound = TRUE;\r
525                 }\r
526             }\r
527             \r
528             if (!resourceFound)\r
529             {\r
530                 /* If the matchingNode does not satisfy allocate requirements update the resource base \r
531                  * to the first resource value after the end of the current matchingNode */\r
532                 findNode.base = matchingNode->base + matchingNode->length;\r
533             }\r
534         }\r
535         else\r
536         {\r
537             /* If not matchingNode has been found the end of the tree has been reached and there\r
538              * is not resource range available that meets the needs of the request */\r
539             retVal = RM_SERVICE_DENIED_RESOURCE_ALLOCATION_REQUIREMENTS_COULD_NOT_BE_SATISFIED;\r
540         }\r
541     } while ((!resourceFound) && \r
542              (retVal != RM_SERVICE_DENIED_RESOURCE_ALLOCATION_REQUIREMENTS_COULD_NOT_BE_SATISFIED));\r
543 \r
544     return(retVal); \r
545 }\r
546 \r
547 /* Assume the policy has already approved of the allocation */\r
548 int32_t Rm_treeAllocate(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
549 {\r
550     Rm_ResourceNode findNode;\r
551     Rm_ResourceNode *matchingNode = NULL;\r
552     Rm_ResourceNode *leftNode = NULL;\r
553     Rm_ResourceNode *rightNode = NULL;  \r
554     uint32_t findEnd, matchingEnd;\r
555     int32_t retVal;\r
556 \r
557     /* Find the tree node that contains the specified resource range */\r
558     findNode.base = opInfo->resourceInfo->base;\r
559     findNode.length = opInfo->resourceInfo->length;\r
560     matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
561 \r
562     if (matchingNode != NULL)\r
563     {\r
564         findEnd = findNode.base + findNode.length - 1;\r
565         matchingEnd = matchingNode->base + matchingNode->length - 1;\r
566         \r
567         /* Does the request range fit within the matching nodes entire range? */\r
568         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd))\r
569         {\r
570             /* Handle node create, combine, deletion based on the request range if\r
571              * resources are available. */\r
572             if (strcmp(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0)\r
573             {\r
574                 /* Handle case where the findNode range matches the matchingNode\r
575                  * range exactly.\r
576                  *\r
577                  * base0                                  base0+length0-1\r
578                  *   |<---------------length0------------------->|  => existing node\r
579                  *   |<---------------length1------------------->|  => requested resources\r
580                  * base1                                  base1+length1-1\r
581                  */    \r
582                 if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))\r
583                 {\r
584                     /* Can reserve matchingNode's resources in-place */\r
585                     strcpy(matchingNode->allocatedTo, opInfo->serviceSrcInstName);\r
586                 }\r
587                 /* Handle case where the findNode range is a subset of the matchingNode\r
588                  * range and neither of the boundaries of the two ranges are equivalent.\r
589                  *\r
590                  * base0                                  base0+length0-1\r
591                  *   |<---------------length0------------------->|  => existing node\r
592                  *         |<---------length1---------->|  => requested resources\r
593                  *       base1                   base1+length1-1\r
594                  */    \r
595                 else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd))\r
596                 {\r
597                     /* Split the matching node into three nodes:\r
598                      * left node - free resources to left of newly allocated resources\r
599                      * middle node - newly allocated resources that satisfy the request\r
600                      * right node - free resources to the right of newly allocated resources */\r
601 \r
602                     /* Remove the matching node from the tree for modification. */\r
603                     RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
604 \r
605                     /* New left node attributes:\r
606                      * base: base of the matching node\r
607                      * length: base of requested resources - base of matching node */\r
608                     leftNode = Rm_newResourceNode(matchingNode->base, findNode.base - matchingNode->base,\r
609                                                       RM_NOT_ALLOCATED_STRING);\r
610                     /* New right node attributes:\r
611                      * base: base of the requested resources + length of requested resources\r
612                      * length: right bound of matching node - right bound of request resources */\r
613                     rightNode = Rm_newResourceNode(findNode.base + findNode.length,\r
614                                                        matchingEnd - findEnd, RM_NOT_ALLOCATED_STRING);\r
615 \r
616                     /* Base and length of matching node become the base and length of the\r
617                      * requested resources */\r
618                     matchingNode->base = findNode.base;                                    \r
619                     matchingNode->length = findNode.length;\r
620                     /* Reserve the resources */\r
621                     strcpy(matchingNode->allocatedTo, opInfo->serviceSrcInstName);\r
622 \r
623                     /* Insert all the nodes */\r
624                     RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
625                     RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
626                     RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
627                 }\r
628                 /* Handle cases where one of findNode range boundaries is equivalent to\r
629                  * one of the matchingNode range boundaries.\r
630                  *\r
631                  * base0                                  base0+length0-1\r
632                  *   |<---------------length0------------------->|  => existing node\r
633                  *   |<---------length1---------->|  => requested resources\r
634                  * base1                   base1+length1-1\r
635                  *\r
636                  * OR\r
637                  *\r
638                  * base0                                  base0+length0-1\r
639                  *   |<---------------length0------------------->|  => existing node\r
640                  *                  |<---------length1---------->|  => requested resources\r
641                  *                base1                   base1+length1-1                 \r
642                  */    \r
643                 else\r
644                 {    \r
645                     if (findNode.base == matchingNode->base)\r
646                     {\r
647                         /* There may be a combine possibility to the left. Extract leftNode to check */\r
648                         leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
649 \r
650                         /* Remove the matchingNode from the tree since it will be edited */\r
651                         RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);                        \r
652                         \r
653                         /* Can the node to the left of the matchingNode be combined with the \r
654                          * findNode's range? */\r
655                         if (leftNode && (strcmp(leftNode->allocatedTo, opInfo->serviceSrcInstName) == 0))\r
656                         {\r
657                             /* Remove the leftNode from the tree for editing */\r
658                             RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
659 \r
660                             /* Combine the leftNode and the findNode */\r
661                             leftNode->length += findNode.length;\r
662                         }\r
663                         else\r
664                         {\r
665                             /* Allocate a new leftNode that will take the place of the findNode\r
666                              * range in tree. */\r
667                             leftNode = Rm_newResourceNode(findNode.base, findNode.length,\r
668                                                               opInfo->serviceSrcInstName);\r
669                         }\r
670 \r
671                         /* Account for the leftNode in the matchingNode */\r
672                         matchingNode->base = findNode.base + findNode.length;\r
673                         matchingNode->length = matchingEnd - findEnd;  \r
674 \r
675                         /* Insert the left node */\r
676                         RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
677                     }\r
678                     else if (findEnd == matchingEnd)\r
679                     {\r
680                         /* There may be a combine possibility to the right. Extract rightNode to check */\r
681                         rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
682 \r
683                         /* Remove the matchingNode from the tree since it will be edited */\r
684                         RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
685                         \r
686                         /* Can the node to the right of the matchingNode be combined with the \r
687                          * findNode's range? */\r
688                         if (rightNode && (strcmp(rightNode->allocatedTo, opInfo->serviceSrcInstName) == 0))\r
689                         {\r
690                             /* Remove the rightNode from the tree for editing */\r
691                             RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
692 \r
693                             /* Combine the rightNode and the findNode */\r
694                             rightNode->base = findNode.base;\r
695                             rightNode->length += findNode.length;\r
696                         }\r
697                         else\r
698                         {\r
699                             /* Allocate a new rightNode that will take the place of the findNode\r
700                              * range in tree. */\r
701                             rightNode = Rm_newResourceNode(findNode.base, findNode.length,\r
702                                                                opInfo->serviceSrcInstName);\r
703                         }\r
704 \r
705                         /* Account for the rightNode in the matchingNode */\r
706                         matchingNode->length -= findNode.length;  \r
707 \r
708                         /* Insert the right node */\r
709                         RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
710                     }\r
711 \r
712                     /* Reinsert the edited matching node */\r
713                     RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
714                 }\r
715                 \r
716                 retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
717             }\r
718             else\r
719             {\r
720                 /* A resource superset containing the requested range has\r
721                  * already been allocated. */\r
722                 retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\r
723             }\r
724         }\r
725         else\r
726         {\r
727             /* Request ranges that span multiple nodes signify resources are\r
728              * not available because nodes are combined into larger contiguous ranges\r
729              * on resource free operations. */\r
730             retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_ALLOCATED;\r
731         }\r
732     }\r
733     else\r
734     {\r
735         /* The requested resources could not be found in the allocator */\r
736         retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
737     }\r
738 \r
739     return(retVal);        \r
740 }\r
741 \r
742 /* Assume policy has already approved of the free */\r
743 int32_t Rm_treeFree(Rm_Allocator *allocator, Rm_AllocatorOpInfo *opInfo)\r
744 {\r
745     Rm_ResourceNode findNode;\r
746     Rm_ResourceNode *matchingNode = NULL;\r
747     Rm_ResourceNode *leftNode = NULL;\r
748     Rm_ResourceNode *rightNode = NULL;\r
749     bool combineLeft = FALSE;\r
750     bool combineRight = FALSE;\r
751     uint32_t findEnd, matchingEnd;\r
752     int32_t retVal;\r
753 \r
754     /* Find the tree node that contains the specified resource range */\r
755     findNode.base = opInfo->resourceInfo->base;\r
756     findNode.length = opInfo->resourceInfo->length;\r
757     matchingNode = RB_FIND(_Rm_ResourceTree, allocator->allocatorRootEntry, &findNode);\r
758 \r
759     if (matchingNode != NULL)\r
760     {\r
761         findEnd = findNode.base + findNode.length - 1;\r
762         matchingEnd = matchingNode->base + matchingNode->length - 1;\r
763         \r
764         /* Does the free range fit within the matching nodes entire range?  It should\r
765          * either be the entire range or a subset set of the found range. (the latter\r
766          * satisfies the case where an entity allocated a contiguous block of resources\r
767          * then attempts to free a contiguous subset of the allocated block. */\r
768         if ((findNode.base >= matchingNode->base) && (findEnd <= matchingEnd))\r
769         {  \r
770             if (strcmp(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING))\r
771             {\r
772                 if (strcmp(matchingNode->allocatedTo, opInfo->serviceSrcInstName) == 0)\r
773                 {\r
774                     /* Resources can be freed */\r
775 \r
776                     if ((findNode.base == matchingNode->base) && (findEnd == matchingEnd))\r
777                     {\r
778                         /* Case 1: free range equals allocated matched node exactly. Attempt to combine \r
779                          *         the range to be freed with the resource nodes to the left and\r
780                          *         right of the free range.\r
781                          *\r
782                          * |<--left node-->||<---matched node--->||<--right node-->|\r
783                          *                  |<---free request--->|\r
784                          */ \r
785 \r
786                         leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
787                         rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
788 \r
789                         /* Remove the matching node from the tree and the nodes to the left and\r
790                          * right of the matching node.  Removing from tree will not\r
791                          * wipe any of the base+length data in the node.  Can reuse since they won't\r
792                          * be freed */\r
793                         RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
794 \r
795                         /* See if the left or right or both nodes can be combined with the matching\r
796                          * node that will be freed. */\r
797                         if (leftNode && (strcmp(leftNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0))\r
798                         {\r
799                             /* Combine the left node and the matching node */\r
800                             RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
801                             combineLeft = TRUE;\r
802                         }\r
803                         if (rightNode && (strcmp(rightNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0))\r
804                         {\r
805                             /* Combine the right node and the matching node */\r
806                             RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
807                             combineRight = TRUE;\r
808                         }\r
809 \r
810                         /* Perform any combines, insert the leftover nodes, and free any memory associated\r
811                          * with any nodes that weren't reinserted into the tree */\r
812                         if (combineLeft && combineRight)\r
813                         {\r
814                             /* Combine all three nodes into the matchingNode.  Insert the freed cumulative\r
815                              * matching node and delete the memory for the old left and right nodes */\r
816                             matchingNode->base = leftNode->base;\r
817                             matchingNode->length = leftNode->length + matchingNode->length + rightNode->length;\r
818 \r
819                             Rm_freeResourceNode(leftNode);\r
820                             Rm_freeResourceNode(rightNode);                        \r
821                         }\r
822                         else if (combineLeft)\r
823                         {\r
824                             /* Combine the left and matching nodes.  Reinsert the right. */\r
825                             matchingNode->base = leftNode->base;\r
826                             matchingNode->length += leftNode->length;\r
827                             \r
828                             Rm_freeResourceNode(leftNode);\r
829                             RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);                        \r
830                         }\r
831                         else if (combineRight)\r
832                         {\r
833                             /* Combine the right and matching nodes.  Reinsert the left. */\r
834                             matchingNode->length += rightNode->length;\r
835                             \r
836                             Rm_freeResourceNode(rightNode);\r
837                             RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
838                         }\r
839                         else\r
840                         {\r
841                             /* Combine cannot be performed.  Reinsert the left and right nodes then\r
842                              * free the matching node and reinsert it */\r
843                             RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
844                             RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
845                         }\r
846 \r
847                         /* No matter the combine route taken the matching node will always be declared\r
848                          * free and reinserted */\r
849                         strcpy(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING);\r
850                         RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);                    \r
851                     }\r
852                     else if ((findNode.base > matchingNode->base) && (findEnd < matchingEnd))\r
853                     {\r
854                         /* Case 2: free range is less than range in matched node. Need to split\r
855                          *         the matched node into three nodes.\r
856                          *\r
857                          * |<----------matched node---------->|\r
858                          *        |<---free request--->|\r
859                          */ \r
860 \r
861                         /* Remove matching node for editing. */\r
862                         RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
863 \r
864                         /* New left node attributes:\r
865                          * base: base of the matching node\r
866                          * length: base of requested resources - base of matching node */\r
867                         leftNode = Rm_newResourceNode(matchingNode->base, findNode.base - matchingNode->base,\r
868                                                           matchingNode->allocatedTo); \r
869                         /* New right node attributes:\r
870                          * base: base of the requested resources + length of requested resources\r
871                          * length: right bound of matching node - right bound of request resources */\r
872                         rightNode = Rm_newResourceNode(findNode.base + findNode.length,\r
873                                                            matchingEnd - findEnd, matchingNode->allocatedTo);\r
874 \r
875                         /* Insert the left and right nodes into the tree. */\r
876                         RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
877                         RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
878 \r
879                         /* Base and length of matching node become the base and length of the freed resources */\r
880                         matchingNode->base = findNode.base;                                    \r
881                         matchingNode->length = findNode.length;\r
882                         /* Free the resources and insert them into the tree */\r
883                         strcpy(matchingNode->allocatedTo, RM_NOT_ALLOCATED_STRING);\r
884                         RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
885                     }\r
886                     else\r
887                     {                        \r
888                         if (findNode.base == matchingNode->base)\r
889                         {\r
890                             /* Case 3: Free range is on left boundary of matched node. Try to \r
891                              *         combine the free range with the left node if free.\r
892                              *\r
893                              * |<---left node (free)--->||<----------matched node---------->|\r
894                              *                           |<---findNode (free req)--->|\r
895                              */ \r
896                        \r
897                             /* There may be a combine possibility to the left. Extract leftNode to check */\r
898                             leftNode = RB_PREV(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
899                             \r
900                             /* Remove the matchingNode from the tree since it will be edited */\r
901                             RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
902                             \r
903                             /* Can the node to the left of the matchingNode be combined with the \r
904                              * findNode's range? */\r
905                             if (leftNode && (strcmp(leftNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0))\r
906                             {\r
907                                 /* Remove the leftNode from the tree for editing */\r
908                                 RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
909 \r
910                                 /* Combine the leftNode and the findNode */\r
911                                 leftNode->length += findNode.length;\r
912                             }\r
913                             else\r
914                             {\r
915                                 /* Allocate a new leftNode that will take the place of the findNode\r
916                                  * range in tree. */\r
917                                 leftNode = Rm_newResourceNode(findNode.base, findNode.length,\r
918                                                                   RM_NOT_ALLOCATED_STRING);\r
919                             }\r
920 \r
921                             /* Account for the leftNode in the matchingNode */\r
922                             matchingNode->base = findNode.base + findNode.length;\r
923                             matchingNode->length = matchingEnd - findEnd;  \r
924 \r
925                             /* Insert the left node */\r
926                             RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, leftNode);\r
927                         }\r
928                         else if (findEnd == matchingEnd)\r
929                         {\r
930                             /* Case 4: Free range is on right boundary of matched node. Try to \r
931                              *         combine the free range with the right node if free.\r
932                              *\r
933                              * |<----------matched node---------->||<---right node (free)--->|\r
934                              *        |<---findNode (free req)--->|\r
935                              */ \r
936                             \r
937                             /* There may be a combine possibility to the right. Extract rightNode to check */\r
938                             rightNode = RB_NEXT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
939 \r
940                             /* Remove the matchingNode from the tree since it will be edited */\r
941                             RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);   \r
942                             \r
943                             /* Can the node to the right of the matchingNode be combined with the \r
944                              * findNode's range? */\r
945                             if (rightNode && (strcmp(rightNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0))\r
946                             {\r
947                                 /* Remove the rightNode from the tree for editing */\r
948                                 RB_REMOVE(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
949 \r
950                                 /* Combine the rightNode and the findNode */\r
951                                 rightNode->base = findNode.base;\r
952                                 rightNode->length += findNode.length;\r
953                             }\r
954                             else\r
955                             {\r
956                                 /* Allocate a new rightNode that will take the place of the findNode\r
957                                  * range in tree. */\r
958                                 rightNode = Rm_newResourceNode(findNode.base, findNode.length,\r
959                                                                    RM_NOT_ALLOCATED_STRING);\r
960                             }\r
961 \r
962                             /* Account for the rightNode in the matchingNode */\r
963                             matchingNode->length -= findNode.length;  \r
964 \r
965                             /* Insert the right node */\r
966                             RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, rightNode);\r
967                         }\r
968 \r
969                         /* Reinsert the edited matching node */\r
970                         RB_INSERT(_Rm_ResourceTree, allocator->allocatorRootEntry, matchingNode);\r
971                     }\r
972 \r
973                     retVal = RM_SERVICE_APPROVED_AND_COMPLETED;\r
974                 }\r
975                 else\r
976                 {\r
977                     /* The matching allocated range to be freed was allocated to a different instance. */\r
978                     retVal = RM_SERVICE_DENIED_RESOURCE_NOT_ALLOCATED_TO_INSTANCE_REQUESTING_THE_SERVICE;\r
979                 }\r
980             }\r
981             else\r
982             {\r
983                 /* Resources are already free */\r
984                 retVal = RM_SERVICE_DENIED_RESOURCE_ALREADY_FREE;\r
985             }\r
986         }\r
987         else\r
988         {\r
989             /* Free resource range crosses over node boundaries.  This signifies a\r
990              * free of both allocated and unallocated resources since nodes are combined\r
991              * on allocate and free operations if possible. */\r
992             retVal = RM_SERVICE_DENIED_INVALID_RESOURCE_RANGE;\r
993         }\r
994     }\r
995     else\r
996     {\r
997         /* The free resources could not be found in the allocator */\r
998         retVal = RM_SERVICE_DENIED_RESOURCE_VALUE_RANGE_DOES_NOT_EXIST;\r
999     }\r
1000 \r
1001     return(retVal);  \r
1002 }\r
1003 \r
1004 int32_t Rm_allocatorOperation(Rm_Inst *rmInst, Rm_AllocatorOpInfo *opInfo)\r
1005 {\r
1006     Rm_Allocator *allocator = NULL;\r
1007     int32_t retVal;\r
1008     void *key;\r
1009 \r
1010     /* Lock access to the RM instance's transaction queue */\r
1011     key = Rm_osalMtCsEnter();\r
1012 \r
1013     /* Get the specified resource's allocator */\r
1014     allocator = Rm_allocatorFind(rmInst, opInfo->resourceInfo->name);\r
1015 \r
1016     if (allocator)\r
1017     {\r
1018         /* Call the allocator's function */\r
1019         if (opInfo->operation == Rm_allocatorOp_PRE_ALLOCATE)\r
1020         {\r
1021             retVal = Rm_treePreAllocate(allocator, opInfo);\r
1022         }               \r
1023         else if (opInfo->operation == Rm_allocatorOp_ALLOCATE)\r
1024         {\r
1025             retVal = Rm_treeAllocate(allocator, opInfo);\r
1026         }\r
1027         else if (opInfo->operation == Rm_allocatorOp_FREE)\r
1028         {\r
1029             retVal = Rm_treeFree(allocator, opInfo);\r
1030         }         \r
1031     }\r
1032     else\r
1033     {\r
1034         /* Allocator could not be found for resource */\r
1035         retVal = RM_SERVICE_DENIED_RESOURCE_DOES_NOT_EXIST;\r
1036     }\r
1037 \r
1038     Rm_osalMtCsExit(key);\r
1039     return(retVal);\r
1040 }\r
1041 \r
1042 void Rm_allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
1043 {\r
1044     Rm_AllocatorOpInfo opInfo;\r
1045     int32_t retVal = transaction->state;\r
1046 \r
1047     /* Initialize the opInfo structure */\r
1048     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
1049     \r
1050     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
1051     {\r
1052         /* TEMP: For now forward all allocations to the RM Server */\r
1053         Rm_transactionForwarder(rmInst, transaction);\r
1054         \r
1055 #if 0  /* Policy psuedo-code.  Will be implemented after basic allocate functionality is ready and tested */   \r
1056         if (resourceBase is unspecified)\r
1057         {\r
1058            while (policy does not approve)\r
1059            {\r
1060                Rm_policy check get allowed base as starting point for prealloc\r
1061                preallocate resource based on the range and alignment\r
1062                Rm_policy...check\r
1063            }\r
1064         }\r
1065         else\r
1066         {\r
1067             /* Check local policy to see if the request can be satisfied with the\r
1068              * resources stored locally */\r
1069             Rm_policy...API()\r
1070 \r
1071             if (policy check approves the resource)\r
1072             {\r
1073                 /* call the allocator to allocate the resource */\r
1074                 if (allocator returns resource)\r
1075                 {\r
1076                     /* Populate the transaction with the allocated resources and the result */\r
1077                     transaction->state = approve reason;\r
1078                     return ...\r
1079                 }\r
1080                 else\r
1081                 {\r
1082                     /* allocator ran out of resources, need to contact Server for more\r
1083                      * resources */\r
1084                     Rm_resourcePoolModRequest(...);\r
1085                 }\r
1086             }\r
1087             else if (policy check denies resource)\r
1088             {\r
1089                 /* Policy check denied resource. */\r
1090                 transaction->state= deny reason;\r
1091                 return ...\r
1092             }\r
1093             else if (policy check says forward to Server for validation)\r
1094             {\r
1095                 /* Forward the transaction to the Server */\r
1096                 Rm_transactionForwarder(rmInst, transaction);\r
1097             }\r
1098         }\r
1099 #endif         \r
1100     }\r
1101     else if (rmInst->instType == Rm_instType_SERVER)\r
1102     {\r
1103         /* TEMP: If resource properties are unspecified allocate the next available.\r
1104          *       If resource properties are specified allocate if they are available. */\r
1105 \r
1106         /* Fill out the allocator operation general information */\r
1107         opInfo.resourceInfo = &transaction->resourceInfo;\r
1108         opInfo.serviceSrcInstName = transaction->serviceSrcInstName;\r
1109 \r
1110         if (strlen(transaction->resourceInfo.nsName) > 0)\r
1111         {\r
1112             /* See if a NameServer name is being used to allocate a resource */\r
1113             if (transaction->resourceInfo.base != 0)\r
1114             {\r
1115                 /* A name and a value cannot be specified for the request.  It's one\r
1116                  * or the other. */\r
1117                 retVal = RM_SERVICE_ERROR_NAMESERVER_NAME_AND_RESOURCE_RANGE_BOTH_DEFINED;\r
1118             }\r
1119             else\r
1120             {\r
1121                 /* Get the resource information from the NameServer */\r
1122                 retVal = Rm_nsFindObject(rmInst, opInfo.resourceInfo);\r
1123             }\r
1124         }\r
1125         else if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED)\r
1126         {\r
1127             if ((transaction->resourceInfo.alignment == RM_RESOURCE_ALIGNMENT_UNSPECIFIED) ||\r
1128                 (transaction->resourceInfo.alignment == 0))\r
1129             {   \r
1130                 /* TEMP: Default resource alignment of 1 if the resource alignment is not\r
1131                  *       specified */\r
1132                 opInfo.resourceInfo->alignment = 1;\r
1133             }\r
1134 \r
1135             /* TODO: set the resourceInfo->base value to be the base of the resource range\r
1136              *       allowed for the RM instance */\r
1137             // opInfo.resourceInfo->base = policy_get_instance_base(...);\r
1138             opInfo.resourceInfo->base = 0;\r
1139 \r
1140             /* Execute the allocator pre-allocate operation to get the next available resources.\r
1141              * NORMALLY CHECKED AGAINST THE POLICY */\r
1142             opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE;\r
1143 \r
1144             /* If the pre-allocate operation succeeds the resourceInfo field pointed to\r
1145              * by opInfo will contain the next available resources that satisfy the\r
1146              * resource properties */\r
1147             retVal = Rm_allocatorOperation(rmInst, &opInfo);\r
1148         }\r
1149 \r
1150         /* Call allocator as long as an error or denial hasn't occurred */\r
1151         if ((retVal == RM_SERVICE_PROCESSING) || (retVal == RM_NS_ACTION_APPROVED))\r
1152         {\r
1153             opInfo.operation = Rm_allocatorOp_ALLOCATE;\r
1154 \r
1155             retVal = Rm_allocatorOperation(rmInst, &opInfo);\r
1156         }\r
1157 \r
1158         transaction->state = retVal;\r
1159 \r
1160         if (strcmp(transaction->serviceSrcInstName, rmInst->name))\r
1161         {\r
1162             /* Source of allocation was not the server instance, provide the transaction\r
1163              * to the transaction responder */\r
1164             Rm_transactionResponder(rmInst, transaction);\r
1165         }\r
1166         /* Otherwise let the return stack return the transaction to the serviceHandler */           \r
1167 \r
1168 #if 0  /* Policy psuedo-code.  Will be implemented after basic allocate functionality is ready and tested */        \r
1169         if (resourceBase is unspecified)\r
1170         {\r
1171            while (policy does not approve)\r
1172            {\r
1173                Rm_policy check get allowed base as starting point for prealloc\r
1174                preallocate resource based on the range and alignment\r
1175                Rm_policy...check\r
1176            }\r
1177         }\r
1178         else\r
1179         {\r
1180             /* Check global policy to see if resource can be allocated. return result\r
1181              * no matter what */\r
1182             Rm_policy...API()\r
1183 \r
1184             if (policy approves)\r
1185             {\r
1186                 /* call allocator to allocate resource */\r
1187             }\r
1188 \r
1189             transaction->state = approve or deny reason;\r
1190             transaction->resourceInfo.base = ...;\r
1191             transaction->resourceInfo.length = ...;\r
1192 \r
1193             /* If source instance name does not match the current instance\r
1194              * name the allocation request came from a Client.  The result\r
1195              * must be sent back to the Client */\r
1196             if (strcmp(transaction->sourceInstName, rmInst->name))\r
1197             {\r
1198                 /* Names don't match.  Send the transaction back to the Client */\r
1199                 Rm_transactionResponder(rmInst, transaction);\r
1200             }\r
1201             else\r
1202             {\r
1203                 /* Resource allocation request originated locally on the active\r
1204                  * instance. Send the response via the service responder. */          \r
1205                 Rm_serviceResponder(rmInst, transaction);                            \r
1206             }\r
1207         }\r
1208 #endif        \r
1209     }   \r
1210 }\r
1211 \r
1212 void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
1213 {\r
1214     Rm_AllocatorOpInfo opInfo;\r
1215     int32_t retVal = transaction->state;\r
1216 \r
1217     /* Initialize the opInfo structure */\r
1218     memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
1219     \r
1220     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
1221     {\r
1222         /* TEMP: Forward all free requests to the Server */\r
1223         Rm_transactionForwarder(rmInst, transaction);\r
1224         \r
1225 #if 0  /* Policy psuedo-code.  Will be implemented after basic allocate functionality is ready and tested */      \r
1226         /* Check local policy to see if the request can be satisfied with the\r
1227          * resources stored locally */\r
1228         Rm_policy...API()\r
1229 \r
1230         if (policy check approves the free)\r
1231         {\r
1232             /* call the allocator to free the resource */\r
1233             /* Run a resource pool check to see if the free combined a resource block\r
1234              * that can be returned to the server */\r
1235             if (resource block has been combined)\r
1236             {\r
1237                   /* allocator ran out of resources, need to contact Server for more\r
1238                  * resources */\r
1239                 Rm_resourcePoolModRequest(free pool block to server...);\r
1240             }\r
1241             else\r
1242             {\r
1243                 /* Populate the receipt with the freed resources and the result */\r
1244                 transaction->state = approve reason;\r
1245                 return ...\r
1246             }\r
1247         }\r
1248         else if (policy check denies resource free)\r
1249         {\r
1250             /* Policy check denied resource. */\r
1251             transaction->state = deny reason;\r
1252             return ...\r
1253         }\r
1254         else if (policy check says forward to Server for validation)\r
1255         {\r
1256             /* Forward the transaction to the Server */\r
1257             Rm_transactionForwarder(rmInst, transaction);\r
1258         }\r
1259 #endif         \r
1260     }\r
1261     else if (rmInst->instType == Rm_instType_SERVER)\r
1262     {\r
1263         /* TEMP: Free the resources if resources are allocated to the source instance. */\r
1264 \r
1265         /* Fill out the allocator operation general information */\r
1266         opInfo.resourceInfo = &transaction->resourceInfo;\r
1267         opInfo.serviceSrcInstName = transaction->serviceSrcInstName;\r
1268 \r
1269         if (strlen(transaction->resourceInfo.nsName) > 0)\r
1270         {\r
1271             /* See if a NameServer name is being used to allocate a resource */\r
1272             if (transaction->resourceInfo.base != 0)\r
1273             {\r
1274                 /* A name and a value cannot be specified for the request.  It's one\r
1275                  * or the other. */\r
1276                 retVal = RM_SERVICE_ERROR_NAMESERVER_NAME_AND_RESOURCE_RANGE_BOTH_DEFINED;\r
1277             }\r
1278             else\r
1279             {\r
1280                 /* Get the resource information from the NameServer */\r
1281                 retVal = Rm_nsFindObject(rmInst, opInfo.resourceInfo);\r
1282             }\r
1283         }\r
1284         \r
1285         /* Call allocator as long as an error or denial hasn't occurred */\r
1286         if ((retVal == RM_SERVICE_PROCESSING) || (retVal == RM_NS_ACTION_APPROVED))\r
1287         {\r
1288             opInfo.operation = Rm_allocatorOp_FREE;\r
1289 \r
1290             retVal = Rm_allocatorOperation(rmInst, &opInfo);\r
1291         }\r
1292 \r
1293         transaction->state = retVal;\r
1294 \r
1295         if (strcmp(transaction->serviceSrcInstName, rmInst->name))\r
1296         {\r
1297             /* Source of allocation was not the server instance, provide the transaction\r
1298              * to the transaction responder */\r
1299             Rm_transactionResponder(rmInst, transaction);\r
1300         }\r
1301         /* Otherwise let the return stack return the transaction to the serviceHandler */  \r
1302         \r
1303 #if 0  /* Policy psuedo-code.  Will be implemented after basic allocate functionality is ready and tested */ \r
1304         /* Check global policy to see if resource can be freed. return result\r
1305          * no matter what */\r
1306         Rm_policy...API()\r
1307         if (policy approves)\r
1308         {\r
1309             /* call allocator to free resources */\r
1310         }\r
1311             \r
1312         transaction->state = approve or deny reason;\r
1313         transaction->resourceInfo.base = ...;\r
1314         transaction->resourceInfo.length = ...;\r
1315 \r
1316         /* If source instance name does not match the current instance\r
1317          * name the allocation request came from a client.  The result\r
1318          * must be sent back to the Client */\r
1319         if (strcmp(transaction->sourceInstName, rmInst->name))\r
1320         {\r
1321             /* Names don't match.  Send the transaction back to the Client Delegate or Client */\r
1322             Rm_transactionResponder(rmInst, transaction);\r
1323         }\r
1324         else\r
1325         {\r
1326             /* Resource allocation request originated locally on the active\r
1327              * instance. Send the response via the service responder. */\r
1328             Rm_serviceResponder(rmInst, transaction);                            \r
1329         }\r
1330 #endif        \r
1331     }   \r
1332 }\r
1333 \r
1334 /* Function used to send RM response transactions to lower level agents */\r
1335 void Rm_transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
1336 {\r
1337     Rm_TransportNode *dstTransportNode = NULL;\r
1338     Rm_Packet *rmPkt = NULL;\r
1339 \r
1340     /* Find the transport for the RM instance that sent the request. */\r
1341     dstTransportNode = Rm_transportNodeFindRemoteName(rmInst, transaction->pktSrcInstName);\r
1342 \r
1343     /* Create a RM packet using the service information */\r
1344     switch (transaction->type)\r
1345     {\r
1346         case Rm_service_RESOURCE_ALLOCATE:\r
1347         case Rm_service_RESOURCE_FREE:\r
1348         case Rm_service_RESOURCE_GET_BY_NAME:\r
1349             rmPkt = Rm_transportCreateResourceResponsePkt(rmInst, dstTransportNode, \r
1350                                                           transaction);\r
1351             break;\r
1352         case Rm_service_RESOURCE_MAP_TO_NAME:\r
1353         case Rm_service_RESOURCE_UNMAP_NAME:\r
1354             rmPkt = Rm_transportCreateNsResponsePkt(rmInst, dstTransportNode,\r
1355                                                     transaction);\r
1356             break;\r
1357         default:\r
1358             /* Invalid service type.  Flag the error and return */\r
1359             transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
1360             break;\r
1361     }\r
1362 \r
1363     if (transaction->state <= RM_SERVICE_ERROR_BASE)\r
1364     {\r
1365         /* Delete the transaction and return immediately because an error occurred \r
1366          * allocating the packet */\r
1367         Rm_transactionQueueDelete(rmInst, transaction->localId);\r
1368         return;\r
1369     }\r
1370 \r
1371     /* Send the RM packet to the application transport */\r
1372     if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL)\r
1373     {\r
1374         /* Negative value returned by transport send.  An error occurred\r
1375          * in the transport while attempting to send the packet.*/\r
1376         transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
1377         /* Clean up the packet */\r
1378         if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\r
1379         {\r
1380             /* Non-NULL value returned by transport packet free. Flag the\r
1381              * error */\r
1382             transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
1383         }\r
1384         return;\r
1385     }\r
1386 \r
1387     /* NEED TO DO SOMETHING IF GET AN ERROR IN THE transaction->state FIELD.  CREATE\r
1388      * NEW TRANSACTION WITH DATA FROM ORIGINAL?  THEN TRY TO SEND FAILED REQUEST BACK\r
1389      * TO REQUESTER???  KEEP RETRYING SEND OF RESPONSE??? */\r
1390 \r
1391     /* Delete the transaction */\r
1392     Rm_transactionQueueDelete(rmInst, transaction->localId);\r
1393 }\r
1394 \r
1395 /* Function used to forward RM transactions to higher level agents */\r
1396 void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
1397 {\r
1398     Rm_TransportNode *dstTransportNode = NULL;\r
1399     Rm_Packet *rmPkt = NULL;\r
1400 \r
1401     /* Make sure the RM instance has a transport registered with a higher level agent */\r
1402     if (rmInst->registeredWithDelegateOrServer == false)\r
1403     {\r
1404         transaction->state = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER;\r
1405         return;\r
1406     }\r
1407 \r
1408     /* Find the transport for the higher level agent.  Check for a connection to a Client Delegate\r
1409      * or a Server.  Clients will be connected to either a Client Delegate or a Server.  Client\r
1410      * Delegates will be connected to a Server. */\r
1411     if (rmInst->instType == Rm_instType_CLIENT)\r
1412     {\r
1413         dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_CLIENT_DELEGATE);\r
1414 \r
1415         if (!dstTransportNode)\r
1416         {\r
1417             /* No Client Delegate connection found.  Check for a Server connection */\r
1418             dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_SERVER);\r
1419         }\r
1420     } \r
1421     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
1422     {\r
1423         dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_SERVER);\r
1424     }\r
1425 \r
1426     /* Create a RM packet using the service information */\r
1427     switch (transaction->type)\r
1428     {\r
1429         case Rm_service_RESOURCE_ALLOCATE:\r
1430         case Rm_service_RESOURCE_FREE:\r
1431         case Rm_service_RESOURCE_GET_BY_NAME:\r
1432             rmPkt = Rm_transportCreateResourceReqPkt(rmInst, dstTransportNode, \r
1433                                                      transaction);\r
1434             break;\r
1435         case Rm_service_RESOURCE_MAP_TO_NAME:\r
1436         case Rm_service_RESOURCE_UNMAP_NAME:\r
1437             rmPkt = Rm_transportCreateNsRequestPkt(rmInst, dstTransportNode,\r
1438                                                    transaction);\r
1439             break;\r
1440         default:\r
1441             /* Invalid service type.  Flag the error and return */\r
1442             transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
1443             break;\r
1444     }\r
1445 \r
1446     if (transaction->state <= RM_SERVICE_ERROR_BASE)\r
1447     {\r
1448         /* Return immediately because an error occurred allocating the packet */\r
1449         return;\r
1450     }\r
1451 \r
1452     /* Send the RM packet to the application transport */\r
1453     if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL)\r
1454     {\r
1455         /* Negative value returned by transport send.  An error occurred\r
1456          * in the transport while attempting to send the packet.*/\r
1457         transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
1458         /* Clean up the packet */\r
1459         if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\r
1460         {\r
1461             /* Non-NULL value returned by transport packet free. Flag the\r
1462              * error */\r
1463             transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
1464         }\r
1465         return;\r
1466     }\r
1467 \r
1468     /* Transaction is not deleted because it is awaiting a response from the higher level\r
1469      * RM instance */\r
1470 }\r
1471 \r
1472 void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
1473 {\r
1474     /* Handle auto-forwarded transactions.  These transactions include:\r
1475      * - All request transactions received on Clients are forwarded to the Client Delegate\r
1476      * - NameServer requests received on the Client Delegate are forwarded to the Server */\r
1477     if ((rmInst->instType == Rm_instType_CLIENT) ||\r
1478         ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
1479          ((transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||\r
1480           (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) ||\r
1481           (transaction->type == Rm_service_RESOURCE_UNMAP_NAME))))\r
1482     {        \r
1483         /* Check if the transaction is a transaction that received a response to its\r
1484          * request. */\r
1485         if (transaction->state != RM_SERVICE_PROCESSING)\r
1486         {\r
1487 \r
1488             /* A transaction has received a response. Send the response to either the \r
1489              * transaction or service responder based on the source instance */\r
1490             if (strcmp(transaction->serviceSrcInstName, rmInst->name))\r
1491             {\r
1492                 /* Transaction originated from another instance.  Use the \r
1493                  * transaction responder to send the result to the source instance.  This\r
1494                  * is not possible on RM Clients since they can't forward RM services */\r
1495                 Rm_transactionResponder(rmInst, transaction);\r
1496             }\r
1497             else\r
1498             {\r
1499                 /* Transaction originated on this instance.  Send to the\r
1500                  * service responder */\r
1501                 Rm_serviceResponder(rmInst, transaction);\r
1502             }\r
1503         }\r
1504         else\r
1505         {\r
1506             /* This is a new transaction that must be forwarded to a higher level RM instance. */\r
1507             Rm_transactionForwarder(rmInst, transaction);\r
1508         }\r
1509     }\r
1510     else\r
1511     {\r
1512         /* Client Delegate and Server transaction processors. */\r
1513         switch (transaction->type)\r
1514         {\r
1515             case Rm_service_RESOURCE_ALLOCATE:\r
1516             case Rm_service_RESOURCE_FREE:               \r
1517                 /* Check if the transaction is fulfilled request */\r
1518                 if (transaction->state != RM_SERVICE_PROCESSING)\r
1519                 {\r
1520                     /* If source instance name does not match the current instance\r
1521                      * name the allocation request came from a client.  The result\r
1522                      * must be sent back to the Client */\r
1523                     if (strcmp(transaction->serviceSrcInstName, rmInst->name))\r
1524                     {\r
1525                         Rm_transactionResponder(rmInst, transaction);\r
1526                     }\r
1527                     else\r
1528                     {\r
1529                         /* Resource allocation request originated locally.  Send the response\r
1530                          * via the service responder. */\r
1531                         Rm_serviceResponder(rmInst, transaction);      \r
1532                     }\r
1533                 }\r
1534                 else\r
1535                 {\r
1536                     /* This is a new transaction request originating from an RM instance with fewer\r
1537                      * allocate/free privileges.  Run the allocation or free handler to see if the resource\r
1538                      * request can be handled locally or if it needs to be forwarded to a higher level\r
1539                      * agent */\r
1540                     if (transaction->type == Rm_service_RESOURCE_ALLOCATE)\r
1541                     {\r
1542                         Rm_allocationHandler(rmInst, transaction);\r
1543                     }\r
1544                     else\r
1545                     {\r
1546                         Rm_freeHandler(rmInst, transaction);\r
1547                     }\r
1548                 }\r
1549                 break;\r
1550             case Rm_service_RESOURCE_MAP_TO_NAME:\r
1551             case Rm_service_RESOURCE_GET_BY_NAME:\r
1552             case Rm_service_RESOURCE_UNMAP_NAME:                \r
1553                 /* Server is the only RM instance capable of adding NameServer objects */\r
1554                 if (rmInst->instType == Rm_instType_SERVER)\r
1555                 {\r
1556                     if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME)\r
1557                     {\r
1558                         /* Create a new NameServer object with the request transaction information.\r
1559                          * Transaction will contain the state result of the NameServer addition. */\r
1560                         if (Rm_nsAddObject(rmInst, &transaction->resourceInfo) == RM_NS_ACTION_APPROVED)\r
1561                         {\r
1562                             transaction->state = RM_SERVICE_APPROVED_AND_COMPLETED;\r
1563                         }\r
1564                         else\r
1565                         {\r
1566                             /* TEMP: UPDATE THIS STATE VALUE */\r
1567                             transaction->state = RM_SERVICE_DENIED_BEGIN;\r
1568                         }\r
1569                     }\r
1570                     else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)\r
1571                     {\r
1572                         /* Create a new NameServer object with the request transaction information.\r
1573                          * Transaction will contain the state result of the NameServer addition. */\r
1574                         if (Rm_nsFindObject(rmInst, &transaction->resourceInfo) == RM_NS_ACTION_APPROVED)\r
1575                         {\r
1576                             transaction->state = RM_SERVICE_APPROVED_AND_COMPLETED;\r
1577                         }\r
1578                         else\r
1579                         {\r
1580                             /* TEMP: UPDATE THIS STATE VALUE */\r
1581                             transaction->state = RM_SERVICE_DENIED_BEGIN;\r
1582                         }                    \r
1583                     }\r
1584                     else\r
1585                     {\r
1586                         /* Delete an existing NameServer object with the request transaction information\r
1587                          * Transaction will contain the state result of the NameServer addition. */\r
1588                         if (Rm_nsDeleteObject(rmInst, &transaction->resourceInfo) == \r
1589                             RM_NS_ACTION_APPROVED)\r
1590                         {\r
1591                             transaction->state = RM_SERVICE_APPROVED_AND_COMPLETED;\r
1592                         }\r
1593                         else\r
1594                         {\r
1595                             /* TEMP: UPDATE THIS STATE VALUE */\r
1596                             transaction->state = RM_SERVICE_DENIED_BEGIN;\r
1597                         }\r
1598                     }\r
1599 \r
1600                     /* If source instance name does not match the local instance\r
1601                      * name the NameServer request came from a Client or Client Delegate.  The \r
1602                      * result must be sent back to the Client or Client Delegate.  Just return if it does\r
1603                      * match since the NameServer transaction result can be returned immediately by the\r
1604                      * Rm_serviceHandler. */\r
1605                     if (strcmp(transaction->serviceSrcInstName, rmInst->name))\r
1606                     {\r
1607                         Rm_transactionResponder(rmInst, transaction);\r
1608                     }\r
1609                 }\r
1610                 else\r
1611                 {\r
1612                     transaction->state = RM_SERVICE_ERROR_NAMESERVER_OBJECT_MOD_ON_INVALID_INSTANCE;\r
1613                 }\r
1614                 break;\r
1615         }\r
1616     }\r
1617 }\r
1618 \r
1619 int32_t Rm_reserveLinuxResource(Rm_Inst *rmInst, Rm_LinuxAlias *linuxAlias, \r
1620                                 Rm_LinuxValueRange *linuxValues, Rm_AllocatorOpInfo *opInfo)\r
1621 {\r
1622     int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\r
1623     bool baseFound = FALSE;\r
1624     bool lengthFound = FALSE;\r
1625     uint32_t valueIndex = 0;\r
1626 \r
1627     while ((linuxValues != NULL) && (!baseFound || !lengthFound))\r
1628     {\r
1629         if (linuxAlias->baseOffset == valueIndex)\r
1630         {\r
1631             /* Found the resource base.  Store it in the operation info structure */\r
1632             opInfo->resourceInfo->base = linuxValues->value;\r
1633             baseFound = TRUE;\r
1634 \r
1635             /* length will always be 1 if there is no length specified in the Linux DTB */\r
1636             if (linuxAlias->lengthOffset == RM_DTB_LINUX_ALIAS_OFFSET_NOT_SET)\r
1637             {\r
1638                 opInfo->resourceInfo->length = 1;\r
1639                 lengthFound = TRUE;\r
1640             }\r
1641         }\r
1642         else if (linuxAlias->lengthOffset == valueIndex)\r
1643         {\r
1644             /* Found the resource length.  Store it in the operation info structure */\r
1645             opInfo->resourceInfo->length = linuxValues->value;\r
1646             lengthFound = TRUE;\r
1647         }\r
1648 \r
1649         linuxValues = (Rm_LinuxValueRange *)linuxValues->nextValue;\r
1650         valueIndex++;\r
1651     }\r
1652 \r
1653     if (!baseFound || !lengthFound)\r
1654     {\r
1655         retVal = -33; /* TODO: ERROR BASE OR LENGTH OFFSET IN LINUX DTB WAS INCORRECT */\r
1656     }\r
1657     else\r
1658     {\r
1659         /* Allocate the resource to Linux */\r
1660         retVal = Rm_allocatorOperation(rmInst, opInfo);\r
1661     }\r
1662 \r
1663     return (retVal);\r
1664 }\r
1665 \r
1666 int32_t Rm_findAndReserveLinuxResource(Rm_Inst *rmInst, const char *resourceName, void *linuxDtb, \r
1667                                        Rm_LinuxAlias *linuxAlias)\r
1668 {\r
1669     Rm_AllocatorOpInfo opInfo;\r
1670     Rm_ResourceInfo resourceInfo;\r
1671     uint32_t pathOffset;\r
1672     uint32_t pathSize;\r
1673     char *spacePtr;\r
1674     int32_t propOffset;\r
1675     int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
1676     int32_t prevDepth = RM_DTB_UTIL_STARTING_DEPTH;\r
1677     int32_t depth;\r
1678     int32_t propertyLen;\r
1679     const char *propertyName;\r
1680     const void *propertyData; \r
1681     Rm_LinuxValueRange *linuxValueRange;\r
1682     int32_t retVal = RM_DTB_UTIL_RESULT_OKAY; \r
1683 \r
1684     /* Initialize the allocator opInfo and resourceInfo structures that will be used to \r
1685      * reserve the resources taken by the Linux kernel */\r
1686     memset((void *) &opInfo, 0, sizeof(Rm_AllocatorOpInfo));\r
1687     memset((void *) &resourceInfo, 0, sizeof(Rm_ResourceInfo));\r
1688 \r
1689     strcpy(resourceInfo.name, resourceName);\r
1690 \r
1691     /* Set the source instance name for allocation to be the Linux Kernel */\r
1692     opInfo.serviceSrcInstName = RM_ALLOCATED_TO_LINUX;\r
1693     opInfo.operation = Rm_allocatorOp_ALLOCATE;\r
1694     opInfo.resourceInfo = &resourceInfo;    \r
1695 \r
1696     /* Find each resource specified in the Linux resource alias list and reserve that \r
1697      * resource as used */\r
1698     while(linuxAlias != NULL)\r
1699     {\r
1700         /* Reset the parsing variables */\r
1701         pathOffset = 0;\r
1702         pathSize = strlen(linuxAlias->path) + 1;\r
1703         nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
1704         prevDepth = RM_DTB_UTIL_STARTING_DEPTH;   \r
1705         resourceInfo.base = 0;\r
1706         resourceInfo.length = 0;\r
1707 \r
1708         spacePtr = strpbrk(linuxAlias->path, " ");\r
1709         if (spacePtr)\r
1710         {\r
1711             *spacePtr = '\0';\r
1712         }       \r
1713         \r
1714         while(pathOffset < pathSize)\r
1715         {\r
1716             /* Move through the DTB nodes until the next alias path node is found */\r
1717             if (strcmp(linuxAlias->path + pathOffset, fdt_get_name(linuxDtb, nodeOffset, NULL)))\r
1718             {\r
1719                 nodeOffset = fdt_next_node(linuxDtb, nodeOffset, &depth);\r
1720 \r
1721                 if ((depth < prevDepth) || (nodeOffset == -FDT_ERR_NOTFOUND))\r
1722                 {\r
1723                     /* Returning from subnode that matched part of alias path without finding\r
1724                      * the resource values */\r
1725                     retVal = (-31); /* TODO: COULD NOT FIND RESOURCE AT ALIAS PATH */\r
1726                     break;\r
1727                 }\r
1728             }\r
1729             else\r
1730             {\r
1731                 /* Found the next alias path node.  Move to the next node name in the path\r
1732                  * string. */\r
1733                 pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);\r
1734                 spacePtr = strpbrk(linuxAlias->path + pathOffset, " ");\r
1735                 if (spacePtr)\r
1736                 {\r
1737                     *spacePtr = '\0';\r
1738                 }       \r
1739                 \r
1740                 prevDepth = fdt_node_depth(linuxDtb, nodeOffset);\r
1741 \r
1742                 /* Check the properties of the node to see if they match the next alias\r
1743                  * path string */\r
1744                 propOffset = fdt_first_property_offset(linuxDtb, nodeOffset);\r
1745            \r
1746                 /* Search the properties for the next alias path string */\r
1747                 while ((propOffset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) &&\r
1748                        (pathOffset < pathSize))\r
1749                 {\r
1750                     propertyData = fdt_getprop_by_offset(linuxDtb, propOffset, \r
1751                                                          &propertyName, &propertyLen);\r
1752 \r
1753                     if (strcmp(linuxAlias->path + pathOffset, propertyName) == 0)\r
1754                     {\r
1755                         pathOffset += (strlen(linuxAlias->path + pathOffset) + 1);\r
1756                         /* Found the alias property.  Extract the values that will\r
1757                          * contain the resource information that must be reserved. */\r
1758                         linuxValueRange = Rm_linuxExtractValues(propertyData, propertyLen);\r
1759                         /* Use the values to reserve resources for the Linux kernel */\r
1760                         retVal = Rm_reserveLinuxResource(rmInst, linuxAlias, \r
1761                                                          linuxValueRange, &opInfo);\r
1762                         \r
1763                         /* Free the memory used to store the values */\r
1764                         Rm_linuxFreeValues(linuxValueRange);\r
1765                     }\r
1766                     \r
1767                     propOffset = fdt_next_property_offset(linuxDtb, propOffset);\r
1768                 } \r
1769 \r
1770                 if (propOffset < -FDT_ERR_NOTFOUND)\r
1771                 {\r
1772                         /* Error was returned by LIBFDT when parsing the properties */\r
1773                     retVal = propOffset;\r
1774                     break;\r
1775                 }\r
1776             }\r
1777         }\r
1778 \r
1779         if (retVal < RM_DTB_UTIL_RESULT_OKAY)\r
1780         {\r
1781             /* Error occurred during parsing of Linux DTB.  Return the error */\r
1782             break;\r
1783         }\r
1784         linuxAlias = (Rm_LinuxAlias *) linuxAlias->nextLinuxAlias;\r
1785     }\r
1786 \r
1787     return (retVal);\r
1788 }\r
1789 \r
1790 int32_t Rm_createAndInitAllocator(Rm_Inst *rmInst, const char *resourceName, \r
1791                                   Rm_ResourceProperties *resourceProperties, void *linuxDtb)\r
1792 {\r
1793     Rm_ResourceRange *range = NULL;\r
1794     Rm_ResourceRange *rangeBasePtr = NULL;\r
1795     Rm_NsAssignment *nsAssignments = NULL;\r
1796     Rm_NsAssignment *nsAssignmentBasePtr = NULL;\r
1797     Rm_LinuxAlias *linuxAlias = NULL;\r
1798     Rm_ResourceInfo resourceInfo;\r
1799     int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\r
1800 \r
1801     if (resourceProperties->rangeData && (resourceProperties->rangeLen > 0))\r
1802     {\r
1803         /* Extract the resource properties from the DTB */\r
1804         range = rangeBasePtr = Rm_resourceExtractRange(resourceProperties->rangeData, \r
1805                                                        resourceProperties->rangeLen);\r
1806 \r
1807         /* Create a tree allocator using the resource properties */\r
1808         retVal = Rm_createTreeAllocator(rmInst, resourceName, range); \r
1809 \r
1810         if (retVal >= RM_DTB_UTIL_RESULT_OKAY)\r
1811         {\r
1812             if (resourceProperties->linuxAliasData && resourceProperties->linuxAliasLen)\r
1813             {\r
1814                 /* Reserve the resources taken by the Linux kernel specified in the Linux DTB */\r
1815                 linuxAlias = Rm_resourceExtractLinuxAlias(resourceProperties->linuxAliasData,\r
1816                                                           resourceProperties->linuxAliasLen);\r
1817 \r
1818                 retVal = Rm_findAndReserveLinuxResource(rmInst, resourceName, linuxDtb, linuxAlias);            \r
1819             }\r
1820         }\r
1821     }\r
1822     \r
1823     if (retVal >= RM_DTB_UTIL_RESULT_OKAY)\r
1824     {\r
1825         /* Create entries in the NameServer if any NameServer assignments were specified */\r
1826         if (resourceProperties->nsAssignData && resourceProperties->nsAssignLen)\r
1827         {\r
1828             nsAssignments = Rm_resourceExtractNsAssignment(resourceProperties->nsAssignData, \r
1829                                                            resourceProperties->nsAssignLen);\r
1830 \r
1831             /* Cycle through the list of assignments and add them to the NameServer */\r
1832             nsAssignmentBasePtr = nsAssignments;\r
1833             while (nsAssignments)\r
1834             {\r
1835                 memset((void *)&resourceInfo, 0, sizeof(Rm_ResourceInfo));\r
1836 \r
1837                 strcpy(resourceInfo.name, resourceName);\r
1838                 resourceInfo.base = nsAssignments->resourceBase;\r
1839                 resourceInfo.length = nsAssignments->resourceLength;\r
1840                 strcpy(resourceInfo.nsName, nsAssignments->nsName);\r
1841                 \r
1842                 /* TODO: RETURN IF ANY OF THE ADDS FAIL??? */\r
1843                 Rm_nsAddObject(rmInst, &resourceInfo);\r
1844                 nsAssignments = nsAssignments->nextNsAssignment;\r
1845             }\r
1846             /* Free the memory allocated for the NameServer assignments */\r
1847             Rm_resourceFreeNsAssignmentList(nsAssignmentBasePtr);\r
1848         }\r
1849     }\r
1850 \r
1851     /* Free the memory allocated for the resource properties */\r
1852     Rm_resourceFreeRange(rangeBasePtr);\r
1853     Rm_resourceFreeLinuxAlias(linuxAlias);\r
1854 \r
1855     return(retVal);\r
1856 }\r
1857 \r
1858 int32_t Rm_parseResourceProperty(void *globalResourceDtb, int32_t offset, Rm_ResourceProperties *propertyInfo)\r
1859 {\r
1860         int32_t propertyLen;\r
1861         const char *propertyName;\r
1862         const void *propertyData;\r
1863     Rm_ResourcePropType propertyType;\r
1864     int32_t retVal = RM_DTB_UTIL_RESULT_OKAY;\r
1865 \r
1866     /* Get the property data and store it in the corresponding propertyInfo field */\r
1867         propertyData = fdt_getprop_by_offset(globalResourceDtb, offset, &propertyName, &propertyLen);\r
1868     if (propertyData)\r
1869     {\r
1870         propertyType = Rm_resourceGetPropertyType(propertyName);\r
1871         if (propertyType == Rm_resourcePropType_RESOURCE_RANGE)\r
1872         {\r
1873             if (propertyInfo->rangeData || propertyInfo->rangeLen)\r
1874             {\r
1875                 /* The range fields have already been populated.  Return an error.\r
1876                  * The resource list has specified a property field more than once\r
1877                  * for a resource node */\r
1878                 retVal = -18; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
1879             }\r
1880             else\r
1881             {\r
1882                 propertyInfo->rangeData = propertyData;\r
1883                 propertyInfo->rangeLen = propertyLen;\r
1884             }\r
1885         }\r
1886         else if (propertyType == Rm_resourcePropType_NSASSIGNMENT)\r
1887         {\r
1888             if (propertyInfo->nsAssignData || propertyInfo->nsAssignLen)\r
1889             {\r
1890                 /* The nsAssign fields have already been populated.  Return an error.\r
1891                  * The resource list has specified a property field more than once\r
1892                  * for a resource node */\r
1893                 retVal = -19; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
1894             }\r
1895             else\r
1896             {\r
1897                 propertyInfo->nsAssignData = propertyData;\r
1898                 propertyInfo->nsAssignLen = propertyLen;\r
1899             }\r
1900         }\r
1901         else if (propertyType == Rm_resourcePropType_RESOURCE_LINUX_ALIAS)\r
1902         {\r
1903             if (propertyInfo->linuxAliasData || propertyInfo->linuxAliasLen)\r
1904             {\r
1905                 /* The linuxAlias fields have already been populated.  Return an error.\r
1906                  * The resource list has specified a property field more than once\r
1907                  * for a resource node */\r
1908                 retVal = -28; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
1909             }\r
1910             else\r
1911             {\r
1912                 propertyInfo->linuxAliasData = propertyData;\r
1913                 propertyInfo->linuxAliasLen = propertyLen;\r
1914             }\r
1915         }        \r
1916         else\r
1917         {\r
1918             retVal = -20; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
1919         }\r
1920     }\r
1921     else\r
1922     {\r
1923         retVal = -16; /* TEMP ERROR: Can't conflict with LIBFDT errors */\r
1924     }\r
1925 \r
1926     /* Don't get anymore properties if error occurred */\r
1927     if (retVal == RM_DTB_UTIL_RESULT_OKAY)\r
1928     {\r
1929         offset = fdt_next_property_offset(globalResourceDtb, offset);\r
1930         if (offset >= 0)\r
1931         {\r
1932             retVal = Rm_parseResourceProperty(globalResourceDtb, offset, propertyInfo);\r
1933         }\r
1934         else if (offset != -FDT_ERR_NOTFOUND)\r
1935         {\r
1936             /* Error was returned by LIBFDT when parsing the properties */\r
1937             retVal = offset;\r
1938         }\r
1939     }\r
1940     \r
1941     return (retVal);\r
1942 }\r
1943 \r
1944 int32_t Rm_parseResourceNode(Rm_Inst *rmInst, void *globalResourceDtb, int32_t nodeOffset, int32_t depth,\r
1945                              void *linuxDtb)\r
1946 {\r
1947         const char *resourceName = fdt_get_name(globalResourceDtb, nodeOffset, NULL);\r
1948     Rm_ResourceProperties resourceProperties;\r
1949         int32_t error = RM_DTB_UTIL_RESULT_OKAY;\r
1950         int32_t offset;\r
1951 \r
1952     /* Initialize the resource properties structure */\r
1953     memset((void *)&resourceProperties, 0, sizeof(Rm_ResourceProperties));\r
1954 \r
1955     /* Ignore properties of the base node */\r
1956     if (strcmp(resourceName, rmDtbStartingNode))\r
1957     {\r
1958         /* Get the properties for the resource node if any exist */\r
1959         offset = fdt_first_property_offset(globalResourceDtb, nodeOffset);\r
1960         if (offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET)\r
1961         {\r
1962             /* Since at least one property exists attempt to parse the property nodes and \r
1963              * use them to create and initialize a resource allocator */\r
1964                 error =  Rm_parseResourceProperty(globalResourceDtb, offset, &resourceProperties);\r
1965             if (error < -FDT_ERR_NOTFOUND)\r
1966             {\r
1967                 return (error);\r
1968             }\r
1969             \r
1970             /* Initialize an allocator with the resource properties if no error was returned */\r
1971             Rm_createAndInitAllocator(rmInst, resourceName, &resourceProperties, linuxDtb);\r
1972         }\r
1973         else if (offset != -FDT_ERR_NOTFOUND)\r
1974         {\r
1975                 /* Error was returned by LIBFDT when parsing the properties */\r
1976             return (offset);\r
1977         }\r
1978     }\r
1979     \r
1980     /* Get the next resource node */\r
1981         offset = fdt_next_node(globalResourceDtb, nodeOffset, &depth);\r
1982     /* Check the offset and depth of the next node to make sure the current node\r
1983      * wasn't the last node in the Resource List.  A depth less than the depth set\r
1984      * at the start of the recursion will signal the end of the resource list */\r
1985     if ((offset >= RM_DTB_UTIL_STARTING_NODE_OFFSET) && (depth >= RM_DTB_UTIL_STARTING_DEPTH))\r
1986     {\r
1987         error = Rm_parseResourceNode(rmInst, globalResourceDtb, offset, depth, linuxDtb);\r
1988         if (error < -FDT_ERR_NOTFOUND)\r
1989         {\r
1990             return (error);\r
1991         }\r
1992     }\r
1993     else if (offset != -FDT_ERR_NOTFOUND)\r
1994     {\r
1995         /* Error was returned by LIBFDT when parsing the nodes */\r
1996         return (offset);\r
1997     }\r
1998 \r
1999     return (RM_DTB_UTIL_RESULT_OKAY);\r
2000 }\r
2001 \r
2002 int32_t Rm_initializeAllocators(Rm_Inst *rmInst, void *globalResourceDtb, void *linuxDtb)\r
2003 {\r
2004     int32_t nodeOffset = RM_DTB_UTIL_STARTING_NODE_OFFSET;\r
2005     int32_t startDepth = RM_DTB_UTIL_STARTING_DEPTH;\r
2006     int32_t result = RM_DTB_UTIL_RESULT_OKAY;\r
2007 \r
2008     /* Recursively parse the Global Resource List, creating an allocator for\r
2009      * each resource as specified in the node */\r
2010     result = Rm_parseResourceNode(rmInst, globalResourceDtb, nodeOffset, startDepth, linuxDtb);\r
2011 \r
2012     return(result);\r
2013 }\r
2014      \r
2015 /**********************************************************************\r
2016  ********************** Application visible APIs **********************\r
2017  **********************************************************************/\r
2018 \r
2019 /* Server Only */\r
2020 void Rm_printResourceStatus(Rm_Handle *rmHandle)\r
2021 {\r
2022     Rm_Inst *rmInst = (Rm_Inst *) rmHandle;\r
2023     Rm_Allocator *allocator = rmInst->allocators;\r
2024     Rm_ResourceTree *treeRoot;\r
2025     Rm_ResourceNode *treeNode;\r
2026     uint32_t numLinuxResources;\r
2027 \r
2028     while (allocator != NULL)\r
2029     {\r
2030         numLinuxResources = 0;\r
2031 \r
2032         Rm_osalLog("Resource: %s\n", allocator->resourceName);\r
2033 \r
2034         treeRoot = allocator->allocatorRootEntry;\r
2035 \r
2036         RB_FOREACH(treeNode, _Rm_ResourceTree, treeRoot)\r
2037         {               \r
2038             Rm_osalLog("          %10d - %10d ", treeNode->base, \r
2039                                                  treeNode->base + treeNode->length -1);\r
2040             \r
2041             if (strcmp(treeNode->allocatedTo, RM_NOT_ALLOCATED_STRING) == 0)\r
2042             {\r
2043                 Rm_osalLog("NOT ALLOCATED\n");\r
2044             }\r
2045             else\r
2046             {\r
2047                 Rm_osalLog("allocated to %s\n", treeNode->allocatedTo);\r
2048             }\r
2049 \r
2050             if (strcmp(treeNode->allocatedTo, RM_ALLOCATED_TO_LINUX) == 0)\r
2051             {\r
2052                 numLinuxResources += treeNode->length;\r
2053             }\r
2054         }\r
2055         \r
2056         Rm_osalLog("Total allocated to Linux: %d\n", numLinuxResources);\r
2057         \r
2058         allocator = allocator->nextAllocator;\r
2059     }\r
2060 \r
2061     Rm_nsPrintObjects(rmInst);\r
2062 }\r
2063 \r
2064 Rm_Handle Rm_init(Rm_InitCfg *initCfg)\r
2065 {\r
2066     Rm_Inst *rmInst;\r
2067     void *globalResourceDtb = NULL;\r
2068     void *linuxResourceDtb = NULL;\r
2069 \r
2070     /* Instance creation checks.  Add one to strlen calculation for null character */\r
2071     if ((strlen(initCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS)\r
2072     {\r
2073         /* Failure: Instance name is too big */\r
2074         return (NULL);\r
2075     }\r
2076     \r
2077     /* Get memory for RM instance from local memory */\r
2078     rmInst = Rm_osalMalloc (sizeof(Rm_Inst));\r
2079     /* Populate instance based on input parameters */\r
2080     strcpy (&rmInst->name[0], initCfg->instName);\r
2081     rmInst->instType = initCfg->instType;\r
2082     rmInst->registeredWithDelegateOrServer = false;\r
2083     rmInst->policyDtb = NULL;\r
2084 \r
2085     /* Initialize the transport routing map linked list pointer to NULL.  The linked list\r
2086      * nodes will be created when the application registers transports */\r
2087     rmInst->routeMap = NULL;\r
2088 \r
2089     /* Initialize the allocators linked list pointer to NULL.  The linked list nodes will\r
2090      * be created on the Server instance when the application reads in the resource list.\r
2091      * Nodes will also be created on Client Delegates when blocks of resources are requested\r
2092      * for allocation to clients. */\r
2093     rmInst->allocators = NULL;\r
2094 \r
2095     /* Initialize the NameServer pointer to NULL.  The NameServer should only be located\r
2096      * on the RM Server */\r
2097     rmInst->nameServer = NULL;\r
2098 \r
2099     /* Initialize the transaction queue elements. */\r
2100     rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
2101     rmInst->transactionQueue= NULL;\r
2102 \r
2103     /* RM Server specific actions */\r
2104     if (rmInst->instType == Rm_instType_SERVER)\r
2105     {\r
2106         /* Initialize the NameServer */\r
2107         Rm_nsInit(rmInst);\r
2108         \r
2109         /* Open the ResourceList file and provide it to the resource initializer.  The Linux\r
2110          * DTB will be parsed simultaneously for resource's consumed by the kernel.  The resources\r
2111          * used by the kernel will be marked as used in the resource allocators. */\r
2112         if (initCfg->globalResourceList)\r
2113         {\r
2114             globalResourceDtb = initCfg->globalResourceList;\r
2115             fdt_open_into(globalResourceDtb, globalResourceDtb, fdt_totalsize(globalResourceDtb));\r
2116 \r
2117             if (initCfg->linuxDtb)\r
2118             {\r
2119                 linuxResourceDtb = initCfg->linuxDtb;\r
2120                 fdt_open_into(linuxResourceDtb, linuxResourceDtb, fdt_totalsize(linuxResourceDtb));   \r
2121             }\r
2122             \r
2123             Rm_initializeAllocators(rmInst, globalResourceDtb, linuxResourceDtb);\r
2124         }\r
2125     }\r
2126 \r
2127     /* Instance startup policies are only used for Servers and Client Delegates */\r
2128     if (rmInst->instType != Rm_instType_CLIENT)\r
2129     {\r
2130         /* Open the instance's policy and store it */\r
2131         if (initCfg->startupPolicy)\r
2132         {\r
2133             rmInst->policyDtb = initCfg->startupPolicy;\r
2134             fdt_open_into(rmInst->policyDtb, rmInst->policyDtb, fdt_totalsize(rmInst->policyDtb));  \r
2135         }\r
2136 \r
2137         /* Store policy via policy APIs ... */\r
2138     }\r
2139 \r
2140     /* Return the RM Handle */\r
2141     return ((Rm_Handle) rmInst);\r
2142 }\r
2143 \r
2144 uint32_t Rm_getVersion (void)\r
2145 {\r
2146     return RM_VERSION_ID;\r
2147 }\r
2148 \r
2149 \r
2150 const char* Rm_getVersionStr (void)\r
2151 {\r
2152     return rmVersionStr;\r
2153 }\r
2154 \r
2155 /**\r
2156 @}\r
2157 */\r