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