]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/rm-lld.git/blob - src/rm_services.c
Transport now directly used to send response packets instead of searching based on...
[keystone-rtos/rm-lld.git] / src / rm_services.c
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     }       
120     
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         if (serviceRequest->resourceNsName) {
135             strncpy(transaction->resourceInfo.nameServerName, serviceRequest->resourceNsName, RM_NAME_MAX_CHARS);
136         }
138         /* Process received transaction */
139         rmProcessRouter(rmInst, transaction);
140             
141         memset((void *)serviceResponse, 0, sizeof(*serviceResponse));
143         if ((rmInst->instType == Rm_instType_SHARED_SERVER) && 
144             (transaction->state == RM_SERVICE_PROCESSING)) {
145             /* Shared Server should always return a fully processed transaction */
146             serviceResponse->serviceState = RM_ERROR_SHARED_INSTANCE_UNFINISHED_REQ;
147             rmTransactionQueueDelete(rmInst, transaction->localId);
148         }
149         else {
150             if ((transaction->state == RM_SERVICE_PROCESSING) && 
151                 (transaction->u.callback.serviceCallback == NULL)) {
152                 /* Block until response is received.  Response will be received in transaction. */
153                 Rm_osalTaskBlock(rmInst->blockHandle);
154             }
156             serviceResponse->rmHandle = rmHandle;
157             serviceResponse->serviceState = transaction->state;
158             /* Owner count will only be set within RM under certain circumstances.  Most of time
159              * it will be RM_RESOURCE_NUM_OWNERS_INVALID */
160             serviceResponse->resourceNumOwners = transaction->resourceInfo.ownerCount;
161             if ((serviceResponse->serviceState == RM_SERVICE_PROCESSING) ||
162                 (serviceResponse->serviceState == RM_SERVICE_APPROVED_STATIC) ||
163                 (serviceResponse->serviceState == RM_SERVICE_PENDING_SERVER_RESPONSE)) {
164                 /* Service still being processed.  Static requests will have their validation responses sent once
165                  * all transports have been established.  Provide transaction ID back to component so it can sort 
166                  * service responses received via callback function */
167                 serviceResponse->serviceId = transaction->localId;
168             }
170             if ((serviceResponse->serviceState == RM_SERVICE_APPROVED) ||
171                 (serviceResponse->serviceState == RM_SERVICE_APPROVED_STATIC)) {
172                 strncpy(serviceResponse->resourceName, transaction->resourceInfo.name, RM_NAME_MAX_CHARS);
173                 serviceResponse->resourceBase = transaction->resourceInfo.base;
174                 serviceResponse->resourceLength = transaction->resourceInfo.length;
175             }
177             /* Transactions still processing not deleted from queue including static transactions which will be 
178              * verified once all transports are up */
179             if ((serviceResponse->serviceState != RM_SERVICE_PROCESSING) &&
180                 (serviceResponse->serviceState != RM_SERVICE_APPROVED_STATIC) &&
181                 (serviceResponse->serviceState != RM_SERVICE_PENDING_SERVER_RESPONSE)) {
182                 rmTransactionQueueDelete(rmInst, transaction->localId);
183             }
184         }
185     }
186     else {
187         serviceResponse->serviceState = RM_ERROR_SERVICE_TRANS_NOT_CREATED;    
188     }
189     RM_SS_INST_WB_EXIT_CS(key);
190     return;
193 /* FUNCTION PURPOSE: Opens the RM instance service handle
194  ***********************************************************************
195  * DESCRIPTION: Returns the service handle for an RM instance.  Only
196  *              one service handle is opened per instance.
197  */
198 Rm_ServiceHandle *Rm_serviceOpenHandle(Rm_Handle rmHandle, int32_t *result)
200     Rm_Inst          *rmInst = (Rm_Inst *)rmHandle;
201     Rm_ServiceHandle *serviceHandle = NULL;
202     void             *key;
203     
204     RM_SS_INST_INV_ENTER_CS(key);
206     *result = RM_OK;
208     serviceHandle = rmInst->serviceHandle;
209     if (serviceHandle == NULL) {
210         serviceHandle = Rm_osalMalloc(sizeof(*serviceHandle));
211         if (serviceHandle) {
212             serviceHandle->rmHandle = rmHandle;
213             serviceHandle->Rm_serviceHandler = Rm_serviceHandler;
214             RM_SS_OBJ_WB(serviceHandle, Rm_ServiceHandle);
215             rmInst->serviceHandle = serviceHandle;
216         }
217         else {
218             *result = RM_ERROR_SERVICE_HANDLE_MEM_ALLOC_FAILED;
219         }
220     }
221     RM_SS_INST_WB_EXIT_CS(key);
222     return (serviceHandle);
225 /* FUNCTION PURPOSE: Closes the RM instance service handle
226  ***********************************************************************
227  * DESCRIPTION: Closes the service handle for an RM instance.
228  */
229 int32_t Rm_serviceCloseHandle(Rm_ServiceHandle *rmServiceHandle)
231     Rm_Inst *rmInst = (Rm_Inst *)rmServiceHandle->rmHandle;
232     int32_t  retVal = RM_OK;
233     void    *key;
235     RM_SS_INST_INV_ENTER_CS(key);
237     if (rmInst->serviceHandle) {
238         Rm_osalFree((void *)rmServiceHandle, sizeof(*rmServiceHandle));
239         rmInst->serviceHandle = NULL;
240     }
241     else {
242         retVal = RM_ERROR_SERVICE_HANDLE_ALREADY_CLOSED;
243     }
244     RM_SS_INST_WB_EXIT_CS(key);
245     return(retVal);