summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 2f7c5a7)
raw | patch | inline | side by side (parent: 2f7c5a7)
author | Justin <jsobota@ti.com> | |
Mon, 5 Nov 2012 21:02:40 +0000 (16:02 -0500) | ||
committer | Justin <jsobota@ti.com> | |
Mon, 5 Nov 2012 21:02:40 +0000 (16:02 -0500) |
include/rm_pvt.h | patch | blob | history | |
rm_services.h | patch | blob | history | |
rm_transport.h | patch | blob | history | |
src/rm.c | patch | blob | history |
diff --git a/include/rm_pvt.h b/include/rm_pvt.h
index 190bf41ca1636a1d0667f7bf258a3e1a855c746f..996a5ef006a1da92b1a36eae3a82ecfb5ee94344 100644 (file)
--- a/include/rm_pvt.h
+++ b/include/rm_pvt.h
typedef struct {
/** The transaction ID for the transaction awaiting a response */
uint32_t transactionId;
+ /** The originating transaction ID. Maps a transaction created in
+ * response to a request received. */
+ uint32_t originatingTransactionId;
+ /** The transport handle that the transaction was received on. Used
+ * to provide a RM response to the right requesting RM instance */
+ Rm_TransportHandle transportHandle;
/** The callback function associated with the transaction ID. Will
* be called when a response is received matching the transaction ID. */
void *transactionCallback;
Rm_command_UNMAP_NAME = Rm_service_RESOURCE_UNMAP_NAME,
/** Get the status of the specified resource */
Rm_command_RESOURCE_STATUS = Rm_service_RESOURCE_STATUS,
+ /** Resource response - Response applies to all above resource commands */
+ Rm_command_RESOURCE_RESPONSE,
/** Policy request */
Rm_command_POLICY_REQUEST,
/** Policy response */
Rm_command_POLICY_RESPONSE
} Rm_Command;
-
-/* REMOVE BELOW??? */
/**
- * @brief RM transaction states. The transaction state describes what processes have
- * been executed on the transaction thus far
+ * @brief RM transaction details values. Details values provide more fine-grained
+ * information regarding a transaction request or response
*/
typedef enum {
- /** Transaction is being processed */
- Rm_transactionState_PROCESSING = 0,
+ /** No details provided for transaction */
+ Rm_transactionDetials_NONE = 0,
/** Transaction has been approved */
- Rm_transactionState_APPROVED = 1,
+ Rm_transactionDetails_RESOURCE_APPROVED = 1,
/** Transaction has been denied */
- Rm_transactionState_DENIED = 2
-} Rm_TransactionState;
+ Rm_transactionDetails_RESOURCE_DENIED = 2
+} Rm_TransactionDetails;
/**
* @brief RM protocol packet resource information
*/
typedef struct {
/** Transaction type */
- Rm_Command transCommand;
- /** Packet ID of packet that transaction originated from. This field will be
- * NULL if transaction originated from a component */
- uint32_t transPktId;
+ Rm_Command command;
+ /** ID of transaction. Maps to the RM protocol packet ID when forwarding
+ * RM requests or received RM responses. */
+ uint32_t pktId;
/** Transaction's associated callback function is the transaction originated
* from a registered component */
- void *transCallback;
+ void *callback;
+ /** Transaction details. Provides detailed request/response codes such as
+ * resource denial reasons */
+ uint32_t details;
+ /** Transport the transaction was received on. Stored in order to provide
+ * responses to received RM packets */
+ Rm_TransportHandle receivedTransport;
/** Transaction details */
union {
/** If the command has to do with resources these fields
* between RM instances.
*/
typedef struct {
- /** Packet ID - Used to synchronize sent command packets with any valid
+ /** Packet ID - Used to synchronize sent command packets with
* response commands. */
uint32_t rmPktId;
- /** Response Packet ID - If protocol packet is sent as response to a
- * received packet the response packet ID field will
- * contain the pktID value of the request packet
- * received */
- uint32_t rmRespPktId;
+ /** Command issued from source RM instance */
+ uint32_t rmCmd;
/** RM Instance Name - Name of RM instance that is issuing the command.
* The instance name will be used to validate the
* command against the instance name data stored in
* the RM policy data */
char rmInstName[RM_INST_NAME_MAX_CHARS];
- /** Command issued from source RM instance */
- uint32_t rmCmd;
- /** Response code provides requesting RM instance with information about
- * the result of any requests made */
- uint32_t rmRespCode;
+ /** Details field provides more information about RM request/response transactions
+ * such as whether a transaction has been approved or denied */
+ uint32_t rmDetails;
/** Union separating resource information from policy information */
union {
/** If the command has to do with one or more resources these fields
diff --git a/rm_services.h b/rm_services.h
index 501a77ee0c7c20d14227ab62d88a104836c1c335..5b62ad634f5c8d4936dc9e5a609fa94f2d3a9722 100644 (file)
--- a/rm_services.h
+++ b/rm_services.h
* the service has been approved. */
#define RM_SERVICE_APPROVED (RM_SERVICE_ACTION_BASE)
/** RM service was denied. The resource data in the response is not valid */
-#define RM_SERVICE_DENIED (RM_SERVICE_APPROVED+1)
+#define RM_SERVICE_DENIED (RM_SERVICE_ACTION_BASE+1)
/** RM service is being processed. Typically this means the service is
* being sent to a higher level RM agent for processing */
-#define RM_SERVICE_PROCESSING (RM_SERVICE_DENIED+2)
+#define RM_SERVICE_PROCESSING (RM_SERVICE_ACTION_BASE+2)
+/** RM response packet sent successfully */
+#define RM_RESPONSE_PACKET_SENT (RM_SERVICE_ACTION_BASE+3)
/** RM Service Request Error Code Base */
#define RM_SERVICE_ERROR_BASE (-64)
/** RM service request needs to be forwarded but the transport packet send API
* has not been provided */
#define RM_SERVICE_ERROR_TRANSPORT_PKT_SEND_API_NULL (RM_SERVICE_ERROR_BASE-8)
+/** RM service response from higher level agent did not match any requests made
+ * by the provided RM instance */
+#define RM_SERVICE_ERROR_TRANSACTION_DOES_NOT_EXST_FOR_THIS_RM_INSTANCE (RM_SERVICE_ERROR_BASE-9)
/**
* @brief RM service types
diff --git a/rm_transport.h b/rm_transport.h
index 32acc35be434c07f7d54a5bbbb61faa70398dd73..ba6553e1ee97f9ef7b70c294680a745dbe071722 100644 (file)
--- a/rm_transport.h
+++ b/rm_transport.h
* @retval
* Failure - NULL
*/
- Rm_Packet *(*rmAllocPkt)(Rm_TransHandle transHandle, uint32_t pktSize);
+ Rm_Packet *(*rmAllocPkt)(Rm_TransportHandle transHandle, uint32_t pktSize);
/**
* @b Description
* @retval
* Non-zero - Send failed.
*/
- Rm_TransportResult (*rmFreePkt)(Rm_TransHandle transHandle, Rm_Packet *pkt);
+ Rm_TransportResult (*rmFreePkt)(Rm_TransportHandle transHandle, Rm_Packet *pkt);
/**
* @b Description
* @retval
* Non-zero - Send failed.
*/
- Rm_TransportResult (*rmSend)(Rm_TransHandle transHandle, Rm_Packet *pkt);
+ Rm_TransportResult (*rmSend)(Rm_TransportHandle transHandle, Rm_Packet *pkt);
/**
* @b Description
* @retval
* Non-zero - Packet receive failed.
*/
- Rm_TransportResult (*rmReceive)(Rm_TransHandle transHandle, Rm_Packet *pkt);
+ Rm_TransportResult (*rmReceive)(Rm_TransportHandle transHandle, Rm_Packet *pkt);
/**
* @b Description
* @retval
* Failure - -1
*/
- int32_t (*rmNumPktsReceived)(Rm_TransHandle transHandle);
+ int32_t (*rmNumPktsReceived)(Rm_TransportHandle transHandle);
} Rm_TransportCallouts;
/**
diff --git a/src/rm.c b/src/rm.c
index f4f134dde2a101f74eeb23f621d7bf0c1ca11f53..a7137978888f48ca9ba98f8d79b82938557b6d3a 100644 (file)
--- a/src/rm.c
+++ b/src/rm.c
-/**
- * @file rm.c
- *
- * @brief
- * This is the Resource Manager source.
- *
- * \par
- * ============================================================================
- * @n (C) Copyright 2012, 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
-*/
-
-/* RM Types */
-#include <ti/drv/rm/rm_types.h>
-
-/* RM includes */
-#include <ti/drv/rm/rm.h>
-#include <ti/drv/rm/rm_services.h>
-#include <ti/drv/rm/rm_transport.h>
-#include <ti/drv/rm/rm_policy.h>
-#include <ti/drv/rm/include/rm_pvt.h>
-
-/* RM OSAL layer */
-#include <rm_osal.h>
-
-/**********************************************************************
- ************************** Globals ***********************************
- **********************************************************************/
-
-/* Place QMSS PDSP permissions array */
-#pragma DATA_SECTION (rmQmssPdspFirmwarePerms, ".rm");
-#pragma DATA_ALIGN (rmQmssPdspFirmwarePerms, 128)
-Rm_Perms rmQmssPdspFirmwarePerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_FIRMWARE_PDSPS, Rm_Perms)];
-
-
-/** @brief Global Variable which describes the RM Version Information */
-const char rmVersionStr[] = RM_VERSION_STR ":" __DATE__ ":" __TIME__;
-
-/**********************************************************************
- ********************** Internal Functions ****************************
- **********************************************************************/
-
-void Rm_transactionQueueAdd(void *rmHandle, uint32_t transactionId, void *callbackFunc)
-{
- Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
- Rm_TransactionQueueEntry *transactionQueue = (Rm_TransactionQueueEntry *) rmInst->transactionQueue;
- Rm_TransactionQueueEntry *newEntry;
- void *key;
-
- /* Lock access to the RM instance's transaction queue */
- key = Rm_osalLocalCsEnter();
-
- /* Get memory for a new transaction queue entry from local memory */
- newEntry = Rm_osalMalloc (sizeof(Rm_TransactionQueueNode), false);
-
- /* Populate the new entry. */
- newEntry->transactionId = transactionId;
- newEntry->transactionCallback = callbackFunc;
- newEntry->nextEntry = NULL; /* New entry's nextEntry pointer will always be NULL */
-
- /* Check if there are any entries in the transaction queue */
- if (transactionQueue)
- {
- /* At least one entry in the transaction queue. Add the new entry to the end of the
- * transaction queue */
- while (transactionQueue->nextEntry != NULL)
- {
- /* Traverse the list until arriving at the last entry */
- transactionQueue = transactionQueue->nextEntry;
- }
-
- /* Add the new entry to the end of the queue */
- transactionQueue->nextEntry = newEntry;
- }
- else
- {
- /* The transaction queue does not currently exist. The new entry is the first entry */
- rmInst->routeMap = newEntry;
- }
-
- Rm_osalLocalCsExit(key);
-}
-
-Rm_TransactionQueueEntry *Rm_transactionQueueFind(void *rmHandle, uint32_t transactionId)
-{
- Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
- Rm_TransactionQueueEntry *entry = (Rm_TransactionQueueEntry *) rmInst->transactionQueue;
- void *key;
-
- /* Lock access to the RM instance's transaction queue */
- key = Rm_osalLocalCsEnter();
-
- /* Make sure there is at least one entry in the transaction queue */
- if (entry != NULL)
- {
- /* Find the transaction ID within the specified RM instance's transaction queue.
- * If the end of the transaction queue is reached without finding the entry the
- * entry pointer will be NULL */
- while (entry != NULL)
- {
- if (entry->transactionId == transactionId)
- {
- /* Match: break out of loop and return the entry */
- break;
- }
- entry = entry->nextEntry;
- }
- }
-
- Rm_osalLocalCsExit(key);
- return (entry);
-}
-
-uint32_t Rm_transactionQueueDelete(void *rmHandle, uint32_t transactionId)
-{
- Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
- Rm_TransactionQueueEntry *currentEntry = (Rm_TransactionQueueEntry *) rmInst->transactionQueue;
- Rm_TransactionQueueEntry *prevEntry = NULL;
- void *key;
-
- /* Lock access to the RM instance's transaction queue */
- key = Rm_osalLocalCsEnter();
-
- /* Make sure there is at least one entry in the transaction queue */
- if (currentEntry == NULL)
- {
- Rm_osalLocalCsExit(key);
- return (-1); /* TEMP ERROR RETURN */
- }
-
- /* Find the transaction ID within the specified RM instance's transaction queue. */
- while (currentEntry != NULL)
- {
- if (currentEntry->transactionId == transactionId)
- {
- /* Match: break out of loop and delete the entry */
- break;
- }
-
- prevEntry = currentEntry;
- currentEntry = currentEntry->nextEntry;
- }
-
- /* Traversed entire queue but did not find transaction */
- if (currentEntry == NULL)
- {
- Rm_osalLocalCsExit(key);
- return (-2); /* TEMP ERROR RETURN */
- }
- else
- {
- /* Delete the transaction queue entry */
- if ((prevEntry == NULL) && currentEntry->nextEntry)
- {
- /* Entry to be deleted exists at start of transaction queue. Map second
- * entry to be start of transaction queue as long as there are more than
- * one entries */
- rmInst->transactionQueue = currentEntry->nextNode;
- }
- else
- {
- /* Entry to be deleted is in the middle or at end of the queue. Adjust adjacent
- * entry pointers. This covers the case where the entry to be removed is at the
- * end of the queue. */
- prevEntry->nextNode = currentEntry->nextNode;
- }
-
- /* Delete the node, free the memory associated with the node. */
- Rm_osalFree((void *) currentEntry, sizeof(Rm_TransactionQueueEntry), false);
- }
-
- Rm_osalLocalCsExit(key);
- return (0); /* RETURN OKAY - FIX MAGIC NUMBER */
-}
-
-/* Used in Client Delegate case where it forwarded requests from Client to Server
- * callback will direct to internal function that forwards response from server back
- * to client */
-void Rm_internalCallback (Rm_ServiceRespInfo *responseInfo)
-{
-
-}
-
-void Rm_transactionForwarder (void *rmHandle, Rm_Transaction *transInfo,
- Rm_TransactionReceipt *transReceipt)
-{
- Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
- Rm_TransRouteMapNode *routeMap = (Rm_TransRouteMapNode *) rmInst->routeMap;
- uint32_t transactionId;
- Rm_Packet *rmPkt = NULL;
- Rm_ProtocolPkt *rmProtPkt = NULL;
-
- /* Make sure at least one transport has been registered */
- if (routeMap == NULL)
- {
- transReceipt->transactionResult = RM_SERVICE_ERROR_NO_TRANSPORT_REGISTERED;
- return;
- }
-
- /* Make sure the RM instance has a transport registered with a higher level agent */
- if (!rmInst->registeredWithDelegateOrServer)
- {
- transReceipt->transactionResult = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER;
- return;
- }
-
- /* Parse the RM instance's routing map to find the higher level agent for forwarding */
- while ((routeMap->remoteInstType != Rm_instType_CLIENT_DELEGATE) ||
- (routeMap->remoteInstType != Rm_instType_SERVER))
- {
- /* Traverse the list until arriving at the upper level agent node */
- routeMap = routeMap->nextNode;
- }
-
- /* Create a RM packet using the service information */
- if (rmInst->transport.rmAllocPkt)
- {
- rmPkt = rmInst->transport.rmAllocPkt(routeMap->transHandle, sizeof(Rm_Packet));
- }
- else
- {
- /* The transport packet alloc API is not plugged */
- transReceipt->transactionResult = RM_SERVICE_ERROR_TRANSPORT_PKT_ALLOC_API_NULL;
- return;
- }
-
- /* Make sure a buffer for the packet was allocated */
- if (rmPkt == NULL)
- {
- transReceipt->transactionResult = RM_SERVICE_ERROR_TRANSPORT_NULL_PKT_BUF;
- return;
- }
-
- /* Make sure allocated buffer is large enough to fit the protocol packet plus the
- * rmPktLen field */
- if (rmPkt->rmPktLen < (sizeof(Rm_ProtocolPkt) + sizeof(uint32_t))
- {
- transReceipt->transactionResult = RM_SERVICE_ERROR_TRANSPORT_PKT_BUF_TOO_SMALL;
- return;
- }
-
- /* Create an ID for this transaction. The ID will be used for two purposes:
- * 1) Matching the response from the higher level RM agent to the request
- * 2) Provided to the service requesting component so that it can match the
- * service request with the response it receives via its callback function */
- transactionId = ...; /* NEED SCHEME FOR CREATING A MUTUALLY EXCLUSIVE PKT ID. CAN'T
- * CONFLICT WITH PCKT IDS CREATED ON OTHER RM INSTANCES */
- /* Initialize the rmPkt. Do not assume the transport code will do it */
- memset((void *)rmPkt, 0, sizeof(Rm_Packet));
-
- /* Assign the rmData field to be the rmProtPkt */
- rmProtPkt = &(rmPkt->rmData[0]);
- /* Populate the RM packet using the service information */
- rmProtPkt->rmPktId = transactionId;
- strcpy((void *)rmProtPkt->rmInstName,(void *)rmInst->name);
- rmProtPkt->rmCmd = (uint32_t) transInfo->transType;
- if ((transInfo->transCommand == Rm_command_POLICY_REQUEST) ||
- (transInfo->transCommand == Rm_command_POLICY_RESPONSE)
- {
- /* Copy the policy data if the transaction is policy based */
- memcpy ((void *)rmProtPkt->u.rmPolicyData, (void *)transInfo->u.policyData,
- RM_MAX_POLICY_SIZE_BYTES);
- }
- else
- {
- /* Otherwise copy the resource data */
- memcpy ((void *)&(rmProtPkt->u.resInfo), (void *) &(transInfo->u.resourceInfo),
- sizeof(Rm_ResourceInfo));
- }
-
- /* Create an entry in the transaction queue */
- Rm_transactionQueueAdd(rmHandle, transactionId, transInfo->transCallback);
-
- /* Send the RM packet to the application transport */
- if (rmInst->transport.rmSend)
- {
- if (!(rmInst->transport.rmSend(routeMap->transHandle, rmPkt))
- {
- /* Transport returned an error */
-
- /* SHOULD TRANSPORT ERROR SOMEHOW BE OR'D WITH THE SERVICE ERROR ??? */
- transReceipt->transactionResult = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;
- return;
- }
- }
- else
- {
- /* The transport packet send API is not plugged */
- transReceipt->transactionResult = RM_SERVICE_ERROR_TRANSPORT_PKT_SEND_API_NULL;
- return;
- }
-
- /* Inform requesting component that the service is being forwarded to a higher lever
- * RM agent for processing. The result of the service will be provided to the
- * component via the specified callback function */
- transReceipt->transactionResult = RM_SERVICE_PROCESSING;
- transReceipt->transactionId = transactionId;
- return;
-}
-
-void Rm_transactionProcessor (void *rmHandle, Rm_Transaction *transaction,
- Rm_TransactionReceipt *transactionReceipt)
-{
- Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
-
- /* All service requests on Clients are forwarded to the higher level RM agent
- * either a Client Delegate or Server, based on the RM system architecture */
- if (rmInst->instType == Rm_instType_CLIENT)
- {
- Rm_transactionForwarder(rmHandle, transaction, transactionReceipt);
-
- if (requestInfo->serviceCallback == NULL)
- {
- /* RM Client's always use a blocking RM transport to consult with a high-level
- * RM agent prior to providing a response to the component. It is assumed the
- * component's cannot block. Therefore, all responses must go through the
- * callback function provided by the component. Return an error if the
- * component does not provide a callback function */
- }
-
- /* Provide a transaction ID back to the component so that it can map service requests
- * to the responses received via the component's callback function */
- responseInfo->requestId = transactionReceipt.transactionId;
- }
- else
- {
-
-
- }
-
-}
-
-void Rm_serviceHandler (void *rmHandle, Rm_ServiceReqInfo *requestInfo,
- Rm_ServiceRespInfo *responseInfo)
-{
- Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
- Rm_Transaction transaction;
- Rm_TransactionReceipt transactionReceipt;
- void *key;
-
- /* Prevent another component using the same instance from wiping out the current
- * service request */
- key = Rm_osalLocalCsEnter();
-
- /* Make sure serviceType is valid and that a callback function has been provided */
- if ((requestInfo->serviceType < Rm_service_FIRST) ||
- (requestInfo->serviceType > Rm_service_LAST))
- {
- responseInfo->serviceResult = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;
- Rm_osalLocalCsExit(key);
- return;
- }
- else if (requestInfo->serviceCallback == NULL)
- {
- responseInfo->serviceResult = RM_SERVICE_ERROR_CALLBACK_NOT_PROVIDED;
- Rm_osalLocalCsExit(key);
- return;
- }
-
- /* Clear the transaction and receipt prior to using them */
- memset((void *) &transaction, 0, sizeof(Rm_Transaction));
- memset((void *) &transactionReceipt, 0, sizeof(Rm_TransactionReceipt));
-
- /* Transfer request information into the internal transaction format */
- transaction.transCommand = (Rm_Command) requestInfo->serviceType;
- transaction.transCallback = requestInfo->serviceCallback;
- /* Policy modifications will never originate from components */
- strcpy ((void *) &(transaction.u.resourceInfo.resName)[0], (void *)requestInfo->resName);
- transaction.u.resourceInfo.resBase = requestInfo->resourceBase;
- transaction.u.resourceInfo.resNum = requestInfo->resourceNum;
- transaction.u.resourceInfo.resAlign = requestInfo->resourceAlign;
- strcpy ((void *) &(transaction.u.resourceInfo.resNsName)[0], (void *)requestInfo->resNsName);
-
- /* Pass the new transaction to the transaction processor */
- Rm_transactionProcessor (rmHandle, &transaction, &transactionReceipt);
-
- /* Copy transaction receipt information into the response info fields for the
- * component based on the result of the transaction. Denied service requests
- * will have only a valid serviceResult field */
- responseInfo->serviceResult = transactionReceipt->transactionResult;
- if (responseInfo->serviceResult == RM_SERVICE_APPROVED)
- {
- /* Service was approved. The resource data should be passed back
- * to the component */
- responseInfo->resBase = transactionReceipt.resBase;
- responseInfo->resNum = transactionReceipt.resNum;
- }
- else if (responseInfo->serviceResult == RM_SERVICE_PROCESSING)
- {
- /* The service is still being processed. Provide the transaction ID
- * back to the component so that it can sort service responses received
- * via the provided callback function */
- responseInfo->requestId = transactionReceipt.transactionId;
- }
-
- Rm_osalLocalCsExit(key);
-
- return;
-}
-
-/**********************************************************************
- *********************** Application visible APIs ***************************
- **********************************************************************/
-
-Rm_Handle Rm_init(Rm_InitCfg *initCfg)
-{
- Rm_Inst *rmInst;
-
- /* Instance creation checks. Add one to strlen calculation for null character */
- if ((strlen(initCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS)
- {
- /* Failure: Instance name is too big */
- return (NULL);
- }
-
- /* Get memory for RM instance from local memory */
- rmInst = Rm_osalMalloc (sizeof(Rm_Inst), false);
- /* Populate instance based on input parameters */
- strcpy (&rmInst->name[0], initCfg->instName);
- rmInst->instType = initCfg->instType;
- rmInst->instState = RM_state_IDLE;
- rmInst->registeredWithDelegateOrServer = false;
- rmInst->serviceCallback = NULL;
-
- /* Populate the instance transport callouts */
- rmInst->transport.rmAllocPkt = initCfg->rmAllocPktFuncPtr;
- rmInst->transport.rmFreePkt = initCfg->rmFreePktFuncPtr;
- rmInst->transport.rmSend = initCfg->rmSendFuncPtr;
- rmInst->transport.rmReceive = initCfg->rmReceiveFuncPtr;
- rmInst->transport.rmNumPktsReceived = initCfg->rmNumPktsReceivedFuncPtr;
-
- /* Initialize the transport routing map linked list pointer to NULL. The linked list
- * nodes will be created when the application registers transports */
- rmInst->routeMap = NULL;
-
- /* Initialize the transaction queue linked list pointer to NULL. The linked list
- * nodes will be created when the transactions are forwarded to higher level RM
- * agents. */
- rmInst->transactionQueue= NULL;
-
- /* RM Server specific actions */
- if (rmInst->instType == Rm_instType_SERVER)
- {
- /* parse DTB, etc */
- }
-
- /* Instance startup policies are only used for Servers and Client Delegates */
- if (rmInst->instType != Rm_instType_CLIENT)
- {
- rmInst->instPolicy = initCfg->startupPolicy;
-
- /* Store policy via policy APIs ... */
- }
-
- /* Return the RM Handle */
- return ((Rm_Handle) rmInst);
-}
-
-Rm_Result Rm_preMainAllocResource(Rm_PreMainAllocInfo
- *preMainAllocInfo)
-{
-
-}
-
-Rm_ServiceHandle Rm_getServiceHandle(Rm_Handle rmHandle)
-{
- Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
- Rm_ServicesPort *newServicePort;
-
- /* Create a new service handle for the specified RM instance */
-
- /* Get memory for a new service port from local memory */
- newServicePort = Rm_osalMalloc (sizeof(Rm_ServicesPort), false);
-
- newServicePort->rmHandle = rmHandle;
- newServicePort->rmService = rmServiceHandler;
-
- return ((Rm_ServiceHandle) newServicePort);
-}
-
-/* Resource requests that come directly from application go through this API */
-void Rm_requestService (void *rmHandle, Rm_ServiceReqInfo *requestInfo,
- Rm_ServiceRespInfo *responseInfo)
-{
- Rm_serviceHandler(rmHandle, requestInfo, responseInfo);
-}
-
-Rm_TransportHandle Rm_registerTransport (Rm_Handle rmHandle, Rm_TransCfg *transCfg)
-{
- Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
- Rm_TransRouteMapNode *existingRouteMap = (Rm_TransRouteMapNode *) rmInst->routeMap;
- Rm_TransRouteMapNode *newRouteMapNode;
-
- /* RM Servers cannot connect to other Servers */
- if ((rmInst->instType == Rm_instType_SERVER) &&
- (transCfg->rmRemoteInstType == Rm_instType_SERVER))
- {
- return (NULL); /* Error -return null */
- }
-
- /* Verify Clients and Client Delegates are not registering with more than one
- * Client Delegate or Server. Assuming a Client Delegate can register with another
- * Client Delegate that can "act" as a server */
- if (((rmInst->instType == Rm_instType_CLIENT) ||
- (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) &&
- ((transCfg->rmRemoteInstType == Rm_instType_CLIENT_DELEGATE) ||
- (transCfg->rmRemoteInstType == Rm_instType_SERVER)) &&
- rmInst->registeredWithDelegateOrServer)
- {
- return (NULL); /* Error -return null */
- }
-
- /* Error checks passed - Create a new transport handle for the specified RM instance */
-
- /* Get memory for a new routing map node from local memory */
- newRouteMapNode = Rm_osalMalloc (sizeof(Rm_TransRouteMapNode), false);
-
- /* Populate the new node. The address of the node itself is stored since this address is returned
- * to the application as the Rm_TransportHandle */
- newRouteMapNode->transHandle = newRouteMapNode;
- newRouteMapNode->remoteInstType = transCfg->rmRemoteInstType;
- newRouteMapNode->nextNode = NULL; /* New node will always be NULL */
-
- /* Check if there are any entries in the routing map */
- if (existingRouteMap)
- {
- /* At least one entry in the routing map. Add the new routing map node to the end of the
- * routing map node list */
- while (existingRouteMap->nextNode != NULL)
- {
- /* Traverse the list until arriving at the last node */
- existingRouteMap = existingRouteMap->nextNode;
- }
-
- /* Add the new node to the end of the list */
- existingRouteMap->nextNode = newRouteMapNode;
- }
- else
- {
- /* A routing map does not currently exist. The new node is the first entry */
- rmInst->routeMap = newRouteMapNode;
- }
-
- /* Specify RM instance has registered with a higher level agent */
- if ((newRouteMapNode->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||
- (newRouteMapNode->remoteInstType == Rm_instType_SERVER))
- {
- rmInst->registeredWithDelegateOrServer = true;
- }
-
- return ((Rm_TransportHandle) newRouteMapNode);
-}
-
-Rm_Result Rm_unregisterTransport (Rm_Handle rmHandle, Rm_TransportHandle transHandle)
-{
- Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
- Rm_TransRouteMapNode *routeMapNode = (Rm_TransRouteMapNode *) rmInst->routeMap;
- Rm_TransRouteMapNode *prevNode = NULL;
-
- /* Make sure a routing map exists for the RM instance */
- if (routeMapNode == NULL)
- {
- return (-1); /* TEMP ERROR RETURN */
- }
-
- /* Find the transport handle within the specified RM instance's routing map. */
- while (1)
- {
- if (routeMapNode->transHandle == transHandle)
- {
- /* Match: break out of loop and delete the node */
- break;
- }
- else if (routeMapNode->nextNode == NULL)
- {
- return (-1); /* TEMP ERROR: transhandle does not exist for RM instance */
- }
-
- prevNode = routeMapNode;
- routeMapNode = routeMapNode->nextNode;
- }
-
- /* Delete the routing map node */
- if ((prevNode == NULL) && routeMapNode->nextNode)
- {
- /* Node to be deleted exists at start of route map. Map second node to be start of
- * node list as long as there are more than one routing map nodes */
- rmInst->routeMap = routeMapNode->nextNode;
- }
- else
- {
- /* Node to be deleted is in the middle or at end of the list. Adjust adjacent
- * nodes pointers. This covers the case where the node to be removed is at the
- * end of the list. */
- prevNode->nextNode = routeMapNode->nextNode;
- }
-
- /* Remove specification in RM instance that it has been connected to an upper level agent
- * if the node to be deleted has a remote instance type of Client Delegate or Server */
- if ((routeMapNode->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||
- (routeMapNode->remoteInstType == Rm_instType_SERVER))
- {
- rmInst->registeredWithDelegateOrServer = false;
- }
-
- /* Delete the node, free the memory associated with the node. */
- Rm_osalFree((void *) routeMapNode, sizeof(Rm_TransRouteMapNode), false);
-
- return (RM_OK);
-}
-
-
-Rm_TransVerifyResult Rm_verifyTransport (Rm_Handle, uint32_t timeout,
- Rm_TransFailData *failData)
-{
-
-}
-
-uint32_t Rm_getVersion (void)
-{
- return RM_VERSION_ID;
-}
-
-
-const char* Rm_getVersionStr (void)
-{
- return rmVersionStr;
-}
-
-/**
-@}
-*/
+/**\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