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 Rm_Transaction *transaction;
64 /* Make sure serviceType is valid and that a callback function has been provided */
65 if ((serviceRequest->type < Rm_service_FIRST) ||
66 (serviceRequest->type > Rm_service_LAST))
67 {
68 serviceResponse->serviceState = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;
69 return;
70 }
71 else if (serviceRequest->callback.serviceCallback == NULL)
72 {
73 /* The RM Client and Client Delegate use blocking transports to consult with a
74 * high-level RM agent prior to providing a response to the component. It is
75 * assumed the component's cannot block. Therefore, all responses must go
76 * through the callback function provided by the component. Return an error
77 * if the component does not provide a callback function. */
78 serviceResponse->serviceState = RM_SERVICE_ERROR_CALLBACK_NOT_PROVIDED;
79 return;
80 }
82 /* Create a new transaction */
83 transaction = Rm_transactionQueueAdd(rmInst);
85 if (transaction == NULL)
86 {
87 /* Failed to create a new transaction */
88 serviceResponse->serviceState = RM_SERVICE_ERROR_TRANSACTION_FAILED_TO_ALLOCATE;
89 }
90 else
91 {
92 /* Transfer request information into the transaction */
93 transaction->type = serviceRequest->type;
94 strcpy(transaction->sourceInstName, rmInst->name);
95 transaction->callback.serviceCallback = serviceRequest->callback.serviceCallback;
96 transaction->state = RM_SERVICE_PROCESSING;
97 strcpy(&(transaction->resourceInfo.name)[0], serviceRequest->resourceName);
98 transaction->resourceInfo.base = serviceRequest->resourceBase;
99 transaction->resourceInfo.length = serviceRequest->resourceLength;
100 transaction->resourceInfo.alignment = serviceRequest->resourceAlignment;
101 strcpy(&(transaction->resourceInfo.nsName)[0], serviceRequest->resourceNsName);
103 /* Pass the new transaction to the transaction processor */
104 Rm_transactionProcessor (rmInst, transaction);
106 /* Provide response to the component that requested the service */
107 serviceResponse->serviceState = transaction->state;
108 if (serviceResponse->serviceState == RM_SERVICE_PROCESSING)
109 {
110 /* The service is still being processed. Provide the transaction ID
111 * back to the component so that it can sort service responses received
112 * via the provided callback function */
113 serviceResponse->serviceId = transaction->localId;
114 }
115 else if (serviceResponse->serviceState == RM_SERVICE_APPROVED_AND_COMPLETED)
116 {
117 /* Service was approved and service was an allocate request the resource
118 * data is passed back to the component */
119 if ((transaction->type == Rm_service_RESOURCE_ALLOCATE) ||
120 (transaction->type == Rm_service_RESOURCE_BLOCK_ALLOCATE) ||
121 (transaction->type == Rm_service_RESOURCE_ALLOCATE_BY_NAME))
122 {
123 serviceResponse->resourceBase = transaction->resourceInfo.base;
124 serviceResponse->resourceLength = transaction->resourceInfo.length;
125 }
127 /* Delete the transaction since a response was received immediately */
128 Rm_transactionQueueDelete(rmInst, transaction->localId);
129 }
130 else if ((serviceResponse->serviceState >= RM_SERVICE_DENIED_BEGIN) &&
131 (serviceResponse->serviceState <= RM_SERVICE_DENIED_END))
132 {
133 /* The serviceState field will contain information regarding why the
134 * service was denied. Just delete the transaction since a response was
135 * received immediately */
136 Rm_transactionQueueDelete(rmInst, transaction->localId);
137 }
138 }
140 return;
141 }
143 /* This function is executed when a RM instance receives a response to one of its requests
144 * and the information in the request must be provided to the original requesting component */
145 void Rm_serviceResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)
146 {
147 Rm_ServiceRespInfo serviceResponse;
149 /* The responseTransaction will contain the resultant state details of
150 * the requestTransaction's service request */
151 serviceResponse.serviceState = transaction->state;
152 /* Pass back the ID that was provided to the component when it requested
153 * the service */
154 serviceResponse.serviceId = transaction->localId;
156 /* Service was approved and service was an allocate request. The resource
157 * data is passed back to the component */
158 if ((serviceResponse.serviceState == RM_SERVICE_APPROVED_AND_COMPLETED) &&
159 ((transaction->type == Rm_service_RESOURCE_ALLOCATE) ||
160 (transaction->type == Rm_service_RESOURCE_BLOCK_ALLOCATE) ||
161 (transaction->type == Rm_service_RESOURCE_ALLOCATE_BY_NAME)))
162 {
163 serviceResponse.resourceBase = transaction->resourceInfo.base;
164 serviceResponse.resourceLength = transaction->resourceInfo.length;
165 }
167 /* Issue the callback to the requesting component with the response information */
168 transaction->callback.serviceCallback(&serviceResponse);
170 /* Delete the transaction from the transaction queue */
171 Rm_transactionQueueDelete(rmInst, transaction->localId);
172 return;
173 }
175 /**********************************************************************
176 ********************** Application visible APIs **********************
177 **********************************************************************/
179 void Rm_preMainAllocService(Rm_PreMainAllocInfo *preMainAllocInfo,
180 Rm_ServiceRespInfo *serviceResponse)
181 {
183 }
185 Rm_ServicePort *Rm_getServicePort(Rm_Handle rmHandle)
186 {
187 Rm_ServicePort *newServicePort = NULL;
189 /* Create a new service handle for the specified RM instance */
191 /* Get memory for a new service port from local memory */
192 newServicePort = Rm_osalMalloc (sizeof(Rm_ServicePort));
194 /* Return NULL immediately if malloc returned NULL */
195 if (newServicePort == NULL)
196 {
197 return (newServicePort);
198 }
200 newServicePort->rmHandle = rmHandle;
201 newServicePort->rmService = Rm_serviceHandler;
203 return (newServicePort);
204 }
206 /**
207 @}
208 */