28e58fcb1349c6b32a95f2c18fa2e44e5f98ac6a
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/rm_services.h>\r
48 #include <ti/drv/rm/rm_transport.h>\r
49 #include <ti/drv/rm/rm_policy.h>\r
50 \r
51 /* RM internal includes */\r
52 #include <ti/drv/rm/include/rm_loc.h>\r
53 #include <ti/drv/rm/include/rm_transportloc.h>\r
54 #include <ti/drv/rm/include/rm_servicesloc.h>\r
55 #include <ti/drv/rm/include/rm_nameserverloc.h>\r
56 \r
57 /* RM OSAL layer */\r
58 #include <rm_osal.h>\r
59 \r
60 /**********************************************************************\r
61 ************************** Globals ***********************************\r
62 **********************************************************************/\r
63 #if 0\r
64 /* Place QMSS PDSP permissions array */\r
65 #pragma DATA_SECTION (rmQmssPdspFirmwarePerms, ".rm");\r
66 #pragma DATA_ALIGN (rmQmssPdspFirmwarePerms, 128)\r
67 Rm_Perms rmQmssPdspFirmwarePerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_FIRMWARE_PDSPS, Rm_Perms)];\r
68 #endif\r
69 \r
70 /** @brief Global Variable which describes the RM Version Information */\r
71 const char rmVersionStr[] = RM_VERSION_STR ":" __DATE__ ":" __TIME__;\r
72 \r
73 /**********************************************************************\r
74 ********************** Internal Functions ****************************\r
75 **********************************************************************/\r
76 \r
77 /* At the very least the transaction ID needs to be provided to create a transaction */\r
78 Rm_Transaction *Rm_transactionQueueAdd(Rm_Inst *rmInst, uint32_t transactionId)\r
79 {\r
80 Rm_Transaction *transactionQueue = (Rm_Transaction *)rmInst->transactionQueue;\r
81 Rm_Transaction *newTransaction = NULL;\r
82 void *key;\r
83 \r
84 /* Lock access to the RM instance's transaction queue */\r
85 key = Rm_osalCsEnter();\r
86 \r
87 /* Get memory for a new transaction from local memory */\r
88 newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction), false);\r
89 \r
90 /* Return if the memory allocated for the transaction entry is NULL */\r
91 if (newTransaction == NULL)\r
92 {\r
93 Rm_osalCsExit(key);\r
94 return(newTransaction);\r
95 }\r
96 \r
97 /* Clear the transaction */\r
98 memset((void *)newTransaction, 0, sizeof(Rm_Transaction));\r
99 \r
100 /* Populate transaction with the provided ID */\r
101 newTransaction->id = transactionId;\r
102 /* New transaction's nextTransaction pointer will always be NULL */\r
103 newTransaction->nextTransaction = NULL; \r
104 \r
105 /* Check if there are any transactions in the transaction queue */\r
106 if (transactionQueue)\r
107 {\r
108 /* At least one transaction in the transaction queue. Add the new entry to the \r
109 * end of the transaction queue */\r
110 while (transactionQueue->nextTransaction != NULL)\r
111 {\r
112 /* Traverse the list until arriving at the last transaction */\r
113 transactionQueue = transactionQueue->nextTransaction;\r
114 }\r
115 \r
116 /* Add the new transaction to the end of the queue */\r
117 transactionQueue->nextTransaction = newTransaction;\r
118 }\r
119 else\r
120 {\r
121 /* The transaction queue does not currently exist. The new transaction is the \r
122 * first transaction */\r
123 rmInst->transactionQueue = newTransaction;\r
124 }\r
125 \r
126 Rm_osalCsExit(key);\r
127 return (newTransaction);\r
128 }\r
129 \r
130 Rm_Transaction *Rm_transactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)\r
131 {\r
132 Rm_Transaction *transaction = (Rm_Transaction *)rmInst->transactionQueue;\r
133 \r
134 /* Make sure there is at least one transaction in the transaction queue */\r
135 if (transaction != NULL)\r
136 {\r
137 /* Find the transaction ID within the specified RM instance's transaction queue.\r
138 * If the end of the transaction queue is reached without finding the transaction the \r
139 * transaction pointer will be NULL */\r
140 while (transaction != NULL)\r
141 {\r
142 if (transaction->id == transactionId)\r
143 {\r
144 /* Match: break out of loop and return the transaction */\r
145 break; \r
146 }\r
147 transaction = transaction->nextTransaction;\r
148 }\r
149 }\r
150 \r
151 return (transaction);\r
152 }\r
153 \r
154 int32_t Rm_transactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)\r
155 {\r
156 Rm_Transaction *transaction = (Rm_Transaction *) rmInst->transactionQueue;\r
157 Rm_Transaction *prevTransaction = NULL;\r
158 void *key;\r
159 \r
160 /* Lock access to the RM instance's transaction queue */\r
161 key = Rm_osalCsEnter();\r
162 \r
163 /* Make sure there is at least one entry in the transaction queue */\r
164 if (transaction == NULL)\r
165 {\r
166 Rm_osalCsExit(key);\r
167 return (RM_SERVICE_ERROR_NO_TRANSACTIONS_IN_QUEUE);\r
168 }\r
169 \r
170 /* Find the transaction ID within the specified RM instance's transaction queue. */\r
171 while (transaction != NULL)\r
172 {\r
173 if (transaction->id == transactionId)\r
174 {\r
175 /* Match: break out of loop and delete the transaction */\r
176 break; \r
177 }\r
178 \r
179 prevTransaction = transaction;\r
180 transaction = transaction->nextTransaction;\r
181 }\r
182 \r
183 /* Traversed entire queue but did not find transaction */\r
184 if (transaction == NULL)\r
185 {\r
186 Rm_osalCsExit(key);\r
187 return (RM_SERVICE_ERROR_SERVICE_TRANSACTION_DOES_NOT_EXIST);\r
188 }\r
189 else\r
190 {\r
191 /* Delete the transaction */\r
192 if ((prevTransaction == NULL) && transaction->nextTransaction)\r
193 {\r
194 /* Transaction to be deleted exists at start of transaction queue. Map second\r
195 * transaction to be start of transaction queue as long as there are more than\r
196 * one transactions */\r
197 rmInst->transactionQueue = transaction->nextTransaction;\r
198 }\r
199 else\r
200 {\r
201 /* Transaction to be deleted is in the middle or at end of the queue. Adjust \r
202 * adjacent transaction pointers. This covers the case where the transaction to be \r
203 * removed is at the end of the queue. */\r
204 prevTransaction->nextTransaction = transaction->nextTransaction;\r
205 }\r
206 \r
207 /* Free the memory associated with the transaction. */\r
208 Rm_osalFree((void *)transaction, sizeof(Rm_Transaction), false);\r
209 }\r
210 \r
211 Rm_osalCsExit(key);\r
212 return (RM_SERVICE_ACTION_OKAY);\r
213 }\r
214 \r
215 uint32_t Rm_transactionGetSequenceNum(Rm_Inst *rmInst)\r
216 {\r
217 uint32_t sequenceNum = 0;\r
218 void *key;\r
219 \r
220 /* Lock access to the RM instance */\r
221 key = Rm_osalCsEnter();\r
222 \r
223 /* Get the next sequence number and then incement. Overflow is okay since\r
224 * it just restarts the sequence number count. */\r
225 sequenceNum = rmInst->transactionSeqNum++;\r
226 \r
227 Rm_osalCsExit(key);\r
228 return (sequenceNum);\r
229 }\r
230 \r
231 /* Function used to send RM response transactions to lower level agents */\r
232 void Rm_transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction,\r
233 Rm_TransactionReceipt *receipt)\r
234 {\r
235 Rm_TransportNode *dstTransportNode = NULL;\r
236 Rm_Packet *rmPkt = NULL;\r
237 \r
238 /* Find the transport for the RM instance that sent the request. */\r
239 dstTransportNode = Rm_transportNodeFindRemoteName(rmInst, transaction->sourceInstName);\r
240 \r
241 /* Create a RM packet using the service information */\r
242 switch (transaction->type)\r
243 {\r
244 case Rm_service_RESOURCE_ALLOCATE:\r
245 case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
246 case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
247 case Rm_service_RESOURCE_FREE:\r
248 case Rm_service_RESOURCE_BLOCK_FREE:\r
249 case Rm_service_RESOURCE_FREE_BY_NAME:\r
250 rmPkt = Rm_transportCreateResourceResponsePkt(rmInst, dstTransportNode, \r
251 transaction, receipt);\r
252 break;\r
253 case Rm_service_RESOURCE_MAP_TO_NAME:\r
254 case Rm_service_RESOURCE_UNMAP_NAME:\r
255 rmPkt = Rm_transportCreateNsResponsePkt(rmInst, dstTransportNode,\r
256 transaction, receipt);\r
257 break;\r
258 default:\r
259 /* Invalid service type. Flag the error and return */\r
260 receipt->serviceResult = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
261 break;\r
262 }\r
263 \r
264 if (receipt->serviceResult <= RM_SERVICE_ERROR_BASE)\r
265 {\r
266 /* Delete the transaction and return immediately because an error occurred \r
267 * allocating the packet */\r
268 Rm_transactionQueueDelete(rmInst, transaction->id);\r
269 return;\r
270 }\r
271 \r
272 /* Send the RM packet to the application transport */\r
273 if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL)\r
274 {\r
275 /* Negative value returned by transport send. An error occurred\r
276 * in the transport while attempting to send the packet.*/\r
277 receipt->serviceResult = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
278 /* Clean up the packet */\r
279 if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\r
280 {\r
281 /* Non-NULL value returned by transport packet free. Flag the\r
282 * error */\r
283 receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
284 }\r
285 return;\r
286 }\r
287 \r
288 /* Fill out the receipt information and delete the transaction */\r
289 receipt->serviceResult = transaction->details;\r
290 Rm_transactionQueueDelete(rmInst, transaction->id);\r
291 }\r
292 \r
293 void Rm_allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction,\r
294 Rm_TransactionReceipt *receipt)\r
295 {\r
296 if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
297 {\r
298 #if 0 \r
299 /* Check local policy to see if the request can be satisfied with the\r
300 * resources stored locally */\r
301 Rm_policy...API()\r
302 \r
303 if (policy check approves the resource)\r
304 {\r
305 /* call the allocator to allocate the resource */\r
306 if (allocator returns resource)\r
307 {\r
308 /* Populate the receipt with the allocated resources and the result */\r
309 receipt->serviceResult = approve reason;\r
310 receipt->serviceId = transaction->id;\r
311 return ...\r
312 }\r
313 else\r
314 {\r
315 /* allocator ran out of resources, need to contact Server for more\r
316 * resources */\r
317 Rm_resourcePoolModRequest(...);\r
318 }\r
319 }\r
320 else if (policy check denies resource)\r
321 {\r
322 /* Policy check denied resource. */\r
323 receipt->serviceResult = deny reason;\r
324 receipt->serviceId = transaction->id;\r
325 return ...\r
326 }\r
327 else if (policy check says forward to Server for validation)\r
328 {\r
329 /* Forward the transaction to the Server */\r
330 Rm_transactionForwarder(rmInst, transaction, receipt);\r
331 }\r
332 #endif \r
333 }\r
334 else if (rmInst->instType == Rm_instType_SERVER)\r
335 {\r
336 #if 0 \r
337 /* Check global policy to see if resource can be allocated. return result\r
338 * no matter what */\r
339 Rm_policy...API()\r
340 \r
341 if (policy approves)\r
342 {\r
343 /* call allocator to allocate resource */\r
344 }\r
345 \r
346 receipt->serviceResult = approve or deny reason;\r
347 receipt->serviceId = transaction->id;\r
348 receipt->resourceBase = ...;\r
349 receipt->resourceRange = ...;\r
350 \r
351 /* If source instance name does not match the current instance\r
352 * name the allocation request came from a client. The result\r
353 * must be sent back to the Client */\r
354 if (strcmp(transaction->sourceInstName, rmInst->name))\r
355 {\r
356 /* Names don't match. Copy the allocation response resource data \r
357 * into the original transaction and send it back to the Client */\r
358 transaction->details = transaction->details;\r
359 transaction->resourceInfo.base = receipt->resourceBase;\r
360 transaction->resourceInfo.range = receipt->resourceRange;\r
361 Rm_transactionResponder(rmInst, transaction, receipt);\r
362 }\r
363 else\r
364 {\r
365 /* Resource allocation request originated locally on the active\r
366 * instance. Send the response via the service responder. */\r
367 transaction->details = transaction->details;\r
368 transaction->resourceInfo.base = receipt->resourceBase;\r
369 transaction->resourceInfo.range = receipt->resourceRange; \r
370 Rm_serviceResponder(rmInst, transaction, NULL, receipt); \r
371 }\r
372 #endif \r
373 } \r
374 }\r
375 \r
376 void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction,\r
377 Rm_TransactionReceipt *receipt)\r
378 {\r
379 if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
380 {\r
381 #if 0 \r
382 /* Check local policy to see if the request can be satisfied with the\r
383 * resources stored locally */\r
384 Rm_policy...API()\r
385 \r
386 if (policy check approves the free)\r
387 {\r
388 /* call the allocator to free the resource */\r
389 /* Run a resource pool check to see if the free combined a resource block\r
390 * that can be returned to the server */\r
391 if (resource block has been combined)\r
392 {\r
393 /* allocator ran out of resources, need to contact Server for more\r
394 * resources */\r
395 Rm_resourcePoolModRequest(free pool block to server...);\r
396 }\r
397 else\r
398 {\r
399 /* Populate the receipt with the freed resources and the result */\r
400 receipt->serviceResult = approve reason;\r
401 receipt->serviceId = transaction->id;\r
402 return ...\r
403 }\r
404 }\r
405 else if (policy check denies resource free)\r
406 {\r
407 /* Policy check denied resource. */\r
408 receipt->serviceResult = deny reason;\r
409 receipt->serviceId = transaction->id;\r
410 return ...\r
411 }\r
412 else if (policy check says forward to Server for validation)\r
413 {\r
414 /* Forward the transaction to the Server */\r
415 Rm_transactionForwarder(rmInst, transaction, receipt);\r
416 }\r
417 #endif \r
418 }\r
419 else if (rmInst->instType == Rm_instType_SERVER)\r
420 {\r
421 #if 0 \r
422 /* Check global policy to see if resource can be freed. return result\r
423 * no matter what */\r
424 Rm_policy...API()\r
425 if (policy approves)\r
426 {\r
427 /* call allocator to free resources */\r
428 }\r
429 \r
430 receipt->serviceResult = approve or deny reason;\r
431 receipt->serviceId = transaction->id;\r
432 receipt->resourceBase = ...;\r
433 receipt->resourceRange = ...;\r
434 \r
435 /* If source instance name does not match the current instance\r
436 * name the allocation request came from a client. The result\r
437 * must be sent back to the Client */\r
438 if (strcmp(transaction->sourceInstName, rmInst->name))\r
439 {\r
440 /* Names don't match. Copy the free response resource data \r
441 * into the original transaction and send it back to the Client Delegate or Client */\r
442 transaction->details = transaction->details;\r
443 transaction->resourceInfo.base = receipt->resourceBase;\r
444 transaction->resourceInfo.range = receipt->resourceRange;\r
445 Rm_transactionResponder(rmInst, transaction, receipt);\r
446 }\r
447 else\r
448 {\r
449 /* Resource allocation request originated locally on the active\r
450 * instance. Send the response via the service responder. */\r
451 transaction->details = transaction->details;\r
452 transaction->resourceInfo.base = receipt->resourceBase;\r
453 transaction->resourceInfo.range = receipt->resourceRange;\r
454 Rm_serviceResponder(rmInst, transaction, NULL, receipt); \r
455 }\r
456 #endif \r
457 } \r
458 }\r
459 \r
460 /* Function used to forward RM transactions to higher level agents */\r
461 void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction,\r
462 Rm_TransactionReceipt *receipt)\r
463 {\r
464 Rm_TransportNode *dstTransportNode = NULL;\r
465 Rm_Packet *rmPkt = NULL;\r
466 \r
467 /* Make sure the RM instance has a transport registered with a higher level agent */\r
468 if (rmInst->registeredWithDelegateOrServer == false)\r
469 {\r
470 receipt->serviceResult = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER;\r
471 return;\r
472 }\r
473 \r
474 /* Find the transport for the higher level agent. Check for a connection to a Client Delegate\r
475 * or a Server. Clients will be connected to either a Client Delegate or a Server. Client\r
476 * Delegates will be connected to a Server. */\r
477 if (rmInst->instType == Rm_instType_CLIENT)\r
478 {\r
479 dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_CLIENT_DELEGATE);\r
480 } \r
481 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
482 {\r
483 dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_SERVER);\r
484 }\r
485 \r
486 /* Create a RM packet using the service information */\r
487 switch (transaction->type)\r
488 {\r
489 case Rm_service_RESOURCE_ALLOCATE:\r
490 case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
491 case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
492 case Rm_service_RESOURCE_FREE:\r
493 case Rm_service_RESOURCE_BLOCK_FREE:\r
494 case Rm_service_RESOURCE_FREE_BY_NAME:\r
495 rmPkt = Rm_transportCreateResourceReqPkt(rmInst, dstTransportNode, \r
496 transaction, receipt);\r
497 break;\r
498 case Rm_service_RESOURCE_MAP_TO_NAME:\r
499 case Rm_service_RESOURCE_UNMAP_NAME:\r
500 rmPkt = Rm_transportCreateNsRequestPkt(rmInst, dstTransportNode,\r
501 transaction, receipt);\r
502 break;\r
503 default:\r
504 /* Invalid service type. Flag the error and return */\r
505 receipt->serviceResult = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
506 break;\r
507 }\r
508 \r
509 if (receipt->serviceResult <= RM_SERVICE_ERROR_BASE)\r
510 {\r
511 /* Return immediately because an error occurred allocating the packet */\r
512 return;\r
513 }\r
514 \r
515 /* Switch the queued transaction to the awaiting response state */\r
516 transaction->state = Rm_transactionState_AWAITING_RESPONSE;\r
517 \r
518 /* Send the RM packet to the application transport */\r
519 if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL)\r
520 {\r
521 /* Negative value returned by transport send. An error occurred\r
522 * in the transport while attempting to send the packet.*/\r
523 receipt->serviceResult = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
524 /* Clean up the packet */\r
525 if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\r
526 {\r
527 /* Non-NULL value returned by transport packet free. Flag the\r
528 * error */\r
529 receipt->serviceResult = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
530 }\r
531 return;\r
532 }\r
533 \r
534 /* Inform requesting component that the service is being forwarded to a higher lever\r
535 * RM agent for processing. The result of the service will be provided to the \r
536 * component via the specified callback function */\r
537 receipt->serviceResult = RM_SERVICE_PROCESSING;\r
538 receipt->serviceId = transaction->id;\r
539 }\r
540 \r
541 void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction, \r
542 Rm_TransactionReceipt *receipt)\r
543 {\r
544 Rm_Transaction *queuedTransaction = NULL;\r
545 \r
546 /* Handle auto-forwarded transactions. These transactions include:\r
547 * - All request transactions received on Clients are forwarded to the Client Delegate\r
548 * - NameServer requests received on the Client Delegate are forwarded to the Server */\r
549 if ((rmInst->instType == Rm_instType_CLIENT) ||\r
550 ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
551 (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||\r
552 (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)))\r
553 {\r
554 /* Check if the new transaction's ID matches any transactions waiting for\r
555 * responses. A transaction received as a response will have an ID that \r
556 * matches the transaction that originated the request packet */\r
557 if (queuedTransaction = Rm_transactionQueueFind(rmInst, transaction->id))\r
558 {\r
559 if (queuedTransaction->state == Rm_transactionState_AWAITING_RESPONSE)\r
560 {\r
561 if (rmInst->instType == Rm_instType_CLIENT)\r
562 {\r
563 /* Client found a transaction awaiting a response. Pass both transactions\r
564 * to the service responder for response processing */\r
565 Rm_serviceResponder(rmInst, transaction, queuedTransaction, receipt);\r
566 }\r
567 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
568 {\r
569 /* Client Delegate found a NameServer transaction awaiting a response. Send the \r
570 * response to either the transaction or service responder based on the \r
571 * source instance */\r
572 if (strcmp(queuedTransaction->sourceInstName, rmInst->name))\r
573 {\r
574 /* NameServer transaction originated from another instance. Use the \r
575 * transaction responder to send the NameServer result to the source instance.\r
576 * Need to transfer the NameServer result details to the request transaction \r
577 * which will be reused for the response. */\r
578 queuedTransaction->details = transaction->details;\r
579 Rm_transactionResponder(rmInst, queuedTransaction, receipt);\r
580 /* Delete the response transaction */\r
581 Rm_transactionQueueDelete(rmInst, transaction->id); \r
582 }\r
583 else\r
584 {\r
585 /* NameServer request originated on the Client Delegate instance. Send to the\r
586 * service responder */\r
587 Rm_serviceResponder(rmInst, transaction, queuedTransaction,\r
588 receipt);\r
589 }\r
590 }\r
591 }\r
592 else\r
593 {\r
594 /* Request transaction was not in the awaiting response state. Flag the\r
595 * error in the receipt and return */\r
596 receipt->serviceResult = RM_SERVICE_ERROR_INVALID_REQUEST_TRANSACTION_STATE_UPON_RESPONSE;\r
597 }\r
598 }\r
599 else\r
600 {\r
601 /* This is a new transaction. Make sure the transaction is not a \r
602 * response transaction sent to the wrong RM instance */\r
603 if ((transaction->state == Rm_transactionState_RESOURCE_APPROVED) ||\r
604 (transaction->state == Rm_transactionState_RESOURCE_DENIED))\r
605 {\r
606 /* No matching request transaction. This transaction result was sent to the\r
607 * wrong RM instance. Flag the error in the receipt and return */\r
608 receipt->serviceResult = RM_SERVICE_ERROR_INVALID_TRANSACTION_RECEIVED_ON_CLIENT;\r
609 }\r
610 else\r
611 {\r
612 /* All service requests on Clients are forwarded to the higher level RM Client \r
613 * Delegate. NameServer requests on Client Delegates are forwarded to the Server. */\r
614 Rm_transactionForwarder(rmInst, transaction, receipt);\r
615 }\r
616 }\r
617 }\r
618 else\r
619 {\r
620 /* Client Delegate and Server transaction processors. */\r
621 switch (transaction->type)\r
622 {\r
623 case Rm_service_RESOURCE_ALLOCATE:\r
624 case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
625 case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
626 /* Run the transaction through the response handler to take care of any\r
627 * transactions that are responses to sent allocation requests. */\r
628 if (queuedTransaction = Rm_transactionQueueFind(rmInst, transaction->id))\r
629 {\r
630 if (queuedTransaction->state == Rm_transactionState_AWAITING_RESPONSE)\r
631 {\r
632 /* If source instance name does not match the current instance\r
633 * name the allocation request came from a client. The result\r
634 * must be sent back to the Client */\r
635 if (strcmp(queuedTransaction->sourceInstName, rmInst->name))\r
636 {\r
637 /* Names don't match. Copy the allocation response resource data \r
638 * into the original transaction and send it back to the Client */\r
639 queuedTransaction->details = transaction->details;\r
640 memcpy ((void *)&(queuedTransaction->resourceInfo), \r
641 (void *)&(transaction->resourceInfo), sizeof(Rm_ResourceInfo));\r
642 Rm_transactionResponder(rmInst, queuedTransaction, receipt);\r
643 /* Delete the response transaction */\r
644 Rm_transactionQueueDelete(rmInst, transaction->id);\r
645 }\r
646 else\r
647 {\r
648 /* Resource allocation request originated locally on Client Delegate\r
649 * instance. Send the response via the service responder. */\r
650 Rm_serviceResponder(rmInst, transaction, queuedTransaction,\r
651 receipt); \r
652 }\r
653 }\r
654 else\r
655 {\r
656 /* Request transaction was not in the awaiting response state. Flag the\r
657 * error in the receipt and return */\r
658 receipt->serviceResult = RM_SERVICE_ERROR_INVALID_REQUEST_TRANSACTION_STATE_UPON_RESPONSE;\r
659 }\r
660 \r
661 }\r
662 else\r
663 {\r
664 /* This is a new transaction request originating from an RM instance with fewer\r
665 * allocate/free privileges. Run the allocation handler to see if the resource\r
666 * request can be handled locally or if it needs to be forwarded to a higher level\r
667 * agent */\r
668 Rm_allocationHandler(rmInst, transaction, receipt);\r
669 }\r
670 break;\r
671 case Rm_service_RESOURCE_FREE:\r
672 case Rm_service_RESOURCE_BLOCK_FREE:\r
673 case Rm_service_RESOURCE_FREE_BY_NAME:\r
674 /* Run the transaction through the response handler to take care of any\r
675 * transactions that are responses to sent free requests. */\r
676 if (queuedTransaction = Rm_transactionQueueFind(rmInst, transaction->id))\r
677 {\r
678 if (queuedTransaction->state == Rm_transactionState_AWAITING_RESPONSE)\r
679 {\r
680 /* If source instance name does not match the current instance\r
681 * name the allocation request came from a client. The result\r
682 * must be sent back to the Client */\r
683 if (strcmp(queuedTransaction->sourceInstName, rmInst->name))\r
684 {\r
685 /* Names don't match. Copy the free response resource data \r
686 * into the original transaction and send it back to the Client */\r
687 queuedTransaction->details = transaction->details;\r
688 memcpy ((void *)&(queuedTransaction->resourceInfo), \r
689 (void *)&(transaction->resourceInfo), sizeof(Rm_ResourceInfo));\r
690 Rm_transactionResponder(rmInst, queuedTransaction, receipt);\r
691 /* Delete the response transaction */\r
692 Rm_transactionQueueDelete(rmInst, transaction->id);\r
693 }\r
694 else\r
695 {\r
696 /* Resource free request originated locally on Client Delegate\r
697 * instance. Send the response via the service responder. */\r
698 Rm_serviceResponder(rmInst, transaction, queuedTransaction,\r
699 receipt); \r
700 }\r
701 }\r
702 else\r
703 {\r
704 /* Request transaction was not in the awaiting response state. Flag the\r
705 * error in the receipt and return */\r
706 receipt->serviceResult = RM_SERVICE_ERROR_INVALID_REQUEST_TRANSACTION_STATE_UPON_RESPONSE;\r
707 }\r
708 \r
709 }\r
710 else\r
711 {\r
712 /* This is a new transaction request originating from an RM instance with fewer\r
713 * allocate/free privileges. Run the free handler to see if the resource\r
714 * request can be handled locally or if it needs to be forwarded to a higher level\r
715 * agent */\r
716 Rm_freeHandler(rmInst, transaction, receipt);\r
717 }\r
718 \r
719 break;\r
720 case Rm_service_RESOURCE_MAP_TO_NAME:\r
721 /* Server is the only RM instance capable of adding NameServer objects */\r
722 if (rmInst->instType == Rm_instType_SERVER)\r
723 {\r
724 /* Create a new NameServer object with the request transaction information */\r
725 Rm_nsAddObject(rmInst, transaction, receipt);\r
726 \r
727 /* Return the result of the NameServer addition to the RM instance\r
728 * that requested it */\r
729 transaction->details = receipt->serviceResult;\r
730 \r
731 /* If source instance name does not match the current instance\r
732 * name the NameServer request came from a Client or Client Delegate. The \r
733 * result must be sent back to the Client or Client Delegate */\r
734 if (strcmp(transaction->sourceInstName, rmInst->name))\r
735 {\r
736 Rm_transactionResponder(rmInst, queuedTransaction, receipt);\r
737 }\r
738 else\r
739 {\r
740 /* NameServer addition request originated locally on Server\r
741 * instance. Send the response via the service responder. In this case\r
742 * the request transaction will be passed as NULL since the request\r
743 * is being reused as the response */\r
744 Rm_serviceResponder(rmInst, transaction, NULL, receipt); \r
745 }\r
746 }\r
747 else\r
748 {\r
749 receipt->serviceResult = RM_SERVICE_ERROR_NAMESERVER_OBJECT_CREATE_ON_INVALID_INSTANCE;\r
750 }\r
751 break;\r
752 case Rm_service_RESOURCE_UNMAP_NAME:\r
753 /* Server is the only RM instance capable of deleting NameServer objects */\r
754 if (rmInst->instType == Rm_instType_SERVER)\r
755 {\r
756 /* Delete an existing NameServer object with the request transaction information */\r
757 Rm_nsDeleteObject(rmInst, transaction, receipt);\r
758 \r
759 /* Return the result of the NameServer deletion to the RM instance\r
760 * that requested it */\r
761 transaction->details = receipt->serviceResult;\r
762 \r
763 /* If source instance name does not match the current instance\r
764 * name the NameServer request came from a Client or Client Delegate. The \r
765 * result must be sent back to the Client or Client Delegate */\r
766 if (strcmp(transaction->sourceInstName, rmInst->name))\r
767 {\r
768 Rm_transactionResponder(rmInst, queuedTransaction, receipt);\r
769 }\r
770 else\r
771 {\r
772 /* NameServer delete request originated locally on Server\r
773 * instance. Send the response via the service responder. In this case\r
774 * the request transaction will be passed as NULL since the request\r
775 * is being reused as the response */\r
776 Rm_serviceResponder(rmInst, transaction, NULL, receipt); \r
777 } \r
778 }\r
779 else\r
780 {\r
781 receipt->serviceResult = RM_SERVICE_ERROR_NAMESERVER_OBJECT_DELETE_ON_INVALID_INSTANCE;\r
782 }\r
783 break;\r
784 }\r
785 }\r
786 }\r
787 \r
788 /**********************************************************************\r
789 ********************** Application visible APIs **********************\r
790 **********************************************************************/\r
791 \r
792 Rm_Handle Rm_init(Rm_InitCfg *initCfg)\r
793 {\r
794 Rm_Inst *rmInst;\r
795 \r
796 /* Instance creation checks. Add one to strlen calculation for null character */\r
797 if ((strlen(initCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS)\r
798 {\r
799 /* Failure: Instance name is too big */\r
800 return (NULL);\r
801 }\r
802 \r
803 /* Get memory for RM instance from local memory */\r
804 rmInst = Rm_osalMalloc (sizeof(Rm_Inst), false);\r
805 /* Populate instance based on input parameters */\r
806 strcpy (&rmInst->name[0], initCfg->instName);\r
807 rmInst->instType = initCfg->instType;\r
808 rmInst->instState = RM_state_IDLE;\r
809 rmInst->registeredWithDelegateOrServer = false;\r
810 \r
811 /* Initialize the transport routing map linked list pointer to NULL. The linked list\r
812 * nodes will be created when the application registers transports */\r
813 rmInst->routeMap = NULL;\r
814 \r
815 /* Initialize the transaction queue elements. The linked list pointer is set to NULL\r
816 * and the transaction sequence number is initialized to 0. */\r
817 rmInst->transactionSeqNum = 0;\r
818 rmInst->transactionQueue= NULL;\r
819 \r
820 /* RM Server specific actions */\r
821 if (rmInst->instType == Rm_instType_SERVER)\r
822 {\r
823 /* parse DTB, etc */\r
824 }\r
825 \r
826 /* Instance startup policies are only used for Servers and Client Delegates */\r
827 if (rmInst->instType != Rm_instType_CLIENT)\r
828 {\r
829 rmInst->instPolicy = initCfg->startupPolicy;\r
830 \r
831 /* Store policy via policy APIs ... */\r
832 }\r
833 \r
834 /* Return the RM Handle */\r
835 return ((Rm_Handle) rmInst);\r
836 }\r
837 \r
838 uint32_t Rm_getVersion (void)\r
839 {\r
840 return RM_VERSION_ID;\r
841 }\r
842 \r
843 \r
844 const char* Rm_getVersionStr (void)\r
845 {\r
846 return rmVersionStr;\r
847 }\r
848 \r
849 /**\r
850 @}\r
851 */\r