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