Wrote tree allocate and free operations
[keystone-rtos/rm-lld.git] / src / rm_services.c
1 /**
2  *   @file  rmservices.c
3  *
4  *   @brief   
5  *      This is the Resource Manager services 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 external API includes */
46 #include <ti/drv/rm/rm_services.h>
48 /* RM internal API includes */
49 #include <ti/drv/rm/include/rm_loc.h>
51 /* RM OSAL layer */
52 #include <rm_osal.h>
54 /**********************************************************************
55  ********************** Internal Functions ****************************
56  **********************************************************************/
58 void Rm_serviceHandler (void *rmHandle, Rm_ServiceReqInfo *serviceRequest,
59                         Rm_ServiceRespInfo *serviceResponse)
60 {
61     Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
62     Rm_Transaction *transaction;
64     /* Make sure serviceType is valid and that a callback function has been provided */
65     if ((serviceRequest->type < Rm_service_FIRST) || 
66         (serviceRequest->type > Rm_service_LAST))
67     {
68         serviceResponse->serviceState = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;
69         return;
70     }
71     else if (serviceRequest->callback.serviceCallback == NULL)
72     {
73         /* The RM Client and Client Delegate use blocking transports to consult with a 
74          * high-level RM agent prior to providing a response to the component.  It is 
75          * assumed the component's cannot block.  Therefore, all responses must go
76          * through the callback function provided by the component.  Return an error 
77          * if the component does not provide a callback function. */
78         serviceResponse->serviceState = RM_SERVICE_ERROR_CALLBACK_NOT_PROVIDED;
79         return;
80     }
81     
82     /* Create a new transaction */
83     transaction = Rm_transactionQueueAdd(rmInst);
85     if (transaction == NULL)
86     {
87         /* Failed to create a new transaction */
88         serviceResponse->serviceState = RM_SERVICE_ERROR_TRANSACTION_FAILED_TO_ALLOCATE;
89     }
90     else
91     {
92         /* Transfer request information into the transaction */
93         transaction->type = serviceRequest->type;
94         strcpy(transaction->sourceInstName, rmInst->name);
95         transaction->callback.serviceCallback = serviceRequest->callback.serviceCallback;
96         transaction->state = RM_SERVICE_PROCESSING;
97         strcpy(&(transaction->resourceInfo.name)[0], serviceRequest->resourceName);
98         transaction->resourceInfo.base = serviceRequest->resourceBase;
99         transaction->resourceInfo.length = serviceRequest->resourceLength;
100         transaction->resourceInfo.alignment = serviceRequest->resourceAlignment;
101         strcpy(&(transaction->resourceInfo.nsName)[0], serviceRequest->resourceNsName);
103         /* Pass the new transaction to the transaction processor */
104         Rm_transactionProcessor (rmInst, transaction);
106         /* Provide response to the component that requested the service */
107         serviceResponse->serviceState = transaction->state;
108         if (serviceResponse->serviceState == RM_SERVICE_PROCESSING)
109         {
110             /* The service is still being processed.  Provide the transaction ID
111              * back to the component so that it can sort service responses received
112              * via the provided callback function */
113             serviceResponse->serviceId = transaction->localId;
114         }
115         else if (serviceResponse->serviceState == RM_SERVICE_APPROVED_AND_COMPLETED)
116         {
117             /* Service was approved and service was an allocate request the resource
118              * data is passed back to the component */
119             if ((transaction->type == Rm_service_RESOURCE_ALLOCATE) ||
120                 (transaction->type == Rm_service_RESOURCE_BLOCK_ALLOCATE) ||
121                 (transaction->type == Rm_service_RESOURCE_ALLOCATE_BY_NAME))
122             {
123                 serviceResponse->resourceBase = transaction->resourceInfo.base;
124                 serviceResponse->resourceLength = transaction->resourceInfo.length;
125             }
127             /* Delete the transaction since a response was received immediately */
128             Rm_transactionQueueDelete(rmInst, transaction->localId);
129         }
130         else if ((serviceResponse->serviceState >= RM_SERVICE_DENIED_BEGIN) &&
131                  (serviceResponse->serviceState <= RM_SERVICE_DENIED_END))
132         {
133             /* The serviceState field will contain information regarding why the 
134              * service was denied.  Just delete the transaction since a response was
135              * received immediately */
136             Rm_transactionQueueDelete(rmInst, transaction->localId);
137         }
138     }
140     return;
143 /* This function is executed when a RM instance receives a response to one of its requests
144  * and the information in the request must be provided to the original requesting component */
145 void Rm_serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
147     Rm_ServiceRespInfo serviceResponse;
149     /* The responseTransaction will contain the resultant state details of
150      * the requestTransaction's service request */
151     serviceResponse.serviceState = transaction->state;
152     /* Pass back the ID that was provided to the component when it requested
153      * the service */
154     serviceResponse.serviceId = transaction->localId;
156     /* Service was approved and service was an allocate request.  The resource
157      * data is passed back to the component */
158     if ((serviceResponse.serviceState == RM_SERVICE_APPROVED_AND_COMPLETED) &&
159         ((transaction->type == Rm_service_RESOURCE_ALLOCATE) ||
160          (transaction->type == Rm_service_RESOURCE_BLOCK_ALLOCATE) ||
161          (transaction->type == Rm_service_RESOURCE_ALLOCATE_BY_NAME)))
162     {
163         serviceResponse.resourceBase = transaction->resourceInfo.base;
164         serviceResponse.resourceLength = transaction->resourceInfo.length;
165     }
167     /* Issue the callback to the requesting component with the response information */
168     transaction->callback.serviceCallback(&serviceResponse);
170     /* Delete the transaction from the transaction queue */
171     Rm_transactionQueueDelete(rmInst, transaction->localId);
172     return;
175 /**********************************************************************
176  ********************** Application visible APIs **********************
177  **********************************************************************/
179 void Rm_preMainAllocService(Rm_PreMainAllocInfo *preMainAllocInfo,
180                             Rm_ServiceRespInfo *serviceResponse)
185 Rm_ServicePort *Rm_getServicePort(Rm_Handle rmHandle)
187     Rm_ServicePort *newServicePort = NULL;
188     
189     /* Create a new service handle for the specified RM instance */
190     
191     /* Get memory for a new service port from local memory */
192     newServicePort = Rm_osalMalloc (sizeof(Rm_ServicePort));
194     /* Return NULL immediately if malloc returned NULL */
195     if (newServicePort == NULL)
196     {
197         return (newServicePort);
198     }
200     newServicePort->rmHandle = rmHandle;
201     newServicePort->rmService = Rm_serviceHandler;
203     return (newServicePort);
206 /**
207 @}
208 */