2ef6cc90c98a878a140a8efb485fe89a007f3808
[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 OSAL layer */\r
58 #include <rm_osal.h>\r
59 \r
60 /**********************************************************************\r
61  ************************** Globals ***********************************\r
62  **********************************************************************/\r
63 #if 0\r
64 /* Place QMSS PDSP permissions array */\r
65 #pragma DATA_SECTION (rmQmssPdspFirmwarePerms, ".rm");\r
66 #pragma DATA_ALIGN (rmQmssPdspFirmwarePerms, 128)\r
67 Rm_Perms rmQmssPdspFirmwarePerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_FIRMWARE_PDSPS, Rm_Perms)];\r
68 #endif\r
69 \r
70 /** @brief Global Variable which describes the RM Version Information */\r
71 const char   rmVersionStr[] = RM_VERSION_STR ":" __DATE__  ":" __TIME__;\r
72 \r
73 /**********************************************************************\r
74  ********************** Internal Functions ****************************\r
75  **********************************************************************/\r
76 \r
77 /* At the very least the transaction ID needs to be provided to create a transaction */\r
78 Rm_Transaction *Rm_transactionQueueAdd(Rm_Inst *rmInst)\r
79 {\r
80     Rm_Transaction *transactionQueue = (Rm_Transaction *)rmInst->transactionQueue;\r
81     Rm_Transaction *newTransaction = NULL;\r
82     void *key;\r
83 \r
84     /* Lock access to the RM instance's transaction queue */\r
85     key = Rm_osalMtCsEnter();\r
86 \r
87     /* Get memory for a new transaction from local memory */\r
88     newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction), false);\r
89 \r
90     /* Return if the memory allocated for the transaction entry is NULL */\r
91     if (newTransaction == NULL)\r
92     {\r
93         Rm_osalMtCsExit(key);\r
94         return(newTransaction);\r
95     }\r
96 \r
97     /* Clear the transaction */\r
98     memset((void *)newTransaction, 0, sizeof(Rm_Transaction));\r
99 \r
100     /* Create an ID for the new transaction.  The ID will be used for two purposes:\r
101      * 1) Matching responses from higher level RM agents to requests\r
102      * 2) Provided to the component that requested the service so that it can match its\r
103      *    request with the response it receives via its callback function it provided */\r
104     newTransaction->localId = Rm_transactionGetSequenceNum(rmInst);\r
105     /* New transaction's nextTransaction pointer will always be NULL */\r
106     newTransaction->nextTransaction = NULL;  \r
107 \r
108     /* Check if there are any transactions in the transaction queue */\r
109     if (transactionQueue)\r
110     {\r
111         /* At least one transaction in the transaction queue.  Add the new entry to the \r
112          * end of the transaction queue */\r
113         while (transactionQueue->nextTransaction != NULL)\r
114         {\r
115             /* Traverse the list until arriving at the last transaction */\r
116             transactionQueue = transactionQueue->nextTransaction;\r
117         }\r
118 \r
119         /* Add the new transaction to the end of the queue */\r
120         transactionQueue->nextTransaction = newTransaction;\r
121     }\r
122     else\r
123     {\r
124         /* The transaction queue does not currently exist.  The new transaction is the \r
125          * first transaction */\r
126         rmInst->transactionQueue = newTransaction;\r
127     }\r
128 \r
129     Rm_osalMtCsExit(key);\r
130     return (newTransaction);\r
131 }\r
132 \r
133 Rm_Transaction *Rm_transactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)\r
134 {\r
135     Rm_Transaction *transaction = (Rm_Transaction *)rmInst->transactionQueue;\r
136 \r
137     /* Make sure there is at least one transaction in the transaction queue */\r
138     if (transaction != NULL)\r
139     {\r
140         /* Find the transaction ID within the specified RM instance's transaction queue.\r
141          * If the end of the transaction queue is reached without finding the transaction the \r
142          * transaction pointer will be NULL */\r
143         while (transaction != NULL)\r
144         {\r
145             if (transaction->localId == transactionId)\r
146             {\r
147                 /* Match: break out of loop and return the transaction */\r
148                 break;             \r
149             }\r
150             transaction = transaction->nextTransaction;\r
151         }\r
152     }\r
153 \r
154     return (transaction);\r
155 }\r
156 \r
157 int32_t Rm_transactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)\r
158 {\r
159     Rm_Transaction *transaction = (Rm_Transaction *) rmInst->transactionQueue;\r
160     Rm_Transaction *prevTransaction = NULL;\r
161     int32_t retVal = RM_SERVICE_STATE_OKAY;\r
162     void *key;\r
163 \r
164     /* Lock access to the RM instance's transaction queue */\r
165     key = Rm_osalMtCsEnter();\r
166 \r
167     /* Find the transaction ID within the specified RM instance's transaction queue. */\r
168     while (transaction != NULL)\r
169     {\r
170         if (transaction->localId == transactionId)\r
171         {\r
172             /* Match: break out of loop and delete the transaction */\r
173             break;             \r
174         }\r
175 \r
176         prevTransaction = transaction;\r
177         transaction = transaction->nextTransaction;\r
178     }\r
179 \r
180     /* Traversed entire queue but did not find transaction */\r
181     if (transaction == NULL)\r
182     {\r
183         retVal = RM_SERVICE_ERROR_SERVICE_TRANSACTION_DOES_NOT_EXIST;\r
184     }\r
185     else\r
186     {\r
187         /* Delete the transaction */\r
188         if (prevTransaction == NULL)\r
189         {\r
190             /* Transaction to be deleted exists at start of transaction queue.  Map second\r
191              * transaction to be start of transaction queue.  This covers case where there is\r
192              * only one transaction in the queue since the nextTransaction will be NULL */\r
193             rmInst->transactionQueue = transaction->nextTransaction;\r
194         }\r
195         else\r
196         {\r
197             /* Transaction to be deleted is in the middle or at end of the queue.  Adjust \r
198              * adjacent transaction pointers.  This covers the case where the transaction to be \r
199              * removed is at the end of the queue. */\r
200             prevTransaction->nextTransaction = transaction->nextTransaction;\r
201         }\r
202 \r
203         /* Free the memory associated with the transaction. */\r
204         Rm_osalFree((void *)transaction, sizeof(Rm_Transaction), false);\r
205     }\r
206 \r
207     Rm_osalMtCsExit(key);\r
208     return (retVal);\r
209 }\r
210 \r
211 uint32_t Rm_transactionInitSequenceNum(void)\r
212 {\r
213     /* Sequence number can never have a value of zero so that there are no conflicts\r
214      * with transactions that have a remoteOriginatingId of zero */\r
215     return (1);\r
216 }\r
217 \r
218 uint32_t Rm_transactionGetSequenceNum(Rm_Inst *rmInst)\r
219 {\r
220     uint32_t sequenceNum = 0;\r
221 \r
222     /* Get the next sequence number and then increment.  If there's an overflow\r
223      * assign the initial value instead of incrementing. */\r
224     if (rmInst->transactionSeqNum + 1 < rmInst->transactionSeqNum)\r
225     {\r
226         /* Overflow */\r
227         sequenceNum = rmInst->transactionSeqNum;\r
228         rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
229     }\r
230     else\r
231     {\r
232         sequenceNum = rmInst->transactionSeqNum++;\r
233     }    \r
234 \r
235     return (sequenceNum);\r
236 }\r
237 \r
238 /* Function used to send RM response transactions to lower level agents */\r
239 void Rm_transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
240 {\r
241     Rm_TransportNode *dstTransportNode = NULL;\r
242     Rm_Packet *rmPkt = NULL;\r
243 \r
244     /* Find the transport for the RM instance that sent the request. */\r
245     dstTransportNode = Rm_transportNodeFindRemoteName(rmInst, transaction->sourceInstName);\r
246 \r
247     /* Create a RM packet using the service information */\r
248     switch (transaction->type)\r
249     {\r
250         case Rm_service_RESOURCE_ALLOCATE:\r
251         case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
252         case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
253         case Rm_service_RESOURCE_FREE:\r
254         case Rm_service_RESOURCE_BLOCK_FREE:\r
255         case Rm_service_RESOURCE_FREE_BY_NAME:\r
256             rmPkt = Rm_transportCreateResourceResponsePkt(rmInst, dstTransportNode, \r
257                                                           transaction);\r
258             break;\r
259         case Rm_service_RESOURCE_MAP_TO_NAME:\r
260         case Rm_service_RESOURCE_UNMAP_NAME:\r
261             rmPkt = Rm_transportCreateNsResponsePkt(rmInst, dstTransportNode,\r
262                                                     transaction);\r
263             break;\r
264         default:\r
265             /* Invalid service type.  Flag the error and return */\r
266             transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
267             break;\r
268     }\r
269 \r
270     if (transaction->state <= RM_SERVICE_ERROR_BASE)\r
271     {\r
272         /* Delete the transaction and return immediately because an error occurred \r
273          * allocating the packet */\r
274         Rm_transactionQueueDelete(rmInst, transaction->localId);\r
275         return;\r
276     }\r
277 \r
278     /* Send the RM packet to the application transport */\r
279     if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL)\r
280     {\r
281         /* Negative value returned by transport send.  An error occurred\r
282          * in the transport while attempting to send the packet.*/\r
283         transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
284         /* Clean up the packet */\r
285         if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\r
286         {\r
287             /* Non-NULL value returned by transport packet free. Flag the\r
288              * error */\r
289             transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
290         }\r
291         return;\r
292     }\r
293 \r
294     /* NEED TO DO SOMETHING IF GET AN ERROR IN THE transaction->state FIELD.  CREATE\r
295      * NEW TRANSACTION WITH DATA FROM ORIGINAL?  THEN TRY TO SEND FAILED REQUEST BACK\r
296      * TO REQUESTER???  KEEP RETRYING SEND OF RESPONSE??? */\r
297 \r
298     /* Delete the transaction */\r
299     Rm_transactionQueueDelete(rmInst, transaction->localId);\r
300 }\r
301 \r
302 void Rm_allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
303 {\r
304     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
305     {\r
306 #if 0        \r
307         /* Check local policy to see if the request can be satisfied with the\r
308          * resources stored locally */\r
309         Rm_policy...API()\r
310 \r
311         if (policy check approves the resource)\r
312         {\r
313             /* call the allocator to allocate the resource */\r
314             if (allocator returns resource)\r
315             {\r
316                 /* Populate the transaction with the allocated resources and the result */\r
317                 transaction->state = approve reason;\r
318                 return ...\r
319             }\r
320             else\r
321             {\r
322                 /* allocator ran out of resources, need to contact Server for more\r
323                  * resources */\r
324                 Rm_resourcePoolModRequest(...);\r
325             }\r
326         }\r
327         else if (policy check denies resource)\r
328         {\r
329             /* Policy check denied resource. */\r
330             transaction->state= deny reason;\r
331             return ...\r
332         }\r
333         else if (policy check says forward to Server for validation)\r
334         {\r
335             /* Forward the transaction to the Server */\r
336             Rm_transactionForwarder(rmInst, transaction);\r
337         }\r
338 #endif         \r
339     }\r
340     else if (rmInst->instType == Rm_instType_SERVER)\r
341     {\r
342 #if 0        \r
343         /* Check global policy to see if resource can be allocated. return result\r
344          * no matter what */\r
345         Rm_policy...API()\r
346 \r
347         if (policy approves)\r
348         {\r
349             /* call allocator to allocate resource */\r
350         }\r
351 \r
352         transaction->state = approve or deny reason;\r
353         transaction->resourceInfo.base = ...;\r
354         transaction->resourceInfo.range = ...;\r
355 \r
356         /* If source instance name does not match the current instance\r
357          * name the allocation request came from a Client.  The result\r
358          * must be sent back to the Client */\r
359         if (strcmp(transaction->sourceInstName, rmInst->name))\r
360         {\r
361             /* Names don't match.  Send the transaction back to the Client */\r
362             Rm_transactionResponder(rmInst, transaction);\r
363         }\r
364         else\r
365         {\r
366             /* Resource allocation request originated locally on the active\r
367              * instance. Send the response via the service responder. */          \r
368             Rm_serviceResponder(rmInst, transaction);                            \r
369         }\r
370 #endif        \r
371     }   \r
372 }\r
373 \r
374 void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
375 {\r
376     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
377     {\r
378 #if 0        \r
379         /* Check local policy to see if the request can be satisfied with the\r
380          * resources stored locally */\r
381         Rm_policy...API()\r
382 \r
383         if (policy check approves the free)\r
384         {\r
385             /* call the allocator to free the resource */\r
386             /* Run a resource pool check to see if the free combined a resource block\r
387              * that can be returned to the server */\r
388             if (resource block has been combined)\r
389             {\r
390                   /* allocator ran out of resources, need to contact Server for more\r
391                  * resources */\r
392                 Rm_resourcePoolModRequest(free pool block to server...);\r
393             }\r
394             else\r
395             {\r
396                 /* Populate the receipt with the freed resources and the result */\r
397                 transaction->state = approve reason;\r
398                 return ...\r
399             }\r
400         }\r
401         else if (policy check denies resource free)\r
402         {\r
403             /* Policy check denied resource. */\r
404             transaction->state = deny reason;\r
405             return ...\r
406         }\r
407         else if (policy check says forward to Server for validation)\r
408         {\r
409             /* Forward the transaction to the Server */\r
410             Rm_transactionForwarder(rmInst, transaction);\r
411         }\r
412 #endif         \r
413     }\r
414     else if (rmInst->instType == Rm_instType_SERVER)\r
415     {\r
416 #if 0        \r
417         /* Check global policy to see if resource can be freed. return result\r
418          * no matter what */\r
419         Rm_policy...API()\r
420         if (policy approves)\r
421         {\r
422             /* call allocator to free resources */\r
423         }\r
424             \r
425         transaction->state = approve or deny reason;\r
426         transaction->resourceInfo.base = ...;\r
427         transaction->resourceInfo.range = ...;\r
428 \r
429         /* If source instance name does not match the current instance\r
430          * name the allocation request came from a client.  The result\r
431          * must be sent back to the Client */\r
432         if (strcmp(transaction->sourceInstName, rmInst->name))\r
433         {\r
434             /* Names don't match.  Send the transaction back to the Client Delegate or Client */\r
435             Rm_transactionResponder(rmInst, transaction);\r
436         }\r
437         else\r
438         {\r
439             /* Resource allocation request originated locally on the active\r
440              * instance. Send the response via the service responder. */\r
441             Rm_serviceResponder(rmInst, transaction);                            \r
442         }\r
443 #endif        \r
444     }   \r
445 }\r
446 \r
447 /* Function used to forward RM transactions to higher level agents */\r
448 void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
449 {\r
450     Rm_TransportNode *dstTransportNode = NULL;\r
451     Rm_Packet *rmPkt = NULL;\r
452 \r
453     /* Make sure the RM instance has a transport registered with a higher level agent */\r
454     if (rmInst->registeredWithDelegateOrServer == false)\r
455     {\r
456         transaction->state = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER;\r
457         return;\r
458     }\r
459 \r
460     /* Find the transport for the higher level agent.  Check for a connection to a Client Delegate\r
461      * or a Server.  Clients will be connected to either a Client Delegate or a Server.  Client\r
462      * Delegates will be connected to a Server. */\r
463     if (rmInst->instType == Rm_instType_CLIENT)\r
464     {\r
465         dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_CLIENT_DELEGATE);\r
466     } \r
467     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
468     {\r
469         dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_SERVER);\r
470     }\r
471 \r
472     /* Create a RM packet using the service information */\r
473     switch (transaction->type)\r
474     {\r
475         case Rm_service_RESOURCE_ALLOCATE:\r
476         case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
477         case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
478         case Rm_service_RESOURCE_FREE:\r
479         case Rm_service_RESOURCE_BLOCK_FREE:\r
480         case Rm_service_RESOURCE_FREE_BY_NAME:\r
481             rmPkt = Rm_transportCreateResourceReqPkt(rmInst, dstTransportNode, \r
482                                                      transaction);\r
483             break;\r
484         case Rm_service_RESOURCE_MAP_TO_NAME:\r
485         case Rm_service_RESOURCE_UNMAP_NAME:\r
486             rmPkt = Rm_transportCreateNsRequestPkt(rmInst, dstTransportNode,\r
487                                                    transaction);\r
488             break;\r
489         default:\r
490             /* Invalid service type.  Flag the error and return */\r
491             transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
492             break;\r
493     }\r
494 \r
495     if (transaction->state <= RM_SERVICE_ERROR_BASE)\r
496     {\r
497         /* Return immediately because an error occurred allocating the packet */\r
498         return;\r
499     }\r
500 \r
501     /* Send the RM packet to the application transport */\r
502     if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL)\r
503     {\r
504         /* Negative value returned by transport send.  An error occurred\r
505          * in the transport while attempting to send the packet.*/\r
506         transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
507         /* Clean up the packet */\r
508         if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\r
509         {\r
510             /* Non-NULL value returned by transport packet free. Flag the\r
511              * error */\r
512             transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
513         }\r
514         return;\r
515     }\r
516 \r
517     /* Transaction is not deleted because it is awaiting a response from the higher level\r
518      * RM instance */\r
519 }\r
520 \r
521 void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
522 {\r
523     /* Handle auto-forwarded transactions.  These transactions include:\r
524      * - All request transactions received on Clients are forwarded to the Client Delegate\r
525      * - NameServer requests received on the Client Delegate are forwarded to the Server */\r
526     if ((rmInst->instType == Rm_instType_CLIENT) ||\r
527         ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
528          (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||\r
529          (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)))\r
530     {\r
531         /* Check if the transaction is a transaction that received a response to its\r
532          * request. */\r
533         if (transaction->state != RM_SERVICE_PROCESSING)\r
534         {\r
535 \r
536             /* A transaction has received a response. Send the response to either the \r
537              * transaction or service responder based on the source instance */\r
538             if (strcmp(transaction->sourceInstName, rmInst->name))\r
539             {\r
540                 /* Transaction originated from another instance.  Use the \r
541                  * transaction responder to send the result to the source instance.  This\r
542                  * is not possible on RM Clients since they can't forward RM services */\r
543                 Rm_transactionResponder(rmInst, transaction);\r
544             }\r
545             else\r
546             {\r
547                 /* Transaction originated on this instance.  Send to the\r
548                  * service responder */\r
549                 Rm_serviceResponder(rmInst, transaction);\r
550             }\r
551         }\r
552         else\r
553         {\r
554             /* This is a new transaction that must be forwarded to a higher level RM instance. */\r
555             Rm_transactionForwarder(rmInst, transaction);\r
556         }\r
557     }\r
558     else\r
559     {\r
560         /* Client Delegate and Server transaction processors. */\r
561         switch (transaction->type)\r
562         {\r
563             case Rm_service_RESOURCE_ALLOCATE:\r
564             case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
565             case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
566             case Rm_service_RESOURCE_FREE:\r
567             case Rm_service_RESOURCE_BLOCK_FREE:\r
568             case Rm_service_RESOURCE_FREE_BY_NAME:                \r
569                 /* Check if the transaction is fulfilled request */\r
570                 if (transaction->state != RM_SERVICE_PROCESSING)\r
571                 {\r
572                     /* If source instance name does not match the current instance\r
573                      * name the allocation request came from a client.  The result\r
574                      * must be sent back to the Client */\r
575                     if (strcmp(transaction->sourceInstName, rmInst->name))\r
576                     {\r
577                         Rm_transactionResponder(rmInst, transaction);\r
578                     }\r
579                     else\r
580                     {\r
581                         /* Resource allocation request originated locally.  Send the response\r
582                          * via the service responder. */\r
583                         Rm_serviceResponder(rmInst, transaction);      \r
584 \r
585 \r
586                         /* WHAT IF TRANSACITON CAME FROM CD AND WAS SOLVED IMMEDIATELY. NEED TO RETURN\r
587                          * THE TRANSACTION RATHER THAN GO THROUGH THE SERVICERESPONDER */\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. */\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 /**********************************************************************\r
645  ********************** Application visible APIs **********************\r
646  **********************************************************************/\r
647 \r
648 Rm_Handle Rm_init(Rm_InitCfg *initCfg)\r
649 {\r
650     Rm_Inst *rmInst;\r
651 \r
652     /* Instance creation checks.  Add one to strlen calculation for null character */\r
653     if ((strlen(initCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS)\r
654     {\r
655         /* Failure: Instance name is too big */\r
656         return (NULL);\r
657     }\r
658     \r
659     /* Get memory for RM instance from local memory */\r
660     rmInst = Rm_osalMalloc (sizeof(Rm_Inst), false);\r
661     /* Populate instance based on input parameters */\r
662     strcpy (&rmInst->name[0], initCfg->instName);\r
663     rmInst->instType = initCfg->instType;\r
664     rmInst->registeredWithDelegateOrServer = false;\r
665 \r
666     /* Initialize the transport routing map linked list pointer to NULL.  The linked list\r
667      * nodes will be created when the application registers transports */\r
668     rmInst->routeMap = NULL;\r
669 \r
670     /* Initialize the transaction queue elements. */\r
671     rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
672     rmInst->transactionQueue= NULL;\r
673 \r
674     /* RM Server specific actions */\r
675     if (rmInst->instType == Rm_instType_SERVER)\r
676     {\r
677        /* parse DTB, etc */\r
678     }\r
679 \r
680     /* Instance startup policies are only used for Servers and Client Delegates */\r
681     if (rmInst->instType != Rm_instType_CLIENT)\r
682     {\r
683         rmInst->instPolicy = initCfg->startupPolicy;\r
684 \r
685         /* Store policy via policy APIs ... */\r
686     }\r
687 \r
688     /* Return the RM Handle */\r
689     return ((Rm_Handle) rmInst);\r
690 }\r
691 \r
692 uint32_t Rm_getVersion (void)\r
693 {\r
694     return RM_VERSION_ID;\r
695 }\r
696 \r
697 \r
698 const char* Rm_getVersionStr (void)\r
699 {\r
700     return rmVersionStr;\r
701 }\r
702 \r
703 /**\r
704 @}\r
705 */\r