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 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->type < Rm_service_FIRST) ||
73 (serviceRequest->type > Rm_service_LAST))
74 {
75 serviceResponse->serviceResult = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;
76 Rm_osalLocalCsExit(key);
77 return;
78 }
79 else if (serviceRequest->callback.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 component 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 = Rm_transactionGetSequenceNum(rmInst);
96 /* Create a new transaction */
97 transaction = Rm_transactionQueueAdd(rmInst, transactionId);
99 if (transaction == NULL)
100 {
101 /* Failed to create a new transaction */
102 serviceResponse->serviceResult = RM_SERVICE_ERROR_TRANSACTION_FAILED_TO_ALLOCATE;
103 }
104 else
105 {
106 /* Clear the receipt */
107 memset((void *) &receipt, 0, sizeof(Rm_TransactionReceipt));
109 /* Transfer request information into the transaction */
110 transaction->type = serviceRequest->type;
111 strcpy(transaction->sourceInstName, rmInst->name);
112 transaction->callback.serviceCallback = serviceRequest->callback.serviceCallback;
113 transaction->state = Rm_transactionState_PROCESSING;
114 transaction->details = RM_SERVICE_PROCESSING;
115 strcpy(&(transaction->resourceInfo.name)[0], serviceRequest->resourceName);
116 transaction->resourceInfo.base = serviceRequest->resourceBase;
117 transaction->resourceInfo.range = serviceRequest->resourceRange;
118 transaction->resourceInfo.alignment = serviceRequest->resourceAlignment;
119 strcpy(&(transaction->resourceInfo.nsName)[0], serviceRequest->resourceNsName);
121 /* Pass the new transaction to the transaction processor */
122 Rm_transactionProcessor (rmInst, transaction, &receipt);
124 /* Copy transaction receipt information into the response info fields for the
125 * component based on the result of the transaction. Denied service requests
126 * will have only a valid serviceResult field */
127 serviceResponse->serviceResult = receipt.serviceResult;
129 /* Service was approved and service was an allocate request the resource
130 * data is passed back to the component */
131 if ((serviceResponse->serviceResult == RM_SERVICE_APPROVED) &&
132 ((transaction->type == Rm_service_RESOURCE_ALLOCATE) ||
133 (transaction->type == Rm_service_RESOURCE_BLOCK_ALLOCATE) ||
134 (transaction->type == Rm_service_RESOURCE_ALLOCATE_BY_NAME)))
135 {
136 serviceResponse->resourceBase = receipt.resourceBase;
137 serviceResponse->resourceRange = receipt.resourceRange;
139 /* Delete the transaction since a response was received immediately */
140 Rm_transactionQueueDelete(rmInst, transaction->id);
141 }
142 else if (serviceResponse->serviceResult == RM_SERVICE_PROCESSING)
143 {
144 /* The service is still being processed. Provide the transaction ID
145 * back to the component so that it can sort service responses received
146 * via the provided callback function */
147 serviceResponse->requestId = receipt.serviceId;
148 }
149 else if (serviceResponse->serviceResult <= RM_SERVICE_ERROR_BASE)
150 {
151 /* Delete the transaction since there was an error processing it. */
152 Rm_transactionQueueDelete(rmInst, transaction->id);
153 }
154 }
156 Rm_osalLocalCsExit(key);
157 return;
158 }
160 /* This function is executed when a RM instance receives a response to one of its requests
161 * and the information in the request must be provided to the original requesting component */
162 void Rm_serviceResponder (Rm_Inst *rmInst, Rm_Transaction *responseTransaction,
163 Rm_Transaction *requestTransaction, Rm_TransactionReceipt *receipt)
164 {
165 Rm_ServiceRespInfo serviceResponse;
167 /* Populate the service response with the transaction response details
168 * for the component */
169 serviceResponse.serviceResult = responseTransaction->details;
170 /* Pass back the ID that was provided to the component when it requested
171 * the service */
172 serviceResponse.requestId = responseTransaction->id;
174 /* Service was approved and service was an allocate request. The resource
175 * data is passed back to the component */
176 if ((serviceResponse.serviceResult == RM_SERVICE_APPROVED) &&
177 ((responseTransaction->type == Rm_service_RESOURCE_ALLOCATE) ||
178 (responseTransaction->type == Rm_service_RESOURCE_BLOCK_ALLOCATE) ||
179 (responseTransaction->type == Rm_service_RESOURCE_ALLOCATE_BY_NAME)))
180 {
181 serviceResponse.resourceBase = receipt->resourceBase;
182 serviceResponse.resourceRange = receipt->resourceRange;
183 }
185 /* Issue the callback to the requesting component with the response information */
186 if (requestTransaction != NULL)
187 {
188 /* The requestTransaction will be NULL if the request transaction is handled
189 * by the same RM instance it was created on. Typically this applies to RM
190 * Client Delegate and RM Server instances. In these cases the response
191 * transaction will be a copy of the request transaction, meaning it will contain
192 * the proper callback information */
193 requestTransaction->callback.serviceCallback(&serviceResponse);
194 }
195 else
196 {
197 responseTransaction->callback.serviceCallback(&serviceResponse);
198 }
200 /* Delete both transactions from the transaction queue */
201 Rm_transactionQueueDelete(rmInst,responseTransaction->id);
202 if (requestTransaction != NULL)
203 {
204 Rm_transactionQueueDelete(rmInst,requestTransaction->id);
205 }
207 /* Response to component completed */
208 receipt->serviceResult = RM_SERVICE_ACTION_OKAY;
209 return;
210 }
212 /**********************************************************************
213 ********************** Application visible APIs **********************
214 **********************************************************************/
216 void Rm_preMainAllocService(Rm_PreMainAllocInfo *preMainAllocInfo,
217 Rm_ServiceRespInfo *serviceResponse)
218 {
220 }
222 Rm_ServicesPort *Rm_getServicePort(Rm_Handle rmHandle)
223 {
224 Rm_ServicesPort *newServicePort = NULL;
226 /* Create a new service handle for the specified RM instance */
228 /* Get memory for a new service port from local memory */
229 newServicePort = Rm_osalMalloc (sizeof(Rm_ServicesPort), false);
231 /* Return NULL immediately if malloc returned NULL */
232 if (newServicePort == NULL)
233 {
234 return (newServicePort);
235 }
237 newServicePort->rmHandle = rmHandle;
238 newServicePort->rmService = Rm_serviceHandler;
240 return (newServicePort);
241 }
243 /**
244 @}
245 */