diff --git a/src/rm.c b/src/rm.c
index a7137978888f48ca9ba98f8d79b82938557b6d3a..d95d87eca17d4eeb22025b3032c2f57351cbafa5 100644 (file)
--- a/src/rm.c
+++ b/src/rm.c
-/**\r
- * @file rm.c\r
- *\r
- * @brief \r
- * This is the Resource Manager source.\r
- *\r
- * \par\r
- * ============================================================================\r
- * @n (C) Copyright 2012, Texas Instruments, Inc.\r
- * \r
- * Redistribution and use in source and binary forms, with or without \r
- * modification, are permitted provided that the following conditions \r
- * are met:\r
- *\r
- * Redistributions of source code must retain the above copyright \r
- * notice, this list of conditions and the following disclaimer.\r
- *\r
- * Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the \r
- * documentation and/or other materials provided with the \r
- * distribution.\r
- *\r
- * Neither the name of Texas Instruments Incorporated nor the names of\r
- * its contributors may be used to endorse or promote products derived\r
- * from this software without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- *\r
- * \par\r
-*/\r
-\r
-/* RM Types */\r
-#include <ti/drv/rm/rm_types.h>\r
-\r
-/* RM includes */\r
-#include <ti/drv/rm/rm.h>\r
-#include <ti/drv/rm/rm_services.h>\r
-#include <ti/drv/rm/rm_transport.h>\r
-#include <ti/drv/rm/rm_policy.h>\r
-#include <ti/drv/rm/include/rm_pvt.h>\r
-\r
-/* RM OSAL layer */\r
-#include <rm_osal.h>\r
-\r
-/**********************************************************************\r
- ************************** Globals ***********************************\r
- **********************************************************************/\r
-\r
-/* Place QMSS PDSP permissions array */\r
-#pragma DATA_SECTION (rmQmssPdspFirmwarePerms, ".rm");\r
-#pragma DATA_ALIGN (rmQmssPdspFirmwarePerms, 128)\r
-Rm_Perms rmQmssPdspFirmwarePerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_FIRMWARE_PDSPS, Rm_Perms)];\r
-\r
-\r
-/** @brief Global Variable which describes the RM Version Information */\r
-const char rmVersionStr[] = RM_VERSION_STR ":" __DATE__ ":" __TIME__;\r
-\r
-/**********************************************************************\r
- ********************** Internal Functions ****************************\r
- **********************************************************************/\r
-\r
-void Rm_transactionQueueAdd(Rm_Inst *rmInst, uint32_t transactionId, \r
- Rm_TransportHandle transportHandle, void *callbackFunc)\r
-{\r
- Rm_TransactionQueueEntry *transactionQueue = (Rm_TransactionQueueEntry *) rmInst->transactionQueue;\r
- Rm_TransactionQueueEntry *newEntry;\r
- void *key;\r
-\r
- /* Lock access to the RM instance's transaction queue */\r
- key = Rm_osalLocalCsEnter();\r
-\r
- /* Get memory for a new transaction queue entry from local memory */\r
- newEntry = Rm_osalMalloc (sizeof(Rm_TransactionQueueNode), false);\r
-\r
- /* Populate the new entry. */\r
- newEntry->transactionId = transactionId;\r
- newEntry->transportHandle = transportHandle;\r
- newEntry->transactionCallback = callbackFunc;\r
- newEntry->nextEntry = NULL; /* New entry's nextEntry pointer will always be NULL */\r
-\r
- /* Check if there are any entries in the transaction queue */\r
- if (transactionQueue)\r
- {\r
- /* At least one entry in the transaction queue. Add the new entry to the end of the\r
- * transaction queue */\r
- while (transactionQueue->nextEntry != NULL)\r
- {\r
- /* Traverse the list until arriving at the last entry */\r
- transactionQueue = transactionQueue->nextEntry;\r
- }\r
-\r
- /* Add the new entry to the end of the queue */\r
- transactionQueue->nextEntry = newEntry;\r
- }\r
- else\r
- {\r
- /* The transaction queue does not currently exist. The new entry is the first entry */\r
- rmInst->routeMap = newEntry;\r
- }\r
-\r
- Rm_osalLocalCsExit(key);\r
-}\r
-\r
-Rm_TransactionQueueEntry *Rm_transactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)\r
-{\r
- Rm_TransactionQueueEntry *entry = (Rm_TransactionQueueEntry *) rmInst->transactionQueue;\r
- void *key;\r
-\r
- /* Lock access to the RM instance's transaction queue */\r
- key = Rm_osalLocalCsEnter();\r
-\r
- /* Make sure there is at least one entry in the transaction queue */\r
- if (entry != NULL)\r
- {\r
- /* Find the transaction ID within the specified RM instance's transaction queue.\r
- * If the end of the transaction queue is reached without finding the entry the \r
- * entry pointer will be NULL */\r
- while (entry != NULL)\r
- {\r
- if (entry->transactionId == transactionId)\r
- {\r
- /* Match: break out of loop and return the entry */\r
- break; \r
- }\r
- entry = entry->nextEntry;\r
- }\r
- }\r
- \r
- Rm_osalLocalCsExit(key);\r
- return (entry);\r
-}\r
-\r
-uint32_t Rm_transactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)\r
-{\r
- Rm_TransactionQueueEntry *currentEntry = (Rm_TransactionQueueEntry *) rmInst->transactionQueue;\r
- Rm_TransactionQueueEntry *prevEntry = NULL;\r
- void *key;\r
-\r
- /* Lock access to the RM instance's transaction queue */\r
- key = Rm_osalLocalCsEnter();\r
-\r
- /* Make sure there is at least one entry in the transaction queue */\r
- if (currentEntry == NULL)\r
- {\r
- Rm_osalLocalCsExit(key);\r
- return (-1); /* TEMP ERROR RETURN */\r
- }\r
-\r
- /* Find the transaction ID within the specified RM instance's transaction queue. */\r
- while (currentEntry != NULL)\r
- {\r
- if (currentEntry->transactionId == transactionId)\r
- {\r
- /* Match: break out of loop and delete the entry */\r
- break; \r
- }\r
-\r
- prevEntry = currentEntry;\r
- currentEntry = currentEntry->nextEntry;\r
- }\r
-\r
- /* Traversed entire queue but did not find transaction */\r
- if (currentEntry == NULL)\r
- {\r
- Rm_osalLocalCsExit(key);\r
- return (-2); /* TEMP ERROR RETURN */\r
- }\r
- else\r
- {\r
- /* Delete the transaction queue entry */\r
- if ((prevEntry == NULL) && currentEntry->nextEntry)\r
- {\r
- /* Entry to be deleted exists at start of transaction queue. Map second\r
- * entry to be start of transaction queue as long as there are more than\r
- * one entries */\r
- rmInst->transactionQueue = currentEntry->nextNode;\r
- }\r
- else\r
- {\r
- /* Entry to be deleted is in the middle or at end of the queue. Adjust adjacent\r
- * entry pointers. This covers the case where the entry to be removed is at the\r
- * end of the queue. */\r
- prevEntry->nextNode = currentEntry->nextNode;\r
- }\r
-\r
- /* Delete the node, free the memory associated with the node. */\r
- Rm_osalFree((void *) currentEntry, sizeof(Rm_TransactionQueueEntry), false);\r
- }\r
-\r
- Rm_osalLocalCsExit(key);\r
- return (0); /* RETURN OKAY - FIX MAGIC NUMBER */\r
-}\r
-\r
-/* Used in Client Delegate case where it forwarded requests from Client to Server\r
- * callback will direct to internal function that forwards response from server back\r
- * to client */\r
-void Rm_internalCallback (Rm_ServiceRespInfo *responseInfo)\r
-{\r
-\r
-}\r
-\r
-/* Function used to send RM response transactions to lower level agents */\r
-void Rm_transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction,\r
- Rm_TransactionReceipt *receipt)\r
-{\r
- Rm_TransactionQueueEntry *transactionEntry;\r
- Rm_Packet *rmPkt = NULL;\r
- Rm_ProtocolPkt *rmProtPkt = NULL;\r
-\r
- /* Find the transaction request that matches the received response */\r
- transactionEntry = Rm_transactionQueueFind(rmInst,transaction->pktId);\r
-\r
- if (transactionEntry == NULL)\r
- {\r
- /* No transaction request matching the transaction ID was forwarded from\r
- * this RM instace */\r
- receipt->transactionResult = RM_SERVICE_ERROR_TRANSACTION_DOES_NOT_EXST_FOR_THIS_RM_INSTANCE;\r
- return;\r
- }\r
-\r
- /* Create a RM packet using the transaction information */\r
- if (rmInst->transport.rmAllocPkt)\r
- {\r
- rmPkt = rmInst->transport.rmAllocPkt(transactionEntry->transportHandle, sizeof(Rm_Packet));\r
- }\r
- else\r
- {\r
- /* The transport packet alloc API is not plugged */\r
- receipt->transactionResult = RM_SERVICE_ERROR_TRANSPORT_PKT_ALLOC_API_NULL;\r
- return;\r
- }\r
-\r
- /* Make sure a buffer for the packet was allocated */\r
- if (rmPkt == NULL)\r
- {\r
- receipt->transactionResult = RM_SERVICE_ERROR_TRANSPORT_NULL_PKT_BUF;\r
- return;\r
- }\r
-\r
- /* Make sure allocated buffer is large enough to fit the protocol packet plus the \r
- * rmPktLen field */\r
- if (rmPkt->rmPktLen < (sizeof(Rm_ProtocolPkt) + sizeof(uint32_t))\r
- { \r
- receipt->transactionResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;\r
- return;\r
- }\r
-\r
-\r
- /* Initialize the rmPkt. Do not assume the transport code will do it */ \r
- memset((void *)rmPkt, 0, sizeof(Rm_Packet));\r
-\r
- /* Assign the rmData field to be the rmProtPkt */\r
- rmProtPkt = &(rmPkt->rmData[0]);\r
-\r
- /* Populate the response packet with the transaction response details for\r
- * the lower leverl RM instance */\r
- rmProtPkt->rmPktId = transactionEntry->transactionId;\r
- strcpy((void *)rmProtPkt->rmInstName,(void *)rmInst->name);\r
- rmProtPkt->rmCmd = (uint32_t) transaction->command;\r
- rmProtPkt->rmDetails = transaction->details;\r
- if (transaction->command == Rm_command_POLICY_RESPONSE)\r
- {\r
- /* Copy the policy data if the transaction is policy based */\r
- memcpy ((void *)rmProtPkt->u.rmPolicyData, (void *)transaction->u.policyData,\r
- RM_MAX_POLICY_SIZE_BYTES);\r
- }\r
- else\r
- {\r
- /* Otherwise copy the resource data */\r
- memcpy ((void *)&(rmProtPkt->u.resInfo), (void *) &(transaction->u.resourceInfo),\r
- sizeof(Rm_ResourceInfo));\r
- }\r
-\r
- /* Send the RM packet to the application transport */\r
- if (rmInst->transport.rmSend)\r
- {\r
- if (!(rmInst->transport.rmSend(transactionEntry->transportHandle, rmPkt))\r
- {\r
- /* Transport returned an error */\r
-\r
- /* SHOULD TRANSPORT ERROR SOMEHOW BE OR'D WITH THE SERVICE ERROR ??? */\r
- receipt->transactionResult = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
- return;\r
- }\r
- }\r
- else\r
- {\r
- /* The transport packet send API is not plugged */\r
- receipt->transactionResult = RM_SERVICE_ERROR_TRANSPORT_PKT_SEND_API_NULL;\r
- return;\r
- } \r
- \r
- receipt->transactionResult = RM_RESPONSE_PACKET_SENT;\r
-\r
- /* Delete the transaction entry from the transaction queue */\r
- Rm_transactionQueueDelete(rmInst,transaction->pktId);\r
-\r
- return;\r
-}\r
-\r
-/* Function used to forward RM transactions to higher level agents */\r
-void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction,\r
- Rm_TransactionReceipt *receipt)\r
-{\r
- Rm_TransRouteMapNode *routeMap = (Rm_TransRouteMapNode *) rmInst->routeMap;\r
- uint32_t transactionId;\r
- Rm_Packet *rmPkt = NULL;\r
- Rm_ProtocolPkt *rmProtPkt = NULL;\r
-\r
- /* Make sure at least one transport has been registered */\r
- if (routeMap == NULL)\r
- {\r
- receipt->transactionResult = RM_SERVICE_ERROR_NO_TRANSPORT_REGISTERED;\r
- return;\r
- }\r
- \r
- /* Make sure the RM instance has a transport registered with a higher level agent */\r
- if (!rmInst->registeredWithDelegateOrServer)\r
- {\r
- receipt->transactionResult = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER;\r
- return;\r
- }\r
-\r
- /* Parse the RM instance's routing map to find the higher level agent for forwarding */\r
- while ((routeMap->remoteInstType != Rm_instType_CLIENT_DELEGATE) || \r
- (routeMap->remoteInstType != Rm_instType_SERVER))\r
- {\r
- /* Traverse the list until arriving at the upper level agent node */\r
- routeMap = routeMap->nextNode;\r
- }\r
-\r
- /* Create a RM packet using the service information */\r
- if (rmInst->transport.rmAllocPkt)\r
- {\r
- rmPkt = rmInst->transport.rmAllocPkt(routeMap->transHandle, sizeof(Rm_Packet));\r
- }\r
- else\r
- {\r
- /* The transport packet alloc API is not plugged */\r
- receipt->transactionResult = RM_SERVICE_ERROR_TRANSPORT_PKT_ALLOC_API_NULL;\r
- return;\r
- }\r
-\r
- /* Make sure a buffer for the packet was allocated */\r
- if (rmPkt == NULL)\r
- {\r
- receipt->transactionResult = RM_SERVICE_ERROR_TRANSPORT_NULL_PKT_BUF;\r
- return;\r
- }\r
-\r
- /* Make sure allocated buffer is large enough to fit the protocol packet plus the \r
- * rmPktLen field */\r
- if (rmPkt->rmPktLen < (sizeof(Rm_ProtocolPkt) + sizeof(uint32_t))\r
- { \r
- receipt->transactionResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;\r
- return;\r
- }\r
-\r
- /* Create an ID for this transaction. The ID will be used for two purposes:\r
- * 1) Matching the response from the higher level RM agent to the request\r
- * 2) Provided to the service requesting component so that it can match the\r
- * service request with the response it receives via its callback function */\r
- transactionId = ...; /* NEED SCHEME FOR CREATING A MUTUALLY EXCLUSIVE PKT ID. CAN'T\r
- * CONFLICT WITH PCKT IDS CREATED ON OTHER RM INSTANCES */\r
- /* Initialize the rmPkt. Do not assume the transport code will do it */ \r
- memset((void *)rmPkt, 0, sizeof(Rm_Packet));\r
- \r
- /* Assign the rmData field to be the rmProtPkt */\r
- rmProtPkt = &(rmPkt->rmData[0]);\r
- /* Populate the RM packet using the service information */\r
- rmProtPkt->rmPktId = transactionId;\r
- strcpy((void *)rmProtPkt->rmInstName,(void *)rmInst->name);\r
- rmProtPkt->rmCmd = (uint32_t) transaction->command;\r
- if ((transaction->command == Rm_command_POLICY_REQUEST) ||\r
- (transaction->command == Rm_command_POLICY_RESPONSE)\r
- {\r
- /* Copy the policy data if the transaction is policy based */\r
- memcpy ((void *)rmProtPkt->u.rmPolicyData, (void *)transaction->u.policyData,\r
- RM_MAX_POLICY_SIZE_BYTES);\r
- }\r
- else\r
- {\r
- /* Otherwise copy the resource data */\r
- memcpy ((void *)&(rmProtPkt->u.resInfo), (void *) &(transaction->u.resourceInfo),\r
- sizeof(Rm_ResourceInfo));\r
- }\r
-\r
- /* Create an entry in the transaction queue */\r
- Rm_transactionQueueAdd(rmInst, transactionId, transaction->callback);\r
-\r
- /* Send the RM packet to the application transport */\r
- if (rmInst->transport.rmSend)\r
- {\r
- if (!(rmInst->transport.rmSend(routeMap->transHandle, rmPkt))\r
- {\r
- /* Transport returned an error */\r
-\r
- /* SHOULD TRANSPORT ERROR SOMEHOW BE OR'D WITH THE SERVICE ERROR ??? */\r
- receipt->transactionResult = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
- return;\r
- }\r
- }\r
- else\r
- {\r
- /* The transport packet send API is not plugged */\r
- receipt->transactionResult = RM_SERVICE_ERROR_TRANSPORT_PKT_SEND_API_NULL;\r
- return;\r
- } \r
-\r
- /* Inform requesting component that the service is being forwarded to a higher lever\r
- * RM agent for processing. The result of the service will be provided to the \r
- * component via the specified callback function */\r
- receipt->transactionResult = RM_SERVICE_PROCESSING;\r
- receipt->transactionId = transactionId;\r
- return;\r
-}\r
-\r
-void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction, \r
- Rm_TransactionReceipt *receipt)\r
-{\r
- if (rmInst->instType == Rm_instType_CLIENT)\r
- {\r
- if (transaction->command == Rm_command_RESOURCE_RESPONSE)\r
- {\r
- /* Responses received by the Client must be issued back to the requesting\r
- * component */\r
- Rm_serviceResponder (rmInst, transaction, receipt);\r
- }\r
- else\r
- {\r
- /* All service requests on Clients are forwarded to the higher level RM agent\r
- * either a Client Delegate or Server, based on the RM system architecture */\r
- Rm_transactionForwarder(rmInst, transaction, receipt);\r
- }\r
- }\r
- else\r
- {\r
- /* Execute a command processor based on the command type */\r
- switch (transaction->transCommand)\r
- {\r
- case Rm_command_ALLOCATE:\r
- case Rm_command_BLOCK_ALLOCATE:\r
- case Rm_command_ALLOCATE_NAMED:\r
- Rm_allocate(rmInst, transaction, receipt);\r
- break;\r
- case Rm_command_FREE:\r
- case Rm_command_BLOCK_FREE:\r
- case Rm_command_FREE_NAMED:\r
- Rm_free(rmInst, transaction, receipt);\r
- break;\r
- case Rm_command_MAP_NAME:\r
- Rm_nsAddObject(rmInst, transaction, receipt);\r
- break;\r
- case Rm_command_UNMAP_NAME:\r
- Rm_nsDeleteObject(rmInst, transaction, receipt);\r
- break;\r
- case Rm_command_RESOURCE_STATUS:\r
- Rm_getResourceStatus(rmInst, transaction, receipt);\r
- break;\r
- case Rm_command_RESOURCE_RESPONSE:\r
- \r
- break;\r
- case Rm_command_POLICY_REQUEST:\r
- break;\r
- case Rm_command_POLICY_RESPONSE:\r
- break;\r
- }\r
-\r
- }\r
-\r
-}\r
-\r
-void Rm_serviceHandler (void *rmHandle, Rm_ServiceReqInfo *requestInfo,\r
- Rm_ServiceRespInfo *responseInfo)\r
-{\r
- Rm_Inst *rmInst = (Rm_Inst *) rmHandle;\r
- Rm_Transaction transaction;\r
- Rm_TransactionReceipt receipt;\r
- void *key;\r
-\r
- /* Prevent another component using the same instance from wiping out the current\r
- * service request */\r
- key = Rm_osalLocalCsEnter();\r
-\r
- /* Make sure serviceType is valid and that a callback function has been provided */\r
- if ((requestInfo->serviceType < Rm_service_FIRST) || \r
- (requestInfo->serviceType > Rm_service_LAST))\r
- {\r
- responseInfo->serviceResult = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
- Rm_osalLocalCsExit(key);\r
- return;\r
- }\r
- else if (requestInfo->serviceCallback == NULL)\r
- {\r
- /* RM Client's and Client Delegate's use blocking transports to consult with a \r
- * high-level RM agent prior to providing a response to the component. It is \r
- * assumed the component's cannot block. Therefore, all responses must go\r
- * through the callback function provided by the component. Return an error \r
- * if the component does not provide a callback function. */\r
- responseInfo->serviceResult = RM_SERVICE_ERROR_CALLBACK_NOT_PROVIDED;\r
- Rm_osalLocalCsExit(key);\r
- return;\r
- }\r
-\r
- /* Clear the transaction and receipt prior to using them */\r
- memset((void *) &transaction, 0, sizeof(Rm_Transaction));\r
- memset((void *) &transactionReceipt, 0, sizeof(Rm_TransactionReceipt));\r
-\r
- /* Transfer request information into the internal transaction format */\r
- transaction.command = (Rm_Command) requestInfo->serviceType;\r
- transaction.callback = requestInfo->serviceCallback;\r
- /* Policy modifications will never originate from components */\r
- strcpy ((void *) &(transaction.u.resourceInfo.resName)[0], (void *)requestInfo->resName);\r
- transaction.u.resourceInfo.resBase = requestInfo->resourceBase;\r
- transaction.u.resourceInfo.resNum = requestInfo->resourceNum;\r
- transaction.u.resourceInfo.resAlign = requestInfo->resourceAlign;\r
- strcpy ((void *) &(transaction.u.resourceInfo.resNsName)[0], (void *)requestInfo->resNsName);\r
-\r
- /* Pass the new transaction to the transaction processor */\r
- Rm_transactionProcessor (rmInst, &transaction, &receipt);\r
-\r
- /* Copy transaction receipt information into the response info fields for the \r
- * component based on the result of the transaction. Denied service requests\r
- * will have only a valid serviceResult field */\r
- responseInfo->serviceResult = receipt->transactionResult;\r
- if (responseInfo->serviceResult == RM_SERVICE_APPROVED)\r
- {\r
- /* Service was approved. The resource data should be passed back\r
- * to the component */\r
- responseInfo->resBase = receipt.resBase;\r
- responseInfo->resNum = receipt.resNum;\r
- }\r
- else if (responseInfo->serviceResult == RM_SERVICE_PROCESSING)\r
- {\r
- /* The service is still being processed. Provide the transaction ID\r
- * back to the component so that it can sort service responses received\r
- * via the provided callback function */\r
- responseInfo->requestId = receipt.transactionId;\r
- }\r
-\r
- Rm_osalLocalCsExit(key);\r
- \r
- return;\r
-}\r
-\r
-/* This function is executed when a RM instance receives a response to one of it's requests\r
- * and the information in the request must be provided to the original requesting component */\r
-void Rm_serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction, \r
- Rm_TransactionReceipt *receipt)\r
-{\r
- Rm_TransactionQueueEntry *transactionEntry;\r
- Rm_ServiceRespInfo responseInfo;\r
-\r
- /* Find the transaction request that matches the received response */\r
- transactionEntry = Rm_transactionQueueFind(rmInst,transaction->pktId);\r
-\r
- if (transactionEntry == NULL)\r
- {\r
- /* No transaction request matching the transaction ID was forwarded from\r
- * this RM instace */\r
- receipt->transactionResult = RM_SERVICE_ERROR_TRANSACTION_DOES_NOT_EXST_FOR_THIS_RM_INSTANCE;\r
- return;\r
- }\r
-\r
- /* Populate the service response with the transaction response details for\r
- * the component */\r
- responseInfo.requestId = transaction->pktId;\r
- responseInfo.serviceResult = transaction->details;\r
- responseInfo.resBase = transaction->u.resourceInfo.resBase;\r
- responseInfo.resNum = transaction->u.resourceInfo.resNum;\r
-\r
- /* Issue the callback to the requesting component with the response information */\r
- transactionEntry->transactionCallback(&responseInfo);\r
-\r
- /* Delete the transaction entry from the transaction queue */\r
- Rm_transactionQueueDelete(rmInst,transaction->pktId);\r
-\r
- return;\r
-}\r
-\r
-/**********************************************************************\r
- *********************** Application visible APIs ***************************\r
- **********************************************************************/\r
-\r
-Rm_Handle Rm_init(Rm_InitCfg *initCfg)\r
-{\r
- Rm_Inst *rmInst;\r
-\r
- /* Instance creation checks. Add one to strlen calculation for null character */\r
- if ((strlen(initCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS)\r
- {\r
- /* Failure: Instance name is too big */\r
- return (NULL);\r
- }\r
- \r
- /* Get memory for RM instance from local memory */\r
- rmInst = Rm_osalMalloc (sizeof(Rm_Inst), false);\r
- /* Populate instance based on input parameters */\r
- strcpy (&rmInst->name[0], initCfg->instName);\r
- rmInst->instType = initCfg->instType;\r
- rmInst->instState = RM_state_IDLE;\r
- rmInst->registeredWithDelegateOrServer = false;\r
- rmInst->serviceCallback = NULL;\r
-\r
- /* Populate the instance transport callouts */\r
- rmInst->transport.rmAllocPkt = initCfg->rmAllocPktFuncPtr;\r
- rmInst->transport.rmFreePkt = initCfg->rmFreePktFuncPtr;\r
- rmInst->transport.rmSend = initCfg->rmSendFuncPtr;\r
- rmInst->transport.rmReceive = initCfg->rmReceiveFuncPtr;\r
- rmInst->transport.rmNumPktsReceived = initCfg->rmNumPktsReceivedFuncPtr;\r
-\r
- /* Initialize the transport routing map linked list pointer to NULL. The linked list\r
- * nodes will be created when the application registers transports */\r
- rmInst->routeMap = NULL;\r
-\r
- /* Initialize the transaction queue linked list pointer to NULL. The linked list\r
- * nodes will be created when the transactions are forwarded to higher level RM\r
- * agents. */\r
- rmInst->transactionQueue= NULL;\r
-\r
- /* RM Server specific actions */\r
- if (rmInst->instType == Rm_instType_SERVER)\r
- {\r
- /* parse DTB, etc */\r
- }\r
-\r
- /* Instance startup policies are only used for Servers and Client Delegates */\r
- if (rmInst->instType != Rm_instType_CLIENT)\r
- {\r
- rmInst->instPolicy = initCfg->startupPolicy;\r
-\r
- /* Store policy via policy APIs ... */\r
- }\r
-\r
- /* Return the RM Handle */\r
- return ((Rm_Handle) rmInst);\r
-}\r
-\r
-Rm_Result Rm_preMainAllocResource(Rm_PreMainAllocInfo *preMainAllocInfo)\r
-{\r
-\r
-}\r
-\r
-Rm_ServiceHandle Rm_getServiceHandle(Rm_Handle rmHandle)\r
-{\r
- Rm_Inst *rmInst = (Rm_Inst *) rmHandle;\r
- Rm_ServicesPort *newServicePort;\r
- \r
- /* Create a new service handle for the specified RM instance */\r
- \r
- /* Get memory for a new service port from local memory */\r
- newServicePort = Rm_osalMalloc (sizeof(Rm_ServicesPort), false);\r
-\r
- newServicePort->rmHandle = rmHandle;\r
- newServicePort->rmService = rmServiceHandler;\r
-\r
- return ((Rm_ServiceHandle) newServicePort);\r
-}\r
-\r
-Rm_TransportHandle Rm_registerTransport (Rm_Handle rmHandle, Rm_TransCfg *transCfg)\r
-{\r
- Rm_Inst *rmInst = (Rm_Inst *) rmHandle;\r
- Rm_TransRouteMapNode *existingRouteMap = (Rm_TransRouteMapNode *) rmInst->routeMap;\r
- Rm_TransRouteMapNode *newRouteMapNode;\r
-\r
- /* RM Servers cannot connect to other Servers */\r
- if ((rmInst->instType == Rm_instType_SERVER) &&\r
- (transCfg->rmRemoteInstType == Rm_instType_SERVER))\r
- {\r
- return (NULL); /* Error -return null */\r
- }\r
-\r
- /* Verify Clients and Client Delegates are not registering with more than one \r
- * Client Delegate or Server. Assuming a Client Delegate can register with another \r
- * Client Delegate that can "act" as a server */\r
- if (((rmInst->instType == Rm_instType_CLIENT) || \r
- (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) &&\r
- ((transCfg->rmRemoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
- (transCfg->rmRemoteInstType == Rm_instType_SERVER)) &&\r
- rmInst->registeredWithDelegateOrServer)\r
- {\r
- return (NULL); /* Error -return null */\r
- } \r
-\r
- /* Error checks passed - Create a new transport handle for the specified RM instance */\r
- \r
- /* Get memory for a new routing map node from local memory */\r
- newRouteMapNode = Rm_osalMalloc (sizeof(Rm_TransRouteMapNode), false);\r
-\r
- /* Populate the new node. The address of the node itself is stored since this address is returned\r
- * to the application as the Rm_TransportHandle */\r
- newRouteMapNode->transHandle = newRouteMapNode;\r
- newRouteMapNode->remoteInstType = transCfg->rmRemoteInstType;\r
- newRouteMapNode->nextNode = NULL; /* New node will always be NULL */\r
-\r
- /* Check if there are any entries in the routing map */\r
- if (existingRouteMap)\r
- {\r
- /* At least one entry in the routing map. Add the new routing map node to the end of the\r
- * routing map node list */\r
- while (existingRouteMap->nextNode != NULL)\r
- {\r
- /* Traverse the list until arriving at the last node */\r
- existingRouteMap = existingRouteMap->nextNode;\r
- }\r
-\r
- /* Add the new node to the end of the list */\r
- existingRouteMap->nextNode = newRouteMapNode;\r
- }\r
- else\r
- {\r
- /* A routing map does not currently exist. The new node is the first entry */\r
- rmInst->routeMap = newRouteMapNode;\r
- }\r
-\r
- /* Specify RM instance has registered with a higher level agent */\r
- if ((newRouteMapNode->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
- (newRouteMapNode->remoteInstType == Rm_instType_SERVER))\r
- {\r
- rmInst->registeredWithDelegateOrServer = true;\r
- }\r
-\r
- return ((Rm_TransportHandle) newRouteMapNode);\r
-}\r
-\r
-Rm_Result Rm_unregisterTransport (Rm_Handle rmHandle, Rm_TransportHandle transHandle)\r
-{\r
- Rm_Inst *rmInst = (Rm_Inst *) rmHandle;\r
- Rm_TransRouteMapNode *routeMapNode = (Rm_TransRouteMapNode *) rmInst->routeMap;\r
- Rm_TransRouteMapNode *prevNode = NULL;\r
-\r
- /* Make sure a routing map exists for the RM instance */\r
- if (routeMapNode == NULL)\r
- {\r
- return (-1); /* TEMP ERROR RETURN */\r
- }\r
-\r
- /* Find the transport handle within the specified RM instance's routing map. */\r
- while (1)\r
- {\r
- if (routeMapNode->transHandle == transHandle)\r
- {\r
- /* Match: break out of loop and delete the node */\r
- break; \r
- }\r
- else if (routeMapNode->nextNode == NULL)\r
- {\r
- return (-1); /* TEMP ERROR: transhandle does not exist for RM instance */\r
- }\r
-\r
- prevNode = routeMapNode;\r
- routeMapNode = routeMapNode->nextNode;\r
- }\r
- \r
- /* Delete the routing map node */\r
- if ((prevNode == NULL) && routeMapNode->nextNode)\r
- {\r
- /* Node to be deleted exists at start of route map. Map second node to be start of\r
- * node list as long as there are more than one routing map nodes */\r
- rmInst->routeMap = routeMapNode->nextNode;\r
- }\r
- else\r
- {\r
- /* Node to be deleted is in the middle or at end of the list. Adjust adjacent\r
- * nodes pointers. This covers the case where the node to be removed is at the\r
- * end of the list. */\r
- prevNode->nextNode = routeMapNode->nextNode;\r
- }\r
-\r
- /* Remove specification in RM instance that it has been connected to an upper level agent\r
- * if the node to be deleted has a remote instance type of Client Delegate or Server */\r
- if ((routeMapNode->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||\r
- (routeMapNode->remoteInstType == Rm_instType_SERVER))\r
- {\r
- rmInst->registeredWithDelegateOrServer = false;\r
- }\r
-\r
- /* Delete the node, free the memory associated with the node. */\r
- Rm_osalFree((void *) routeMapNode, sizeof(Rm_TransRouteMapNode), false);\r
-\r
- return (RM_OK);\r
-}\r
-\r
-\r
-Rm_TransVerifyResult Rm_verifyTransport (Rm_Handle rmHandle, uint32_t timeout, \r
- Rm_TransFailData *failData)\r
-{\r
-\r
-}\r
-\r
-/* Resource requests that come directly from application go through this API */\r
-void Rm_requestService (void *rmHandle, Rm_ServiceReqInfo *requestInfo,\r
- Rm_ServiceRespInfo *responseInfo)\r
-{\r
- Rm_serviceHandler(rmHandle, requestInfo, responseInfo);\r
-}\r
-\r
-/* Used by the application to pass RM packets received from a transport to RM.\r
- * CODE THE FUNCTION SUCH THAT IT CAN BE CALLED DIRECTLY BY APP OR BE PLUGGED\r
- * AS PART OF AN ISR HANDLER FOR THE TRANSACTION RECEIVE */\r
-Rm_Result Rm_receiveRmPkt(Rm_Handle rmHandle, Rm_TransportHandle transHandle, Rm_Packet *pkt)\r
-{\r\r\r
- Rm_Inst *rmInst = (Rm_Inst *)rmHandle;\r
- Rm_ProtocolPkt rmProtPkt = &(pkt->rmData)[0];\r
- Rm_Transaction transaction;\r
- Rm_TransactionReceipt receipt;\r
- void *key;\r
-\r
- /* Lock access to the RM instance's transaction queue */\r
- key = Rm_osalLocalCsEnter(); \r
-\r
- /* Initialize the transaction and receipt */\r
- memset((void *)&transaction, 0, sizeof(Rm_Transaction));\r
- memset((void *)&receipt, 0, sizeof(Rm_TransactionReceipt));\r
-\r
- /* Create a new transaction based on the packet details */\r
- transaction.pktId = rmProtPkt->rmPktId;\r
- transaction.command = (Rm_Command) rmProtPkt->rmCmd;\r
- transaction.details = rmProtPkt->rmDetails;\r
- transaction.receivedTransport = transHandle;\r
- if ((transaction->command == Rm_command_POLICY_REQUEST) ||\r
- (transaction->command == Rm_command_POLICY_RESPONSE)\r
- {\r
- /* Copy the policy data if the transaction is policy based */\r
- memcpy ((void *)transInfo->u.policyData, (void *)rmProtPkt->u.rmPolicyData,\r
- RM_MAX_POLICY_SIZE_BYTES);\r
- }\r
- else\r
- {\r
- /* Otherwise copy the resource data */\r
- memcpy((void *)transaction.u.resourceInfo,(void *)rmProtPkt->u.resInfo, \r
- sizeof(Rm_ResourceInfo));\r
- }\r
-\r
- /* Process the transaction */\r
- Rm_transactionProcessor(rmInst,&transaction,&receipt)\r
-\r
- /* IS RECEIPT DATA NEEDED FOR ANYTHING HERE??*/\r
-\r
- Rm_osalLocalCsExit(key);\r
- return (0); \r
-}\r
-\r
-/* Application can call this API so that RM handles reception of packets based on\r
- * the RM handle and transport handle provided */\r
-Rm_Result Rm_getRmPkt(Rm_Handle rmHandle, Rm_TransportHandle transHandle)\r
-{\r
- Rm_Inst *rmInst = (Rm_Inst *)rmHandle;\r
- Rm_TransRouteMapNode *transNode = rmInst->routeMap;\r
- Rm_Packet *rmPkt = NULL;\r
- Rm_Result retVal = 0;\r
- void *key;\r
-\r
- /* Lock access to the RM instance's transaction queue */\r
- key = Rm_osalLocalCsEnter(); \r
-\r
- /* Verify the transport handle is registered with the RM handle */\r
- while (transNode != NULL)\r
- {\r
- if (transNode->transHandle == transHandle)\r
- {\r
- /* Break out of loop if an entry in the route map has been found */\r
- break;\r
- }\r
- transNode = transNode->nextNode;\r
- }\r
-\r
- if (transNode == NULL)\r
- {\r
- Rm_osalLocalCsExit(key);\r
- return (-1) /* ERROR: THE TRANSPORT HANDLE IS NOT REGISTERED WITH THE RM HANDLE */\r
- }\r
-\r
- /* Check to see if any RM packets are available. Process any available packets. */\r
- while (rmInst->transport.rmNumPktsReceived(transHandle))\r
- {\r
- rmInst->transport.rmReceive(transHandle, rmPkt);\r
-\r
- if (rmPkt == NULL)\r
- {\r
- retVal = -1; /* ERROR - PACKET RECEIVED FROM TRANSPORT IS NULL */\r
- }\r
-\r
- /* Pass the packet to RM */\r
- retVal = Rm_receiveRmPkt(rmHandle, transHandle, rmPkt);\r
- /* Delete the packet */\r
- rmInst->transport.rmFreePkt(transHandle, rmPkt);\r
-\r
- if (retVal)\r
- {\r
- /* If retVal is not 0 (Okay) there was an error so break out of loop and return */\r
- break;\r
- }\r
- }\r
- \r
- Rm_osalLocalCsExit(key);\r
- return (retVal); \r
-}\r
-\r
-uint32_t Rm_getVersion (void)\r
-{\r
- return RM_VERSION_ID;\r
-}\r
-\r
-\r
-const char* Rm_getVersionStr (void)\r
-{\r
- return rmVersionStr;\r
-}\r
-\r
-/**\r
-@}\r
-*/\r
+/**
+ * @file rm.c
+ *
+ * @brief
+ * This is the Resource Manager source.
+ *
+ * \par
+ * ============================================================================
+ * @n (C) Copyright 2012-2015, Texas Instruments, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \par
+*/
+
+/* Standard includes */
+#include <stdint.h>
+
+/* RM external includes */
+#include <ti/drv/rm/rm.h>
+#include <ti/drv/rm/rmver.h>
+#include <ti/drv/rm/rm_services.h>
+#include <ti/drv/rm/rm_transport.h>
+
+/* RM internal includes */
+#include <ti/drv/rm/include/rm_internal.h>
+#include <ti/drv/rm/include/rm_loc.h>
+#include <ti/drv/rm/include/rm_allocatorloc.h>
+#include <ti/drv/rm/include/rm_transportloc.h>
+#include <ti/drv/rm/include/rm_nameserverloc.h>
+#include <ti/drv/rm/include/rm_servicesloc.h>
+
+/* RM LIBFDT includes */
+#include <ti/drv/rm/util/libfdt/libfdt.h>
+
+/* RM OSAL layer */
+#include <rm_osal.h>
+
+/**********************************************************************
+ ************************** Globals ***********************************
+ **********************************************************************/
+
+/* Global Variable which describes the RM Version Information */
+const char rmVersionStr[] = RM_VERSION_STR ":" __DATE__ ":" __TIME__;
+
+/**********************************************************************
+ ************************ Local Functions *****************************
+ **********************************************************************/
+
+/* FUNCTION PURPOSE: Initializes a RM inst's transaction sequence number
+ ***********************************************************************
+ * DESCRIPTION: The RM instance transaction sequence number can never
+ * have a value of 0 to avoid conflicts with transactions
+ * that have a remoteOriginatingId of 0 (transaction ID
+ * will be used as the remoteOriginatingId for
+ * transactions that are responses to requests).
+ */
+static uint32_t transactionInitSequenceNum(void)
+{
+ return (1);
+}
+
+/* FUNCTION PURPOSE: Provides a sequence number for new transactions
+ ***********************************************************************
+ * DESCRIPTION: Returns a sequence number for a new transaction
+ * specific to a RM instance. Handles rollover of
+ * sequence number.
+ */
+static uint32_t transactionGetSequenceNum(Rm_Inst *rmInst)
+{
+ rmInst->transactionSeqNum++;
+ if (!rmInst->transactionSeqNum) {
+ rmInst->transactionSeqNum++;
+ }
+ return(rmInst->transactionSeqNum);
+}
+
+/* FUNCTION PURPOSE: Creates a resource request packet
+ ***********************************************************************
+ * DESCRIPTION: Returns a RM packet handle that points to a RM
+ * resource request packet that has been prepared
+ * for sending to another RM instance. The packet
+ * is allocated via the rmAllocPkt API using the
+ * appTransport handle provided by the application
+ */
+static Rm_Packet *createResourceReqPkt(Rm_ResourceReqPktType resReqType,
+ Rm_Transport *dstTrans,
+ const char *locInstName,
+ Rm_Transaction *transaction,
+ Rm_PacketHandle *pktHandle)
+{
+ Rm_Packet *rmPkt = NULL;
+ Rm_ResourceRequestPkt *resourceReqPkt = NULL;
+
+ rmPkt = dstTrans->callouts.rmAllocPkt(dstTrans->appTransportHandle,
+ sizeof(Rm_Packet), pktHandle);
+ if ((rmPkt == NULL) || (pktHandle == NULL)) {
+ transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
+ goto errorExit;
+ }
+
+ rmPkt->pktType = Rm_pktType_RESOURCE_REQUEST;
+ resourceReqPkt = (Rm_ResourceRequestPkt *) rmPkt->data;
+ resourceReqPkt->requestId = transaction->localId;
+ resourceReqPkt->resourceReqType = resReqType;
+ rm_strncpy(resourceReqPkt->pktSrcInstName, locInstName,
+ RM_NAME_MAX_CHARS);
+ rm_strncpy(resourceReqPkt->serviceSrcInstName,
+ transaction->serviceSrcInstName, RM_NAME_MAX_CHARS);
+ memcpy((void *)&(resourceReqPkt->resourceInfo),
+ (void *)&(transaction->resourceInfo),
+ sizeof(Rm_ResourceInfo));
+
+errorExit:
+ return(rmPkt);
+}
+
+/* FUNCTION PURPOSE: Creates a resource response packet
+ ***********************************************************************
+ * DESCRIPTION: Returns a RM packet handle that points to a RM
+ * resource response packet that has been prepared
+ * for sending to another RM instance. The packet
+ * is allocated via the rmAllocPkt API using the
+ * appTransport handle provided by the application
+ */
+static void createResourceResponsePkt(Rm_Packet *rmPkt,
+ Rm_Transaction *transaction)
+{
+ Rm_ResourceResponsePkt *resourceRespPkt = NULL;
+
+ rmPkt->pktType = Rm_pktType_RESOURCE_RESPONSE;
+ resourceRespPkt = (Rm_ResourceResponsePkt *)rmPkt->data;
+ resourceRespPkt->responseId = transaction->remoteOriginatingId;
+ resourceRespPkt->requestState = transaction->state;
+ memcpy((void *)&(resourceRespPkt->resourceInfo),
+ (void *)&(transaction->resourceInfo),
+ sizeof(Rm_ResourceInfo));
+}
+
+/* FUNCTION PURPOSE: Creates a NameServer request packet
+ ***********************************************************************
+ * DESCRIPTION: Returns a RM packet handle that points to a RM
+ * NameServer request packet that has been prepared
+ * for sending to another RM instance. The packet
+ * is allocated via the rmAllocPkt API using the
+ * appTransport handle provided by the application
+ */
+static Rm_Packet *createNsRequestPkt(Rm_NsReqPktType nsReqType,
+ Rm_Transport *dstTrans,
+ const char *locInstName,
+ Rm_Transaction *transaction,
+ Rm_PacketHandle *pktHandle)
+{
+ Rm_Packet *rmPkt = NULL;
+ Rm_NsRequestPkt *nsReqPkt = NULL;
+
+
+ rmPkt = dstTrans->callouts.rmAllocPkt(dstTrans->appTransportHandle,
+ sizeof(Rm_Packet), pktHandle);
+ if ((rmPkt == NULL) || (pktHandle == NULL)) {
+ transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
+ goto errorExit;
+ }
+
+ rmPkt->pktType = Rm_pktType_NAMESERVER_REQUEST;
+ nsReqPkt = (Rm_NsRequestPkt *)rmPkt->data;
+ nsReqPkt->requestId = transaction->localId;
+ nsReqPkt->nsRequestType = nsReqType;
+ rm_strncpy(nsReqPkt->pktSrcInstName, locInstName, RM_NAME_MAX_CHARS);
+ rm_strncpy(nsReqPkt->serviceSrcInstName, transaction->serviceSrcInstName,
+ RM_NAME_MAX_CHARS);
+ memcpy((void *)&(nsReqPkt->resourceInfo),
+ (void *)&(transaction->resourceInfo),
+ sizeof(Rm_ResourceInfo));
+
+errorExit:
+ return(rmPkt);
+}
+
+/* FUNCTION PURPOSE: Creates a NameServer response packet
+ ***********************************************************************
+ * DESCRIPTION: Returns a RM packet handle that points to a RM
+ * NameServer response packet that has been prepared
+ * for sending to another RM instance. The packet
+ * is allocated via the rmAllocPkt API using the
+ * appTransport handle provided by the application
+ */
+static void createNsResponsePkt(Rm_Packet *rmPkt, Rm_Transaction *transaction)
+{
+ Rm_NsResponsePkt *nsRespPkt = NULL;
+
+ rmPkt->pktType = Rm_pktType_NAMESERVER_RESPONSE;
+ nsRespPkt = (Rm_NsResponsePkt *)rmPkt->data;
+ nsRespPkt->responseId = transaction->remoteOriginatingId;
+ nsRespPkt->requestState = transaction->state;
+}
+
+/* FUNCTION PURPOSE: Creates a request packet
+ ***********************************************************************
+ * DESCRIPTION: Returns a RM packet handle that points to a request packet.
+ * The request packet type is based on the transaction type.
+ */
+static Rm_Packet *createRequestPkt(Rm_Transport *dstTrans,
+ const char *locInstName,
+ Rm_Transaction *transaction,
+ Rm_PacketHandle *pktHandle)
+{
+ Rm_Packet *rmPkt = NULL;
+
+ switch (transaction->type) {
+ case Rm_service_RESOURCE_ALLOCATE_INIT:
+ rmPkt = createResourceReqPkt(Rm_resReqPktType_ALLOCATE_INIT,
+ dstTrans, locInstName, transaction,
+ pktHandle);
+ break;
+ case Rm_service_RESOURCE_ALLOCATE_USE:
+ rmPkt = createResourceReqPkt(Rm_resReqPktType_ALLOCATE_USE,
+ dstTrans, locInstName, transaction,
+ pktHandle);
+ break;
+ case Rm_service_RESOURCE_STATUS:
+ rmPkt = createResourceReqPkt(Rm_resReqPktType_GET_STATUS,
+ dstTrans, locInstName, transaction,
+ pktHandle);
+ break;
+ case Rm_service_RESOURCE_FREE:
+ rmPkt = createResourceReqPkt(Rm_resReqPktType_FREE,
+ dstTrans, locInstName, transaction,
+ pktHandle);
+ break;
+ case Rm_service_RESOURCE_GET_BY_NAME:
+ rmPkt = createResourceReqPkt(Rm_resReqPktType_GET_NAMED,
+ dstTrans, locInstName, transaction,
+ pktHandle);
+ break;
+ case Rm_service_RESOURCE_MAP_TO_NAME:
+ rmPkt = createNsRequestPkt(Rm_nsReqPktType_MAP_RESOURCE,
+ dstTrans, locInstName, transaction,
+ pktHandle);
+ break;
+ case Rm_service_RESOURCE_UNMAP_NAME:
+ rmPkt = createNsRequestPkt(Rm_nsReqPktType_UNMAP_RESOURCE,
+ dstTrans, locInstName, transaction,
+ pktHandle);
+ break;
+ default:
+ transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
+ break;
+ }
+
+ return(rmPkt);
+}
+
+/* FUNCTION PURPOSE: Issues a service response to application
+ ***********************************************************************
+ * DESCRIPTION: Provides a service response back to the application
+ * using the service callback function provided to
+ * the RM instance at the time of the service request.
+ */
+static void serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
+{
+ Rm_ServiceRespInfo serviceResponse;
+
+ serviceResponse.rmHandle = (Rm_Handle)rmInst;
+ /* The responseTransaction will contain the resultant state details of
+ * the requestTransaction's service request */
+ serviceResponse.serviceState = transaction->state;
+ /* Pass back the ID that was provided to the component when it requested
+ * the service */
+ serviceResponse.serviceId = transaction->localId;
+ /* Owner and instance allocation count will only be set within RM under
+ * certain circumstances. */
+ serviceResponse.resourceNumOwners = transaction->resourceInfo.ownerCount;
+ serviceResponse.instAllocCount = transaction->resourceInfo.instAllocCount;
+
+ /* Service was approved and service was an allocate request. The resource
+ * data is passed back to the component */
+ if ((serviceResponse.serviceState == RM_SERVICE_APPROVED) &&
+ ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
+ (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
+ (transaction->type == Rm_service_RESOURCE_FREE) ||
+ (transaction->type == Rm_service_RESOURCE_STATUS) ||
+ (transaction->type == Rm_service_RESOURCE_GET_BY_NAME))) {
+ rm_strncpy(serviceResponse.resourceName, transaction->resourceInfo.name,
+ RM_NAME_MAX_CHARS);
+ serviceResponse.resourceBase = transaction->resourceInfo.base;
+ serviceResponse.resourceLength = transaction->resourceInfo.length;
+ }
+
+ if (transaction->u.callback.serviceCallback) {
+ /* Issue the callback to the requesting component with the response
+ * information */
+ transaction->u.callback.serviceCallback(&serviceResponse);
+ /* Delete the transaction from the transaction queue */
+ rmTransactionQueueDelete(rmInst, transaction->localId);
+ } else {
+ rmServiceInternalCallback((Rm_Handle)rmInst);
+ }
+
+ return;
+}
+
+/* FUNCTION PURPOSE: Sends RM response packets
+ ***********************************************************************
+ * DESCRIPTION: Sends RM response packets to RM instance's that sent
+ * RM request packets to the RM instance. The response
+ * is sent via the RM transport API which is plugged
+ * with an application created transport path.
+ */
+static void transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
+{
+ Rm_Transport *dstTransport = transaction->u.respTrans;
+ Rm_Packet *rmPkt = NULL;
+ Rm_PacketHandle pktHandle = NULL;
+
+ rmPkt = dstTransport->callouts.rmAllocPkt(dstTransport->appTransportHandle,
+ sizeof(Rm_Packet), &pktHandle);
+ if (!rmPkt || !pktHandle) {
+ transaction->state = RM_ERROR_TRANSPORT_ALLOC_PKT_ERROR;
+ goto errorExit;
+ }
+
+ switch (transaction->type) {
+ case Rm_service_RESOURCE_ALLOCATE_INIT:
+ case Rm_service_RESOURCE_ALLOCATE_USE:
+ case Rm_service_RESOURCE_STATUS:
+ case Rm_service_RESOURCE_FREE:
+ case Rm_service_RESOURCE_GET_BY_NAME:
+ createResourceResponsePkt(rmPkt, transaction);
+ break;
+ case Rm_service_RESOURCE_MAP_TO_NAME:
+ case Rm_service_RESOURCE_UNMAP_NAME:
+ createNsResponsePkt(rmPkt, transaction);
+ break;
+ default:
+ transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
+ goto errorExit;
+ }
+ if (dstTransport->callouts.rmSendPkt(dstTransport->appTransportHandle,
+ pktHandle) < RM_OK) {
+ transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
+ goto errorExit;
+ }
+
+ /* Response packet sent: Delete transaction from queue */
+ rmTransactionQueueDelete(rmInst, transaction->localId);
+
+errorExit:
+ /* Do not delete transaction on transport error. Transport error
+ * transactions should be visible from Rm_printInstanceStatus() */
+ return;
+}
+
+/* FUNCTION PURPOSE: Sends RM request packets
+ ***********************************************************************
+ * DESCRIPTION: Sends RM request packets to RM instance's that are
+ * capable of forwarding or validating service requests.
+ * The request is sent via the RM transport API which is
+ * plugged with an application created transport path.
+ */
+static void transactionForwarder(Rm_Inst *rmInst, Rm_Transaction *transaction)
+{
+ Rm_Transport *dstTrans;
+
+ if (rmInst->instType == Rm_instType_CLIENT) {
+ dstTrans = rmTransportFindRemoteInstType(rmInst->transports,
+ Rm_instType_CLIENT_DELEGATE);
+ if (dstTrans == NULL) {
+ dstTrans = rmTransportFindRemoteInstType(rmInst->transports,
+ Rm_instType_SERVER);
+ }
+ } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
+ dstTrans = rmTransportFindRemoteInstType(rmInst->transports,
+ Rm_instType_SERVER);
+ } else {
+ dstTrans = NULL;
+ }
+
+ /* Just queue transaction if transport hasn't been registered. Do not
+ * return error */
+ if (dstTrans) {
+ Rm_Packet *rmPkt = NULL;
+ Rm_PacketHandle pktHandle = NULL;
+
+ rmPkt = createRequestPkt(dstTrans, rmInst->instName, transaction,
+ &pktHandle);
+ if ((rmPkt == NULL) || (pktHandle == NULL)) {
+ /* Error returned via transaction->state */
+ goto errorExit;
+ }
+
+ if (dstTrans->callouts.rmSendPkt(dstTrans->appTransportHandle,
+ pktHandle) < RM_OK) {
+ transaction->state = RM_ERROR_TRANSPORT_SEND_ERROR;
+ goto errorExit;
+ }
+ transaction->hasBeenForwarded = RM_TRUE;
+ /* Transaction not deleted. Waiting for response from RM CD or
+ * Server */
+ } else {
+ transaction->state = RM_ERROR_TRANSPORT_HANDLE_DOES_NOT_EXIST;
+ }
+errorExit:
+ /* Do not delete transaction on transport error. Transport error
+ * transactions should be visible from Rm_printInstanceStatus() */
+ return;
+}
+
+/* FUNCTION PURPOSE: Handles static allocation requests
+ ***********************************************************************
+ * DESCRIPTION: Validates allocation requests received on CDs and
+ * Clients prior to the instance's registering
+ * with a Server. The allocation request is validated
+ * against a static policy.
+ */
+static void staticAllocationHandler(Rm_Handle rmHandle,
+ Rm_Transaction *transaction)
+{
+ Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
+ Rm_AllocatorNode *allocNode = NULL;
+ Rm_PolicyCheckCfg privCheckCfg;
+
+ if (rmInst->allocatorTree) {
+ allocNode = rmAllocatorFind(rmHandle, transaction->resourceInfo.name);
+
+ if (allocNode &&
+ ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
+ (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE))) {
+ /* Check request against static policy */
+ memset((void *)&privCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
+
+ if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
+ privCheckCfg.type = Rm_policyCheck_INIT;
+ } else {
+ privCheckCfg.type = Rm_policyCheck_USE;
+ }
+ privCheckCfg.negCheck = RM_FALSE;
+ privCheckCfg.validInstNode = rmPolicyGetValidInstNode(rmHandle,
+ rmInst->instName);
+ privCheckCfg.polTree = allocNode->policyRoot;
+ privCheckCfg.resourceBase = transaction->resourceInfo.base;
+ privCheckCfg.resourceLength = transaction->resourceInfo.length;
+
+ if (rmPolicyCheckPrivilege(&privCheckCfg)) {
+ transaction->state = RM_SERVICE_APPROVED_STATIC;
+ } else {
+ transaction->state = RM_SERVICE_DENIED_BY_STATIC_POLICY;
+ }
+ } else {
+ transaction->state = RM_SERVICE_DENIED_INVALID_STATIC_REQUEST;
+ }
+ } else {
+ transaction->state = RM_ERROR_REQ_FAILED_NO_STATIC_POLICY;
+ }
+}
+
+/* FUNCTION PURPOSE: Requests resources from Server for CD
+ ***********************************************************************
+ * DESCRIPTION: Function creates a service request to allocate resources
+ * from the Server for local management by the CD. The
+ * transaction which causes this request is put in the
+ * pending state in order to wait for the response from the
+ * Server
+ */
+static int32_t cdRequestServerResources(Rm_Inst *rmInst,
+ Rm_Transaction *transaction)
+{
+ Rm_AllocatorNode *allocNode = NULL;
+ Rm_Transaction *newTrans = NULL;
+ uint32_t allocSize = 0;
+ int32_t retVal;
+
+ allocNode = rmAllocatorFind((Rm_Handle)rmInst,
+ transaction->resourceInfo.name);
+
+ if (allocNode) {
+ if ((allocSize = rmPolicyGetCdAllocSize(allocNode->policyRoot))) {
+ if ((newTrans = rmTransactionQueueAdd(rmInst))) {
+ newTrans->type = transaction->type;
+ rm_strncpy(newTrans->serviceSrcInstName, rmInst->instName,
+ RM_NAME_MAX_CHARS);
+ newTrans->state = RM_SERVICE_PROCESSING;
+ rm_strncpy(newTrans->resourceInfo.name,
+ transaction->resourceInfo.name,
+ RM_NAME_MAX_CHARS);
+ newTrans->resourceInfo.base = RM_RESOURCE_BASE_UNSPECIFIED;
+ /* Make sure request length will satisfy transaction length */
+ newTrans->resourceInfo.length = allocSize;
+ while (newTrans->resourceInfo.length <
+ transaction->resourceInfo.length) {
+ newTrans->resourceInfo.length += allocSize;
+ }
+ newTrans->resourceInfo.alignment = transaction->resourceInfo.alignment;
+ newTrans->pendingTransactionId = transaction->localId;
+ transactionForwarder(rmInst, newTrans);
+
+ retVal = RM_SERVICE_PENDING_SERVER_RESPONSE;
+ } else {
+ retVal = RM_ERROR_TRANS_REQ_TO_SERVER_NOT_CREATED;
+ }
+ } else {
+ /* Forward request to Server for completion if policy has
+ * no allocation size for resource */
+ retVal = RM_SERVICE_PROCESSING;
+ }
+ } else {
+ /* Resource could not be found in policy */
+ retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
+ }
+ return(retVal);
+}
+
+/* FUNCTION PURPOSE: Frees local resources to Server from CD
+ ***********************************************************************
+ * DESCRIPTION: Function creates a service request to free locally
+ * managed resources that are now localized back to
+ * the Server.
+ */
+static int32_t cdFreeResourcesToServer(Rm_Inst *rmInst,
+ Rm_Transaction *transaction)
+{
+ int32_t baseToFree = transaction->resourceInfo.base;
+ uint32_t lenToFree = transaction->resourceInfo.length;
+ Rm_Transaction *newTrans = NULL;
+ /* This function should only be called after a free was approved */
+ int32_t retVal = RM_SERVICE_APPROVED;
+
+ /* Did free result in a localized free node that can be given back to
+ * Server? If so create transaction to Server to free localized
+ * resource node */
+ if (rmAllocatorGetNodeLocalization((Rm_Handle)rmInst,
+ transaction->resourceInfo.name,
+ &baseToFree, &lenToFree)) {
+ if ((newTrans = rmTransactionQueueAdd(rmInst))) {
+ newTrans->type = transaction->type;
+ rm_strncpy(newTrans->serviceSrcInstName, rmInst->instName,
+ RM_NAME_MAX_CHARS);
+ newTrans->state = RM_SERVICE_PROCESSING;
+ rm_strncpy(newTrans->resourceInfo.name,
+ transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
+ newTrans->resourceInfo.base = baseToFree;
+ newTrans->resourceInfo.length = lenToFree;
+ newTrans->pendingTransactionId = transaction->localId;
+ transactionForwarder(rmInst, newTrans);
+
+ retVal = RM_SERVICE_PENDING_SERVER_RESPONSE;
+ } else {
+ /* Error: Need to re-allocate what was freed */
+ retVal = RM_ERROR_TRANS_REQ_TO_SERVER_NOT_CREATED;
+ }
+ }
+ return(retVal);
+}
+
+/* FUNCTION PURPOSE: Arbitrates allocation service requests
+ ***********************************************************************
+ * DESCRIPTION: Issues a set of allocator operations in order to
+ * handle a received allocation request. Allocation
+ * requests are always forwarded to the Server on Client
+ * CD instances. If a request is made with a NameServer
+ * name the resource base and length parameters are
+ * retrieved from the NameServer prior to the allocation
+ * attempt.
+ */
+static void allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)
+{
+ Rm_AllocatorOpInfo opInfo;
+ Rm_NameServerObjCfg nameServerObjCfg;
+ int32_t retVal = transaction->state;
+
+ memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
+ opInfo.resourceInfo = &transaction->resourceInfo;
+ opInfo.serviceInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst,
+ transaction->serviceSrcInstName);
+ if (opInfo.serviceInstNode == NULL) {
+ retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
+ goto errorExit;
+ }
+
+ if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
+ if (transaction->resourceInfo.base != RM_RESOURCE_BASE_UNSPECIFIED) {
+ if (rmAllocatorFind((Rm_Handle)rmInst,
+ transaction->resourceInfo.name)) {
+ /* Attempt to allocate from local resources that were provided
+ * by Server */
+ if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
+ opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
+ } else if (transaction->type ==
+ Rm_service_RESOURCE_ALLOCATE_USE) {
+ opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
+ } else {
+ retVal = RM_ERROR_INVALID_SERVICE_TYPE;
+ goto errorExit;
+ }
+ retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
+
+ if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
+ /* Request resource range was not found within local
+ * resources provided by Server. Set back to PROCESSING so
+ * request is forwarded to Server */
+ retVal = RM_SERVICE_PROCESSING;
+ }
+ }
+ } else {
+ if (rmAllocatorFind((Rm_Handle)rmInst,
+ transaction->resourceInfo.name)) {
+ int32_t oldAlign = transaction->resourceInfo.alignment;
+
+ /* Attempt to allocate from local resources that were provided
+ * by Server */
+ if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
+ opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_INIT;
+ } else if (transaction->type ==
+ Rm_service_RESOURCE_ALLOCATE_USE) {
+ opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_USE;
+ } else {
+ retVal = RM_ERROR_INVALID_SERVICE_TYPE;
+ goto errorExit;
+ }
+ retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
+
+ if (retVal == RM_SERVICE_PROCESSING) {
+ if (transaction->type ==
+ Rm_service_RESOURCE_ALLOCATE_INIT) {
+ opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
+ } else if (transaction->type ==
+ Rm_service_RESOURCE_ALLOCATE_USE) {
+ opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
+ } else {
+ retVal = RM_ERROR_INVALID_SERVICE_TYPE;
+ goto errorExit;
+ }
+ retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
+
+ if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
+ /* Request resource range was not found within local
+ * resources provided by Server. Set back to
+ * PROCESSING so request is forwarded to Server */
+ retVal = RM_SERVICE_PROCESSING;
+ }
+ } else if (retVal == RM_SERVICE_DENIED_RES_ALLOC_REQS_NOT_MET) {
+ if (transaction->pendingTransactionId) {
+ /* Request to Server for resources to complete
+ * transaction locally performed once already. Forward
+ * transaction to Server for completion */
+ retVal = RM_SERVICE_PROCESSING;
+ } else {
+ /* Restore base and alignment since they were replaced
+ * in pre-allocate routine */
+ transaction->resourceInfo.base = RM_RESOURCE_BASE_UNSPECIFIED;
+ transaction->resourceInfo.alignment = oldAlign;
+
+ retVal = cdRequestServerResources(rmInst, transaction);
+ }
+ }
+ /* else: fall through to return */
+ } else {
+ retVal = cdRequestServerResources(rmInst, transaction);
+ }
+ }
+ } else if ((rmInst->instType == Rm_instType_SERVER)||
+ (rmInst->instType == Rm_instType_SHARED_SERVER)) {
+ /* Populated NameServer name has precedence over base */
+ if (strlen(transaction->resourceInfo.nameServerName) > 0) {
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ rmNameServerTreeInv(rmInst->u.server.nameServer);
+ }
+ memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
+ nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
+ nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
+ if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) ==
+ RM_SERVICE_PROCESSING) {
+ rm_strncpy(transaction->resourceInfo.name,
+ nameServerObjCfg.nodeCfg.resourceName,
+ RM_NAME_MAX_CHARS);
+ transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
+ transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
+ } else {
+ goto errorExit;
+ }
+ }
+
+ if (transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) {
+ if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
+ opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_INIT;
+ } else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
+ opInfo.operation = Rm_allocatorOp_PRE_ALLOCATE_USE;
+ } else {
+ retVal = RM_ERROR_INVALID_SERVICE_TYPE;
+ goto errorExit;
+ }
+ retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
+ }
+
+ if (retVal == RM_SERVICE_PROCESSING) {
+ if (transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
+ opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
+ } else if (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) {
+ opInfo.operation = Rm_allocatorOp_ALLOCATE_USE;
+ } else {
+ retVal = RM_ERROR_INVALID_SERVICE_TYPE;
+ goto errorExit;
+ }
+ retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
+ }
+ } else {
+ retVal = RM_ERROR_INVALID_INST_TYPE;
+ }
+errorExit:
+ transaction->state = retVal;
+}
+
+/* FUNCTION PURPOSE: Handles resource status service requests
+ ***********************************************************************
+ * DESCRIPTION: Issues a set of allocator operations to retrieve the
+ * current status (currently just owner reference count)
+ * for the resource specified in the transaction
+ */
+static void statusHandler(Rm_Inst *rmInst, Rm_Transaction *transaction)
+{
+ Rm_AllocatorOpInfo opInfo;
+ Rm_NameServerObjCfg nameServerObjCfg;
+ int32_t retVal = transaction->state;
+
+ memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
+ opInfo.operation = Rm_allocatorOp_GET_STATUS;
+ opInfo.resourceInfo = &transaction->resourceInfo;
+ opInfo.serviceInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst,
+ transaction->serviceSrcInstName);
+ if (opInfo.serviceInstNode == NULL) {
+ retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
+ goto errorExit;
+ }
+
+ if ((strlen(transaction->resourceInfo.nameServerName) == 0) &&
+ ((transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) ||
+ (transaction->resourceInfo.length == 0))) {
+ retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
+ goto errorExit;
+ }
+
+ if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
+ if (rmAllocatorFind((Rm_Handle)rmInst,
+ transaction->resourceInfo.name)) {
+ /* Attempt to get status from local resources that were provided by
+ * Server */
+ retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
+
+ if (retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) {
+ /* Request resource range was not found within local allocator
+ * resources provided by Server. Set back to PROCESSING so
+ * request is forwarded to Server */
+ retVal = RM_SERVICE_PROCESSING;
+ }
+ }
+ } else if ((rmInst->instType == Rm_instType_SERVER)||
+ (rmInst->instType == Rm_instType_SHARED_SERVER)) {
+ /* Populated NameServer name has precedence over base and length
+ * values */
+ if (strlen(transaction->resourceInfo.nameServerName) > 0) {
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ rmNameServerTreeInv(rmInst->u.server.nameServer);
+ }
+ memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
+ nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
+ nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
+ if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) ==
+ RM_SERVICE_PROCESSING) {
+ rm_strncpy(transaction->resourceInfo.name,
+ nameServerObjCfg.nodeCfg.resourceName,
+ RM_NAME_MAX_CHARS);
+ transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
+ transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
+ } else {
+ goto errorExit;
+ }
+ }
+ retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
+ } else {
+ retVal = RM_ERROR_INVALID_INST_TYPE;
+ }
+errorExit:
+ transaction->state = retVal;
+}
+
+/* FUNCTION PURPOSE: Arbitrates free service requests
+ ***********************************************************************
+ * DESCRIPTION: Issues a set of allocator operations in order to
+ * handle a received free request. Free
+ * requests are always forwarded to the Server on Client
+ * CD instances. If a request is made with a NameServer
+ * name the resource base and length parameters are
+ * retrieved from the NameServer prior to the free
+ * attempt.
+ */
+static void freeHandler(Rm_Inst *rmInst, Rm_Transaction *transaction)
+{
+ Rm_AllocatorOpInfo opInfo;
+ Rm_NameServerObjCfg nameServerObjCfg;
+ int32_t retVal = transaction->state;
+
+ memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
+ opInfo.operation = Rm_allocatorOp_FREE;
+ opInfo.resourceInfo = &transaction->resourceInfo;
+ opInfo.serviceInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst,
+ transaction->serviceSrcInstName);
+ if (opInfo.serviceInstNode == NULL) {
+ retVal = RM_SERVICE_DENIED_INST_NAME_NOT_VALID;
+ goto errorExit;
+ }
+
+ if ((strlen(transaction->resourceInfo.nameServerName) == 0) &&
+ ((transaction->resourceInfo.base == RM_RESOURCE_BASE_UNSPECIFIED) ||
+ (transaction->resourceInfo.length == 0))) {
+ retVal = RM_SERVICE_DENIED_RES_DOES_NOT_EXIST;
+ goto errorExit;
+ }
+
+ if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
+ /* Attempt to free from local resources that were provided by Server */
+ retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
+
+ if (retVal == RM_SERVICE_APPROVED) {
+ /* Check if free allows local resources to be freed back to
+ * Server */
+ retVal = cdFreeResourcesToServer(rmInst, transaction);
+ } else if ((retVal == RM_SERVICE_DENIED_RES_RANGE_DOES_NOT_EXIST) ||
+ (retVal == RM_SERVICE_DENIED_RES_DOES_NOT_EXIST)) {
+ /* Requested resource or its range were not found within local
+ * allocator resources provided by Server. Set back to PROCESSING
+ * so request is forwarded to Server */
+ retVal = RM_SERVICE_PROCESSING;
+ }
+ /* else: fall through to exit */
+ } else if ((rmInst->instType == Rm_instType_SERVER) ||
+ (rmInst->instType == Rm_instType_SHARED_SERVER)) {
+ /* Populated NameServer name has precedence over base */
+ if (strlen(transaction->resourceInfo.nameServerName) > 0) {
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ rmNameServerTreeInv(rmInst->u.server.nameServer);
+ }
+ memset((void *)&nameServerObjCfg, 0, sizeof(Rm_NameServerObjCfg));
+ nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
+ nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
+ if ((retVal = rmNameServerFindObject(&nameServerObjCfg)) ==
+ RM_SERVICE_PROCESSING) {
+ rm_strncpy(transaction->resourceInfo.name,
+ nameServerObjCfg.nodeCfg.resourceName,
+ RM_NAME_MAX_CHARS);
+ transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
+ transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
+ } else {
+ goto errorExit;
+ }
+ }
+ retVal = rmAllocatorOperation((Rm_Handle)rmInst, &opInfo);
+ } else {
+ retVal = RM_ERROR_INVALID_INST_TYPE;
+ }
+errorExit:
+ transaction->state = retVal;
+}
+
+/* FUNCTION PURPOSE: Client transaction handling process
+ ***********************************************************************
+ * DESCRIPTION: Client process for handling transactions created
+ * from services received via the service handle or the
+ * transport. The Client process:
+ * - Performs static allocations if no transport
+ * to CD or Server has been registered
+ * - Forwards all service requests to CD or Server
+ * once transport has been registered
+ */
+static void clientProcess(Rm_Inst *rmInst, Rm_Transaction *transaction)
+{
+ Rm_Transaction *transQ;
+
+ if (!rmInst->registeredWithDelegateOrServer) {
+ staticAllocationHandler((Rm_Handle)rmInst, transaction);
+ } else {
+ if (transaction->state == RM_SERVICE_PROCESSING) {
+ /* Forward all new transactions to CD or Server */
+ transactionForwarder(rmInst, transaction);
+ } else {
+ /* Transaction validated. Return result. */
+ serviceResponder(rmInst, transaction);
+ }
+
+ /* Forward any queued static requests that weren't forwarded */
+ transQ = rmInst->transactionQueue;
+ while(transQ) {
+ if ((transQ->state == RM_SERVICE_APPROVED_STATIC) &&
+ (!transQ->hasBeenForwarded)) {
+ transactionForwarder(rmInst, transQ);
+ }
+ transQ = transQ->nextTransaction;
+ }
+ }
+ /* Let call stack return transaction result app via Rm_serviceHandler */
+}
+
+/* FUNCTION PURPOSE: Client Delegate transaction handling process
+ ***********************************************************************
+ * DESCRIPTION: Client Delegate process for handling transactions created
+ * from services received via the service handle or the
+ * transport. The Client Delegate process:
+ * - Performs static allocations if no transport
+ * to Server has been registered
+ * - Forwards all NameServer related service requests
+ * to Server once transport has been registered
+ * - Attempts to complete resource service requests
+ * received from registered Clients
+ */
+static void cdProcess(Rm_Inst *rmInst, Rm_Transaction *transaction)
+{
+ Rm_Transaction *newTrans = NULL;
+ Rm_AllocatorNode *allocator = NULL;
+ Rm_Transaction *transQ;
+
+ if (!rmInst->registeredWithDelegateOrServer) {
+ if ((transaction->state == RM_SERVICE_PROCESSING) &&
+ (strncmp(transaction->serviceSrcInstName, rmInst->instName,
+ RM_NAME_MAX_CHARS) == 0)) {
+ /* Attempt static allocation of requests originating from CD inst */
+ staticAllocationHandler((Rm_Handle)rmInst, transaction);
+ }
+ /* Everything else left in transaction queue for forwarding once
+ * transport to Server is registered */
+ } else {
+ if (transaction->pendingTransactionId) {
+ Rm_Transaction *pendingTrans = rmTransactionQueueFind(rmInst,
+ transaction->pendingTransactionId);
+
+ /* Transaction is response from Server for transaction sent to get
+ * information in order to complete pending transaction */
+ if (transaction->state == RM_SERVICE_APPROVED) {
+ if (transaction->type == Rm_service_RESOURCE_GET_BY_NAME) {
+ /* Transfer resource data tied to name to pending
+ * transaction */
+ rm_strncpy(pendingTrans->resourceInfo.name,
+ transaction->resourceInfo.name,
+ RM_NAME_MAX_CHARS);
+ pendingTrans->resourceInfo.base = transaction->resourceInfo.base;
+ pendingTrans->resourceInfo.length = transaction->resourceInfo.length;
+ /* Delete NS name from pending transaction so Server isn't
+ * queried again */
+ memset(pendingTrans->resourceInfo.nameServerName, 0,
+ RM_NAME_MAX_CHARS);
+ /* Now that resource values have been retrieved clear
+ * pending transaction ID so CD doesn't think a resource
+ * request was sent to Server already for more local
+ * resources */
+ pendingTrans->pendingTransactionId = 0;
+
+ /* Return original transaction to processing state to
+ * attempt completion. */
+ pendingTrans->state = RM_SERVICE_PROCESSING;
+ } else if ((transaction->type ==
+ Rm_service_RESOURCE_ALLOCATE_INIT) ||
+ (transaction->type ==
+ Rm_service_RESOURCE_ALLOCATE_USE)) {
+ /* Add resources provided by Server to those managed by
+ * CD */
+ if ((allocator = rmAllocatorFind((Rm_Handle)rmInst,
+ transaction->resourceInfo.name))) {
+ rmAllocatorAddResNode((Rm_Handle)rmInst,
+ allocator,
+ transaction->resourceInfo.base,
+ transaction->resourceInfo.length);
+ }
+
+ /* Return original transaction to processing state to
+ * attempt completion */
+ pendingTrans->state = RM_SERVICE_PROCESSING;
+ } else if (transaction->type == Rm_service_RESOURCE_FREE) {
+ allocator = rmAllocatorFind((Rm_Handle)rmInst,
+ transaction->resourceInfo.name);
+
+ /* Local resource freed on Server. Remove node in
+ * local allocator's resource tree as well */
+ rmAllocatorDeleteResNode((Rm_Handle)rmInst,
+ allocator,
+ transaction->resourceInfo.base,
+ transaction->resourceInfo.length);
+
+ /* Allow original free to complete */
+ pendingTrans->state = RM_SERVICE_APPROVED;
+ } else {
+ pendingTrans->state = RM_ERROR_SERVER_RESP_INVALID_SERVICE_TYPE;
+ }
+ } else {
+ if (transaction->type == Rm_service_RESOURCE_FREE) {
+ /* Error occurred when trying to free local resource on
+ * Server. Reinsert local resources freed by original
+ * request */
+ Rm_AllocatorOpInfo opInfo;
+
+ memset((void *)&opInfo, 0, sizeof(Rm_AllocatorOpInfo));
+ opInfo.resourceInfo = &pendingTrans->resourceInfo;
+ opInfo.serviceInstNode = rmPolicyGetValidInstNode((Rm_Handle)rmInst,
+ pendingTrans->serviceSrcInstName);
+ /* Can't regain the original type of allocate. Default to
+ * init */
+ opInfo.operation = Rm_allocatorOp_ALLOCATE_INIT;
+ if (rmAllocatorOperation((Rm_Handle)rmInst, &opInfo) !=
+ RM_SERVICE_APPROVED) {
+ transaction->state = RM_ERROR_LOST_RESOURCES_ON_CD;
+ }
+ }
+ /* Transfer error or denial to pending transaction */
+ pendingTrans->state = transaction->state;
+ }
+ rmTransactionQueueDelete(rmInst, transaction->localId);
+ /* Switch to pending transaction */
+ transaction = pendingTrans;
+ }
+
+ if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
+ (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
+ (transaction->type == Rm_service_RESOURCE_STATUS) ||
+ (transaction->type == Rm_service_RESOURCE_FREE)) {
+ if ((transaction->state == RM_SERVICE_PROCESSING) &&
+ (strlen(transaction->resourceInfo.nameServerName) > 0)) {
+ /* Create and forward new transaction to Server to
+ * retrieve resource data mapped to name */
+ if ((newTrans = rmTransactionQueueAdd(rmInst))) {
+ newTrans->type = Rm_service_RESOURCE_GET_BY_NAME;
+ rm_strncpy(newTrans->serviceSrcInstName, rmInst->instName,
+ RM_NAME_MAX_CHARS);
+ newTrans->state = RM_SERVICE_PROCESSING;
+ rm_strncpy(newTrans->resourceInfo.nameServerName,
+ transaction->resourceInfo.nameServerName,
+ RM_NAME_MAX_CHARS);
+ newTrans->pendingTransactionId = transaction->localId;
+ transactionForwarder(rmInst, newTrans);
+
+ transaction->state = RM_SERVICE_PENDING_SERVER_RESPONSE;
+ } else {
+ transaction->state = RM_ERROR_TRANS_REQ_TO_SERVER_NOT_CREATED;
+ }
+ }
+ }
+
+ if (transaction->state == RM_SERVICE_PROCESSING) {
+ switch(transaction->type) {
+ case Rm_service_RESOURCE_ALLOCATE_INIT:
+ case Rm_service_RESOURCE_ALLOCATE_USE:
+ allocationHandler(rmInst, transaction);
+ break;
+ case Rm_service_RESOURCE_FREE:
+ freeHandler(rmInst, transaction);
+ break;
+ case Rm_service_RESOURCE_STATUS:
+ statusHandler(rmInst, transaction);
+ break;
+ case Rm_service_RESOURCE_MAP_TO_NAME:
+ case Rm_service_RESOURCE_GET_BY_NAME:
+ case Rm_service_RESOURCE_UNMAP_NAME:
+ /* Forward all NameServer-based transactions */
+ break;
+ default:
+ transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
+ break;
+ }
+ }
+
+ if (transaction->state == RM_SERVICE_PROCESSING) {
+ uint32_t transId = transaction->localId;
+
+ /* NameServer transaction or CD could not complete alloc/free
+ * transaction. Forward to Server */
+ transactionForwarder(rmInst, transaction);
+
+ /* Refresh transaction for reentrancy of cases where mix of Client
+ * CD and Server are running on the same core and connected via
+ * transport implemented over direct function calls instead of
+ * traditional transport that returns after sending the data */
+ transaction = rmTransactionQueueFind(rmInst, transId);
+ }
+
+ if (transaction) {
+ if ((transaction->state != RM_SERVICE_PROCESSING) &&
+ (transaction->state != RM_SERVICE_PENDING_SERVER_RESPONSE)) {
+ /* Transaction completed by CD or completed response received
+ * from Server. Return result */
+ if (strncmp(transaction->serviceSrcInstName, rmInst->instName,
+ RM_NAME_MAX_CHARS)) {
+ /* Transaction did not originate on this instance */
+ transactionResponder(rmInst, transaction);
+ } else {
+ /* Transaction originated on this instance */
+ serviceResponder(rmInst, transaction);
+ }
+ }
+ }
+
+ /* Attempt allocation of any queued static requests:
+ * RM_SERVICE_APPROVED_STATIC - Originated locally
+ * RM_SERVICE_PROCESSING - Received from any registered Clients */
+ transQ = rmInst->transactionQueue;
+ while(transQ) {
+ if (((transQ->state == RM_SERVICE_PROCESSING) ||
+ (transQ->state == RM_SERVICE_APPROVED_STATIC)) &&
+ (!transQ->hasBeenForwarded)) {
+ transactionForwarder(rmInst, transQ);
+ }
+ transQ = transQ->nextTransaction;
+ }
+ }
+}
+
+/* FUNCTION PURPOSE: Server transaction handling process
+ ***********************************************************************
+ * DESCRIPTION: Server process for handling transactions created
+ * from services received via the service handle or the
+ * transport. The Server process:
+ * - Validates all service requests received from
+ * the service handle and registered CDs and
+ * Clients
+ */
+static void serverProcess(Rm_Inst *rmInst, Rm_Transaction *transaction)
+{
+ Rm_NameServerObjCfg nameServerObjCfg;
+
+ switch (transaction->type) {
+ case Rm_service_RESOURCE_STATUS:
+ statusHandler(rmInst, transaction);
+ break;
+ case Rm_service_RESOURCE_ALLOCATE_INIT:
+ case Rm_service_RESOURCE_ALLOCATE_USE:
+ allocationHandler(rmInst, transaction);
+ break;
+ case Rm_service_RESOURCE_FREE:
+ freeHandler(rmInst, transaction);
+ break;
+ case Rm_service_RESOURCE_MAP_TO_NAME:
+ case Rm_service_RESOURCE_GET_BY_NAME:
+ case Rm_service_RESOURCE_UNMAP_NAME:
+ if (rmInst->u.server.nameServer) {
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ rmNameServerTreeInv(rmInst->u.server.nameServer);
+ }
+ memset((void *)&nameServerObjCfg, 0,
+ sizeof(Rm_NameServerObjCfg));
+ nameServerObjCfg.nameServerTree = rmInst->u.server.nameServer;
+ nameServerObjCfg.nodeCfg.objName = transaction->resourceInfo.nameServerName;
+ if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) {
+ nameServerObjCfg.nodeCfg.resourceName = transaction->resourceInfo.name;
+ nameServerObjCfg.nodeCfg.resourceBase= transaction->resourceInfo.base;
+ nameServerObjCfg.nodeCfg.resourceLength = transaction->resourceInfo.length;
+ transaction->state = rmNameServerAddObject(&nameServerObjCfg);
+ } else if (transaction->type ==
+ Rm_service_RESOURCE_GET_BY_NAME) {
+ if ((transaction->state = rmNameServerFindObject(&nameServerObjCfg)) ==
+ RM_SERVICE_PROCESSING) {
+ rm_strncpy(transaction->resourceInfo.name,
+ nameServerObjCfg.nodeCfg.resourceName,
+ RM_NAME_MAX_CHARS);
+ transaction->resourceInfo.base = nameServerObjCfg.nodeCfg.resourceBase;
+ transaction->resourceInfo.length = nameServerObjCfg.nodeCfg.resourceLength;
+ transaction->state = RM_SERVICE_APPROVED;
+ }
+ } else if (transaction->type ==
+ Rm_service_RESOURCE_UNMAP_NAME) {
+ transaction->state = rmNameServerDeleteObject(&nameServerObjCfg);
+ } else {
+ transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
+ }
+
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ rmNameServerTreeWb(rmInst->u.server.nameServer);
+ }
+ } else {
+ transaction->state = RM_ERROR_NAMESERVER_DOES_NOT_EXIST;
+ }
+ break;
+ default:
+ transaction->state = RM_ERROR_INVALID_SERVICE_TYPE;
+ break;
+ }
+
+ /* Source of shared server transaction will always be local. */
+ if (rmInst->instType != Rm_instType_SHARED_SERVER) {
+ if (strncmp(transaction->serviceSrcInstName, rmInst->instName,
+ RM_NAME_MAX_CHARS)) {
+ /* Source of transaction was not Server, return transaction via
+ * responder */
+ transactionResponder(rmInst, transaction);
+ }
+ }
+ /* Otherwise let call stack return transaction result app via
+ * Rm_serviceHandler */
+}
+
+/**********************************************************************
+ ********************** Internal Functions ****************************
+ **********************************************************************/
+
+/* FUNCTION PURPOSE: Adds a transaction
+ ***********************************************************************
+ * DESCRIPTION: Returns a pointer to a newly created transaction.
+ * The transaction is created based on a new service
+ * request received via the service API or the
+ * transport API (service forwarded from another instance)
+ */
+Rm_Transaction *rmTransactionQueueAdd(Rm_Inst *rmInst)
+{
+ Rm_Transaction *transactionQueue = rmInst->transactionQueue;
+ Rm_Transaction *newTransaction = NULL;
+
+ newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));
+ if (newTransaction) {
+ memset((void *)newTransaction, 0, sizeof(Rm_Transaction));
+
+ newTransaction->localId = transactionGetSequenceNum(rmInst);
+ newTransaction->nextTransaction = NULL;
+ if (transactionQueue) {
+ while (transactionQueue->nextTransaction) {
+ transactionQueue = transactionQueue->nextTransaction;
+ }
+ transactionQueue->nextTransaction = newTransaction;
+ } else {
+ rmInst->transactionQueue = newTransaction;
+ }
+ }
+ return(newTransaction);
+}
+
+/* FUNCTION PURPOSE: Finds a transaction
+ ***********************************************************************
+ * DESCRIPTION: Returns a pointer to a transaction resident
+ * in the transaction queue that matches the provided
+ * transaction ID.
+ */
+Rm_Transaction *rmTransactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)
+{
+ Rm_Transaction *transaction = rmInst->transactionQueue;
+
+ while (transaction) {
+ if (transaction->localId == transactionId) {
+ break;
+ }
+ transaction = transaction->nextTransaction;
+ }
+
+ return(transaction);
+}
+
+/* FUNCTION PURPOSE: Deletes a transaction
+ ***********************************************************************
+ * DESCRIPTION: Deletes the transaction with the provided transaction
+ * ID from the instance's transaction queue.
+ */
+int32_t rmTransactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
+{
+ Rm_Transaction *transaction = rmInst->transactionQueue;
+ Rm_Transaction *prevTransaction = NULL;
+ int32_t retVal = RM_OK;
+
+ while (transaction) {
+ if (transaction->localId == transactionId) {
+ break;
+ }
+
+ prevTransaction = transaction;
+ transaction = transaction->nextTransaction;
+ }
+
+ if (transaction) {
+ if (prevTransaction == NULL) {
+ /* Transaction at start of queue. Map second transaction to start
+ * of queue as long as more than one transactions. */
+ rmInst->transactionQueue = transaction->nextTransaction;
+ } else {
+ /* Transaction in middle or end of queue. */
+ prevTransaction->nextTransaction = transaction->nextTransaction;
+ }
+ Rm_osalFree((void *)transaction, sizeof(Rm_Transaction));
+ } else {
+ retVal = RM_ERROR_SERVICE_TRANS_DOES_NOT_EXIST;
+ }
+ return(retVal);
+}
+
+/* FUNCTION PURPOSE: Routes a transaction for processing
+ ***********************************************************************
+ * DESCRIPTION: Routes a received transaction to the appropriate
+ * instance processing routine
+ */
+void rmProcessRouter(Rm_Inst *rmInst, Rm_Transaction *transaction)
+{
+ if (rmInst->instType == Rm_instType_CLIENT) {
+ clientProcess(rmInst, transaction);
+ } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
+ cdProcess(rmInst, transaction);
+ } else if ((rmInst->instType == Rm_instType_SERVER) ||
+ (rmInst->instType == Rm_instType_SHARED_SERVER)) {
+ serverProcess(rmInst, transaction);
+ } else {
+ transaction->state = RM_ERROR_INVALID_INST_TYPE;
+ }
+}
+
+/**********************************************************************
+ ********************** Application visible APIs **********************
+ **********************************************************************/
+
+/* FUNCTION PURPOSE: Display status of managed resources
+ ***********************************************************************
+ * DESCRIPTION: Prints the status (allocate/free status, as well as
+ * owners) for all resources managed by the RM
+ * instance network. Also, prints the NameServer name
+ * entries. The number of resource range owners is
+ * returned as well. This function is only available on
+ * Server and CD instances.
+ */
+int32_t Rm_resourceStatus(Rm_Handle rmHandle, int printResources)
+{
+ Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
+ Rm_AllocatorTree *allocTree = NULL;
+ Rm_AllocatorNode *allocator;
+ Rm_Owner *owners;
+ Rm_ResourceTree *treeRoot;
+ Rm_ResourceNode *treeNode;
+ int32_t totalResOwners = 0;
+ void *key;
+ void *mtKey;
+
+ RM_SS_INST_INV_ENTER_CS(rmInst, key);
+ RM_SC_INST_INV_ENTER_CS(rmInst, key);
+ if (rmInst->mtSemObj) {
+ mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);
+ }
+
+ if (rmInst->instType != Rm_instType_CLIENT) {
+ Rm_osalLog("Instance name: %s\n", rmInst->instName);
+ Rm_osalLog("Handle: 0x%08x\n", rmHandle);
+ if (rmInst->instType == Rm_instType_SERVER) {
+ Rm_osalLog("Type: Server\n");
+ } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
+ Rm_osalLog("Type: Client Delegate\n");
+ } else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ Rm_osalLog("Type: Shared Server\n");
+ } else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
+ Rm_osalLog("Type: Shared Client\n");
+ } else {
+ Rm_osalLog("Type: UNKNOWN\n");
+ goto errorExit;
+ }
+
+ Rm_osalLog("\nResource Status:\n\n");
+ }
+
+ if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
+ /* Transfer control to shared server instance */
+ rmInst = rmInst->u.sharedClient.sharedServerHandle;
+ }
+
+ if ((rmInst->instType == Rm_instType_SERVER) ||
+ (rmInst->instType == Rm_instType_SHARED_SERVER) ||
+ (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) {
+
+ allocTree = rmInst->allocatorTree;
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ rmAllocatorTreeInv(allocTree);
+ }
+
+ RB_FOREACH(allocator, _Rm_AllocatorTree, allocTree) {
+ RM_SS_OBJ_INV(rmInst, allocator, Rm_AllocatorNode);
+ if (printResources) {
+ Rm_osalLog("Resource: %s\n", allocator->resourceName);
+ }
+
+ treeRoot = allocator->resourceRoot;
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ rmResourceTreeInv(treeRoot);
+ }
+ RB_FOREACH(treeNode, _Rm_AllocatorResourceTree, treeRoot) {
+ if (printResources) {
+ if ((treeNode->base >= 65536) ||
+ ((treeNode->base + treeNode->length - 1) >= 65536)) {
+ /* Print in hex if number is very large */
+ Rm_osalLog(" 0x%08x - 0x%08x ",
+ treeNode->base,
+ treeNode->base + treeNode->length - 1);
+ } else {
+ Rm_osalLog(" %10d - %10d ",
+ treeNode->base,
+ treeNode->base + treeNode->length - 1);
+ }
+ }
+
+ if (treeNode->allocationCount == 0) {
+ if (printResources) {
+ Rm_osalLog("FREE\n");
+ }
+ } else {
+ owners = treeNode->ownerList;
+ while (owners) {
+ RM_SS_OBJ_INV(rmInst, owners, Rm_Owner);
+ if (printResources) {
+ Rm_osalLog("%s (%d) ", owners->instNameNode->name,
+ owners->refCnt);
+ }
+ totalResOwners++;
+ owners = owners->nextOwner;
+ }
+ if (printResources) {
+ Rm_osalLog("\n");
+ }
+ }
+ }
+ }
+
+ if ((rmInst->instType == Rm_instType_SERVER) ||
+ (rmInst->instType == Rm_instType_SHARED_SERVER)) {
+ if (printResources) {
+ rmNameServerPrintObjects((Rm_Handle)rmInst);
+ }
+ }
+ } else {
+ totalResOwners = RM_ERROR_INVALID_RES_STATUS_INSTANCE;
+ }
+
+errorExit:
+ /* Free sem object using originating instance in case the Shared Client to Shared
+ * Server instance switch took place */
+ if (((Rm_Inst *)rmHandle)->mtSemObj) {
+ Rm_osalMtCsExit(((Rm_Inst *)rmHandle)->mtSemObj, mtKey);
+ }
+ RM_SS_INST_WB_EXIT_CS(rmInst, key);
+ return(totalResOwners);
+}
+
+/* FUNCTION PURPOSE: Display status of a RM instance
+ ***********************************************************************
+ * DESCRIPTION: Prints the current status of various RM instance
+ * properties such as the state of all transactions
+ * in the transaction queue and registered transports
+ */
+void Rm_instanceStatus(Rm_Handle rmHandle)
+{
+ Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
+ Rm_Transport *transportList = NULL;
+ Rm_Transaction *transactionQ = NULL;
+ void *key;
+ void *mtKey;
+
+ RM_SS_INST_INV_ENTER_CS(rmInst, key);
+ RM_SC_INST_INV_ENTER_CS(rmInst, key);
+ if (rmInst->mtSemObj) {
+ mtKey = Rm_osalMtCsEnter(rmInst->mtSemObj);
+ }
+
+ Rm_osalLog("Instance name: %s\n", rmInst->instName);
+ Rm_osalLog("Handle: 0x%08x\n", rmHandle);
+ if (rmInst->instType == Rm_instType_SERVER) {
+ Rm_osalLog("Type: Server\n");
+ } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
+ Rm_osalLog("Type: Client Delegate\n");
+ } else if (rmInst->instType == Rm_instType_CLIENT) {
+ Rm_osalLog("Type: Client\n");
+ } else if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ Rm_osalLog("Type: Shared Server\n");
+ } else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
+ Rm_osalLog("Type: Shared Client\n");
+
+ Rm_osalLog("\nShared Server Properties:\n");
+ /* Transfer to Shared Server instance to print out transport and
+ * transaction status */
+ rmInst = rmInst->u.sharedClient.sharedServerHandle;
+ Rm_osalLog("Instance name: %s\n", rmInst->instName);
+ Rm_osalLog("Handle: 0x%08x\n", rmHandle);
+ } else {
+ Rm_osalLog("Type: UNKNOWN\n");
+ goto errorExit;
+ }
+
+ transportList = rmInst->transports;
+ if (transportList) {
+ Rm_osalLog("\nRegistered Transports:\n");
+ while (transportList) {
+ RM_SS_OBJ_INV(rmInst, transportList, Rm_Transport);
+ if (transportList->remoteInstType == Rm_instType_SERVER) {
+ Rm_osalLog(" Remote instType: Server\n");
+ } else if (transportList->remoteInstType ==
+ Rm_instType_CLIENT_DELEGATE) {
+ Rm_osalLog(" Remote instType: Client Delegate\n");
+ } else {
+ Rm_osalLog(" Remote instType: Client\n");
+ }
+ Rm_osalLog(" appTransportHandle: 0x%08x\n",
+ transportList->appTransportHandle);
+ Rm_osalLog("\n");
+ transportList = transportList->nextTransport;
+ }
+ }
+
+ transactionQ = rmInst->transactionQueue;
+ if (transactionQ) {
+ Rm_osalLog("\nQueued Service Transactions:\n");
+ while (transactionQ) {
+ RM_SS_OBJ_INV(rmInst, transactionQ, Rm_Transaction);
+ Rm_osalLog(" Service type: %d\n",
+ transactionQ->type);
+ Rm_osalLog(" Service ID: %d\n", transactionQ->localId);
+ Rm_osalLog(" Service srcInstName %s\n",
+ transactionQ->serviceSrcInstName);
+ Rm_osalLog(" Service state: %d\n", transactionQ->state);
+ Rm_osalLog(" Resource name: %s\n",
+ transactionQ->resourceInfo.name);
+ Rm_osalLog(" Resource base: %d\n",
+ transactionQ->resourceInfo.base);
+ Rm_osalLog(" Resource length: %d\n",
+ transactionQ->resourceInfo.length);
+ Rm_osalLog(" Resource alignment: %d\n",
+ transactionQ->resourceInfo.alignment);
+ Rm_osalLog(" Resource NS name: %s\n",
+ transactionQ->resourceInfo.nameServerName);
+ Rm_osalLog("\n");
+ transactionQ = transactionQ->nextTransaction;
+ }
+ }
+
+errorExit:
+ /* Free sem object using originating instance in case the Shared Client
+ * to Shared Server instance switch took place */
+ if (((Rm_Inst *)rmHandle)->mtSemObj) {
+ Rm_osalMtCsExit(((Rm_Inst *)rmHandle)->mtSemObj, mtKey);
+ }
+ RM_SS_INST_WB_EXIT_CS(rmInst, key);
+}
+
+/* FUNCTION PURPOSE: RM instance creation and initialization
+ ***********************************************************************
+ * DESCRIPTION: Returns a new RM instance created and initialized
+ * using the parameters provided via the initCfg
+ * structure.
+ */
+Rm_Handle Rm_init(const Rm_InitCfg *initCfg, int32_t *result)
+{
+ Rm_Inst *rmInst = NULL;
+ void *grlDtb = NULL;
+ void *policyDtb = NULL;
+ void *linuxDtb = NULL;
+ int addLinux = RM_FALSE;
+ void *key;
+
+ *result = RM_OK;
+
+ if ((initCfg->instName == NULL) ||
+ ((strlen(initCfg->instName) + 1) > RM_NAME_MAX_CHARS)) {
+ *result = RM_ERROR_INVALID_INST_NAME;
+ goto errorExit;
+ }
+
+ if (initCfg->instType >= Rm_instType_LAST) {
+ *result = RM_ERROR_INVALID_INST_TYPE;
+ goto errorExit;
+ }
+
+ /* Create and initialize instance */
+ rmInst = Rm_osalMalloc(sizeof(*rmInst));
+ memset((void *)rmInst, 0, sizeof(*rmInst));
+ rmInst->isLocked = RM_FALSE;
+ rmInst->registeredWithDelegateOrServer = RM_FALSE;
+ rmInst->transactionSeqNum = transactionInitSequenceNum();
+
+ rmInst->instType = initCfg->instType;
+ rm_strncpy(rmInst->instName, initCfg->instName, RM_NAME_MAX_CHARS);
+ rmInst->mtSemObj = initCfg->mtSemObj;
+
+ if ((rmInst->instType == Rm_instType_SERVER) ||
+ (rmInst->instType == Rm_instType_SHARED_SERVER)) {
+ if (!initCfg->instCfg.serverCfg.globalResourceList ||
+ !initCfg->instCfg.serverCfg.globalPolicy) {
+ *result = RM_ERROR_INVALID_SERVER_CONFIGURATION;
+ goto errorExit;
+ }
+
+ if (initCfg->instCfg.serverCfg.linuxDtb) {
+ linuxDtb = initCfg->instCfg.serverCfg.linuxDtb;
+ addLinux = RM_TRUE;
+ }
+
+ /* Create valid instance list from policy. Must be done prior to
+ * parsing GRL so that Linux resources can be reserved correctly */
+ policyDtb = initCfg->instCfg.serverCfg.globalPolicy;
+ rmInst->validInstTree = rmPolicyVInstTreeInit(rmInst, policyDtb,
+ addLinux, result);
+ if (*result != RM_OK) {
+ goto errorExit;
+ }
+
+ rmNameServerInit((Rm_Handle)rmInst);
+ grlDtb = initCfg->instCfg.serverCfg.globalResourceList;
+ if ((*result = rmAllocatorTreeInit(rmInst, grlDtb,
+ policyDtb, linuxDtb)) != RM_OK) {
+ goto errorExit;
+ }
+ } else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE) {
+ if (!initCfg->instCfg.cdCfg.cdPolicy) {
+ *result = RM_ERROR_INVALID_CD_CONFIGURATION;
+ goto errorExit;
+ }
+
+ policyDtb = initCfg->instCfg.cdCfg.cdPolicy;
+ rmInst->validInstTree = rmPolicyVInstTreeInit(rmInst, policyDtb,
+ addLinux, result);
+ if (*result != RM_OK) {
+ goto errorExit;
+ }
+
+ if ((*result = rmAllocatorTreeInit(rmInst, NULL,
+ policyDtb, NULL)) != RM_OK) {
+ goto errorExit;
+ }
+
+ /* Remove once CD instance is stable - tracked by SDOCM00100797 */
+ *result = RM_WARNING_CD_INSTANCE_NOT_STABLE;
+
+ } else if (rmInst->instType == Rm_instType_CLIENT) {
+ if (initCfg->instCfg.clientCfg.staticPolicy) {
+ policyDtb = initCfg->instCfg.clientCfg.staticPolicy;
+ rmInst->validInstTree = rmPolicyVInstTreeInit(rmInst, policyDtb,
+ addLinux, result);
+ if (*result != RM_OK) {
+ goto errorExit;
+ }
+
+ if ((*result = rmAllocatorTreeInit(rmInst, NULL,
+ policyDtb, NULL)) != RM_OK) {
+ goto errorExit;
+ }
+ }
+
+ } else if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
+ Rm_Handle sHdl = initCfg->instCfg.sharedClientCfg.sharedServerHandle;
+ Rm_Inst *ssInst = NULL;
+
+ if (sHdl) {
+ rmInst->u.sharedClient.sharedServerHandle = sHdl;
+ /* Invalidate the Shared server instance structure on this core to
+ * get the latest instance data. */
+ key = Rm_osalCsEnter();
+ Rm_osalBeginMemAccess((void *)sHdl, sizeof(Rm_Inst));
+ ssInst = rmInst->u.sharedClient.sharedServerHandle;
+ if (ssInst->instType != Rm_instType_SHARED_SERVER) {
+ *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
+ Rm_osalCsExit(key);
+ goto errorExit;
+ } else {
+ /* Invalidate all the trees */
+ rmPolicyValidInstTreeInv(ssInst->validInstTree);
+ rmAllocatorTreeInv(ssInst->allocatorTree);
+ rmNameServerTreeInv(ssInst->u.server.nameServer);
+ }
+ Rm_osalCsExit(key);
+ } else {
+ *result = RM_ERROR_INVALID_SHARED_SERVER_HANDLE;
+ goto errorExit;
+ }
+ } else {
+ *result = RM_ERROR_INVALID_INST_TYPE;
+ goto errorExit;
+ }
+
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ /* Writeback instance and trees for other cores */
+ rmPolicyValidInstTreeWb(rmInst->validInstTree);
+ rmAllocatorTreeWb(rmInst->allocatorTree);
+ rmNameServerTreeWb(rmInst->u.server.nameServer);
+ Rm_osalEndMemAccess((void *)rmInst, sizeof(*rmInst));
+ } else if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
+ /* Create the instance's task blocking mechanism */
+ rmInst->blockHandle = Rm_osalTaskBlockCreate();
+ }
+ /* else: just return handle */
+
+ return((Rm_Handle)rmInst);
+
+errorExit:
+ if (rmInst) {
+ rmAllocatorTreeDelete((Rm_Handle)rmInst);
+ rmNameServerDelete((Rm_Handle)rmInst);
+ rmPolicyVInstTreeDelete((Rm_Handle)rmInst);
+ Rm_osalFree((void *)rmInst, sizeof(*rmInst));
+ }
+ return(NULL);
+}
+
+/* FUNCTION PURPOSE: Deletes an RM instance
+ ***********************************************************************
+ * DESCRIPTION: Frees all memory associated with an RM instance
+ * as long as all transports have been unregistered
+ * and the service handle has been closed
+ */
+int32_t Rm_delete(Rm_Handle rmHandle, int ignorePendingServices)
+{
+ Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
+ void *key;
+
+ key = Rm_osalCsEnter();
+ if (rmInst->instType == Rm_instType_SHARED_SERVER) {
+ Rm_osalBeginMemAccess((void *)rmInst, sizeof(*rmInst));
+ }
+
+ if (rmInst->serviceHandle) {
+ return(RM_ERROR_CANT_DELETE_WITH_OPEN_SERV_HNDL);
+ } else if (rmInst->transports) {
+ return(RM_ERROR_CANT_DELETE_WITH_REGD_TRANSPORT);
+ } else if (rmInst->transactionQueue && !ignorePendingServices) {
+ return(RM_ERROR_CANT_DELETE_PENDING_TRANSACTIONS);
+ }
+ /* else: delete instance since no more deletion failure cases */
+
+ if (rmInst->instType != Rm_instType_SHARED_CLIENT) {
+ rmNameServerDelete(rmHandle);
+ rmAllocatorTreeDelete(rmHandle);
+ rmPolicyVInstTreeDelete(rmHandle);
+
+ /* Delete any transactions */
+ while(rmInst->transactionQueue) {
+ rmTransactionQueueDelete(rmInst, rmInst->transactionQueue->localId);
+ }
+
+ if (rmInst->instType != Rm_instType_SHARED_SERVER) {
+ /* Delete the instance's task blocking mechanism */
+ Rm_osalTaskBlockDelete(rmInst->blockHandle);
+ } else {
+ rmInst->allocatorTree = NULL;
+ rmInst->validInstTree = NULL;
+ rmInst->u.server.nameServer = NULL;
+ Rm_osalEndMemAccess((void *)rmInst, sizeof(*rmInst));
+ }
+ }
+
+ Rm_osalFree((void *)rmInst, sizeof(*rmInst));
+ Rm_osalCsExit(key);
+ return(RM_OK);
+}
+
+/* FUNCTION PURPOSE: Returns RM version information
+ ***********************************************************************
+ */
+uint32_t Rm_getVersion(void)
+{
+ return(RM_VERSION_ID);
+}
+
+/* FUNCTION PURPOSE: Returns RM version string
+ ***********************************************************************
+ */
+const char* Rm_getVersionStr(void)
+{
+ return(rmVersionStr);
+}
+