d42769cc9eb9c7e686a7ee9d811cdbdbfd8e53f8
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 void *key;
66 /* Prevent another component using the same instance from wiping out the current
67 * service request */
68 key = Rm_osalCsEnter();
70 /* Make sure serviceType is valid and that a callback function has been provided */
71 if ((serviceRequest->type < Rm_service_FIRST) ||
72 (serviceRequest->type > Rm_service_LAST))
73 {
74 serviceResponse->serviceResult = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;
75 Rm_osalCsExit(key);
76 return;
77 }
78 else if (serviceRequest->callback.serviceCallback == NULL)
79 {
80 /* The RM Client and Client Delegate use blocking transports to consult with a
81 * high-level RM agent prior to providing a response to the component. It is
82 * assumed the component's cannot block. Therefore, all responses must go
83 * through the callback function provided by the component. Return an error
84 * if the component does not provide a callback function. */
85 serviceResponse->serviceResult = RM_SERVICE_ERROR_CALLBACK_NOT_PROVIDED;
86 Rm_osalCsExit(key);
87 return;
88 }
90 /* Create an ID for this transaction. The ID will be used for two purposes:
91 * 1) Matching responses from higher level RM agents to requests
92 * 2) Provided to the component that requested the service so that it can match its
93 * request with the response it receives via its callback function it provided */
94 transactionId = Rm_transactionGetSequenceNum(rmInst);
95 /* Create a new transaction */
96 transaction = Rm_transactionQueueAdd(rmInst, transactionId);
98 if (transaction == NULL)
99 {
100 /* Failed to create a new transaction */
101 serviceResponse->serviceResult = RM_SERVICE_ERROR_TRANSACTION_FAILED_TO_ALLOCATE;
102 }
103 else
104 {
105 /* Transfer request information into the transaction */
106 transaction->type = serviceRequest->type;
107 strcpy(transaction->sourceInstName, rmInst->name);
108 transaction->callback.serviceCallback = serviceRequest->callback.serviceCallback;
109 transaction->state = Rm_transactionState_PROCESSING;
110 strcpy(&(transaction->resourceInfo.name)[0], serviceRequest->resourceName);
111 transaction->resourceInfo.base = serviceRequest->resourceBase;
112 transaction->resourceInfo.range = serviceRequest->resourceRange;
113 transaction->resourceInfo.alignment = serviceRequest->resourceAlignment;
114 strcpy(&(transaction->resourceInfo.nsName)[0], serviceRequest->resourceNsName);
116 /* Pass the new transaction to the transaction processor */
117 Rm_transactionProcessor (rmInst, transaction);
119 /* Provide response to the component that requested the service */
120 if (transaction->state == Rm_transactionState_PROCESSING)
121 {
122 /* The service is still being processed. Provide the transaction ID
123 * back to the component so that it can sort service responses received
124 * via the provided callback function */
125 serviceResponse->serviceResult == RM_SERVICE_PROCESSING;
126 serviceResponse->requestId = transaction->localId;
127 }
128 else if (transaction->state == Rm_transactionState_TRANSACTION_APPROVED)
129 {
130 serviceResponse->serviceResult = RM_SERVICE_APPROVED;
131 /* Service was approved and service was an allocate request the resource
132 * data is passed back to the component */
133 if ((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 = transaction->resourceInfo.base;
138 serviceResponse->resourceRange = transaction->resourceInfo.range;
139 }
141 /* Delete the transaction since a response was received immediately */
142 Rm_transactionQueueDelete(rmInst, transaction->id);
143 }
144 else if (transaction->state == Rm_transactionState_TRANSACTION_DENIED)
145 {
146 /* Transaction result field will contain a vlaue specifying why resource was
147 * denied */
148 serviceResponse->serviceResult = transaction->result;
149 /* Delete the transaction since a response was received immediately */
150 Rm_transactionQueueDelete(rmInst, transaction->id);
151 }
152 }
154 Rm_osalCsExit(key);
155 return;
156 }
158 /* This function is executed when a RM instance receives a response to one of its requests
159 * and the information in the request must be provided to the original requesting component */
160 void Rm_serviceResponder (Rm_Inst *rmInst, Rm_Transaction *responseTransaction,
161 Rm_Transaction *requestTransaction)
162 {
163 Rm_ServiceRespInfo serviceResponse;
166 /* CODING HERE */
168 /* Populate the service response with the transaction response details
169 * for the component */
170 serviceResponse.serviceResult = responseTransaction->result;
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 = responseTransaction->resourceInfo.base;
183 serviceResponse.resourceRange = responseTransaction->resourceInfo.range;
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.serviceCallback(&serviceResponse);
195 }
196 else
197 {
198 responseTransaction->callback.serviceCallback(&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;
211 }
213 /**********************************************************************
214 ********************** Application visible APIs **********************
215 **********************************************************************/
217 void Rm_preMainAllocService(Rm_PreMainAllocInfo *preMainAllocInfo,
218 Rm_ServiceRespInfo *serviceResponse)
219 {
221 }
223 Rm_ServicePort *Rm_getServicePort(Rm_Handle rmHandle)
224 {
225 Rm_ServicePort *newServicePort = NULL;
227 /* Create a new service handle for the specified RM instance */
229 /* Get memory for a new service port from local memory */
230 newServicePort = Rm_osalMalloc (sizeof(Rm_ServicePort), false);
232 /* Return NULL immediately if malloc returned NULL */
233 if (newServicePort == NULL)
234 {
235 return (newServicePort);
236 }
238 newServicePort->rmHandle = rmHandle;
239 newServicePort->rmService = Rm_serviceHandler;
241 return (newServicePort);
242 }
244 /**
245 @}
246 */