Tested ability to read in and parse resource and policy DTB files
[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 \r
57 /* RM LIBFDT includes */\r
58 #include <ti/drv/rm/src/libfdt/libfdt.h>\r
59 \r
60 /* RM OSAL layer */\r
61 #include <rm_osal.h>\r
62 \r
63 /**********************************************************************\r
64  ************************** Globals ***********************************\r
65  **********************************************************************/\r
66 #if 0\r
67 /* Place QMSS PDSP permissions array */\r
68 #pragma DATA_SECTION (rmQmssPdspFirmwarePerms, ".rm");\r
69 #pragma DATA_ALIGN (rmQmssPdspFirmwarePerms, 128)\r
70 Rm_Perms rmQmssPdspFirmwarePerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_FIRMWARE_PDSPS, Rm_Perms)];\r
71 #endif\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  ********************** Internal Functions ****************************\r
78  **********************************************************************/\r
79 \r
80 /* At the very least the transaction ID needs to be provided to create a transaction */\r
81 Rm_Transaction *Rm_transactionQueueAdd(Rm_Inst *rmInst)\r
82 {\r
83     Rm_Transaction *transactionQueue = (Rm_Transaction *)rmInst->transactionQueue;\r
84     Rm_Transaction *newTransaction = NULL;\r
85     void *key;\r
86 \r
87     /* Lock access to the RM instance's transaction queue */\r
88     key = Rm_osalMtCsEnter();\r
89 \r
90     /* Get memory for a new transaction from local memory */\r
91     newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));\r
92 \r
93     /* Return if the memory allocated for the transaction entry is NULL */\r
94     if (newTransaction == NULL)\r
95     {\r
96         Rm_osalMtCsExit(key);\r
97         return(newTransaction);\r
98     }\r
99 \r
100     /* Clear the transaction */\r
101     memset((void *)newTransaction, 0, sizeof(Rm_Transaction));\r
102 \r
103     /* Create an ID for the new transaction.  The ID will be used for two purposes:\r
104      * 1) Matching responses from higher level RM agents to requests\r
105      * 2) Provided to the component that requested the service so that it can match its\r
106      *    request with the response it receives via its callback function it provided */\r
107     newTransaction->localId = Rm_transactionGetSequenceNum(rmInst);\r
108     /* New transaction's nextTransaction pointer will always be NULL */\r
109     newTransaction->nextTransaction = NULL;  \r
110 \r
111     /* Check if there are any transactions in the transaction queue */\r
112     if (transactionQueue)\r
113     {\r
114         /* At least one transaction in the transaction queue.  Add the new entry to the \r
115          * end of the transaction queue */\r
116         while (transactionQueue->nextTransaction != NULL)\r
117         {\r
118             /* Traverse the list until arriving at the last transaction */\r
119             transactionQueue = transactionQueue->nextTransaction;\r
120         }\r
121 \r
122         /* Add the new transaction to the end of the queue */\r
123         transactionQueue->nextTransaction = newTransaction;\r
124     }\r
125     else\r
126     {\r
127         /* The transaction queue does not currently exist.  The new transaction is the \r
128          * first transaction */\r
129         rmInst->transactionQueue = newTransaction;\r
130     }\r
131 \r
132     Rm_osalMtCsExit(key);\r
133     return (newTransaction);\r
134 }\r
135 \r
136 Rm_Transaction *Rm_transactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)\r
137 {\r
138     Rm_Transaction *transaction = (Rm_Transaction *)rmInst->transactionQueue;\r
139 \r
140     /* Make sure there is at least one transaction in the transaction queue */\r
141     if (transaction != NULL)\r
142     {\r
143         /* Find the transaction ID within the specified RM instance's transaction queue.\r
144          * If the end of the transaction queue is reached without finding the transaction the \r
145          * transaction pointer will be NULL */\r
146         while (transaction != NULL)\r
147         {\r
148             if (transaction->localId == transactionId)\r
149             {\r
150                 /* Match: break out of loop and return the transaction */\r
151                 break;             \r
152             }\r
153             transaction = transaction->nextTransaction;\r
154         }\r
155     }\r
156 \r
157     return (transaction);\r
158 }\r
159 \r
160 int32_t Rm_transactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)\r
161 {\r
162     Rm_Transaction *transaction = (Rm_Transaction *) rmInst->transactionQueue;\r
163     Rm_Transaction *prevTransaction = NULL;\r
164     int32_t retVal = RM_SERVICE_STATE_OKAY;\r
165     void *key;\r
166 \r
167     /* Lock access to the RM instance's transaction queue */\r
168     key = Rm_osalMtCsEnter();\r
169 \r
170     /* Find the transaction ID within the specified RM instance's transaction queue. */\r
171     while (transaction != NULL)\r
172     {\r
173         if (transaction->localId == transactionId)\r
174         {\r
175             /* Match: break out of loop and delete the transaction */\r
176             break;             \r
177         }\r
178 \r
179         prevTransaction = transaction;\r
180         transaction = transaction->nextTransaction;\r
181     }\r
182 \r
183     /* Traversed entire queue but did not find transaction */\r
184     if (transaction == NULL)\r
185     {\r
186         retVal = RM_SERVICE_ERROR_SERVICE_TRANSACTION_DOES_NOT_EXIST;\r
187     }\r
188     else\r
189     {\r
190         /* Delete the transaction */\r
191         if (prevTransaction == NULL)\r
192         {\r
193             /* Transaction to be deleted exists at start of transaction queue.  Map second\r
194              * transaction to be start of transaction queue.  This covers case where there is\r
195              * only one transaction in the queue since the nextTransaction will be NULL */\r
196             rmInst->transactionQueue = transaction->nextTransaction;\r
197         }\r
198         else\r
199         {\r
200             /* Transaction to be deleted is in the middle or at end of the queue.  Adjust \r
201              * adjacent transaction pointers.  This covers the case where the transaction to be \r
202              * removed is at the end of the queue. */\r
203             prevTransaction->nextTransaction = transaction->nextTransaction;\r
204         }\r
205 \r
206         /* Free the memory associated with the transaction. */\r
207         Rm_osalFree((void *)transaction, sizeof(Rm_Transaction), false);\r
208     }\r
209 \r
210     Rm_osalMtCsExit(key);\r
211     return (retVal);\r
212 }\r
213 \r
214 uint32_t Rm_transactionInitSequenceNum(void)\r
215 {\r
216     /* Sequence number can never have a value of zero so that there are no conflicts\r
217      * with transactions that have a remoteOriginatingId of zero */\r
218     return (1);\r
219 }\r
220 \r
221 uint32_t Rm_transactionGetSequenceNum(Rm_Inst *rmInst)\r
222 {\r
223     uint32_t sequenceNum = 0;\r
224 \r
225     /* Get the next sequence number and then increment.  If there's an overflow\r
226      * assign the initial value instead of incrementing. */\r
227     if (rmInst->transactionSeqNum + 1 < rmInst->transactionSeqNum)\r
228     {\r
229         /* Overflow */\r
230         sequenceNum = rmInst->transactionSeqNum;\r
231         rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
232     }\r
233     else\r
234     {\r
235         sequenceNum = rmInst->transactionSeqNum++;\r
236     }    \r
237 \r
238     return (sequenceNum);\r
239 }\r
240 \r
241 /* Function used to send RM response transactions to lower level agents */\r
242 void Rm_transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
243 {\r
244     Rm_TransportNode *dstTransportNode = NULL;\r
245     Rm_Packet *rmPkt = NULL;\r
246 \r
247     /* Find the transport for the RM instance that sent the request. */\r
248     dstTransportNode = Rm_transportNodeFindRemoteName(rmInst, transaction->sourceInstName);\r
249 \r
250     /* Create a RM packet using the service information */\r
251     switch (transaction->type)\r
252     {\r
253         case Rm_service_RESOURCE_ALLOCATE:\r
254         case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
255         case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
256         case Rm_service_RESOURCE_FREE:\r
257         case Rm_service_RESOURCE_BLOCK_FREE:\r
258         case Rm_service_RESOURCE_FREE_BY_NAME:\r
259             rmPkt = Rm_transportCreateResourceResponsePkt(rmInst, dstTransportNode, \r
260                                                           transaction);\r
261             break;\r
262         case Rm_service_RESOURCE_MAP_TO_NAME:\r
263         case Rm_service_RESOURCE_UNMAP_NAME:\r
264             rmPkt = Rm_transportCreateNsResponsePkt(rmInst, dstTransportNode,\r
265                                                     transaction);\r
266             break;\r
267         default:\r
268             /* Invalid service type.  Flag the error and return */\r
269             transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
270             break;\r
271     }\r
272 \r
273     if (transaction->state <= RM_SERVICE_ERROR_BASE)\r
274     {\r
275         /* Delete the transaction and return immediately because an error occurred \r
276          * allocating the packet */\r
277         Rm_transactionQueueDelete(rmInst, transaction->localId);\r
278         return;\r
279     }\r
280 \r
281     /* Send the RM packet to the application transport */\r
282     if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL)\r
283     {\r
284         /* Negative value returned by transport send.  An error occurred\r
285          * in the transport while attempting to send the packet.*/\r
286         transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
287         /* Clean up the packet */\r
288         if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\r
289         {\r
290             /* Non-NULL value returned by transport packet free. Flag the\r
291              * error */\r
292             transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
293         }\r
294         return;\r
295     }\r
296 \r
297     /* NEED TO DO SOMETHING IF GET AN ERROR IN THE transaction->state FIELD.  CREATE\r
298      * NEW TRANSACTION WITH DATA FROM ORIGINAL?  THEN TRY TO SEND FAILED REQUEST BACK\r
299      * TO REQUESTER???  KEEP RETRYING SEND OF RESPONSE??? */\r
300 \r
301     /* Delete the transaction */\r
302     Rm_transactionQueueDelete(rmInst, transaction->localId);\r
303 }\r
304 \r
305 void Rm_allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
306 {\r
307     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
308     {\r
309 #if 0        \r
310         /* Check local policy to see if the request can be satisfied with the\r
311          * resources stored locally */\r
312         Rm_policy...API()\r
313 \r
314         if (policy check approves the resource)\r
315         {\r
316             /* call the allocator to allocate the resource */\r
317             if (allocator returns resource)\r
318             {\r
319                 /* Populate the transaction with the allocated resources and the result */\r
320                 transaction->state = approve reason;\r
321                 return ...\r
322             }\r
323             else\r
324             {\r
325                 /* allocator ran out of resources, need to contact Server for more\r
326                  * resources */\r
327                 Rm_resourcePoolModRequest(...);\r
328             }\r
329         }\r
330         else if (policy check denies resource)\r
331         {\r
332             /* Policy check denied resource. */\r
333             transaction->state= deny reason;\r
334             return ...\r
335         }\r
336         else if (policy check says forward to Server for validation)\r
337         {\r
338             /* Forward the transaction to the Server */\r
339             Rm_transactionForwarder(rmInst, transaction);\r
340         }\r
341 #endif         \r
342     }\r
343     else if (rmInst->instType == Rm_instType_SERVER)\r
344     {\r
345 #if 0        \r
346         /* Check global policy to see if resource can be allocated. return result\r
347          * no matter what */\r
348         Rm_policy...API()\r
349 \r
350         if (policy approves)\r
351         {\r
352             /* call allocator to allocate resource */\r
353         }\r
354 \r
355         transaction->state = approve or deny reason;\r
356         transaction->resourceInfo.base = ...;\r
357         transaction->resourceInfo.range = ...;\r
358 \r
359         /* If source instance name does not match the current instance\r
360          * name the allocation request came from a Client.  The result\r
361          * must be sent back to the Client */\r
362         if (strcmp(transaction->sourceInstName, rmInst->name))\r
363         {\r
364             /* Names don't match.  Send the transaction back to the Client */\r
365             Rm_transactionResponder(rmInst, transaction);\r
366         }\r
367         else\r
368         {\r
369             /* Resource allocation request originated locally on the active\r
370              * instance. Send the response via the service responder. */          \r
371             Rm_serviceResponder(rmInst, transaction);                            \r
372         }\r
373 #endif        \r
374     }   \r
375 }\r
376 \r
377 void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
378 {\r
379     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
380     {\r
381 #if 0        \r
382         /* Check local policy to see if the request can be satisfied with the\r
383          * resources stored locally */\r
384         Rm_policy...API()\r
385 \r
386         if (policy check approves the free)\r
387         {\r
388             /* call the allocator to free the resource */\r
389             /* Run a resource pool check to see if the free combined a resource block\r
390              * that can be returned to the server */\r
391             if (resource block has been combined)\r
392             {\r
393                   /* allocator ran out of resources, need to contact Server for more\r
394                  * resources */\r
395                 Rm_resourcePoolModRequest(free pool block to server...);\r
396             }\r
397             else\r
398             {\r
399                 /* Populate the receipt with the freed resources and the result */\r
400                 transaction->state = approve reason;\r
401                 return ...\r
402             }\r
403         }\r
404         else if (policy check denies resource free)\r
405         {\r
406             /* Policy check denied resource. */\r
407             transaction->state = deny reason;\r
408             return ...\r
409         }\r
410         else if (policy check says forward to Server for validation)\r
411         {\r
412             /* Forward the transaction to the Server */\r
413             Rm_transactionForwarder(rmInst, transaction);\r
414         }\r
415 #endif         \r
416     }\r
417     else if (rmInst->instType == Rm_instType_SERVER)\r
418     {\r
419 #if 0        \r
420         /* Check global policy to see if resource can be freed. return result\r
421          * no matter what */\r
422         Rm_policy...API()\r
423         if (policy approves)\r
424         {\r
425             /* call allocator to free resources */\r
426         }\r
427             \r
428         transaction->state = approve or deny reason;\r
429         transaction->resourceInfo.base = ...;\r
430         transaction->resourceInfo.range = ...;\r
431 \r
432         /* If source instance name does not match the current instance\r
433          * name the allocation request came from a client.  The result\r
434          * must be sent back to the Client */\r
435         if (strcmp(transaction->sourceInstName, rmInst->name))\r
436         {\r
437             /* Names don't match.  Send the transaction back to the Client Delegate or Client */\r
438             Rm_transactionResponder(rmInst, transaction);\r
439         }\r
440         else\r
441         {\r
442             /* Resource allocation request originated locally on the active\r
443              * instance. Send the response via the service responder. */\r
444             Rm_serviceResponder(rmInst, transaction);                            \r
445         }\r
446 #endif        \r
447     }   \r
448 }\r
449 \r
450 /* Function used to forward RM transactions to higher level agents */\r
451 void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
452 {\r
453     Rm_TransportNode *dstTransportNode = NULL;\r
454     Rm_Packet *rmPkt = NULL;\r
455 \r
456     /* Make sure the RM instance has a transport registered with a higher level agent */\r
457     if (rmInst->registeredWithDelegateOrServer == false)\r
458     {\r
459         transaction->state = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER;\r
460         return;\r
461     }\r
462 \r
463     /* Find the transport for the higher level agent.  Check for a connection to a Client Delegate\r
464      * or a Server.  Clients will be connected to either a Client Delegate or a Server.  Client\r
465      * Delegates will be connected to a Server. */\r
466     if (rmInst->instType == Rm_instType_CLIENT)\r
467     {\r
468         dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_CLIENT_DELEGATE);\r
469     } \r
470     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
471     {\r
472         dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_SERVER);\r
473     }\r
474 \r
475     /* Create a RM packet using the service information */\r
476     switch (transaction->type)\r
477     {\r
478         case Rm_service_RESOURCE_ALLOCATE:\r
479         case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
480         case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
481         case Rm_service_RESOURCE_FREE:\r
482         case Rm_service_RESOURCE_BLOCK_FREE:\r
483         case Rm_service_RESOURCE_FREE_BY_NAME:\r
484             rmPkt = Rm_transportCreateResourceReqPkt(rmInst, dstTransportNode, \r
485                                                      transaction);\r
486             break;\r
487         case Rm_service_RESOURCE_MAP_TO_NAME:\r
488         case Rm_service_RESOURCE_UNMAP_NAME:\r
489             rmPkt = Rm_transportCreateNsRequestPkt(rmInst, dstTransportNode,\r
490                                                    transaction);\r
491             break;\r
492         default:\r
493             /* Invalid service type.  Flag the error and return */\r
494             transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
495             break;\r
496     }\r
497 \r
498     if (transaction->state <= RM_SERVICE_ERROR_BASE)\r
499     {\r
500         /* Return immediately because an error occurred allocating the packet */\r
501         return;\r
502     }\r
503 \r
504     /* Send the RM packet to the application transport */\r
505     if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL)\r
506     {\r
507         /* Negative value returned by transport send.  An error occurred\r
508          * in the transport while attempting to send the packet.*/\r
509         transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
510         /* Clean up the packet */\r
511         if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\r
512         {\r
513             /* Non-NULL value returned by transport packet free. Flag the\r
514              * error */\r
515             transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
516         }\r
517         return;\r
518     }\r
519 \r
520     /* Transaction is not deleted because it is awaiting a response from the higher level\r
521      * RM instance */\r
522 }\r
523 \r
524 void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
525 {\r
526     /* Handle auto-forwarded transactions.  These transactions include:\r
527      * - All request transactions received on Clients are forwarded to the Client Delegate\r
528      * - NameServer requests received on the Client Delegate are forwarded to the Server */\r
529     if ((rmInst->instType == Rm_instType_CLIENT) ||\r
530         ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
531          (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||\r
532          (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)))\r
533     {\r
534         /* Check if the transaction is a transaction that received a response to its\r
535          * request. */\r
536         if (transaction->state != RM_SERVICE_PROCESSING)\r
537         {\r
538 \r
539             /* A transaction has received a response. Send the response to either the \r
540              * transaction or service responder based on the source instance */\r
541             if (strcmp(transaction->sourceInstName, rmInst->name))\r
542             {\r
543                 /* Transaction originated from another instance.  Use the \r
544                  * transaction responder to send the result to the source instance.  This\r
545                  * is not possible on RM Clients since they can't forward RM services */\r
546                 Rm_transactionResponder(rmInst, transaction);\r
547             }\r
548             else\r
549             {\r
550                 /* Transaction originated on this instance.  Send to the\r
551                  * service responder */\r
552                 Rm_serviceResponder(rmInst, transaction);\r
553             }\r
554         }\r
555         else\r
556         {\r
557             /* This is a new transaction that must be forwarded to a higher level RM instance. */\r
558             Rm_transactionForwarder(rmInst, transaction);\r
559         }\r
560     }\r
561     else\r
562     {\r
563         /* Client Delegate and Server transaction processors. */\r
564         switch (transaction->type)\r
565         {\r
566             case Rm_service_RESOURCE_ALLOCATE:\r
567             case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
568             case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
569             case Rm_service_RESOURCE_FREE:\r
570             case Rm_service_RESOURCE_BLOCK_FREE:\r
571             case Rm_service_RESOURCE_FREE_BY_NAME:                \r
572                 /* Check if the transaction is fulfilled request */\r
573                 if (transaction->state != RM_SERVICE_PROCESSING)\r
574                 {\r
575                     /* If source instance name does not match the current instance\r
576                      * name the allocation request came from a client.  The result\r
577                      * must be sent back to the Client */\r
578                     if (strcmp(transaction->sourceInstName, rmInst->name))\r
579                     {\r
580                         Rm_transactionResponder(rmInst, transaction);\r
581                     }\r
582                     else\r
583                     {\r
584                         /* Resource allocation request originated locally.  Send the response\r
585                          * via the service responder. */\r
586                         Rm_serviceResponder(rmInst, transaction);      \r
587                     }\r
588                 }\r
589                 else\r
590                 {\r
591                     /* This is a new transaction request originating from an RM instance with fewer\r
592                      * allocate/free privileges.  Run the allocation or free handler to see if the resource\r
593                      * request can be handled locally or if it needs to be forwarded to a higher level\r
594                      * agent */\r
595                     if ((transaction->type == Rm_service_RESOURCE_ALLOCATE) ||\r
596                         (transaction->type == Rm_service_RESOURCE_BLOCK_ALLOCATE) ||\r
597                         (transaction->type == Rm_service_RESOURCE_ALLOCATE_BY_NAME))\r
598                     {\r
599                         Rm_allocationHandler(rmInst, transaction);\r
600                     }\r
601                     else\r
602                     {\r
603                         Rm_freeHandler(rmInst, transaction);\r
604                     }\r
605                 }\r
606                 break;\r
607             case Rm_service_RESOURCE_MAP_TO_NAME:\r
608             case Rm_service_RESOURCE_UNMAP_NAME:                \r
609                 /* Server is the only RM instance capable of adding NameServer objects */\r
610                 if (rmInst->instType == Rm_instType_SERVER)\r
611                 {\r
612                     if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME)\r
613                     {\r
614                         /* Create a new NameServer object with the request transaction information.\r
615                          * Transaction will contain the state result of the NameServer addition. */\r
616                         Rm_nsAddObject(rmInst, transaction);\r
617                     }\r
618                     else\r
619                     {\r
620                         /* Delete an existing NameServer object with the request transaction information\r
621                          * Transaction will contain the state result of the NameServer addition. */\r
622                         Rm_nsDeleteObject(rmInst, transaction);\r
623                     }\r
624 \r
625                     /* If source instance name does not match the local instance\r
626                      * name the NameServer request came from a Client or Client Delegate.  The \r
627                      * result must be sent back to the Client or Client Delegate.  Just return if it does\r
628                      * match since the NameServer transaction result can be returned immediately by the\r
629                      * Rm_serviceHandler. */\r
630                     if (strcmp(transaction->sourceInstName, rmInst->name))\r
631                     {\r
632                         Rm_transactionResponder(rmInst, transaction);\r
633                     }\r
634                 }\r
635                 else\r
636                 {\r
637                     transaction->state = RM_SERVICE_ERROR_NAMESERVER_OBJECT_MOD_ON_INVALID_INSTANCE;\r
638                 }\r
639                 break;\r
640         }\r
641     }\r
642 }\r
643 \r
644 void reverse_properties(void *fdt, int32_t offset)\r
645 {\r
646         int32_t len;\r
647         const char *name;\r
648     char nameTest[] = "resource-range";\r
649         const void *data;\r
650     uint32_t *dataPtr;\r
651     uint32_t i;\r
652 \r
653         data = fdt_getprop_by_offset(fdt, offset, &name, &len);\r
654     if (!data)\r
655         Rm_osalLog("Error traverse_properties fdt_getprop_by_offset: %d\n", len);\r
656     else\r
657     {\r
658         Rm_osalLog("Property name: %s with length: %d offset: %d and address: %x\n", name, len, offset, data);\r
659         Rm_osalLog("Property value: %s\n", (char *)data);\r
660         \r
661         if(strcmp(nameTest, name) == 0)\r
662         {\r
663             dataPtr = (uint32_t *)data;\r
664             Rm_osalLog("Range value: %d %d\n", dtb32_to_cpu(dataPtr[0]), dtb32_to_cpu(dataPtr[1]));\r
665         }\r
666     }\r
667 \r
668         offset = fdt_next_property_offset(fdt, offset);\r
669         if (offset >= 0)\r
670                 reverse_properties(fdt, offset);\r
671         else if (offset != -FDT_ERR_NOTFOUND)\r
672                 Rm_osalLog("Error traverse_properties fdt_next_property_offset: %d\n", offset);\r
673 }\r
674 \r
675 void reverse_node(void *fdt, int32_t nodeOffset);\r
676 \r
677 void reverse_children(void *fdt, int32_t offset)\r
678 {\r
679     const char *nodeName;\r
680         int32_t error;\r
681         int32_t nextOffset = offset;\r
682         int32_t depth = 1;\r
683 \r
684         do {\r
685                 char path[256];\r
686 \r
687         nodeName = fdt_get_name(fdt, nextOffset, NULL);\r
688                 error = fdt_get_path(fdt, nextOffset, path, sizeof(path));\r
689         if (error)\r
690             Rm_osalLog("Error reverse_children fdt_get_path: %d\n", error);\r
691         else\r
692             Rm_osalLog("Node path: %s with name %s\n", path, nodeName);\r
693 \r
694 \r
695                 nextOffset = fdt_next_node(fdt, nextOffset, &depth);\r
696         if (error < 0)\r
697             Rm_osalLog("Error reverse_children fdt_next_node: %d\n", offset);\r
698         else\r
699             Rm_osalLog("Next node offset: %d with depth: %d\n", nextOffset, depth);\r
700         } while ((depth >= 0) && (depth != 1));\r
701 \r
702         if (depth == 1)\r
703                 reverse_children(fdt, nextOffset);\r
704 \r
705         reverse_node(fdt, offset);\r
706 }\r
707 \r
708 void reverse_node(void *fdt, int32_t nodeOffset)\r
709 {\r
710         const char *nodeName = fdt_get_name(fdt, nodeOffset, NULL);\r
711         char path[256];\r
712         int32_t error;\r
713         int32_t offset;\r
714         int32_t depth = 0;\r
715 \r
716         error = fdt_get_path(fdt, nodeOffset, path, sizeof(path));\r
717     if (error)\r
718         Rm_osalLog("Error traverse_node fdt_get_path: %d\n", error);\r
719     else\r
720         Rm_osalLog("Node path: %s with name %s\n", path, nodeName);\r
721 \r
722     /* Get the properties for the node if any exist */\r
723         offset = fdt_first_property_offset(fdt, nodeOffset);\r
724         if (offset >= 0)\r
725                 reverse_properties(fdt, offset);\r
726         else if (offset != -FDT_ERR_NOTFOUND)\r
727                 Rm_osalLog("Error traverse_node fdt_first_property_offset: %d\n", offset);\r
728 \r
729     /* Get the next node */\r
730         offset = fdt_next_node(fdt, nodeOffset, &depth);\r
731     if (offset >= 0)\r
732     {\r
733         Rm_osalLog("Next node offset: %d with depth: %d\n", offset, depth);\r
734     }\r
735     else if (offset != -FDT_ERR_NOTFOUND)\r
736         Rm_osalLog("Error traverse_node fdt_next_node: %d\n", offset);\r
737 \r
738     if (depth == 1)\r
739         reverse_children(fdt, offset);\r
740 }\r
741 \r
742 void traverseFdt (void *fdt)\r
743 {\r
744     int32_t nodeOffset = 0;  /* offset starts at 0, beginning of tree */\r
745 \r
746     reverse_node(fdt, nodeOffset);\r
747 }\r
748 \r
749 \r
750 /**********************************************************************\r
751  ********************** Application visible APIs **********************\r
752  **********************************************************************/\r
753 \r
754 Rm_Handle Rm_init(Rm_InitCfg *initCfg)\r
755 {\r
756     Rm_Inst *rmInst;\r
757     void *fdt = initCfg->globalResourceList;  \r
758 \r
759     /* Instance creation checks.  Add one to strlen calculation for null character */\r
760     if ((strlen(initCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS)\r
761     {\r
762         /* Failure: Instance name is too big */\r
763         return (NULL);\r
764     }\r
765     \r
766     /* Get memory for RM instance from local memory */\r
767     rmInst = Rm_osalMalloc (sizeof(Rm_Inst));\r
768     /* Populate instance based on input parameters */\r
769     strcpy (&rmInst->name[0], initCfg->instName);\r
770     rmInst->instType = initCfg->instType;\r
771     rmInst->registeredWithDelegateOrServer = false;\r
772 \r
773     /* Initialize the transport routing map linked list pointer to NULL.  The linked list\r
774      * nodes will be created when the application registers transports */\r
775     rmInst->routeMap = NULL;\r
776 \r
777     /* Initialize the transaction queue elements. */\r
778     rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
779     rmInst->transactionQueue= NULL;\r
780 \r
781     /* RM Server specific actions */\r
782     if (rmInst->instType == Rm_instType_SERVER)\r
783     {\r
784         /* Open the ResourceList file */\r
785         fdt_open_into(initCfg->globalResourceList, fdt, fdt_totalsize(initCfg->globalResourceList));\r
786 \r
787         /* TEST: Try to parse the entire fdt */\r
788         traverseFdt(fdt);\r
789     }\r
790 \r
791     /* Instance startup policies are only used for Servers and Client Delegates */\r
792     if (rmInst->instType != Rm_instType_CLIENT)\r
793     {\r
794         rmInst->instPolicy = initCfg->startupPolicy;\r
795 \r
796         /* Store policy via policy APIs ... */\r
797     }\r
798 \r
799     /* Return the RM Handle */\r
800     return ((Rm_Handle) rmInst);\r
801 }\r
802 \r
803 uint32_t Rm_getVersion (void)\r
804 {\r
805     return RM_VERSION_ID;\r
806 }\r
807 \r
808 \r
809 const char* Rm_getVersionStr (void)\r
810 {\r
811     return rmVersionStr;\r
812 }\r
813 \r
814 /**\r
815 @}\r
816 */\r