1 /**\r
2 * @file rm.c\r
3 *\r
4 * @brief \r
5 * This is the Resource Manager source.\r
6 *\r
7 * \par\r
8 * ============================================================================\r
9 * @n (C) Copyright 2012, Texas Instruments, Inc.\r
10 * \r
11 * Redistribution and use in source and binary forms, with or without \r
12 * modification, are permitted provided that the following conditions \r
13 * are met:\r
14 *\r
15 * Redistributions of source code must retain the above copyright \r
16 * notice, this list of conditions and the following disclaimer.\r
17 *\r
18 * Redistributions in binary form must reproduce the above copyright\r
19 * notice, this list of conditions and the following disclaimer in the \r
20 * documentation and/or other materials provided with the \r
21 * distribution.\r
22 *\r
23 * Neither the name of Texas Instruments Incorporated nor the names of\r
24 * its contributors may be used to endorse or promote products derived\r
25 * from this software without specific prior written permission.\r
26 *\r
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
31 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
32 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
33 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
38 *\r
39 * \par\r
40 */\r
41 \r
42 /* RM Types */\r
43 #include <ti/drv/rm/rm_types.h>\r
44 \r
45 /* RM external includes */\r
46 #include <ti/drv/rm/rm.h>\r
47 #include <ti/drv/rm/rmservices.h>\r
48 #include <ti/drv/rm/rmtransport.h>\r
49 #include <ti/drv/rm/rmpolicy.h>\r
50 \r
51 /* RM internal includes */\r
52 #include <ti/drv/rm/include/rmloc.h>\r
53 \r
54 /* RM OSAL layer */\r
55 #include <rm_osal.h>\r
56 \r
57 /**********************************************************************\r
58 ************************** Globals ***********************************\r
59 **********************************************************************/\r
60 \r
61 /* Place QMSS PDSP permissions array */\r
62 #pragma DATA_SECTION (rmQmssPdspFirmwarePerms, ".rm");\r
63 #pragma DATA_ALIGN (rmQmssPdspFirmwarePerms, 128)\r
64 Rm_Perms rmQmssPdspFirmwarePerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_FIRMWARE_PDSPS, Rm_Perms)];\r
65 \r
66 \r
67 /** @brief Global Variable which describes the RM Version Information */\r
68 const char rmVersionStr[] = RM_VERSION_STR ":" __DATE__ ":" __TIME__;\r
69 \r
70 /**********************************************************************\r
71 ********************** Internal Functions ****************************\r
72 **********************************************************************/\r
73 \r
74 /* At the very least the transaction ID needs to be provided to create a transaction */\r
75 Rm_Transaction *Rm_transactionQueueAdd(Rm_Inst *rmInst, uint32_t transactionId)\r
76 {\r
77 Rm_Transaction *transactionQueue = (Rm_Transaction *)rmInst->transactionQueue;\r
78 Rm_Transaction *newTransaction = NULL;\r
79 void *key;\r
80 \r
81 /* Lock access to the RM instance's transaction queue */\r
82 key = Rm_osalLocalCsEnter();\r
83 \r
84 /* Get memory for a new transaction from local memory */\r
85 newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction), false);\r
86 \r
87 /* Return if the memory allocated for the transaction entry is NULL */\r
88 if (newTransaction == NULL)\r
89 {\r
90 Rm_osalLocalCsExit(key);\r
91 return(newTransaction);\r
92 }\r
93 \r
94 /* Clear the transaction */\r
95 memset((void *)newTransaction, 0, sizeof(Rm_Transaction));\r
96 \r
97 /* Populate transaction with the provided ID */\r
98 newTransaction->id = transactionId;\r
99 /* New transaction's nextTransaction pointer will always be NULL */\r
100 newTransaction->nextTransaction = NULL; \r
101 \r
102 /* Check if there are any transactions in the transaction queue */\r
103 if (transactionQueue)\r
104 {\r
105 /* At least one transaction in the transaction queue. Add the new entry to the \r
106 * end of the transaction queue */\r
107 while (transactionQueue->nextTransaction != NULL)\r
108 {\r
109 /* Traverse the list until arriving at the last transaction */\r
110 transactionQueue = transactionQueue->nextTransaction;\r
111 }\r
112 \r
113 /* Add the new transaction to the end of the queue */\r
114 transactionQueue->nextTransaction = newTransaction;\r
115 }\r
116 else\r
117 {\r
118 /* The transaction queue does not currently exist. The new transaction is the \r
119 * first transaction */\r
120 rmInst->transactionQueue = newTransaction;\r
121 }\r
122 \r
123 Rm_osalLocalCsExit(key);\r
124 return (newTransaction);\r
125 }\r
126 \r
127 Rm_Transaction *Rm_transactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)\r
128 {\r
129 Rm_Transaction *transaction = (Rm_Transaction *)rmInst->transactionQueue;\r
130 void *key;\r
131 \r
132 /* Make sure there is at least one transaction in the transaction queue */\r
133 if (transaction != NULL)\r
134 {\r
135 /* Find the transaction ID within the specified RM instance's transaction queue.\r
136 * If the end of the transaction queue is reached without finding the transaction the \r
137 * transaction pointer will be NULL */\r
138 while (transaction != NULL)\r
139 {\r
140 if (transaction->transactionId == transactionId)\r
141 {\r
142 /* Match: break out of loop and return the transaction */\r
143 break; \r
144 }\r
145 transaction = transaction->nextTransaction;\r
146 }\r
147 }\r
148 \r
149 return (transaction);\r
150 }\r
151 \r
152 int32_t Rm_transactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)\r
153 {\r
154 Rm_Transaction *transaction = (Rm_Transaction *) rmInst->transactionQueue;\r
155 Rm_Transaction *prevTransaction = NULL;\r
156 void *key;\r
157 \r
158 /* Lock access to the RM instance's transaction queue */\r
159 key = Rm_osalLocalCsEnter();\r
160 \r
161 /* Make sure there is at least one entry in the transaction queue */\r
162 if (transaction == NULL)\r
163 {\r
164 Rm_osalLocalCsExit(key);\r
165 return (RM_SERVICE_ERROR_NO_TRANSACTIONS_IN_QUEUE);\r
166 }\r
167 \r
168 /* Find the transaction ID within the specified RM instance's transaction queue. */\r
169 while (transaction != NULL)\r
170 {\r
171 if (transaction->transactionId == transactionId)\r
172 {\r
173 /* Match: break out of loop and delete the transaction */\r
174 break; \r
175 }\r
176 \r
177 prevTransaction = transaction;\r
178 transaction = transaction->nextEntry;\r
179 }\r
180 \r
181 /* Traversed entire queue but did not find transaction */\r
182 if (transaction == NULL)\r
183 {\r
184 Rm_osalLocalCsExit(key);\r
185 return (RM_SERVICE_ERROR_SERVICE_TRANSACTION_DOES_NOT_EXIST);\r
186 }\r
187 else\r
188 {\r
189 /* Delete the transaction */\r
190 if ((prevTransaction == NULL) && transaction->nextTransaction)\r
191 {\r
192 /* Transaction to be deleted exists at start of transaction queue. Map second\r
193 * transaction to be start of transaction queue as long as there are more than\r
194 * one transactions */\r
195 rmInst->transactionQueue = transaction->nextTransaction;\r
196 }\r
197 else\r
198 {\r
199 /* Transaction to be deleted is in the middle or at end of the queue. Adjust \r
200 * adjacent transaction pointers. This covers the case where the transaction to be \r
201 * removed is at the end of the queue. */\r
202 prevTransaction->nextTransaction = transaction->nextTransaction;\r
203 }\r
204 \r
205 /* Free the memory associated with the transaction. */\r
206 Rm_osalFree((void *)transaction, sizeof(Rm_Transaction), false);\r
207 }\r
208 \r
209 Rm_osalLocalCsExit(key);\r
210 return (RM_SERVICE_ACTION_OKAY);\r
211 }\r
212 \r
213 /* Function used to send RM response transactions to lower level agents */\r
214 void Rm_transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction,\r
215 Rm_TransactionReceipt *receipt)\r
216 {\r
217 Rm_TransportNode *dstTransportNode = NULL;\r
218 Rm_Packet *rmPkt = NULL;\r
219 \r
220 /* Find the transport for the RM instance that sent the request. */\r
221 dstTransportNode = Rm_transportNodeFindRemoteName(rmInst, transaction->sourceInstName);\r
222 \r
223 /* Create a RM packet using the service information */\r
224 switch (transaction->type)\r
225 {\r
226 case Rm_service_RESOURCE_ALLOCATE:\r
227 case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
228 case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
229 case Rm_service_RESOURCE_FREE:\r
230 case Rm_service_RESOURCE_BLOCK_FREE:\r
231 case Rm_service_RESOURCE_FREE_BY_NAME:\r
232 rmPkt = Rm_transportCreateResourceResponsePkt(rmInst, dstTransportNode, \r
233 transaction, receipt);\r
234 break;\r
235 case Rm_service_RESOURCE_MAP_TO_NAME:\r
236 case Rm_service_RESOURCE_UNMAP_NAME:\r
237 rmPkt = Rm_transportCreateNsResponsePkt(rmInst, dstTransportNode,\r
238 transaction, receipt);\r
239 break;\r
240 default:\r
241 /* Invalid service type. Flag the error and return */\r
242 receipt->serviceResult = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
243 break;\r
244 }\r
245 \r
246 if (receipt->serviceResult <= RM_SERVICE_ERROR_BASE)\r
247 {\r
248 /* Delete the transaction and return immediately because an error occurred \r
249 * allocating the packet */\r
250 Rm_transactionQueueDelete(rmInst, transaction->id);\r
251 return;\r
252 }\r
253 \r
254 /* Send the RM packet to the application transport */\r
255 if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt))\r
256 {\r
257 /* Non-NULL value returned by transport send. An error occurred\r
258 * in the transport while attempting to send the packet.*/\r
259 receipt->serviceResult = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
260 /* Clean up the packet */\r
261 if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\r
262 {\r
263 /* Non-NULL value returned by transport packet free. Flag the\r
264 * error */\r
265 receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
266 }\r
267 return;\r
268 }\r
269 \r
270 /* Fill out the receipt information and delete the transaction */\r
271 receipt->serviceResult = transaction->details;\r
272 Rm_transactionQueueDelete(rmInst, transaction->id);\r
273 }\r
274 \r
275 void Rm_allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction,\r
276 Rm_TransactionReceipt *receipt)\r
277 {\r
278 \r
279 }\r
280 \r
281 void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction,\r
282 Rm_TransactionReceipt *receipt)\r
283 {\r
284 \r
285 }\r
286 \r
287 \r
288 /* Function used to forward RM transactions to higher level agents */\r
289 void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction,\r
290 Rm_TransactionReceipt *receipt)\r
291 {\r
292 Rm_TransportNode *dstTransportNode = NULL;\r
293 Rm_Packet *rmPkt = NULL;\r
294 \r
295 /* Make sure the RM instance has a transport registered with a higher level agent */\r
296 if (rmInst->registeredWithDelegateOrServer == false)\r
297 {\r
298 receipt->serviceResult = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER;\r
299 return;\r
300 }\r
301 \r
302 /* Find the transport for the higher level agent. Check for a connection to a Client Delegate\r
303 * or a Server. Clients will be connected to either a Client Delegate or a Server. Client\r
304 * Delegates will be connected to a Server. */\r
305 if (rmInst->instType == Rm_instType_CLIENT)\r
306 {\r
307 dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_CLIENT_DELEGATE);\r
308 } \r
309 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
310 {\r
311 dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_SERVER);\r
312 }\r
313 \r
314 /* Create a RM packet using the service information */\r
315 switch (transaction->type)\r
316 {\r
317 case Rm_service_RESOURCE_ALLOCATE:\r
318 case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
319 case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
320 case Rm_service_RESOURCE_FREE:\r
321 case Rm_service_RESOURCE_BLOCK_FREE:\r
322 case Rm_service_RESOURCE_FREE_BY_NAME:\r
323 rmPkt = Rm_transportCreateResourceReqPkt(rmInst, dstTransportNode, \r
324 transaction, receipt);\r
325 break;\r
326 case Rm_service_RESOURCE_MAP_TO_NAME:\r
327 case Rm_service_RESOURCE_UNMAP_NAME:\r
328 rmPkt = Rm_transportCreateNsRequestPkt(rmInst, dstTransportNode,\r
329 transaction, receipt);\r
330 break;\r
331 default:\r
332 /* Invalid service type. Flag the error and return */\r
333 receipt->serviceResult = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
334 break;\r
335 }\r
336 \r
337 if (receipt->serviceResult <= RM_SERVICE_ERROR_BASE)\r
338 {\r
339 /* Return immediately because an error occurred allocating the packet */\r
340 return;\r
341 }\r
342 \r
343 /* Switch the queued transaction to the awaiting response state */\r
344 transaction->state = Rm_transactionState_AWAITING_RESPONSE;\r
345 \r
346 /* Send the RM packet to the application transport */\r
347 if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt))\r
348 {\r
349 /* Non-NULL value returned by transport send. An error occurred\r
350 * in the transport while attempting to send the packet.*/\r
351 receipt->serviceResult = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
352 /* Clean up the packet */\r
353 if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\r
354 {\r
355 /* Non-NULL value returned by transport packet free. Flag the\r
356 * error */\r
357 receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
358 }\r
359 return;\r
360 }\r
361 \r
362 /* Inform requesting component that the service is being forwarded to a higher lever\r
363 * RM agent for processing. The result of the service will be provided to the \r
364 * component via the specified callback function */\r
365 receipt->serviceResult = RM_SERVICE_PROCESSING;\r
366 receipt->serviceId = transaction->id;\r
367 }\r
368 \r
369 void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction, \r
370 Rm_TransactionReceipt *receipt)\r
371 {\r
372 Rm_Transaction *queuedTransaction = NULL;\r
373 \r
374 /* Handle auto-forwarded transactions. These transactions include:\r
375 * - All request transactions received on Clients are forwarded to the Client Delegate\r
376 * - NameServer requests received on the Client Delegate are forwarded to the Server */\r
377 if ((rmInst->instType == Rm_instType_CLIENT) ||\r
378 ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
379 (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||\r
380 (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)))\r
381 {\r
382 /* Check if the new transaction's ID matches any transactions waiting for\r
383 * responses. A transaction received as a response will have an ID that \r
384 * matches the transaction that originated the request packet */\r
385 if (queuedTransaction = Rm_transactionQueueFind(rmInst, transaction->id))\r
386 {\r
387 if (queuedTransaction->state == Rm_transactionState_AWAITING_RESPONSE)\r
388 {\r
389 if (rmInst->instType == Rm_instType_CLIENT)\r
390 {\r
391 /* Client found a transaction awaiting a response. Pass both transactions\r
392 * to the service responder for response processing */\r
393 Rm_serviceResponder(rmInst, transaction, queuedTransaction, receipt);\r
394 }\r
395 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
396 {\r
397 /* Client Delegate found a NameServer transaction awaiting a response. Send the \r
398 * response to either the transaction or service responder based on the \r
399 * source instance */\r
400 if (strcmp(queuedTransaction->sourceInstName, rmInst->name)\r
401 {\r
402 /* NameServer transaction originated from another instance. Use the \r
403 * transaction responder to send the NameServer result to the source instance.\r
404 * Need to transfer the NameServer result details to the request transaction \r
405 * which will be reused for the response. */\r
406 queuedTransaction->details = transaction->details;\r
407 Rm_transactionResponder(rmInst, queuedTransaction, receipt);\r
408 /* Delete the response transaction */\r
409 Rm_transactionQueueDelete(rmInst, transaction->id); \r
410 }\r
411 else\r
412 {\r
413 /* NameServer request originated on the Client Delegate instance. Send to the\r
414 * service responder */\r
415 Rm_serviceResponder(rmInst, transaction, queuedTransaction,\r
416 receipt);\r
417 }\r
418 }\r
419 }\r
420 else\r
421 {\r
422 /* Request transaction was not in the awaiting response state. Flag the\r
423 * error in the receipt and return */\r
424 receipt->serviceResult = RM_SERVICE_ERROR_INVALID_REQUEST_TRANSACTION_STATE_UPON_RESPONSE;\r
425 }\r
426 }\r
427 else\r
428 {\r
429 /* This is a new transaction. Make sure the transaction is not a \r
430 * response transaction sent to the wrong RM instance */\r
431 if ((transaction->state == Rm_transactionState_RESOURCE_APPROVED) ||\r
432 (transaction->state == Rm_transactionState_RESOURCE_DENIED))\r
433 {\r
434 /* No matching request transaction. This transaction result was sent to the\r
435 * wrong RM instance. Flag the error in the receipt and return */\r
436 receipt->serviceResult = RM_SERVICE_ERROR_INVALID_TRANSACTION_RECEIVED_ON_CLIENT;\r
437 }\r
438 else\r
439 {\r
440 /* All service requests on Clients are forwarded to the higher level RM Client \r
441 * Delegate. NameServer requests on Client Delegates are forwarded to the Server. */\r
442 Rm_transactionForwarder(rmInst, transaction, receipt);\r
443 }\r
444 }\r
445 }\r
446 else\r
447 {\r
448 /* Client Delegate and Server transaction processors. */\r
449 switch (transaction->type)\r
450 {\r
451 case Rm_service_RESOURCE_ALLOCATE:\r
452 case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
453 case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
454 /* Run the transaction through the response handler to take care of any\r
455 * transactions that are responses to sent allocation requests. */\r
456 if (queuedTransaction = Rm_transactionQueueFind(rmInst, transaction->id))\r
457 {\r
458 if (queuedTransaction->state == Rm_transactionState_AWAITING_RESPONSE)\r
459 {\r
460 /* If source instance name does not match the current instance\r
461 * name the allocation request came from a client. The result\r
462 * must be sent back to the Client */\r
463 if (strcmp(queuedTransaction->sourceInstName, rmInst->name))\r
464 {\r
465 /* Names don't match. Copy the allocation response resource data \r
466 * into the original transaction and send it back to the Client */\r
467 queuedTransaction->details = transaction->details;\r
468 memcpy ((void *)&(queuedTransaction->resourceInfo), \r
469 (void *)&(transaction->resourceInfo), sizeof(Rm_ResourceInfo));\r
470 Rm_transactionResponder(rmInst, queuedTransaction, receipt);\r
471 /* Delete the response transaction */\r
472 Rm_transactionQueueDelete(rmInst, transaction->id);\r
473 }\r
474 else\r
475 {\r
476 /* Resource allocation request originated locally on Client Delegate\r
477 * instance. Send the response via the service responder. */\r
478 Rm_serviceResponder(rmInst, transaction, queuedTransaction,\r
479 receipt); \r
480 }\r
481 }\r
482 else\r
483 {\r
484 /* Request transaction was not in the awaiting response state. Flag the\r
485 * error in the receipt and return */\r
486 receipt->serviceResult = RM_SERVICE_ERROR_INVALID_REQUEST_TRANSACTION_STATE_UPON_RESPONSE;\r
487 }\r
488 \r
489 }\r
490 else\r
491 {\r
492 /* This is a new transaction request originating from an RM instance with fewer\r
493 * allocate/free privileges. Run the allocation handler to see if the resource\r
494 * request can be handled locally or if it needs to be forwarded to a higher level\r
495 * agent */\r
496 Rm_allocationHandler(rmInst, transaction, receipt);\r
497 }\r
498 break;\r
499 case Rm_service_RESOURCE_FREE:\r
500 case Rm_service_RESOURCE_BLOCK_FREE:\r
501 case Rm_service_RESOURCE_FREE_BY_NAME:\r
502 /* Run the transaction through the response handler to take care of any\r
503 * transactions that are responses to sent free requests. */\r
504 if (queuedTransaction = Rm_transactionQueueFind(rmInst, transaction->id))\r
505 {\r
506 if (queuedTransaction->state == Rm_transactionState_AWAITING_RESPONSE)\r
507 {\r
508 /* If source instance name does not match the current instance\r
509 * name the allocation request came from a client. The result\r
510 * must be sent back to the Client */\r
511 if (strcmp(queuedTransaction->sourceInstName, rmInst->name))\r
512 {\r
513 /* Names don't match. Copy the free response resource data \r
514 * into the original transaction and send it back to the Client */\r
515 queuedTransaction->details = transaction->details;\r
516 memcpy ((void *)&(queuedTransaction->resourceInfo), \r
517 (void *)&(transaction->resourceInfo), sizeof(Rm_ResourceInfo));\r
518 Rm_transactionResponder(rmInst, queuedTransaction, receipt);\r
519 /* Delete the response transaction */\r
520 Rm_transactionQueueDelete(rmInst, transaction->id);\r
521 }\r
522 else\r
523 {\r
524 /* Resource free request originated locally on Client Delegate\r
525 * instance. Send the response via the service responder. */\r
526 Rm_serviceResponder(rmInst, transaction, queuedTransaction,\r
527 receipt); \r
528 }\r
529 }\r
530 else\r
531 {\r
532 /* Request transaction was not in the awaiting response state. Flag the\r
533 * error in the receipt and return */\r
534 receipt->serviceResult = RM_SERVICE_ERROR_INVALID_REQUEST_TRANSACTION_STATE_UPON_RESPONSE;\r
535 }\r
536 \r
537 }\r
538 else\r
539 {\r
540 /* This is a new transaction request originating from an RM instance with fewer\r
541 * allocate/free privileges. Run the free handler to see if the resource\r
542 * request can be handled locally or if it needs to be forwarded to a higher level\r
543 * agent */\r
544 Rm_freeHandler(rmInst, transaction, receipt);\r
545 }\r
546 \r
547 break;\r
548 case Rm_service_RESOURCE_MAP_TO_NAME:\r
549 /* Server is the only RM instance capable of adding NameServer objects */\r
550 if (rmInst->instType == Rm_instType_SERVER)\r
551 {\r
552 /* Create a new NameServer object with the request transaction information */\r
553 Rm_nsAddObject(rmInst, transaction, receipt);\r
554 \r
555 /* Return the result of the NameServer addition to the RM instance\r
556 * that requested it */\r
557 transaction->details = receipt->serviceResult;\r
558 \r
559 /* If source instance name does not match the current instance\r
560 * name the NameServer request came from a Client or Client Delegate. The \r
561 * result must be sent back to the Client or Client Delegate */\r
562 if (strcmp(transaction->sourceInstName, rmInst->name))\r
563 {\r
564 Rm_transactionResponder(rmInst, queuedTransaction, receipt);\r
565 }\r
566 else\r
567 {\r
568 /* NameServer addition request originated locally on Server\r
569 * instance. Send the response via the service responder. In this case\r
570 * the request transaction will be passed as NULL since the request\r
571 * is being reused as the response */\r
572 Rm_serviceResponder(rmInst, transaction, NULL, receipt); \r
573 }\r
574 }\r
575 else\r
576 {\r
577 receipt->serviceResult = RM_SERVICE_ERROR_NAMESERVER_OBJECT_CREATE_ON_INVALID_INSTANCE;\r
578 }\r
579 break;\r
580 case Rm_service_RESOURCE_UNMAP_NAME:\r
581 /* Server is the only RM instance capable of deleting NameServer objects */\r
582 if (rmInst->instType == Rm_instType_SERVER)\r
583 {\r
584 /* Delete an existing NameServer object with the request transaction information */\r
585 Rm_nsDeleteObject(rmInst, transaction, receipt);\r
586 \r
587 /* Return the result of the NameServer deletion to the RM instance\r
588 * that requested it */\r
589 transaction->details = receipt->serviceResult;\r
590 \r
591 /* If source instance name does not match the current instance\r
592 * name the NameServer request came from a Client or Client Delegate. The \r
593 * result must be sent back to the Client or Client Delegate */\r
594 if (strcmp(transaction->sourceInstName, rmInst->name))\r
595 {\r
596 Rm_transactionResponder(rmInst, queuedTransaction, receipt);\r
597 }\r
598 else\r
599 {\r
600 /* NameServer delete request originated locally on Server\r
601 * instance. Send the response via the service responder. In this case\r
602 * the request transaction will be passed as NULL since the request\r
603 * is being reused as the response */\r
604 Rm_serviceResponder(rmInst, transaction, NULL, receipt); \r
605 } \r
606 }\r
607 else\r
608 {\r
609 receipt->serviceResult = RM_SERVICE_ERROR_NAMESERVER_OBJECT_DELETE_ON_INVALID_INSTANCE;\r
610 }\r
611 break;\r
612 }\r
613 }\r
614 }\r
615 \r
616 /**********************************************************************\r
617 ********************** Application visible APIs **********************\r
618 **********************************************************************/\r
619 \r
620 Rm_Handle Rm_init(Rm_InitCfg *initCfg)\r
621 {\r
622 Rm_Inst *rmInst;\r
623 \r
624 /* Instance creation checks. Add one to strlen calculation for null character */\r
625 if ((strlen(initCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS)\r
626 {\r
627 /* Failure: Instance name is too big */\r
628 return (NULL);\r
629 }\r
630 \r
631 /* Get memory for RM instance from local memory */\r
632 rmInst = Rm_osalMalloc (sizeof(Rm_Inst), false);\r
633 /* Populate instance based on input parameters */\r
634 strcpy (&rmInst->name[0], initCfg->instName);\r
635 rmInst->instType = initCfg->instType;\r
636 rmInst->instState = RM_state_IDLE;\r
637 rmInst->registeredWithDelegateOrServer = false;\r
638 rmInst->serviceCallback = NULL;\r
639 \r
640 /* The transport APIs must be provided */\r
641 if ((initCfg->rmAllocPktFuncPtr == NULL) ||\r
642 (initCfg->rmFreePktFuncPtr == NULL) ||\r
643 (initCfg->rmSendFuncPtr == NULL) ||\r
644 (initCfg->rmReceiveFuncPtr == NULL) ||\r
645 (initCfg->rmNumPktsReceivedFuncPtr == NULL))\r
646 {\r
647 return (NULL);\r
648 }\r
649 \r
650 /* Populate the instance transport callouts */\r
651 rmInst->transport.rmAllocPkt = initCfg->rmAllocPktFuncPtr;\r
652 rmInst->transport.rmFreePkt = initCfg->rmFreePktFuncPtr;\r
653 rmInst->transport.rmSend = initCfg->rmSendFuncPtr;\r
654 rmInst->transport.rmReceive = initCfg->rmReceiveFuncPtr;\r
655 rmInst->transport.rmNumPktsReceived = initCfg->rmNumPktsReceivedFuncPtr;\r
656 \r
657 /* Initialize the transport routing map linked list pointer to NULL. The linked list\r
658 * nodes will be created when the application registers transports */\r
659 rmInst->routeMap = NULL;\r
660 \r
661 /* Initialize the transaction queue linked list pointer to NULL. The linked list\r
662 * nodes will be created when the transactions are forwarded to higher level RM\r
663 * agents. */\r
664 rmInst->transactionQueue= NULL;\r
665 \r
666 /* RM Server specific actions */\r
667 if (rmInst->instType == Rm_instType_SERVER)\r
668 {\r
669 /* parse DTB, etc */\r
670 }\r
671 \r
672 /* Instance startup policies are only used for Servers and Client Delegates */\r
673 if (rmInst->instType != Rm_instType_CLIENT)\r
674 {\r
675 rmInst->instPolicy = initCfg->startupPolicy;\r
676 \r
677 /* Store policy via policy APIs ... */\r
678 }\r
679 \r
680 /* Return the RM Handle */\r
681 return ((Rm_Handle) rmInst);\r
682 }\r
683 \r
684 uint32_t Rm_getVersion (void)\r
685 {\r
686 return RM_VERSION_ID;\r
687 }\r
688 \r
689 \r
690 const char* Rm_getVersionStr (void)\r
691 {\r
692 return rmVersionStr;\r
693 }\r
694 \r
695 /**\r
696 @}\r
697 */\r