1cfd0a41313066b758685b5d0b3e7655eae4b439
[keystone-rtos/rm-lld.git] / src / rm.c
1 /**
2  *   @file  rm.c
3  *
4  *   @brief   
5  *      This is the Resource Manager source.
6  *
7  *  \par
8  *  ============================================================================
9  *  @n   (C) Copyright 2012-2013, Texas Instruments, Inc.
10  * 
11  *  Redistribution and use in source and binary forms, with or without 
12  *  modification, are permitted provided that the following conditions 
13  *  are met:
14  *
15  *    Redistributions of source code must retain the above copyright 
16  *    notice, this list of conditions and the following disclaimer.
17  *
18  *    Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the 
20  *    documentation and/or other materials provided with the   
21  *    distribution.
22  *
23  *    Neither the name of Texas Instruments Incorporated nor the names of
24  *    its contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
28  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
29  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
31  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
32  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
33  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
36  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
37  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38  *
39  *  \par
40 */
42 /* Standard includes */
43 #include <stdint.h>
44 #include <string.h>
46 /* RM external includes */
47 #include <ti/drv/rm/rm.h>
48 #include <ti/drv/rm/rmver.h>
49 #include <ti/drv/rm/rm_services.h>
50 #include <ti/drv/rm/rm_transport.h>
52 /* RM internal includes */
53 #include <ti/drv/rm/include/rm_internal.h>
54 #include <ti/drv/rm/include/rm_loc.h>
55 #include <ti/drv/rm/include/rm_allocatorloc.h>
56 #include <ti/drv/rm/include/rm_transportloc.h>
57 #include <ti/drv/rm/include/rm_nameserverloc.h>
58 #include <ti/drv/rm/include/rm_servicesloc.h>
60 /* RM LIBFDT includes */
61 #include <ti/drv/rm/util/libfdt/libfdt.h>
63 /* RM OSAL layer */
64 #include <rm_osal.h>
66 /**********************************************************************
67  ************************** Globals ***********************************
68  **********************************************************************/
70 /* Global Variable which describes the RM Version Information */
71 const char  rmVersionStr[] = RM_VERSION_STR ":" __DATE__  ":" __TIME__;
73 /**********************************************************************
74  ************************ Local Functions *****************************
75  **********************************************************************/
77 /* FUNCTION PURPOSE: Initializes a RM inst's transaction sequence number
78  ***********************************************************************
79  * DESCRIPTION: The RM instance transaction sequence number can never
80  *              have a value of 0 to avoid conflicts with transactions
81  *              that have a remoteOriginatingId of 0 (transaction ID
82  *              will be used as the remoteOriginatingId for
83  *              transactions that are responses to requests).
84  */
85 static uint32_t transactionInitSequenceNum(void)
86 {
87     return (1);
88 }
90 /* FUNCTION PURPOSE: Provides a sequence number for new transactions
91  ***********************************************************************
92  * DESCRIPTION: Returns a sequence number for a new transaction
93  *              specific to a RM instance.  Handles rollover of
94  *              sequence number.
95  */
96 static uint32_t transactionGetSequenceNum(Rm_Inst *rmInst)
97 {
98     rmInst->transactionSeqNum++;
99     if (!rmInst->transactionSeqNum) {
100         rmInst->transactionSeqNum++;
101     }    
102     return (rmInst->transactionSeqNum);
105 /* FUNCTION PURPOSE: Creates a resource request packet
106  ***********************************************************************
107  * DESCRIPTION: Returns a RM packet handle that points to a RM
108  *              resource request packet that has been prepared
109  *              for sending to another RM instance.  The packet
110  *              is allocated via the rmAllocPkt API using the
111  *              appTransport handle provided by the application
112  */
113 void createResourceReqPkt(Rm_Packet *rmPkt, char *localInstName, Rm_Transaction *transaction)
115     Rm_ResourceRequestPkt *resourceReqPkt = NULL;
116        
117     rmPkt->pktType = Rm_pktType_RESOURCE_REQUEST;
118     resourceReqPkt = (Rm_ResourceRequestPkt *) rmPkt->data;
119     resourceReqPkt->requestId = transaction->localId;
120     if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
121         resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_INIT;
122     }
123     else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
124         resourceReqPkt->resourceReqType = Rm_resReqPktType_ALLOCATE_USE;
125     }    
126     else if (transaction->type == Rm_service_RESOURCE_FREE) {
127         resourceReqPkt->resourceReqType = Rm_resReqPktType_FREE;
128     }
129     else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
130         resourceReqPkt->resourceReqType = Rm_resReqPktType_GET_NAMED;
131     }
132     strncpy(resourceReqPkt->pktSrcInstName, localInstName, RM_NAME_MAX_CHARS);
133     strncpy(resourceReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);
134     memcpy ((void *)&(resourceReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),
135             sizeof(Rm_ResourceInfo));
138 /* FUNCTION PURPOSE: Creates a resource response packet
139  ***********************************************************************
140  * DESCRIPTION: Returns a RM packet handle that points to a RM
141  *              resource response packet that has been prepared
142  *              for sending to another RM instance.  The packet
143  *              is allocated via the rmAllocPkt API using the
144  *              appTransport handle provided by the application
145  */
146 void createResourceResponsePkt(Rm_Packet *rmPkt, Rm_Transaction *transaction)
148     Rm_ResourceResponsePkt *resourceRespPkt = NULL;
149      
150     rmPkt->pktType = Rm_pktType_RESOURCE_RESPONSE;                 
151     resourceRespPkt = (Rm_ResourceResponsePkt *)rmPkt->data;
152     resourceRespPkt->responseId = transaction->remoteOriginatingId;
153     resourceRespPkt->requestState = transaction->state;
154     memcpy ((void *)&(resourceRespPkt->resourceInfo), (void *)&(transaction->resourceInfo),
155             sizeof(Rm_ResourceInfo));
158 /* FUNCTION PURPOSE: Creates a NameServer request packet
159  ***********************************************************************
160  * DESCRIPTION: Returns a RM packet handle that points to a RM
161  *              NameServer request packet that has been prepared
162  *              for sending to another RM instance.  The packet
163  *              is allocated via the rmAllocPkt API using the
164  *              appTransport handle provided by the application
165  */
166 void createNsRequestPkt(Rm_Packet *rmPkt, char *localInstName, Rm_Transaction *transaction)
167
168     Rm_NsRequestPkt *nsReqPkt = NULL;
170     rmPkt->pktType = Rm_pktType_NAMESERVER_REQUEST;                   
171     nsReqPkt = (Rm_NsRequestPkt *)rmPkt->data;
172     nsReqPkt->requestId = transaction->localId;
173     if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
174         nsReqPkt->nsRequestType = Rm_nsReqPktType_MAP_RESOURCE;
175     }
176     else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
177         nsReqPkt->nsRequestType = Rm_nsReqPktType_UNMAP_RESOURCE;
178     }
179     strncpy(nsReqPkt->pktSrcInstName, localInstName, RM_NAME_MAX_CHARS);
180     strncpy(nsReqPkt->serviceSrcInstName, transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);
181     memcpy ((void *)&(nsReqPkt->resourceInfo), (void *)&(transaction->resourceInfo),
182             sizeof(Rm_ResourceInfo));
185 /* FUNCTION PURPOSE: Creates a NameServer response packet
186  ***********************************************************************
187  * DESCRIPTION: Returns a RM packet handle that points to a RM
188  *              NameServer response packet that has been prepared
189  *              for sending to another RM instance.  The packet
190  *              is allocated via the rmAllocPkt API using the
191  *              appTransport handle provided by the application
192  */
193 void createNsResponsePkt(Rm_Packet *rmPkt, Rm_Transaction *transaction)
195     Rm_NsResponsePkt *nsRespPkt = NULL;
197     rmPkt->pktType = Rm_pktType_NAMESERVER_RESPONSE;                
198     nsRespPkt = (Rm_NsResponsePkt *)rmPkt->data;
199     nsRespPkt->responseId = transaction->remoteOriginatingId;
200     nsRespPkt->requestState = transaction->state;
203 /* FUNCTION PURPOSE: Issues a service response to application
204  ***********************************************************************
205  * DESCRIPTION: Provides a service response back to the application
206  *              using the service callback function provided to
207  *              the RM instance at the time of the service request.
208  */
209 static void serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
211     Rm_ServiceRespInfo serviceResponse;
213     serviceResponse.rmHandle = (Rm_Handle)rmInst;
214     /* The responseTransaction will contain the resultant state details of
215      * the requestTransaction's service request */
216     serviceResponse.serviceState = transaction->state;
217     /* Pass back the ID that was provided to the component when it requested
218      * the service */
219     serviceResponse.serviceId = transaction->localId;
221     /* Service was approved and service was an allocate request.  The resource
222      * data is passed back to the component */
223     if ((serviceResponse.serviceState == RM_SERVICE_APPROVED) &&
224         ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
225          (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
226          (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)))
227     {
228         strncpy(serviceResponse.resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
229         serviceResponse.resourceBase = transaction->resourceInfo.base;
230         serviceResponse.resourceLength = transaction->resourceInfo.length;
231     }
233     if (transaction->callback.serviceCallback) {
234         /* Issue the callback to the requesting component with the response information */
235         transaction->callback.serviceCallback(&serviceResponse);
236         /* Delete the transaction from the transaction queue */
237         rmTransactionQueueDelete(rmInst, transaction->localId);
238     }
239     else {
240         rmServiceInternalCallback((Rm_Handle)rmInst);
241     }
242     
243     return;
246 /* FUNCTION PURPOSE: Sends RM response packets
247  ***********************************************************************
248  * DESCRIPTION: Sends RM response packets to RM instance's that sent
249  *              RM request packets to the RM instance.  The response
250  *              is sent via the RM transport API which is plugged
251  *              with an application created transport path.
252  */
253 static void transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
255     Rm_Transport    *dstTransport = NULL;
256     Rm_Packet       *rmPkt = NULL;
257     Rm_PacketHandle  pktHandle = NULL;
259     if (dstTransport = rmTransportFindRemoteName(rmInst->transports, transaction->pktSrcInstName)) {
260         rmPkt = dstTransport->callouts.rmAllocPkt(dstTransport->appTransportHandle, 
261                                                   sizeof(Rm_Packet), &pktHandle);
262         if (!rmPkt || !pktHandle) {
263             transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
264             goto errorExit;
265         }
267         switch (transaction->type) {
268             case Rm_service_RESOURCE_ALLOCATE_INIT:
269             case Rm_service_RESOURCE_ALLOCATE_USE:
270             case Rm_service_RESOURCE_FREE:
271             case Rm_service_RESOURCE_GET_BY_NAME:
272                 createResourceResponsePkt(rmPkt, transaction);
273                 break;
274             case Rm_service_RESOURCE_MAP_TO_NAME:
275             case Rm_service_RESOURCE_UNMAP_NAME:
276                 createNsResponsePkt(rmPkt, transaction);
277                 break;
278         }
279         if (dstTransport->callouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {
280             transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
281             goto errorExit;
282         }
283         
284         /* Response packet sent: Delete transaction from queue */
285         rmTransactionQueueDelete(rmInst, transaction->localId);
286     }
287     else {
288         transaction->state = RM_ERROR_TRANSPORT_REMOTE_HNDL_NOT_REGD;
289     }
290 errorExit:
291     /* Do not delete transaction on transport error.  Transport rrror transactions should be visible
292      * from Rm_printInstanceStatus() */
293     return;
296 /* FUNCTION PURPOSE: Sends RM request packets
297  ***********************************************************************
298  * DESCRIPTION: Sends RM request packets to RM instance's that are
299  *              capable of forwarding or validating service requests.
300  *              The request is sent via the RM transport API which is
301  *              plugged with an application created transport path.
302  */
303 static void transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)
305     Rm_Transport    *dstTransport = NULL;
306     Rm_Packet       *rmPkt = NULL;    
307     Rm_PacketHandle  pktHandle = NULL;
309     if (rmInst->instType == Rm_instType_CLIENT) {
310         dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_CLIENT_DELEGATE);
312         if (!dstTransport) {
313             dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_SERVER);
314         }
315     } 
316     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
317         dstTransport = rmTransportFindRemoteInstType(rmInst->transports, Rm_instType_SERVER);
318     }
320     /* Just queue transaction if transport hasn't been registered.  Do not return error */
321     if (dstTransport) {            
322         rmPkt = dstTransport->callouts.rmAllocPkt(dstTransport->appTransportHandle, 
323                                                   sizeof(Rm_Packet), &pktHandle);
324         if (!rmPkt || !pktHandle) {
325             transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
326             goto errorExit;
327         }
329         switch (transaction->type) {
330             case Rm_service_RESOURCE_ALLOCATE_INIT:
331             case Rm_service_RESOURCE_ALLOCATE_USE:
332             case Rm_service_RESOURCE_FREE:
333             case Rm_service_RESOURCE_GET_BY_NAME:
334                 createResourceReqPkt(rmPkt, rmInst->instName, transaction);
335                 break;
336             case Rm_service_RESOURCE_MAP_TO_NAME:
337             case Rm_service_RESOURCE_UNMAP_NAME:
338                 createNsRequestPkt(rmPkt, rmInst->instName, transaction);
339                 break;
340         }
341   
342         if (dstTransport->callouts.rmSendPkt(dstTransport->appTransportHandle, pktHandle) < RM_OK) {
343             transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
344             goto errorExit;
345         }              
346         transaction->hasBeenForwarded = RM_TRUE;
347         /* Transaction not deleted.  Waiting for response from RM CD or Server */
348     }
349 errorExit: 
350     /* Do not delete transaction on transport error.  Transport error transactions should be visible
351      * from Rm_printInstanceStatus() */               
352     return;
355 /* FUNCTION PURPOSE: Handles static allocation requests
356  ***********************************************************************
357  * DESCRIPTION: Validates allocation requests received on CDs and
358  *              Clients prior to the instance's registering
359  *              with a Server.  The allocation request is validated
360  *              against a static policy.
361  */
362 static void staticAllocationHandler (Rm_Handle rmHandle, Rm_Transaction *transaction)
364     Rm_Inst           *rmInst = (Rm_Inst *)rmHandle;
365     void              *staticPolicy = rmPolicyGetPolicy(rmHandle);
366     Rm_PolicyCheckCfg  privCheckCfg;
367     int32_t            result;
368     
369     if (staticPolicy) {
370         if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
371             (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {
372             /* Check request against static policy */
373             memset((void *)&privCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
374     
375             if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
376                 privCheckCfg.type = Rm_policyCheck_INIT;
377             }
378             else {
379                 privCheckCfg.type = Rm_policyCheck_USE;
380             }
381             privCheckCfg.policyDtb = staticPolicy;
382             privCheckCfg.validInstNode = rmPolicyGetValidInstNode(rmHandle, rmInst->instName);
383             privCheckCfg.resourceOffset = rmPolicyGetResourceOffset(staticPolicy,
384                                                                     transaction->resourceInfo.name);
385             privCheckCfg.resourceBase = transaction->resourceInfo.base;
386             privCheckCfg.resourceLength = transaction->resourceInfo.length;
387     
388             if (rmPolicyCheckPrivilege(&privCheckCfg, &result)) {
389                 transaction->state = RM_SERVICE_APPROVED_STATIC;
390             }
391             else if (result == RM_OK) {
392                 /* Privilege check returned false without error */
393                 transaction->state = RM_SERVICE_DENIED_BY_STATIC_POLICY;
394             }
395             else {
396                 /* Privilege check returned false with error */
397                 transaction->state = result;
398             }
399         }
400         else {
401             transaction->state = RM_SERVICE_DENIED_INVALID_STATIC_REQUEST;
402         }
403     }
404     else {
405         transaction->state = RM_ERROR_REQ_FAILED_NO_STATIC_POLICY;
406     } 
409 /* FUNCTION PURPOSE: Arbitrates allocation service requests
410  ***********************************************************************
411  * DESCRIPTION: Issues a set of allocator operations in order to
412  *              handle a received allocation request.  Allocation
413  *              requests are always forwarded to the Server on Client
414  *              CD instances.  If a request is made with a NameServer
415  *              name the resource base and length parameters are
416  *              retrieved from the NameServer prior to the allocation
417  *              attempt.
418  */
419 static void allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
421     Rm_AllocatorOpInfo  opInfo;
422     
423     Rm_NameServerObjCfg nameServerObjCfg;
424     int32_t             retVal = transaction->state;
426     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
427         /* Fill in allocation logic for CDs */  
428     }
429     else if ((rmInst->instType == Rm_instType_SERVER)||
430              (rmInst->instType == Rm_instType_SHARED_SERVER)) {
431         memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
432         
433         opInfo.policy = rmInst->u.server.globalPolicy;
434         opInfo.resourceInfo = &transaction->resourceInfo;
435         opInfo.serviceSrcInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst, transaction->serviceSrcInstName);
436         if (opInfo.serviceSrcInstNode) {
437             switch (transaction->type) {
438                 case Rm_service_RESOURCE_ALLOCATE_INIT:
439                     RM_policy_SET_PERM(opInfo.allocType, RM_POLICY_PERM_INIT_SHIFT, 1);
440                     break;
441                 case Rm_service_RESOURCE_ALLOCATE_USE:
442                     RM_policy_SET_PERM(opInfo.allocType, RM_POLICY_PERM_USE_SHIFT, 1);    
443                     break;
444             }        
446             /* Populated NameServer name has precedence over base */
447             if (strlen(transaction->resourceInfo.nameServerName) > 0) {
448                 if ((transaction->resourceInfo.base == 0) &&
449                     (transaction->resourceInfo.length == 0) &&
450                     (transaction->resourceInfo.alignment == 0)) {
451                     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
452                         rmNameServerTreeInv(rmInst->u.server.nameServer);
453                     }
454                     memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
455                     nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
456                     nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
457                     if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
458                         strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
459                         transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
460                         transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
461                     }                
462                 }
463                 else {
464                     retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;
465                 }
466             }
468             if (retVal == RM_SERVICE_PROCESSING) {      
469                 if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) {
470                     opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE;
471                     retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
472                 }
473             
474                 if (retVal == RM_SERVICE_PROCESSING) {
475                     opInfo.operation = Rm_allocatorOp_ALLOCATE;
476                     retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
477                 }      
478             }
479         }
480         else {
481             retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
482         }
483         
484         transaction->state = retVal;                 
485     }   
488 /* FUNCTION PURPOSE: Arbitrates free service requests
489  ***********************************************************************
490  * DESCRIPTION: Issues a set of allocator operations in order to
491  *              handle a received free request.  Free
492  *              requests are always forwarded to the Server on Client
493  *              CD instances.  If a request is made with a NameServer
494  *              name the resource base and length parameters are
495  *              retrieved from the NameServer prior to the free
496  *              attempt.
497  */
498 static void freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
500     Rm_AllocatorOpInfo  opInfo; 
501     Rm_NameServerObjCfg nameServerObjCfg;    
502     int32_t             retVal = transaction->state;
503     
504     if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
505         /* Fill in free logic for CDs */    
506     }
507     else if ((rmInst->instType == Rm_instType_SERVER) ||
508              (rmInst->instType == Rm_instType_SHARED_SERVER)) {
509         memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
510         
511         opInfo.policy = rmInst->u.server.globalPolicy;
512         opInfo.resourceInfo = &transaction->resourceInfo;
513         opInfo.serviceSrcInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst, transaction->serviceSrcInstName);
514         if (opInfo.serviceSrcInstNode) {
515             /* Populated NameServer name has precedence over base */
516             if (strlen(transaction->resourceInfo.nameServerName) > 0) {
517                 if ((transaction->resourceInfo.base == 0) &&
518                     (transaction->resourceInfo.length == 0) &&
519                     (transaction->resourceInfo.alignment == 0)) {
520                     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
521                         rmNameServerTreeInv(rmInst->u.server.nameServer);
522                     }                    
523                     memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
524                     nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
525                     nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
526                     if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) == RM_SERVICE_PROCESSING) {
527                         strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
528                         transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
529                         transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
530                     } 
531                 }
532                 else {
533                     retVal = RM_ERROR_NS_NAME_AND_RES_VAL_CONFLICT;
534                 }                
535             }
536             
537             if(retVal == RM_SERVICE_PROCESSING) {        
538                 opInfo.operation = Rm_allocatorOp_FREE;
539                 retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
540             }    
541         }
542         else {
543             retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
544         }
546         transaction->state = retVal;       
547     }   
550 /* FUNCTION PURPOSE: Client transaction handling process
551  ***********************************************************************
552  * DESCRIPTION: Client process for handling transactions created
553  *              from services received via the service handle or the
554  *              transport.  The Client process:
555  *                  - Performs static allocations if no transport
556  *                    to CD or Server has been registered
557  *                  - Forwards all service requests to CD or Server
558  *                    once transport has been registered
559  */
560 static void clientProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
562     Rm_Transaction    *transQ = rmInst->transactionQueue;
563     
564     if (!rmInst->registeredWithDelegateOrServer) {
565         staticAllocationHandler((Rm_Handle)rmInst, transaction);
566     }
567     else {
568         if (transaction->state == RM_SERVICE_PROCESSING) {
569             /* Forward all new transactions to CD or Server */
570             transactionForwarder(rmInst, transaction);                
571         }
572         else {
573             /* Transaction validated.  Return result. */
574             serviceResponder(rmInst, transaction);
575         }
577         /* Forward any queued static requests that weren't forwarded */
578         while(transQ) {
579             if ((transQ->state == RM_SERVICE_APPROVED_STATIC) &&
580                 (!transQ->hasBeenForwarded)) {
581                 transactionForwarder(rmInst, transQ);
582             }
583             transQ = transQ->nextTransaction;
584         }        
585     }
586     /* Let call stack return transaction result app via Rm_serviceHandler */
589 /* FUNCTION PURPOSE: Client Delegate transaction handling process
590  ***********************************************************************
591  * DESCRIPTION: Client Delegate process for handling transactions created
592  *              from services received via the service handle or the
593  *              transport.  The Client Delegate process:
594  *                  - Performs static allocations if no transport
595  *                    to Server has been registered
596  *                  - Forwards all NameServer related service requests 
597  *                    to Server once transport has been registered
598  *                  - Attempts to complete resource service requests
599  *                    received from registered Clients
600  */
601 static void cdProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
602 {        
603     Rm_Transaction *transQ = rmInst->transactionQueue;    
605     if (!rmInst->registeredWithDelegateOrServer) {
606         if ((transaction->state == RM_SERVICE_PROCESSING) &&
607             (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS) == 0)) {
608             /* Attempt static allocation of requests originating from CD inst */
609             staticAllocationHandler((Rm_Handle)rmInst, transaction);
610         }
611         /* Everything else left in transaction queue for forwarding once transport to
612          * Server is registered */
613     }
614     else {
615         if ((transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||
616             (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) ||
617             (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)) {
618             if (transaction->state == RM_SERVICE_PROCESSING) {
619                 /* Forward all NameServer requests. */
620                 transactionForwarder(rmInst, transaction);
621             }
622             else {
623                 /* NameServer transaction validated.  Return result. */
624                 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
625                     /* Transaction did not originate on this instance */
626                     transactionResponder(rmInst, transaction);
627                 }
628                 else {
629                     /* Transaction originated on this instance */
630                     serviceResponder(rmInst, transaction);
631                 }
632             }
633         }        
634         else if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
635                  (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE)) {
636             if ((transaction->state == RM_SERVICE_PROCESSING) ||
637                 (transaction->state == RM_SERVICE_APPROVED_STATIC)) {   
638                 transactionForwarder(rmInst, transaction);
639             }
640             else {
641                 /* Transaction validated.  Return result. */
642                 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
643                     /* Transaction did not originate on this instance */
644                     transactionResponder(rmInst, transaction);
645                 }
646                 else {
647                     /* Transaction originated on this instance */
648                     serviceResponder(rmInst, transaction);
649                 }
650             }
651         }
652         else if (transaction->type == Rm_service_RESOURCE_FREE) {     
653             if (transaction->state == RM_SERVICE_PROCESSING) {
654                 freeHandler(rmInst, transaction);
656                 if (transaction->state == RM_SERVICE_PROCESSING) {
657                     /* CD could not handle free.  Forward to Server */
658                     transactionForwarder(rmInst, transaction);
659                 }
660                 else {
661                     /* Free validated by CD.  Return result */
662                     if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
663                         /* Transaction did not originate on this instance */
664                         transactionResponder(rmInst, transaction);
665                     }
666                     else {
667                         /* Transaction originated on this instance */
668                         serviceResponder(rmInst, transaction);
669                     }                    
670                 }
671             }
672             else {
673                 /* Transaction validated.  Return result. */
674                 if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
675                     /* Transaction did not originate on this instance */
676                     transactionResponder(rmInst, transaction);
677                 }
678                 else {
679                     /* Transaction originated on this instance */
680                     serviceResponder(rmInst, transaction);
681                 }
682             }
683         }
685         /* Attempt allocation of any queued static requests:
686          * RM_SERVICE_APPROVED_STATIC - Originated locally
687          * RM_SERVICE_PROCESSING - Received from any registered Clients */
688         while(transQ) {
689             if (((transQ->state == RM_SERVICE_PROCESSING) ||
690                  (transQ->state == RM_SERVICE_APPROVED_STATIC)) &&
691                 (!transQ->hasBeenForwarded)) {
692                 transactionForwarder(rmInst, transQ);
693             }
694             transQ = transQ->nextTransaction;
695         }        
696     }
699 /* FUNCTION PURPOSE: Server transaction handling process
700  ***********************************************************************
701  * DESCRIPTION: Server process for handling transactions created
702  *              from services received via the service handle or the
703  *              transport.  The Server process:
704  *                  - Validates all service requests received from
705  *                    the service handle and registered CDs and
706  *                    Clients
707  */
708 static void serverProcess (Rm_Inst *rmInst, Rm_Transaction *transaction)
710     Rm_NameServerObjCfg  nameServerObjCfg;        
712     switch (transaction->type) {
713         case Rm_service_RESOURCE_ALLOCATE_INIT:
714         case Rm_service_RESOURCE_ALLOCATE_USE:
715             allocationHandler(rmInst, transaction);
716             break;
717         case Rm_service_RESOURCE_FREE:               
718             freeHandler(rmInst, transaction);
719             break;
720         case Rm_service_RESOURCE_MAP_TO_NAME:
721         case Rm_service_RESOURCE_GET_BY_NAME:
722         case Rm_service_RESOURCE_UNMAP_NAME:             
723             if (rmInst->u.server.nameServer) {
724                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
725                     rmNameServerTreeInv(rmInst->u.server.nameServer);
726                 }                
727                 memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
728                 nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
729                 nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
730                 if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
731                     nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;
732                     nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;
733                     nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;
734                     transaction->state = rmNameServerAddObject(&nameServerObjCfg);
735                 }
736                 else if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
737                     if ((transaction->state = rmNameServerFindObject(&nameServerObjCfg)) ==
738                         RM_SERVICE_PROCESSING) {
739                         strncpy(transaction->resourceInfo.name, nameServerObjCfg.nodeCfg.resourceName, RM_NAME_MAX_CHARS);
740                         transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
741                         transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
742                         transaction->state = RM_SERVICE_APPROVED;
743                     } 
744                 }
745                 else if (transaction->type == Rm_service_RESOURCE_UNMAP_NAME) {
746                     transaction->state = rmNameServerDeleteObject(&nameServerObjCfg);
747                 }
748                 
749                 if (rmInst->instType == Rm_instType_SHARED_SERVER) {
750                     rmNameServerTreeWb(rmInst->u.server.nameServer);
751                 }
752             }
753             else {
754                 transaction->state = RM_ERROR_NAMESERVER_DOES_NOT_EXIST;
755             }
756             break;
757     }
759     /* Source of shared server transaction will always be local. */
760     if (rmInst->instType != Rm_instType_SHARED_SERVER) {
761         if (strncmp(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS)) {
762             /* Source of transaction was not Server, return transaction via responder */
763             transactionResponder(rmInst, transaction);
764         }
765     }
766     /* Otherwise let call stack return transaction result app via Rm_serviceHandler */ 
769 /**********************************************************************
770  ********************** Internal Functions ****************************
771  **********************************************************************/
773 /* FUNCTION PURPOSE: Adds a transaction
774  ***********************************************************************
775  * DESCRIPTION: Returns a pointer to a newly created transaction.
776  *              The transaction is created based on a new service
777  *              request received via the service API or the
778  *              transport API (service forwarded from another instance)
779  */
780 Rm_Transaction *rmTransactionQueueAdd(Rm_Inst *rmInst)
782     Rm_Transaction *transactionQueue = rmInst->transactionQueue;
783     Rm_Transaction *newTransaction   = NULL;
785     newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));
786     if (newTransaction) {
787         memset((void *)newTransaction, 0, sizeof(Rm_Transaction));
789         newTransaction->localId = transactionGetSequenceNum(rmInst);
790         newTransaction->nextTransaction = NULL;  
791         if (transactionQueue) {
792             while (transactionQueue->nextTransaction) {
793                 transactionQueue = transactionQueue->nextTransaction;
794             }
795             transactionQueue->nextTransaction = newTransaction;
796         }
797         else {
798             rmInst->transactionQueue = newTransaction;
799         }
800     }
801     return (newTransaction);
804 /* FUNCTION PURPOSE: Finds a transaction
805  ***********************************************************************
806  * DESCRIPTION: Returns a pointer to a transaction resident
807  *              in the transaction queue that matches the provided
808  *              transaction ID.
809  */
810 Rm_Transaction *rmTransactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)
812     Rm_Transaction *transaction = rmInst->transactionQueue;
814     while (transaction) {
815         if (transaction->localId == transactionId) {
816             break;             
817         }
818         transaction = transaction->nextTransaction;
819     }
821     return (transaction);
824 /* FUNCTION PURPOSE: Deletes a transaction
825  ***********************************************************************
826  * DESCRIPTION: Deletes the transaction with the provided transaction
827  *              ID from the instance's transaction queue.
828  */
829 int32_t rmTransactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
831     Rm_Transaction *transaction     = rmInst->transactionQueue;
832     Rm_Transaction *prevTransaction = NULL;
833     int32_t         retVal          = RM_OK;
835     while (transaction) {
836         if (transaction->localId == transactionId) {
837             break;             
838         }
840         prevTransaction = transaction;
841         transaction = transaction->nextTransaction;
842     }
844     if (transaction) {
845         if (prevTransaction == NULL) {
846             /* Transaction at start of queue. Map second transaction to start of queue 
847              * as long as more than one transactions. */
848             rmInst->transactionQueue = transaction->nextTransaction;
849         }
850         else {
851             /* Transaction in middle or end of queue. */
852             prevTransaction->nextTransaction = transaction->nextTransaction;
853         }
854         Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));
855     }
856     else {
857         retVal = RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST;
858     }    
859     return (retVal);
862 /* FUNCTION PURPOSE: Routes a transaction for processing
863  ***********************************************************************
864  * DESCRIPTION: Routes a received transaction to the appropriate
865  *              instance processing routine
866  */
867 void rmProcessRouter (Rm_Inst *rmInst, Rm_Transaction *transaction)
869     if (rmInst->instType == Rm_instType_CLIENT) {
870         clientProcess(rmInst, transaction);
871     }
872     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
873         cdProcess(rmInst, transaction);
874     }
875     else if ((rmInst->instType == Rm_instType_SERVER) ||
876              (rmInst->instType == Rm_instType_SHARED_SERVER)) {
877         serverProcess(rmInst, transaction);
878     } 
880      
881 /**********************************************************************
882  ********************** Application visible APIs **********************
883  **********************************************************************/
885 /* FUNCTION PURPOSE: Display status of managed resources
886  ***********************************************************************
887  * DESCRIPTION: Prints the status (allocate/free status, as well as
888  *              owners) for all resources managed by the RM 
889  *              instance network.  Also, prints the NameServer name
890  *              entries.  The number of resource range owners is
891  *              returned as well.  This function is only available on
892  *              server instances.
893  */
894 int32_t Rm_resourceStatus(Rm_Handle rmServerHandle, int printResources)
896     Rm_Inst         *rmInst = (Rm_Inst *)rmServerHandle;
897     Rm_Allocator    *allocator = NULL;
898     Rm_Owner        *owners;
899     Rm_ResourceTree *treeRoot;
900     Rm_ResourceNode *treeNode;
901     int32_t          totalResOwners = 0;
902     void            *key; 
904     RM_SS_INST_INV_ENTER_CS(key);
905     RM_SC_INST_INV_ENTER_CS(key);
907     if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
908         /* Transfer control to shared server instance */
909         rmInst = rmInst->u.sharedClient.sharedServerHandle;
910     }
912     if ((rmInst->instType == Rm_instType_SERVER) ||
913         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
914         allocator = rmInst->u.server.allocators;
915         while (allocator) {
916             RM_SS_OBJ_INV(allocator, Rm_Allocator);
917             if (printResources) {
918                 Rm_osalLog("Resource: %s\n", allocator->resourceName);
919             }
921             treeRoot = allocator->allocatorRootEntry;
922             if (rmInst->instType == Rm_instType_SHARED_SERVER) {
923                 rmResourceTreeInv(treeRoot);
924             }
925             RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) {
926                 if (printResources) {
927                     if ((treeNode->base >= 65536) ||
928                         ((treeNode->base + treeNode->length - 1) >= 65536)) {
929                         /* Print in hex if number is very large */
930                         Rm_osalLog("          0x%08x - 0x%08x ", treeNode->base, 
931                                                                  treeNode->base + treeNode->length - 1);
932                     }
933                     else {
934                         Rm_osalLog("          %10d - %10d ", treeNode->base, 
935                                                              treeNode->base + treeNode->length - 1);
936                     }
937                 }
938                 
939                 if (treeNode->allocationCount == 0) {
940                     if (printResources) {
941                         Rm_osalLog("FREE\n");
942                     }
943                 }
944                 else {
945                     owners = treeNode->ownerList;
946                     while (owners) {
947                         RM_SS_OBJ_INV(owners, Rm_Owner);
948                         if (printResources) {
949                             Rm_osalLog("%s ", owners->instNameNode->name);
950                         }
951                         totalResOwners++;
952                         owners = owners->nextOwner;
953                     }
954                     if (printResources) {
955                         Rm_osalLog("\n");
956                     }
957                 }
958             }        
959             allocator = allocator->nextAllocator; 
960         }
961         if (printResources) {
962             rmNameServerPrintObjects((Rm_Handle)rmInst);
963         }
964     }
965     else {
966         totalResOwners = RM_ERROR_INVALID_RES_STATUS_INSTANCE;
967     }  
969     RM_SS_INST_WB_EXIT_CS(key);
970     return(totalResOwners);
973 /* FUNCTION PURPOSE: Display status of a RM instance
974  ***********************************************************************
975  * DESCRIPTION: Prints the current status of various RM instance
976  *              properties such as the state of all transactions
977  *              in the transaction queue and registered transports
978  */
979 void Rm_instanceStatus(Rm_Handle rmHandle)
981     Rm_Inst        *rmInst = (Rm_Inst *)rmHandle;
982     Rm_Transport   *transportList = NULL;
983     Rm_Transaction *transactionQ = NULL;
984     void           *key; 
986     RM_SS_INST_INV_ENTER_CS(key);
987     RM_SC_INST_INV_ENTER_CS(key);
989     Rm_osalLog("Instance name: %s\n", rmInst->instName);
990     Rm_osalLog("Handle: 0x%08x\n", rmHandle);    
991     if (rmInst->instType == Rm_instType_SERVER) {
992         Rm_osalLog("Type:   Server\n");
993     }
994     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
995         Rm_osalLog("Type:   Client Delegate\n");
996     }
997     else if (rmInst->instType == Rm_instType_CLIENT) {
998         Rm_osalLog("Type:   Client\n");
999     }
1000     else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1001         Rm_osalLog("Type:   Shared Server\n");
1002     }
1003     else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1004         Rm_osalLog("Type:   Shared Client\n");
1006         Rm_osalLog("\nShared Server Properties:\n");
1007         /* Transfer to Shared Server instance to print out transport and
1008          * transaction status */
1009         rmInst = rmInst->u.sharedClient.sharedServerHandle;
1010         Rm_osalLog("Instance name: %s\n", rmInst->instName);
1011         Rm_osalLog("Handle: 0x%08x\n", rmHandle);
1012     }
1013     
1014     transportList = rmInst->transports;
1015     if (transportList) {
1016         Rm_osalLog("\nRegistered Transports:\n");
1017         while (transportList) {
1018             RM_SS_OBJ_INV(transportList, Rm_Transport);
1019             Rm_osalLog("    Remote instName:    %s\n", transportList->remoteInstName);
1020             if (transportList->remoteInstType == Rm_instType_SERVER) {
1021                 Rm_osalLog("    Remote instType:    Server\n");
1022             }
1023             else if (transportList->remoteInstType == Rm_instType_CLIENT_DELEGATE) {
1024                 Rm_osalLog("    Remote instType:    Client Delegate\n");
1025             }
1026             else {
1027                 Rm_osalLog("    Remote instType:    Client\n");
1028             }
1029             Rm_osalLog("    appTransportHandle: 0x%08x\n", transportList->appTransportHandle);
1030             Rm_osalLog("\n");
1031             transportList = transportList->nextTransport;
1032         }
1033     }
1035     transactionQ = rmInst->transactionQueue;
1036     if (transactionQ) {
1037         Rm_osalLog("\nQueued Service Transactions:\n");
1038         while (transactionQ) {
1039             RM_SS_OBJ_INV(transactionQ, Rm_Transaction);
1040             Rm_osalLog("    Service type:       %d\n", transactionQ->type);
1041             Rm_osalLog("    Service ID:         %d\n", transactionQ->localId);
1042             Rm_osalLog("    Service srcInstName %s\n", transactionQ->serviceSrcInstName);
1043             Rm_osalLog("    Service state:      %d\n", transactionQ->state);
1044             Rm_osalLog("    Resource name:      %s\n", transactionQ->resourceInfo.name);
1045             Rm_osalLog("    Resource base:      %d\n", transactionQ->resourceInfo.base);
1046             Rm_osalLog("    Resource length:    %d\n", transactionQ->resourceInfo.length);
1047             Rm_osalLog("    Resource alignment: %d\n", transactionQ->resourceInfo.alignment);
1048             Rm_osalLog("    Resource NS name:   %s\n", transactionQ->resourceInfo.nameServerName);
1049             Rm_osalLog("\n");
1050             transactionQ = transactionQ->nextTransaction;
1051         }    
1052     }
1053     RM_SS_INST_WB_EXIT_CS(key);    
1056 /* FUNCTION PURPOSE: RM instance creation and initialization
1057  ***********************************************************************
1058  * DESCRIPTION: Returns a new RM instance created and initialized
1059  *              using the parameters provided via the initCfg
1060  *              structure.
1061  */
1062 Rm_Handle Rm_init(const Rm_InitCfg *initCfg, int32_t *result)
1064     Rm_Inst  *rmInst = NULL;
1065     Rm_Inst  *sharedServerInst = NULL;
1066     uint32_t  policySize;
1067     void     *globalResourceDtb = NULL;
1068     void     *linuxResourceDtb = NULL;
1069     int       addLinux = RM_FALSE;   
1070     void     *key;     
1072     *result = RM_OK;
1073     
1074     if ((initCfg->instName == NULL) ||
1075         ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {
1076         *result = RM_ERROR_INVALID_INST_NAME;
1077         goto errorExit;
1078     }
1080     if (initCfg->instType >= Rm_instType_LAST) {
1081         *result = RM_ERROR_INVALID_INST_TYPE;
1082         goto errorExit;
1083     }
1085     /* Create and initialize instance */
1086     rmInst = Rm_osalMalloc(sizeof(*rmInst));
1087     memset ((void *)rmInst, 0, sizeof(*rmInst));
1088     rmInst->isLocked = RM_FALSE;
1089     rmInst->registeredWithDelegateOrServer = RM_FALSE;
1090     rmInst->transactionSeqNum = transactionInitSequenceNum();
1092     rmInst->instType = initCfg->instType;    
1093     strncpy (rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);
1095     if ((rmInst->instType == Rm_instType_SERVER) ||
1096         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1097         if (!initCfg->instCfg.serverCfg.globalResourceList ||
1098             !initCfg->instCfg.serverCfg.globalPolicy) {
1099             *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;
1100             goto errorExit;
1101         }
1103         if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1104             /* Shared Server makes copy of policy in shared memory for Shared Clients
1105              * on other cores */
1106             policySize = fdt_totalsize(initCfg->instCfg.serverCfg.globalPolicy);
1107             /* Align policy size to cache boundary */
1108             if (policySize % RM_MAX_CACHE_ALIGN) {
1109                 policySize += (RM_MAX_CACHE_ALIGN - (policySize % RM_MAX_CACHE_ALIGN));
1110             }
1111             rmInst->u.server.policySize = policySize;
1112             rmInst->u.server.globalPolicy = Rm_osalMalloc(rmInst->u.server.policySize);
1113             memcpy(rmInst->u.server.globalPolicy, initCfg->instCfg.serverCfg.globalPolicy, rmInst->u.server.policySize);
1114         }
1115         else {
1116             rmInst->u.server.globalPolicy = initCfg->instCfg.serverCfg.globalPolicy;
1117         }
1119         if (initCfg->instCfg.serverCfg.linuxDtb) {
1120             linuxResourceDtb = initCfg->instCfg.serverCfg.linuxDtb;
1121             addLinux = RM_TRUE;
1122         }
1124         /* Create valid instance list from policy.  Must be done prior to parsing
1125          * GRL so that Linux resources can be reserved correctly */
1126         rmInst->u.server.globalValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);
1127         if (*result == RM_OK) {
1128             *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);  
1129         }
1130         
1131         if (*result != RM_OK) {
1132             if (rmInst->u.server.globalValidInstTree) {
1133                 rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1134             }
1135             goto errorExit;
1136         }
1137         else {
1138             rmNameServerInit((Rm_Handle)rmInst);
1140             globalResourceDtb = initCfg->instCfg.serverCfg.globalResourceList;
1142             if ((*result = rmAllocatorInitializeResources((Rm_Handle) rmInst, globalResourceDtb, linuxResourceDtb)) == RM_OK) {  
1143                 *result = rmPolicyValidatePolicyResourceNames((Rm_Handle)rmInst);
1144             }
1146             if (*result != RM_OK) {
1147                 rmAllocatorDeleteResources((Rm_Handle)rmInst);
1148                 rmNameServerDelete((Rm_Handle)rmInst);
1149                 goto errorExit;
1150             }
1151         }
1152     }
1153     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1154         if (initCfg->instCfg.cdCfg.cdPolicy) {
1155             rmInst->u.cd.cdPolicy = initCfg->instCfg.cdCfg.cdPolicy;
1156             rmInst->u.cd.cdValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);        
1157             if (*result == RM_OK) {
1158                 *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1159             }
1161             if (*result != RM_OK) {
1162                 if (rmInst->u.cd.cdValidInstTree) {
1163                     rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1164                 }
1165                 goto errorExit;
1166             }
1167         }
1169         rmInst->u.cd.allocators = NULL;
1170     }
1171     else if (rmInst->instType == Rm_instType_CLIENT) {
1172         if (initCfg->instCfg.clientCfg.staticPolicy) { 
1173             rmInst->u.client.staticPolicy = initCfg->instCfg.clientCfg.staticPolicy;
1174             rmInst->u.client.staticValidInstTree = rmPolicyCreateValidInstTree((Rm_Handle)rmInst, addLinux, result);        
1175             if (*result == RM_OK) {
1176                 *result = rmPolicyValidatePolicy((Rm_Handle)rmInst);
1177             }
1178             
1179             if (*result != RM_OK) {
1180                 if (rmInst->u.client.staticValidInstTree) {
1181                     rmPolicyFreeValidInstTree((Rm_Handle)rmInst);
1182                 }
1183                 goto errorExit;
1184             }
1185         }
1186     }
1187     else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
1188         if (initCfg->instCfg.sharedClientCfg.sharedServerHandle) {
1189             rmInst->u.sharedClient.sharedServerHandle = initCfg->instCfg.sharedClientCfg.sharedServerHandle;
1190             /* Invalidate the Shared server instance structure on this core to get the latest
1191              * instance data. */
1192             key = Rm_osalCsEnter();
1193             Rm_osalBeginMemAccess((void *)rmInst->u.sharedClient.sharedServerHandle, sizeof(Rm_Inst));
1194             sharedServerInst = rmInst->u.sharedClient.sharedServerHandle;
1195             if (sharedServerInst->instType != Rm_instType_SHARED_SERVER) {
1196                 *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1197                 Rm_osalCsExit(key);
1198                 goto errorExit;
1199             }
1200             else {
1201                 /* Invalidate the policy */
1202                 Rm_osalBeginMemAccess((void *)sharedServerInst->u.server.globalPolicy, 
1203                                       sharedServerInst->u.server.policySize);
1204             }
1205             Rm_osalCsExit(key);
1206         }
1207         else {
1208             *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
1209             goto errorExit;
1210         }
1211     }
1213     if (initCfg->instType == Rm_instType_SHARED_SERVER) {
1214         /* Writeback the instance and policy for other cores */
1215         Rm_osalEndMemAccess ((void *)rmInst, sizeof(Rm_Inst));
1216         Rm_osalEndMemAccess ((void *)rmInst->u.server.globalPolicy, rmInst->u.server.policySize);
1217     }
1218     else if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1219         /* Create the instance's task blocking mechanism */
1220         rmInst->blockHandle = Rm_osalTaskBlockCreate();
1221     }
1223     return ((Rm_Handle) rmInst);
1224 errorExit:
1225     if (rmInst) {
1226         Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
1227     }
1228     return (NULL); 
1231 /* FUNCTION PURPOSE: Deletes an RM instance
1232  ***********************************************************************
1233  * DESCRIPTION: Frees all memory associated with an RM instance
1234  *              as long as all transports have been unregistered
1235  *              and the service handle has been closed
1236  */
1237 int32_t Rm_delete(Rm_Handle rmHandle, int ignorePendingServices)
1239     Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
1240     void    *key; 
1242     key = Rm_osalCsEnter();
1243     if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1244         Rm_osalBeginMemAccess((void *)rmInst, sizeof(Rm_Inst));
1245     }
1247     if (rmInst->serviceHandle) {
1248         return (RM_ERROR_CANT_DELETE_WITH_OPEN_SERV_HNDL);
1249     }
1250     else if (rmInst->transports) {
1251         return (RM_ERROR_CANT_DELETE_WITH_REGD_TRANSPORT);
1252     }
1253     else if (rmInst->transactionQueue && !ignorePendingServices) {
1254         return (RM_ERROR_CANT_DELETE_PENDING_TRANSACTIONS);
1255     }
1257     if ((rmInst->instType == Rm_instType_SERVER) ||
1258         (rmInst->instType == Rm_instType_SHARED_SERVER)) {
1259         rmAllocatorDeleteResources(rmHandle);
1260         rmNameServerDelete(rmHandle);
1261         rmInst->u.server.allocators = NULL;
1263         if (rmInst->instType == Rm_instType_SHARED_SERVER) {
1264             Rm_osalFree((void *)rmInst->u.server.globalPolicy, rmInst->u.server.policySize);
1265         }
1266     }
1267     else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
1268         rmAllocatorDeleteResources(rmHandle);
1269         rmInst->u.cd.allocators = NULL;
1270     }
1272     if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
1273         /* Delete valid instance tree */
1274         rmPolicyFreeValidInstTree(rmHandle);
1276         /* Delete any transactions */
1277         while(rmInst->transactionQueue) {
1278             rmTransactionQueueDelete(rmInst, rmInst->transactionQueue->localId);
1279         }
1281         if (rmInst->instType != Rm_instType_SHARED_SERVER) {
1282             /* Delete the instance's task blocking mechanism */
1283             Rm_osalTaskBlockDelete(rmInst->blockHandle);
1284         }
1285         else {
1286             Rm_osalEndMemAccess((void *)rmInst, sizeof(Rm_Inst));
1287         }
1288     }
1290     Rm_osalFree((void *)rmInst, sizeof(Rm_Inst));
1291    
1292     Rm_osalCsExit(key);   
1293     return (RM_OK);
1296 /* FUNCTION PURPOSE: Returns RM version information
1297  ***********************************************************************
1298  */
1299 uint32_t Rm_getVersion(void)
1301     return RM_VERSION_ID;
1304 /* FUNCTION PURPOSE: Returns RM version string
1305  ***********************************************************************
1306  */
1307 const char* Rm_getVersionStr(void)
1309     return rmVersionStr;