]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/rm-lld.git/blob - src/rm_services.c
885fd96380b8999b5d1a07159633cd4758afae73
[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-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_services.h>
48 /* RM internal API includes */
49 #include <ti/drv/rm/include/rm_servicesloc.h>
50 #include <ti/drv/rm/include/rm_loc.h>
51 #include <ti/drv/rm/include/rm_policyloc.h>
53 /* RM OSAL layer */
54 #include <rm_osal.h>
56 /**********************************************************************
57  ********************** Application visible APIs **********************
58  **********************************************************************/
60 void Rm_serviceHandler (void *rmHandle, Rm_ServiceReqInfo *serviceRequest,
61                         Rm_ServiceRespInfo *serviceResponse)
62 {
63     Rm_Inst             *rmInst = (Rm_Inst *)rmHandle;
64     Rm_Transaction      *transaction;
65     Rm_PolicyCheckCfg    privCheckCfg;
66     Rm_ServiceStaticReq *lastStaticReq;
68     if (serviceRequest->reqType == Rm_reqType_STATIC) {
69         serviceResponse->serviceState = RM_SERVICE_PROCESSING;
71         if ((serviceRequest->serviceType == Rm_service_RESOURCE_ALLOCATE_INIT) ||
72             (serviceRequest->serviceType == Rm_service_RESOURCE_ALLOCATE_USE) ||
73             (serviceRequest->resourceBase != RM_RESOURCE_BASE_UNSPECIFIED)) {
74             /* Check request against startup policy */
75             memset((void *)&privCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
77             if (serviceRequest->serviceType == Rm_service_RESOURCE_ALLOCATE_INIT) {
78                 privCheckCfg.type = Rm_policyCheck_INIT;
79             }
80             else {
81                 privCheckCfg.type = Rm_policyCheck_USE;
82             }
83             privCheckCfg.policyDtb = rmInst->staticInfo.staticPolicy;
84             privCheckCfg.validInstNode = rmPolicyGetValidInstNode(rmInst->staticInfo.staticValidInstTree, 
85                                                                   rmInst->instName);
86             privCheckCfg.resourceOffset = rmPolicyGetResourceOffset(rmInst->staticInfo.staticPolicy,
87                                                                     serviceRequest->resourceName);
88             privCheckCfg.resourceBase = serviceRequest->resourceBase;
89             privCheckCfg.resourceLength = serviceRequest->resourceLength;
91             if (rmPolicyCheckPrivilege(&privCheckCfg, &serviceResponse->serviceState)) {
92                 serviceResponse->serviceState = RM_SERVICE_APPROVED_AND_COMPLETED;
93             }
94             else if (serviceResponse->serviceState == RM_SERVICE_PROCESSING) {
95                 /* Privilege check returned FALSE without error */
96                 serviceResponse->serviceState = RM_SERVICE_DENIED_POLICY_DENIED_STATIC_ALLOCATION;
97             }
98         }
99         else {
100             serviceResponse->serviceState = RM_SERVICE_DENIED_INVALID_STATIC_REQUEST;
101         }
103         /* Store request for validation after instance transports have been established */
104         if (serviceResponse->serviceState == RM_SERVICE_APPROVED_AND_COMPLETED) {
105             lastStaticReq = rmInst->staticInfo.staticReqList;
106             while(lastStaticReq) {
107                 lastStaticReq = lastStaticReq->nextStaticReq;
108             }
109             lastStaticReq = (Rm_ServiceStaticReq *) Rm_osalMalloc (sizeof(Rm_ServiceStaticReq));
110             lastStaticReq->nextStaticReq = NULL;
111             lastStaticReq->staticReq = (Rm_ServiceReqInfo *) Rm_osalMalloc(sizeof(Rm_ServiceReqInfo));
112             memcpy((void *)lastStaticReq->staticReq, (void *)serviceRequest, sizeof(Rm_ServiceReqInfo));
114             /* Fill out response */
115             serviceResponse->resourceBase = serviceRequest->resourceBase;
116             serviceResponse->resourceLength = serviceRequest->resourceLength;
117             strncpy(serviceResponse->resourceName, serviceRequest->resourceName, RM_NAME_MAX_CHARS);
118             serviceResponse->serviceId = rmTransactionGetSequenceNum(rmInst);
119         }
120     }
121     else if (serviceRequest->reqType == Rm_reqType_DYNAMIC) {
122         if (serviceRequest->callback.serviceCallback == NULL) {
123             serviceResponse->serviceState = RM_SERVICE_ERROR_CALLBACK_NOT_PROVIDED;
124             return;
125         }
127         if (serviceRequest->serviceType >= Rm_service_LAST) {
128             serviceResponse->serviceState = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;
129             return;
130         }
131         
132         transaction = rmTransactionQueueAdd(rmInst);
133         if (transaction) {
134             transaction->type = serviceRequest->serviceType;
135             strncpy(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);
136             transaction->callback.serviceCallback = serviceRequest->callback.serviceCallback;
137             transaction->state = RM_SERVICE_PROCESSING;
138             if (serviceRequest->resourceName) {
139                 strncpy(transaction->resourceInfo.name, serviceRequest->resourceName, RM_NAME_MAX_CHARS);
140             }
141             transaction->resourceInfo.base = serviceRequest->resourceBase;
142             transaction->resourceInfo.length = serviceRequest->resourceLength;
143             transaction->resourceInfo.alignment = serviceRequest->resourceAlignment;
144             if (serviceRequest->resourceNsName) {
145                 strncpy(transaction->resourceInfo.nameServerName, serviceRequest->resourceNsName, RM_NAME_MAX_CHARS);
146             }
148             rmTransactionProcessor (rmInst, transaction);
149             serviceResponse->serviceState = transaction->state;
150             if (serviceResponse->serviceState == RM_SERVICE_PROCESSING) {
151                 /* Service still being processed.  Provide transaction ID
152                  * back to component so it can sort service responses received
153                  * via callback function */
154                 serviceResponse->serviceId = transaction->localId;
155             }
156             else if (serviceResponse->serviceState == RM_SERVICE_APPROVED_AND_COMPLETED) {
157                 if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
158                     (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
159                     (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)) {
160                     strncpy(serviceResponse->resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
161                     serviceResponse->resourceBase = transaction->resourceInfo.base;
162                     serviceResponse->resourceLength = transaction->resourceInfo.length;
163                 }
164                 rmTransactionQueueDelete(rmInst, transaction->localId);
165             }
166             else {
167                 rmTransactionQueueDelete(rmInst, transaction->localId);
168             }
169         }
170         else {
171             serviceResponse->serviceState = RM_SERVICE_ERROR_TRANSACTION_FAILED_TO_ALLOCATE;    
172         }
173     }
174     return;
177 void Rm_serviceValidateStaticRequests(Rm_Handle rmHandle, Rm_ServiceCallback validateCallback)
179     Rm_Inst             *rmInst = (Rm_Inst *)rmHandle;
180     Rm_ServiceReqInfo   *staticRequest;
181     Rm_ServiceStaticReq *nextServiceReq;
182     Rm_Transaction      *transaction;
183     Rm_ServiceRespInfo   serviceResponse;
185     if (validateCallback.serviceCallback == NULL) {
186         serviceResponse->serviceState = RM_SERVICE_ERROR_CALLBACK_NOT_PROVIDED;
187         return;
188     }
190     /* Validate static requests against the global policyDtb */
191     while(rmInst->staticInfo.staticReqList) {
192         transaction = rmTransactionQueueAdd(rmInst);
193         if (transaction) {
194             staticRequest = rmInst->staticInfo.staticReqList->staticReq;
195             transaction->type = staticRequest->serviceType;
196             strncpy(transaction->serviceSrcInstName, rmInst->instName, RM_NAME_MAX_CHARS);
197             transaction->callback.serviceCallback = validateCallback.serviceCallback;
198             transaction->state = RM_SERVICE_PROCESSING;
199             if (staticRequest->resourceName) {
200                 strncpy(transaction->resourceInfo.name, staticRequest->resourceName, RM_NAME_MAX_CHARS);
201             }
202             transaction->resourceInfo.base = staticRequest->resourceBase;
203             transaction->resourceInfo.length = staticRequest->resourceLength;
204             transaction->resourceInfo.alignment = staticRequest->resourceAlignment;
205             if (staticRequest->resourceNsName) {
206                 strncpy(transaction->resourceInfo.nameServerName, staticRequest->resourceNsName, RM_NAME_MAX_CHARS);
207             }
208         
209             rmTransactionProcessor (rmInst, transaction);
210             memset((void *)&serviceResponse, 0, sizeof(Rm_ServiceRespInfo));
211             serviceResponse->serviceState = transaction->state;
212             if (serviceResponse->serviceState == RM_SERVICE_PROCESSING) {
213                 /* Service still being processed.  Provide transaction ID
214                  * back to component so it can sort service responses received
215                  * via callback function */
216                 serviceResponse->serviceId = transaction->localId;
217             }
218             else if (serviceResponse->serviceState == RM_SERVICE_APPROVED_AND_COMPLETED) {
219                 if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
220                     (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
221                     (transaction->type == Rm_service_RESOURCE_GET_BY_NAME)) {
222                     strncpy(serviceResponse->resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
223                     serviceResponse->resourceBase = transaction->resourceInfo.base;
224                     serviceResponse->resourceLength = transaction->resourceInfo.length;
225                 }
226                 rmTransactionQueueDelete(rmInst, transaction->localId);
227             }
228             else {
229                 rmTransactionQueueDelete(rmInst, transaction->localId);
230             }
231             /* Issue response via callback since function won't return until all static requests have
232              * been handled */
233             validateCallback->serviceCallback(&serviceResponse);
234         }
235         else {
236             serviceResponse->serviceState = RM_SERVICE_ERROR_TRANSACTION_FAILED_TO_ALLOCATE;
237             return;
238         }
239         /* Free memory associated with static requests sent for validation */
240         nextServiceReq = rmInst->staticInfo.staticReqList->nextStaticReq;
241         Rm_osalFree((void *)rmInst->staticInfo.staticReqList->staticReq, sizeof(Rm_ServiceReqInfo));
242         Rm_osalFree((void *)rmInst->staticInfo.staticReqList, sizeof(Rm_ServiceStaticReq));
243         rmInst->staticInfo.staticReqList = nextServiceReq;
244     }
247 Rm_ServiceHandle *Rm_serviceOpenHandle(Rm_Handle rmHandle, int32_t *result)
249     Rm_Inst          *rmInst = (Rm_Inst *)rmHandle;
250     Rm_ServiceHandle *newServiceHandle = NULL;
252     *result = RM_INIT_OK;
254     if (rmInst->serviceHandle == NULL) {
255         newServiceHandle = Rm_osalMalloc (sizeof(Rm_ServiceHandle));
256         if (newServiceHandle) {
257             newServiceHandle->rmHandle = rmHandle;
258             newServiceHandle->Rm_serviceHandler = Rm_serviceHandler;
259             rmInst->serviceHandle = newServiceHandle;
260         }
261         else {
262             *result = RM_INIT_ERROR_SERVICE_HANDLE_MEMORY_ALLOC_FAILED;
263         }
264     }
265     else {
266         *result = RM_INIT_ERROR_SERVICE_HANDLE_ALREADY_ALLOCATED;
267     }
268     return (newServiceHandle);
271 int32_t Rm_serviceCloseHandle(Rm_ServiceHandle *rmServiceHandle)
273     Rm_Inst *rmInst = (Rm_Inst *)rmServiceHandle->rmHandle;
274     int32_t  retVal = RM_INIT_OK;
276     if (rmInst->serviceHandle) {
277         Rm_osalFree((void *)rmServiceHandle, sizeof(Rm_ServiceHandle));
278         rmInst->serviceHandle = NULL;
279     }
280     else {
281         retVal = RM_INIT_ERROR_SERVICE_HANDLE_ALREADY_CLOSED_FOR_INSTANCE;
282     }
283     return(retVal);