1 /**
2 * @file rm_services.c
3 *
4 * @brief
5 * This is the Resource Manager services source.
6 *
7 * \par
8 * ============================================================================
9 * @n (C) Copyright 2012-2013, 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 /* Standard includes */
43 #include <string.h>
45 /* RM external API includes */
46 #include <ti/drv/rm/rm.h>
47 #include <ti/drv/rm/rm_services.h>
49 /* RM internal API includes */
50 #include <ti/drv/rm/include/rm_loc.h>
52 /* RM OSAL layer */
53 #include <rm_osal.h>
55 /**********************************************************************
56 ********************** Internal Functions ****************************
57 **********************************************************************/
59 /* FUNCTION PURPOSE: Internal Callback to unblock RM instance
60 ***********************************************************************
61 * DESCRIPTION: Internal callback function executed when the result
62 * of a service request has been received from a remote
63 * instance. The original service request did not specify
64 * a callback function so the Rm_serviceHandler is blocked
65 * waiting for the response. This function unblocks the
66 * Rm_serviceHandler to return the response to the
67 * application.
68 */
69 void rmServiceInternalCallback(Rm_Handle rmHandle)
70 {
71 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
73 /* Unblock so Rm_serviceHandler can provide response to application */
74 Rm_osalTaskUnblock(rmInst->blockHandle);
75 }
77 /**********************************************************************
78 ********************** Application visible APIs **********************
79 **********************************************************************/
81 /* FUNCTION PURPOSE: Handles application component service requests
82 ***********************************************************************
83 * DESCRIPTION: Receives service requests from application components
84 * and routes them to the transaction processor. If
85 * the service can be handled immediately the response
86 * will be provided in the service response. If the
87 * service requires a blocking operation the handler
88 * will provide a service ID back to the application.
89 * The response will be sent at a later time via the
90 * application supplied callback function.
91 */
92 void Rm_serviceHandler (void *rmHandle, const Rm_ServiceReqInfo *serviceRequest,
93 Rm_ServiceRespInfo *serviceResponse)
94 {
95 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
96 char *instanceName;
97 Rm_Transaction *transaction;
98 void *key;
100 RM_SS_INST_INV_ENTER_CS(key);
101 RM_SC_INST_INV_ENTER_CS(key);
103 if (rmInst->isLocked) {
104 serviceResponse->serviceState = RM_SERVICE_DENIED_RM_INSTANCE_LOCKED;
105 return;
106 }
108 if (serviceRequest->type >= Rm_service_LAST) {
109 serviceResponse->serviceState = RM_ERROR_INVALID_SERVICE_TYPE;
110 return;
111 }
113 /* Copy location of instance name to local variable in case Shared Client needs to
114 * transfer control to a shared server */
115 instanceName = rmInst->instName;
116 if (rmInst->instType == Rm_instType_SHARED_CLIENT) {
117 /* Transfer control to shared server instance */
118 rmInst = rmInst->u.sharedClient.sharedServerHandle;
119 }
121 transaction = rmTransactionQueueAdd(rmInst);
122 if (transaction) {
123 transaction->type = serviceRequest->type;
124 strncpy(transaction->serviceSrcInstName, instanceName, RM_NAME_MAX_CHARS);
125 transaction->u.callback.serviceCallback = serviceRequest->callback.serviceCallback;
126 transaction->state = RM_SERVICE_PROCESSING;
127 if (serviceRequest->resourceName) {
128 strncpy(transaction->resourceInfo.name, serviceRequest->resourceName, RM_NAME_MAX_CHARS);
129 }
130 transaction->resourceInfo.base = serviceRequest->resourceBase;
131 transaction->resourceInfo.length = serviceRequest->resourceLength;
132 transaction->resourceInfo.alignment = serviceRequest->resourceAlignment;
133 transaction->resourceInfo.ownerCount = RM_RESOURCE_NUM_OWNERS_INVALID;
134 transaction->resourceInfo.instAllocCount = RM_INST_ALLOC_COUNT_INVALID;
135 if (serviceRequest->resourceNsName) {
136 strncpy(transaction->resourceInfo.nameServerName, serviceRequest->resourceNsName, RM_NAME_MAX_CHARS);
137 }
139 /* Process received transaction */
140 rmProcessRouter(rmInst, transaction);
142 memset((void *)serviceResponse, 0, sizeof(*serviceResponse));
144 if ((rmInst->instType == Rm_instType_SHARED_SERVER) &&
145 (transaction->state == RM_SERVICE_PROCESSING)) {
146 /* Shared Server should always return a fully processed transaction */
147 serviceResponse->serviceState = RM_ERROR_SHARED_INSTANCE_UNFINISHED_REQ;
148 rmTransactionQueueDelete(rmInst, transaction->localId);
149 }
150 else {
151 if ((transaction->state == RM_SERVICE_PROCESSING) &&
152 (transaction->u.callback.serviceCallback == NULL)) {
153 /* Block until response is received. Response will be received in transaction. */
154 Rm_osalTaskBlock(rmInst->blockHandle);
155 }
157 serviceResponse->rmHandle = rmHandle;
158 serviceResponse->serviceState = transaction->state;
159 /* Owner and instance allocation count will only be set within RM under certain circumstances. */
160 serviceResponse->resourceNumOwners = transaction->resourceInfo.ownerCount;
161 serviceResponse->instAllocCount = transaction->resourceInfo.instAllocCount;
162 if ((serviceResponse->serviceState == RM_SERVICE_PROCESSING) ||
163 (serviceResponse->serviceState == RM_SERVICE_APPROVED_STATIC) ||
164 (serviceResponse->serviceState == RM_SERVICE_PENDING_SERVER_RESPONSE)) {
165 /* Service still being processed. Static requests will have their validation responses sent once
166 * all transports have been established. Provide transaction ID back to component so it can sort
167 * service responses received via callback function */
168 serviceResponse->serviceId = transaction->localId;
169 }
171 if ((serviceResponse->serviceState == RM_SERVICE_APPROVED) ||
172 (serviceResponse->serviceState == RM_SERVICE_APPROVED_STATIC)) {
173 strncpy(serviceResponse->resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
174 serviceResponse->resourceBase = transaction->resourceInfo.base;
175 serviceResponse->resourceLength = transaction->resourceInfo.length;
176 }
178 /* Transactions still processing not deleted from queue including static transactions which will be
179 * verified once all transports are up */
180 if ((serviceResponse->serviceState != RM_SERVICE_PROCESSING) &&
181 (serviceResponse->serviceState != RM_SERVICE_APPROVED_STATIC) &&
182 (serviceResponse->serviceState != RM_SERVICE_PENDING_SERVER_RESPONSE)) {
183 rmTransactionQueueDelete(rmInst, transaction->localId);
184 }
185 }
186 }
187 else {
188 serviceResponse->serviceState = RM_ERROR_SERVICE_TRANS_NOT_CREATED;
189 }
190 RM_SS_INST_WB_EXIT_CS(key);
191 return;
192 }
194 /* FUNCTION PURPOSE: Opens the RM instance service handle
195 ***********************************************************************
196 * DESCRIPTION: Returns the service handle for an RM instance. Only
197 * one service handle is opened per instance.
198 */
199 Rm_ServiceHandle *Rm_serviceOpenHandle(Rm_Handle rmHandle, int32_t *result)
200 {
201 Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
202 Rm_ServiceHandle *serviceHandle = NULL;
203 void *key;
205 RM_SS_INST_INV_ENTER_CS(key);
207 *result = RM_OK;
209 serviceHandle = rmInst->serviceHandle;
210 if (serviceHandle == NULL) {
211 serviceHandle = Rm_osalMalloc(sizeof(*serviceHandle));
212 if (serviceHandle) {
213 serviceHandle->rmHandle = rmHandle;
214 serviceHandle->Rm_serviceHandler = Rm_serviceHandler;
215 RM_SS_OBJ_WB(serviceHandle, Rm_ServiceHandle);
216 rmInst->serviceHandle = serviceHandle;
217 }
218 else {
219 *result = RM_ERROR_SERVICE_HANDLE_MEM_ALLOC_FAILED;
220 }
221 }
222 RM_SS_INST_WB_EXIT_CS(key);
223 return (serviceHandle);
224 }
226 /* FUNCTION PURPOSE: Closes the RM instance service handle
227 ***********************************************************************
228 * DESCRIPTION: Closes the service handle for an RM instance.
229 */
230 int32_t Rm_serviceCloseHandle(Rm_ServiceHandle *rmServiceHandle)
231 {
232 Rm_Inst *rmInst = (Rm_Inst *)rmServiceHandle->rmHandle;
233 int32_t retVal = RM_OK;
234 void *key;
236 RM_SS_INST_INV_ENTER_CS(key);
238 if (rmInst->serviceHandle) {
239 Rm_osalFree((void *)rmServiceHandle, sizeof(*rmServiceHandle));
240 rmInst->serviceHandle = NULL;
241 }
242 else {
243 retVal = RM_ERROR_SERVICE_HANDLE_ALREADY_CLOSED;
244 }
245 RM_SS_INST_WB_EXIT_CS(key);
246 return(retVal);
247 }