8f54b2ef90baf6e45a0182c10062bdd3418fb417
[keystone-rtos/rm-lld.git] / src / rm.c
1 /**
2  *   @file  rm.c
3  *
4  *   @brief   
5  *      This is the Resource Manager source.
6  *
7  *  \par
8  *  ============================================================================
9  *  @n   (C) Copyright 2012, Texas Instruments, Inc.
10  * 
11  *  Redistribution and use in source and binary forms, with or without 
12  *  modification, are permitted provided that the following conditions 
13  *  are met:
14  *
15  *    Redistributions of source code must retain the above copyright 
16  *    notice, this list of conditions and the following disclaimer.
17  *
18  *    Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the 
20  *    documentation and/or other materials provided with the   
21  *    distribution.
22  *
23  *    Neither the name of Texas Instruments Incorporated nor the names of
24  *    its contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
28  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
29  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
31  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
32  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
33  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
36  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
37  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38  *
39  *  \par
40 */
42 /* RM Types */
43 #include <ti/drv/rm/rm_types.h>
45 /* RM includes */
46 #include <ti/drv/rm/rm.h>
47 #include <ti/drv/rm/rm_services.h>
48 #include <ti/drv/rm/rm_transport.h>
49 #include <ti/drv/rm/rm_policy.h>
50 #include <ti/drv/rm/include/rm_pvt.h>
52 /* RM OSAL layer */
53 #include <rm_osal.h>
55 /**********************************************************************
56  ************************** Globals ***********************************
57  **********************************************************************/
59 /* Place QMSS PDSP permissions array */
60 #pragma DATA_SECTION (rmQmssPdspFirmwarePerms, ".rm");
61 #pragma DATA_ALIGN (rmQmssPdspFirmwarePerms, 128)
62 Rm_Perms rmQmssPdspFirmwarePerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_FIRMWARE_PDSPS, Rm_Perms)];
65 /** @brief Global Variable which describes the RM Version Information */
66 const char   rmVersionStr[] = RM_VERSION_STR ":" __DATE__  ":" __TIME__;
68 /**********************************************************************
69  ********************** Internal Functions *********************************
70  **********************************************************************/
72 Rm_TransactionResult rmTransactionForwarder (void *rmHandle, Rm_Transaction *transInfo,
73                                                          Rm_TransactionReceipt *transReceipt)
74 {
75     Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
76     Rm_TransRouteMapNode *routeMap = (Rm_TransRouteMapNode *) rmInst->routeMap;
77     Rm_ProtocolPkt *rmPkt = NULL;
79     /* Error if no transports have been registered and a service has been requested that
80      * must be forwarded to another RM agent */
81     if (routeMap == NULL)
82     {
83         return (-1); /* temp error */
84     }
85     
86     /* Make sure the RM instance has a transport registered with a higher level agent */
87     if (!rmInst->registeredWithDelegateOrServer)
88     {
89         return (-1); /* temp error - can't handle request because client delegate or server not registered */
90     }
92     /* Parse the RM instance's routing map to find the higher level agent for forwarding */
93     while ((routeMap->remoteInstType != Rm_instType_CLIENT_DELEGATE) || 
94               (routeMap->remoteInstType != Rm_instType_SERVER))
95     {
96         /* Traverse the list until arriving at the upper level agent node */
97         routeMap = routeMap->nextNode;
98     }
100     /* Create a RM packet using the service information */
101     if (rmInst->transport.rmAllocPkt)
102     {
103         rmPkt = rmInst->transport.rmAllocPkt (routeMap->transHandle, sizeof(Rm_ProtocolPkt));
104     }
106     /* Return error if the packet allocation API is not plugged or if a NULL packet pointer
107      * was returned */
108     if (!rmPkt)
109     {
110         return (-1); /* temp error */
111     }
113     /* Populate the RM packet using the service information */
117     /* Inform component that requested the service that the resource is being requested
118      * from the higher level RM agent.  The component must assume the resource service
119      * result will be returned using the specified callback function */
120     return (RM_REQUESTING_RESOURCE);
123 Rm_TransactionResult rmTransactionProcessor (rmHandle, Rm_Transaction *newTransaction, 
124                                                                Rm_TransactionReceipt *newTransactionReceipt)
129 Rm_ServiceResult rmServiceHandler (void *rmHandle, Rm_ServiceReqInfo *requestInfo,
130                                                                Rm_ServiceRespInfo *responseInfo)
132     Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
133     Rm_Transaction newTransaction;
134     Rm_TransactionReceipt newTransactionReceipt;
135     Rm_ServiceResult retVal = RM_service_OKAY;
136     void *key;
138     /* Prevent another component using the same instance from wiping out the current
139      * service request */
140     key = Rm_osalLocalCsEnter();
142     /* Transfer request information into the internal transaction format */
143     newTransaction.transType = (Rm_Command) requestInfo->serviceType;
144     /* Policy modifications will never originate from components */
145     strcpy ((void *) &(newTransaction.u.transInfo.resName)[0], (void *)requestInfo->resName);
146     newTransaction.u.transInfo.resBase = requestInfo->resourceAlign;
147     newTransaction.u.transInfo.resNum = requestInfo->resourceNum;
148     newTransaction.u.transInfo.resAlign = requestInfo->resourceAlign;
149     strcpy ((void *) &(newTransaction.u.transInfo.resNsName)[0], (void *)requestInfo->resNsName);
151     /* All service requests on Clients are forwarded to the higher level RM agent
152      * either a Client Delegate or Server, based on the RM system architecture */
153     if (rmInst->instType == Rm_instType_CLIENT)
154     {
155         retVal = (Rm_ServiceResult) rmTransactionForwarder (rmHandle, &newTransaction, &newTransactionReceipt);
157         /* Copy internal transaction receipt information into the response info fields for the 
158          * component */
159         responseInfo->requestId = newTransactionReceipt.transactionId;
160         responseInfo->resBase = newTransactionReceipt.resBase;
161         responseInfo->resNum = newTransactionReceipt.resNum;
162     }
163     else
164     {
165         /* Directly handle the request if on a Client Delegate or Server.  On Client Delegates, if
166          * the request cannot be serviced it will be forwarded to the higher level RM instance. */
167         retVal = (Rm_ServiceResult) rmTransactionProcessor (rmHandle, &newTransaction, &newTransactionReceipt);
169         /* Copy internal transaction receipt information into the response info fields for the 
170          * component */
171         responseInfo->requestId = newTransactionReceipt.transactionId;
172         responseInfo->resBase = newTransactionReceipt.resBase;
173         responseInfo->resNum = newTransactionReceipt.resNum;
174     }
176     Rm_osalLocalCsExit(key);
177     
178     return (retVal);
181 /**********************************************************************
182  *********************** Application visible APIs ***************************
183  **********************************************************************/
185 Rm_Handle Rm_init(Rm_InitCfg *initCfg)
187     Rm_Inst *rmInst;
189     /* Instance creation checks.  Add one to strlen calculation for null character */
190     if ((strlen(initCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS)
191     {
192         /* Failure: Instance name is too big */
193         return (NULL);
194     }
195     
196     /* Get memory for RM instance from local memory */
197     rmInst = Rm_osalMalloc (sizeof(Rm_Inst), false);
198     /* Populate instance based on input parameters */
199     strcpy (&rmInst->name[0], initCfg->instName);
200     rmInst->instType = initCfg->instType;
201     rmInst->instState = RM_state_IDLE;
202     rmInst->registeredWithDelegateOrServer = false;
203     rmInst->serviceCallback = NULL;
205     /* Populate the instance transport callouts */
206     rmInst->transport.rmAllocPkt = initCfg->rmAllocPktFuncPtr;
207     rmInst->transport.rmFreePkt = initCfg->rmFreePktFuncPtr;
208     rmInst->transport.rmSend = initCfg->rmSendFuncPtr;
209     rmInst->transport.rmReceive = initCfg->rmReceiveFuncPtr;
210     rmInst->transport.rmNumPktsReceived = initCfg->rmNumPktsReceivedFuncPtr;
212     /* Initialize the transport routing map linked list pointer to NULL.  The linked list
213       * nodes will be created when the application registers transports */
214     rmInst->routeMap = NULL;
216     /* RM Server specific actions */
217     if (rmInst->instType == Rm_instType_SERVER)
218     {
220     }
222     /* Instance startup policies are only used for Servers and Client Delegates */
223     if (rmInst->instType != Rm_instType_CLIENT)
224     {
225         rmInst->instPolicy = initCfg->startupPolicy;
227         /* Store policy via policy APIs ... */
228     }
230     /* Return the RM Handle */
231     return ((Rm_Handle) rmInst);
234 Rm_Result Rm_preMainAllocResource(Rm_PreMainAllocInfo 
235                                                    *preMainAllocInfo)
240 Rm_ServiceHandle Rm_getServiceHandle(Rm_Handle rmHandle)
242     Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
243     Rm_ServicesPort *newServicePort;
244     
245     /* Create a new service handle for the specified RM instance */
246     
247     /* Get memory for a new service port from local memory */
248     newServicePort = Rm_osalMalloc (sizeof(Rm_ServicesPort), false);
250     newServicePort->rmHandle = rmHandle;
251     newServicePort->rmService = rmServiceHandler;
253     return ((Rm_ServiceHandle) newServicePort);
256 Rm_TransportHandle Rm_registerTransport (Rm_Handle rmHandle, 
257                                      Rm_TransCfg *transCfg)
259     Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
260     Rm_TransRouteMapNode *existingRouteMap = (Rm_TransRouteMapNode *) rmInst->routeMap;
261     Rm_TransRouteMapNode *newRouteMapNode;
263     /* RM Servers cannot connect to other Servers */
264     if ((rmInst->instType == Rm_instType_SERVER) &&
265          (transCfg->rmRemoteInstType == Rm_instType_SERVER))
266     {
267         return (NULL); /* Error -return null */
268     }
270     /* Verify Clients and Client Delegates are not registering with more than one Client Delegate or Server.
271      * Assuming a Client Delegate can register with another Client Delegate that can "act" as a server */
272     if (((rmInst->instType == Rm_instType_CLIENT) || (rmInst->instType == Rm_instType_CLIENT_DELEGATE)) &&
273          ((transCfg->rmRemoteInstType == Rm_instType_CLIENT_DELEGATE) ||
274            (transCfg->rmRemoteInstType == Rm_instType_SERVER)) &&
275           rmInst->registeredWithDelegateOrServer)
276     {
277         return (NULL); /* Error -return null */
278     }         
280     /* Error checks passed - Create a new transport handle for the specified RM instance */
281     
282     /* Get memory for a new routing map node from local memory */
283     newRouteMapNode = Rm_osalMalloc (sizeof(Rm_TransRouteMapNode), false);
285     /* Populate the new node.  The address of the node itself is stored since this address is returned
286      *  to the application as the Rm_TransportHandle */
287     newRouteMapNode->transHandle = newRouteMapNode;
288     newRouteMapNode->remoteInstType = transCfg->rmRemoteInstType;
289     newRouteMapNode->nextNode = NULL;  /* New node will always be NULL */
291     /* Check if there are any entries in the routing map */
292     if (existingRouteMap)
293     {
294         /* At least one entry in the routing map.  Add the new routing map node to the end of the
295          * routing map node list */
296         while (existingRouteMap->nextNode != NULL)
297         {
298             /* Traverse the list until arriving at the last node */
299             existingRouteMap = existingRouteMap->nextNode;
300         }
302         /* Add the new node to the end of the list */
303         existingRouteMap->nextNode = newRouteMapNode;
304     }
305     else
306     {
307         /* A routing map does not currently exist.  The new node is the first entry */
308         rmInst->routeMap = newRouteMapNode;
309     }
311     /* Specify RM instance has registered with a higher level agent */
312     if ((newRouteMapNode->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||
313          (newRouteMapNode->remoteInstType == Rm_instType_SERVER))
314     {
315         rmInst->registeredWithDelegateOrServer = true;
316     }
318     return ((Rm_TransportHandle) newRouteMapNode);
321 Rm_Result Rm_unregisterTransport (Rm_Handle rmHandle, Rm_TransportHandle transHandle)
323     Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
324     Rm_TransRouteMapNode *routeMapNode = (Rm_TransRouteMapNode *) rmInst->routeMap;
325     Rm_TransRouteMapNode *prevNode = NULL;
327     /* Make sure a routing map exists for the RM instance */
328     if (!routeMapNode)
329     {
330         return (-1); /* TEMP ERROR RETURN */
331     }
333     /* Find the transport handle within the specified RM instance's routing map. */
334     while (1)
335     {
336          if (routeMapNode->transHandle == transHandle)
337          {
338              /* Match: break out of loop and delete the node */
339              break;             
340          }
341          else if (routeMapNode->nextNode == NULL)
342          {
343              return (-1); /* TEMP ERROR: transhandle does not exist for RM instance */
344          }
346          prevNode = routeMapNode;
347          routeMapNode = routeMapNode->nextNode;
348     }
349     
350     /* Delete the routing map node */
351     if ((prevNode == NULL) && routeMapNode->nextNode)
352     {
353         /* Node to be deleted exists at start of route map.  Map second node to be start of
354          * node list as long as there are more than one routing map nodes */
355         rmInst->routeMap = routeMapNode->nextNode;
356     }
357     else
358     {
359         /* Node to be deleted is in the middle or at end of the list.  Adjust adjacent
360          * nodes pointers.  This covers the case where the node to be removed is at the
361          * end of the list. */
362         prevNode->nextNode = routeMapNode->nextNode;
363     }
365     /* Remove specification in RM instance that it has been connected to an upper level agent
366      * if the node to be deleted has a remote instance type of Client Delegate or Server */
367     if ((routeMapNode->remoteInstType == Rm_instType_CLIENT_DELEGATE) ||
368          (routeMapNode->remoteInstType == Rm_instType_SERVER))
369     {
370         rmInst->registeredWithDelegateOrServer = false;
371     }
373     /* Delete the node, free the memory associated with the node. */
374     Rm_osalFree((void *) routeMapNode, sizeof(Rm_TransRouteMapNode), false);
376     return (RM_OK);
380 Rm_TransVerifyResult Rm_verifyTransport (Rm_Handle, uint32_t timeout, 
381                                          Rm_TransFailData *failData)
386 uint32_t Rm_getVersion (void)
388     return RM_VERSION_ID;
392 const char* Rm_getVersionStr (void)
394     return rmVersionStr;
397 /**
398 @}
399 */