completed request/response infrastructure
[keystone-rtos/rm-lld.git] / src / rmservices.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/rmtypes.h>
45 /* RM external API includes */
46 #include <ti/drv/rm/rmservices.h>
48 /* RM internal API includes */
49 #include <ti/drv/rm/include/rmloc.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     uint32_t transactionId = 0;
63     Rm_Transaction *transaction;
64     Rm_TransactionReceipt receipt;
65     void *key;
67     /* Prevent another component using the same instance from wiping out the current
68      * service request */
69     key = Rm_osalLocalCsEnter();
71     /* Make sure serviceType is valid and that a callback function has been provided */
72     if ((serviceRequest->serviceType < Rm_service_FIRST) || 
73         (serviceRequest->serviceType > Rm_service_LAST))
74     {
75         serviceResponse->serviceResult = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;
76         Rm_osalLocalCsExit(key);
77         return;
78     }
79     else if (serviceRequest->serviceCallback == NULL)
80     {
81         /* The RM Client and Client Delegate use blocking transports to consult with a 
82          * high-level RM agent prior to providing a response to the component.  It is 
83          * assumed the component's cannot block.  Therefore, all responses must go
84          * through the callback function provided by the component.  Return an error 
85          * if the component does not provide a callback function. */
86         serviceResponse->serviceResult = RM_SERVICE_ERROR_CALLBACK_NOT_PROVIDED;
87         Rm_osalLocalCsExit(key);
88         return;
89     }
91     /* Create an ID for this transaction.  The ID will be used for two purposes:
92      * 1) Matching responses from higher level RM agents to requests
93      * 2) Provided to the entity that requested the service so that it can match its
94      *    request with the response it receives via its callback function it provided */
95     transactionId = ...; /* NEED SCHEME FOR CREATING A MUTUALLY EXCLUSIVE PKT ID.  CAN'T
96                            * CONFLICT WITH PCKT IDS CREATED ON OTHER RM INSTANCES */
97     /* Create a new transaction */
98     transaction = Rm_transactionQueueAdd(rmInst, transactionId);
100     if (transaction == NULL)
101     {
102         /* Failed to create a new transaction */
103         serviceResponse->serviceResult = RM_SERVICE_ERROR_TRANSACTION_FAILED_TO_ALLOCATE;
104     }
105     else
106     {
107         /* Clear the receipt */
108         memset((void *) &receipt, 0, sizeof(Rm_TransactionReceipt));
110         /* Transfer request information into the transaction */
111         transaction->type = serviceRequest->serviceType;
112         strcpy((transaction->sourceInstName, rmInst->name);
113         transaction->callback = serviceRequest->serviceCallback;
114         transaction->state = Rm_transactionState_PROCESSING;
115         transaction->details = RM_SERVICE_PROCESSING;
116         strcpy(&(transaction->resourceInfo.name)[0], serviceRequest->resourceName);
117         transaction->resourceInfo.base = serviceRequest->resourceBase;
118         transaction->resourceInfo.range = serviceRequest->resourceRange;
119         transaction->resourceInfo.alignment = serviceRequest->resourceAlignment;
120         strcpy(&(transaction->resourceInfo.nsName)[0], serviceRequest->resourceNsName);
122         /* Pass the new transaction to the transaction processor */
123         Rm_transactionProcessor (rmInst, transaction, &receipt);
125         /* Copy transaction receipt information into the response info fields for the 
126          * component based on the result of the transaction.  Denied service requests
127          * will have only a valid serviceResult field */
128         serviceResponse->serviceResult = receipt->serviceResult;
130         /* Service was approved and service was an allocate request the resource
131          * data is passed back to the component */
132         if ((serviceResponse->serviceResult == RM_SERVICE_APPROVED) &&
133             ((transaction->type == Rm_service_RESOURCE_ALLOCATE) ||
134              (transaction->type == Rm_service_RESOURCE_BLOCK_ALLOCATE) ||
135              (transaction->type == Rm_service_RESOURCE_ALLOCATE_BY_NAME)))
136         {
137             serviceResponse->resourceBase = receipt.resourceBase;
138             serviceResponse->resourceRange = receipt.resourceRange;
140             /* Delete the transaction since a response was received immediately */
141             Rm_transactionQueueDelete(rmInst, transaction->id);
142         }
143         else if (serviceResponse->serviceResult == RM_SERVICE_PROCESSING)
144         {
145             /* The service is still being processed.  Provide the transaction ID
146              * back to the component so that it can sort service responses received
147              * via the provided callback function */
148             serviceResponse->requestId = receipt.serviceId;
149         }
150         else if (serviceResponse->serviceResult <= RM_SERVICE_ERROR_BASE)
151         {
152             /* Delete the transaction since there was an error processing it. */
153             Rm_transactionQueueDelete(rmInst, transaction->id);
154         }
155     }
157     Rm_osalLocalCsExit(key); 
158     return;
161 /* This function is executed when a RM instance receives a response to one of its requests
162  * and the information in the request must be provided to the original requesting component */
163 void Rm_serviceResponder (Rm_Inst *rmInst, Rm_Transaction *responseTransaction,
164                           Rm_Transaction *requestTransaction, Rm_TransactionReceipt *receipt)
166     Rm_ServiceRespInfo serviceResponse;
168     /* Populate the service response with the transaction response details
169      * for the component */
170     serviceResponse.serviceResult = responseTransaction->details;
171     /* Pass back the ID that was provided to the component when it requested
172      * the service */
173     serviceResponse.requestId = responseTransaction->id;
175     /* Service was approved and service was an allocate request.  The resource
176      * data is passed back to the component */
177     if ((serviceResponse->serviceResult == RM_SERVICE_APPROVED) &&
178         ((responseTransaction.type == Rm_service_RESOURCE_ALLOCATE) ||
179          (responseTransaction.type == Rm_service_RESOURCE_BLOCK_ALLOCATE) ||
180          (responseTransaction.type == Rm_service_RESOURCE_ALLOCATE_BY_NAME)))
181     {
182         serviceResponse->resourceBase = receipt.resourceBase;
183         serviceResponse->resourceRange = receipt.resourceRange;
184     }
186     /* Issue the callback to the requesting component with the response information */
187     if (requestTransaction != NULL)
188     {
189         /* The requestTransaction will be NULL if the request transaction is handled
190          * by the same RM instance it was created on.  Typically this applies to RM
191          * Client Delegate and RM Server instances.  In these cases the response
192          * transaction will be a copy of the request transaction, meaning it will contain
193          * the proper callback information */
194         requestTransaction->callback(&serviceResponse);
195     }
196     else
197     {
198         responseTransaction->callback(&serviceResponse);
199     }
201     /* Delete both transactions from the transaction queue */
202     Rm_transactionQueueDelete(rmInst,responseTransaction->id);
203     if (requestTransaction != NULL)
204     {
205         Rm_transactionQueueDelete(rmInst,requestTransaction->id);
206     }
208     /* Response to component completed */
209     receipt.serviceResult = RM_SERVICE_ACTION_OKAY;
210     return;
213 /**********************************************************************
214  ********************** Application visible APIs **********************
215  **********************************************************************/
217 void Rm_preMainAllocService(Rm_PreMainAllocInfo *preMainAllocInfo,
218                             Rm_ServiceRespInfo *serviceResponse)
224 Rm_ServicesPort *Rm_getServicePort(Rm_Handle rmHandle)
226     Rm_Inst *rmInst = (Rm_Inst *) rmHandle;
227     Rm_ServicesPort *newServicePort = NULL;
228     
229     /* Create a new service handle for the specified RM instance */
230     
231     /* Get memory for a new service port from local memory */
232     newServicePort = Rm_osalMalloc (sizeof(Rm_ServicesPort), false);
234     /* Return NULL immediately if malloc returned NULL */
235     if (newServicePort == NULL)
236     {
237         return (newServicePort);
238     }
240     newServicePort->rmHandle = rmHandle;
241     newServicePort->rmService = Rm_serviceHandler;
243     return (newServicePort);
246 /**
247 @}
248 */