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)\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_osalMtCsEnter();\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_osalMtCsExit(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 /* Create an ID for the new transaction. The ID will be used for two purposes:\r
101 * 1) Matching responses from higher level RM agents to requests\r
102 * 2) Provided to the component that requested the service so that it can match its\r
103 * request with the response it receives via its callback function it provided */\r
104 newTransaction->localId = Rm_transactionGetSequenceNum(rmInst);\r
105 /* New transaction's nextTransaction pointer will always be NULL */\r
106 newTransaction->nextTransaction = NULL; \r
107 \r
108 /* Check if there are any transactions in the transaction queue */\r
109 if (transactionQueue)\r
110 {\r
111 /* At least one transaction in the transaction queue. Add the new entry to the \r
112 * end of the transaction queue */\r
113 while (transactionQueue->nextTransaction != NULL)\r
114 {\r
115 /* Traverse the list until arriving at the last transaction */\r
116 transactionQueue = transactionQueue->nextTransaction;\r
117 }\r
118 \r
119 /* Add the new transaction to the end of the queue */\r
120 transactionQueue->nextTransaction = newTransaction;\r
121 }\r
122 else\r
123 {\r
124 /* The transaction queue does not currently exist. The new transaction is the \r
125 * first transaction */\r
126 rmInst->transactionQueue = newTransaction;\r
127 }\r
128 \r
129 Rm_osalMtCsExit(key);\r
130 return (newTransaction);\r
131 }\r
132 \r
133 Rm_Transaction *Rm_transactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)\r
134 {\r
135 Rm_Transaction *transaction = (Rm_Transaction *)rmInst->transactionQueue;\r
136 \r
137 /* Make sure there is at least one transaction in the transaction queue */\r
138 if (transaction != NULL)\r
139 {\r
140 /* Find the transaction ID within the specified RM instance's transaction queue.\r
141 * If the end of the transaction queue is reached without finding the transaction the \r
142 * transaction pointer will be NULL */\r
143 while (transaction != NULL)\r
144 {\r
145 if (transaction->localId == transactionId)\r
146 {\r
147 /* Match: break out of loop and return the transaction */\r
148 break; \r
149 }\r
150 transaction = transaction->nextTransaction;\r
151 }\r
152 }\r
153 \r
154 return (transaction);\r
155 }\r
156 \r
157 int32_t Rm_transactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)\r
158 {\r
159 Rm_Transaction *transaction = (Rm_Transaction *) rmInst->transactionQueue;\r
160 Rm_Transaction *prevTransaction = NULL;\r
161 int32_t retVal = RM_SERVICE_STATE_OKAY;\r
162 void *key;\r
163 \r
164 /* Lock access to the RM instance's transaction queue */\r
165 key = Rm_osalMtCsEnter();\r
166 \r
167 /* Find the transaction ID within the specified RM instance's transaction queue. */\r
168 while (transaction != NULL)\r
169 {\r
170 if (transaction->localId == transactionId)\r
171 {\r
172 /* Match: break out of loop and delete the transaction */\r
173 break; \r
174 }\r
175 \r
176 prevTransaction = transaction;\r
177 transaction = transaction->nextTransaction;\r
178 }\r
179 \r
180 /* Traversed entire queue but did not find transaction */\r
181 if (transaction == NULL)\r
182 {\r
183 retVal = RM_SERVICE_ERROR_SERVICE_TRANSACTION_DOES_NOT_EXIST;\r
184 }\r
185 else\r
186 {\r
187 /* Delete the transaction */\r
188 if (prevTransaction == NULL)\r
189 {\r
190 /* Transaction to be deleted exists at start of transaction queue. Map second\r
191 * transaction to be start of transaction queue. This covers case where there is\r
192 * only one transaction in the queue since the nextTransaction will be NULL */\r
193 rmInst->transactionQueue = transaction->nextTransaction;\r
194 }\r
195 else\r
196 {\r
197 /* Transaction to be deleted is in the middle or at end of the queue. Adjust \r
198 * adjacent transaction pointers. This covers the case where the transaction to be \r
199 * removed is at the end of the queue. */\r
200 prevTransaction->nextTransaction = transaction->nextTransaction;\r
201 }\r
202 \r
203 /* Free the memory associated with the transaction. */\r
204 Rm_osalFree((void *)transaction, sizeof(Rm_Transaction), false);\r
205 }\r
206 \r
207 Rm_osalMtCsExit(key);\r
208 return (retVal);\r
209 }\r
210 \r
211 uint32_t Rm_transactionInitSequenceNum(void)\r
212 {\r
213 /* Sequence number can never have a value of zero so that there are no conflicts\r
214 * with transactions that have a remoteOriginatingId of zero */\r
215 return (1);\r
216 }\r
217 \r
218 uint32_t Rm_transactionGetSequenceNum(Rm_Inst *rmInst)\r
219 {\r
220 uint32_t sequenceNum = 0;\r
221 \r
222 /* Get the next sequence number and then increment. If there's an overflow\r
223 * assign the initial value instead of incrementing. */\r
224 if (rmInst->transactionSeqNum + 1 < rmInst->transactionSeqNum)\r
225 {\r
226 /* Overflow */\r
227 sequenceNum = rmInst->transactionSeqNum;\r
228 rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
229 }\r
230 else\r
231 {\r
232 sequenceNum = rmInst->transactionSeqNum++;\r
233 } \r
234 \r
235 return (sequenceNum);\r
236 }\r
237 \r
238 /* Function used to send RM response transactions to lower level agents */\r
239 void Rm_transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
240 {\r
241 Rm_TransportNode *dstTransportNode = NULL;\r
242 Rm_Packet *rmPkt = NULL;\r
243 \r
244 /* Find the transport for the RM instance that sent the request. */\r
245 dstTransportNode = Rm_transportNodeFindRemoteName(rmInst, transaction->sourceInstName);\r
246 \r
247 /* Create a RM packet using the service information */\r
248 switch (transaction->type)\r
249 {\r
250 case Rm_service_RESOURCE_ALLOCATE:\r
251 case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
252 case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
253 case Rm_service_RESOURCE_FREE:\r
254 case Rm_service_RESOURCE_BLOCK_FREE:\r
255 case Rm_service_RESOURCE_FREE_BY_NAME:\r
256 rmPkt = Rm_transportCreateResourceResponsePkt(rmInst, dstTransportNode, \r
257 transaction);\r
258 break;\r
259 case Rm_service_RESOURCE_MAP_TO_NAME:\r
260 case Rm_service_RESOURCE_UNMAP_NAME:\r
261 rmPkt = Rm_transportCreateNsResponsePkt(rmInst, dstTransportNode,\r
262 transaction);\r
263 break;\r
264 default:\r
265 /* Invalid service type. Flag the error and return */\r
266 transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
267 break;\r
268 }\r
269 \r
270 if (transaction->state <= RM_SERVICE_ERROR_BASE)\r
271 {\r
272 /* Delete the transaction and return immediately because an error occurred \r
273 * allocating the packet */\r
274 Rm_transactionQueueDelete(rmInst, transaction->localId);\r
275 return;\r
276 }\r
277 \r
278 /* Send the RM packet to the application transport */\r
279 if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL)\r
280 {\r
281 /* Negative value returned by transport send. An error occurred\r
282 * in the transport while attempting to send the packet.*/\r
283 transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
284 /* Clean up the packet */\r
285 if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\r
286 {\r
287 /* Non-NULL value returned by transport packet free. Flag the\r
288 * error */\r
289 transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
290 }\r
291 return;\r
292 }\r
293 \r
294 /* NEED TO DO SOMETHING IF GET AN ERROR IN THE transaction->state FIELD. CREATE\r
295 * NEW TRANSACTION WITH DATA FROM ORIGINAL? THEN TRY TO SEND FAILED REQUEST BACK\r
296 * TO REQUESTER??? KEEP RETRYING SEND OF RESPONSE??? */\r
297 \r
298 /* Delete the transaction */\r
299 Rm_transactionQueueDelete(rmInst, transaction->localId);\r
300 }\r
301 \r
302 void Rm_allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
303 {\r
304 if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
305 {\r
306 #if 0 \r
307 /* Check local policy to see if the request can be satisfied with the\r
308 * resources stored locally */\r
309 Rm_policy...API()\r
310 \r
311 if (policy check approves the resource)\r
312 {\r
313 /* call the allocator to allocate the resource */\r
314 if (allocator returns resource)\r
315 {\r
316 /* Populate the transaction with the allocated resources and the result */\r
317 transaction->state = approve reason;\r
318 return ...\r
319 }\r
320 else\r
321 {\r
322 /* allocator ran out of resources, need to contact Server for more\r
323 * resources */\r
324 Rm_resourcePoolModRequest(...);\r
325 }\r
326 }\r
327 else if (policy check denies resource)\r
328 {\r
329 /* Policy check denied resource. */\r
330 transaction->state= deny reason;\r
331 return ...\r
332 }\r
333 else if (policy check says forward to Server for validation)\r
334 {\r
335 /* Forward the transaction to the Server */\r
336 Rm_transactionForwarder(rmInst, transaction);\r
337 }\r
338 #endif \r
339 }\r
340 else if (rmInst->instType == Rm_instType_SERVER)\r
341 {\r
342 #if 0 \r
343 /* Check global policy to see if resource can be allocated. return result\r
344 * no matter what */\r
345 Rm_policy...API()\r
346 \r
347 if (policy approves)\r
348 {\r
349 /* call allocator to allocate resource */\r
350 }\r
351 \r
352 transaction->state = approve or deny reason;\r
353 transaction->resourceInfo.base = ...;\r
354 transaction->resourceInfo.range = ...;\r
355 \r
356 /* If source instance name does not match the current instance\r
357 * name the allocation request came from a Client. The result\r
358 * must be sent back to the Client */\r
359 if (strcmp(transaction->sourceInstName, rmInst->name))\r
360 {\r
361 /* Names don't match. Send the transaction back to the Client */\r
362 Rm_transactionResponder(rmInst, transaction);\r
363 }\r
364 else\r
365 {\r
366 /* Resource allocation request originated locally on the active\r
367 * instance. Send the response via the service responder. */ \r
368 Rm_serviceResponder(rmInst, transaction); \r
369 }\r
370 #endif \r
371 } \r
372 }\r
373 \r
374 void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
375 {\r
376 if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
377 {\r
378 #if 0 \r
379 /* Check local policy to see if the request can be satisfied with the\r
380 * resources stored locally */\r
381 Rm_policy...API()\r
382 \r
383 if (policy check approves the free)\r
384 {\r
385 /* call the allocator to free the resource */\r
386 /* Run a resource pool check to see if the free combined a resource block\r
387 * that can be returned to the server */\r
388 if (resource block has been combined)\r
389 {\r
390 /* allocator ran out of resources, need to contact Server for more\r
391 * resources */\r
392 Rm_resourcePoolModRequest(free pool block to server...);\r
393 }\r
394 else\r
395 {\r
396 /* Populate the receipt with the freed resources and the result */\r
397 transaction->state = approve reason;\r
398 return ...\r
399 }\r
400 }\r
401 else if (policy check denies resource free)\r
402 {\r
403 /* Policy check denied resource. */\r
404 transaction->state = deny reason;\r
405 return ...\r
406 }\r
407 else if (policy check says forward to Server for validation)\r
408 {\r
409 /* Forward the transaction to the Server */\r
410 Rm_transactionForwarder(rmInst, transaction);\r
411 }\r
412 #endif \r
413 }\r
414 else if (rmInst->instType == Rm_instType_SERVER)\r
415 {\r
416 #if 0 \r
417 /* Check global policy to see if resource can be freed. return result\r
418 * no matter what */\r
419 Rm_policy...API()\r
420 if (policy approves)\r
421 {\r
422 /* call allocator to free resources */\r
423 }\r
424 \r
425 transaction->state = approve or deny reason;\r
426 transaction->resourceInfo.base = ...;\r
427 transaction->resourceInfo.range = ...;\r
428 \r
429 /* If source instance name does not match the current instance\r
430 * name the allocation request came from a client. The result\r
431 * must be sent back to the Client */\r
432 if (strcmp(transaction->sourceInstName, rmInst->name))\r
433 {\r
434 /* Names don't match. Send the transaction back to the Client Delegate or Client */\r
435 Rm_transactionResponder(rmInst, transaction);\r
436 }\r
437 else\r
438 {\r
439 /* Resource allocation request originated locally on the active\r
440 * instance. Send the response via the service responder. */\r
441 Rm_serviceResponder(rmInst, transaction); \r
442 }\r
443 #endif \r
444 } \r
445 }\r
446 \r
447 /* Function used to forward RM transactions to higher level agents */\r
448 void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
449 {\r
450 Rm_TransportNode *dstTransportNode = NULL;\r
451 Rm_Packet *rmPkt = NULL;\r
452 \r
453 /* Make sure the RM instance has a transport registered with a higher level agent */\r
454 if (rmInst->registeredWithDelegateOrServer == false)\r
455 {\r
456 transaction->state = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER;\r
457 return;\r
458 }\r
459 \r
460 /* Find the transport for the higher level agent. Check for a connection to a Client Delegate\r
461 * or a Server. Clients will be connected to either a Client Delegate or a Server. Client\r
462 * Delegates will be connected to a Server. */\r
463 if (rmInst->instType == Rm_instType_CLIENT)\r
464 {\r
465 dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_CLIENT_DELEGATE);\r
466 } \r
467 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
468 {\r
469 dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_SERVER);\r
470 }\r
471 \r
472 /* Create a RM packet using the service information */\r
473 switch (transaction->type)\r
474 {\r
475 case Rm_service_RESOURCE_ALLOCATE:\r
476 case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
477 case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
478 case Rm_service_RESOURCE_FREE:\r
479 case Rm_service_RESOURCE_BLOCK_FREE:\r
480 case Rm_service_RESOURCE_FREE_BY_NAME:\r
481 rmPkt = Rm_transportCreateResourceReqPkt(rmInst, dstTransportNode, \r
482 transaction);\r
483 break;\r
484 case Rm_service_RESOURCE_MAP_TO_NAME:\r
485 case Rm_service_RESOURCE_UNMAP_NAME:\r
486 rmPkt = Rm_transportCreateNsRequestPkt(rmInst, dstTransportNode,\r
487 transaction);\r
488 break;\r
489 default:\r
490 /* Invalid service type. Flag the error and return */\r
491 transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
492 break;\r
493 }\r
494 \r
495 if (transaction->state <= RM_SERVICE_ERROR_BASE)\r
496 {\r
497 /* Return immediately because an error occurred allocating the packet */\r
498 return;\r
499 }\r
500 \r
501 /* Send the RM packet to the application transport */\r
502 if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL)\r
503 {\r
504 /* Negative value returned by transport send. An error occurred\r
505 * in the transport while attempting to send the packet.*/\r
506 transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
507 /* Clean up the packet */\r
508 if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\r
509 {\r
510 /* Non-NULL value returned by transport packet free. Flag the\r
511 * error */\r
512 transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
513 }\r
514 return;\r
515 }\r
516 \r
517 /* Transaction is not deleted because it is awaiting a response from the higher level\r
518 * RM instance */\r
519 }\r
520 \r
521 void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
522 {\r
523 /* Handle auto-forwarded transactions. These transactions include:\r
524 * - All request transactions received on Clients are forwarded to the Client Delegate\r
525 * - NameServer requests received on the Client Delegate are forwarded to the Server */\r
526 if ((rmInst->instType == Rm_instType_CLIENT) ||\r
527 ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
528 (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||\r
529 (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)))\r
530 {\r
531 /* Check if the transaction is a transaction that received a response to its\r
532 * request. */\r
533 if (transaction->state != RM_SERVICE_PROCESSING)\r
534 {\r
535 \r
536 /* A transaction has received a response. Send the response to either the \r
537 * transaction or service responder based on the source instance */\r
538 if (strcmp(transaction->sourceInstName, rmInst->name))\r
539 {\r
540 /* Transaction originated from another instance. Use the \r
541 * transaction responder to send the result to the source instance. This\r
542 * is not possible on RM Clients since they can't forward RM services */\r
543 Rm_transactionResponder(rmInst, transaction);\r
544 }\r
545 else\r
546 {\r
547 /* Transaction originated on this instance. Send to the\r
548 * service responder */\r
549 Rm_serviceResponder(rmInst, transaction);\r
550 }\r
551 }\r
552 else\r
553 {\r
554 /* This is a new transaction that must be forwarded to a higher level RM instance. */\r
555 Rm_transactionForwarder(rmInst, transaction);\r
556 }\r
557 }\r
558 else\r
559 {\r
560 /* Client Delegate and Server transaction processors. */\r
561 switch (transaction->type)\r
562 {\r
563 case Rm_service_RESOURCE_ALLOCATE:\r
564 case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
565 case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
566 case Rm_service_RESOURCE_FREE:\r
567 case Rm_service_RESOURCE_BLOCK_FREE:\r
568 case Rm_service_RESOURCE_FREE_BY_NAME: \r
569 /* Check if the transaction is fulfilled request */\r
570 if (transaction->state != RM_SERVICE_PROCESSING)\r
571 {\r
572 /* If source instance name does not match the current instance\r
573 * name the allocation request came from a client. The result\r
574 * must be sent back to the Client */\r
575 if (strcmp(transaction->sourceInstName, rmInst->name))\r
576 {\r
577 Rm_transactionResponder(rmInst, transaction);\r
578 }\r
579 else\r
580 {\r
581 /* Resource allocation request originated locally. Send the response\r
582 * via the service responder. */\r
583 Rm_serviceResponder(rmInst, transaction); \r
584 \r
585 \r
586 /* WHAT IF TRANSACITON CAME FROM CD AND WAS SOLVED IMMEDIATELY. NEED TO RETURN\r
587 * THE TRANSACTION RATHER THAN GO THROUGH THE SERVICERESPONDER */\r
588 }\r
589 }\r
590 else\r
591 {\r
592 /* This is a new transaction request originating from an RM instance with fewer\r
593 * allocate/free privileges. Run the allocation or free handler to see if the resource\r
594 * request can be handled locally or if it needs to be forwarded to a higher level\r
595 * agent */\r
596 if ((transaction->type == Rm_service_RESOURCE_ALLOCATE) ||\r
597 (transaction->type == Rm_service_RESOURCE_BLOCK_ALLOCATE) ||\r
598 (transaction->type == Rm_service_RESOURCE_ALLOCATE_BY_NAME))\r
599 {\r
600 Rm_allocationHandler(rmInst, transaction);\r
601 }\r
602 else\r
603 {\r
604 Rm_freeHandler(rmInst, transaction);\r
605 }\r
606 }\r
607 break;\r
608 case Rm_service_RESOURCE_MAP_TO_NAME:\r
609 case Rm_service_RESOURCE_UNMAP_NAME: \r
610 /* Server is the only RM instance capable of adding NameServer objects */\r
611 if (rmInst->instType == Rm_instType_SERVER)\r
612 {\r
613 if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME)\r
614 {\r
615 /* Create a new NameServer object with the request transaction information.\r
616 * Transaction will contain the state result of the NameServer addition. */\r
617 Rm_nsAddObject(rmInst, transaction);\r
618 }\r
619 else\r
620 {\r
621 /* Delete an existing NameServer object with the request transaction information\r
622 * Transaction will contain the state result of the NameServer addition. */\r
623 Rm_nsDeleteObject(rmInst, transaction);\r
624 }\r
625 \r
626 /* If source instance name does not match the local instance\r
627 * name the NameServer request came from a Client or Client Delegate. The \r
628 * result must be sent back to the Client or Client Delegate. Just return if it does\r
629 * match since the NameServer transaction result can be returned immediately. */\r
630 if (strcmp(transaction->sourceInstName, rmInst->name))\r
631 {\r
632 Rm_transactionResponder(rmInst, transaction);\r
633 }\r
634 }\r
635 else\r
636 {\r
637 transaction->state = RM_SERVICE_ERROR_NAMESERVER_OBJECT_MOD_ON_INVALID_INSTANCE;\r
638 }\r
639 break;\r
640 }\r
641 }\r
642 }\r
643 \r
644 /**********************************************************************\r
645 ********************** Application visible APIs **********************\r
646 **********************************************************************/\r
647 \r
648 Rm_Handle Rm_init(Rm_InitCfg *initCfg)\r
649 {\r
650 Rm_Inst *rmInst;\r
651 \r
652 /* Instance creation checks. Add one to strlen calculation for null character */\r
653 if ((strlen(initCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS)\r
654 {\r
655 /* Failure: Instance name is too big */\r
656 return (NULL);\r
657 }\r
658 \r
659 /* Get memory for RM instance from local memory */\r
660 rmInst = Rm_osalMalloc (sizeof(Rm_Inst), false);\r
661 /* Populate instance based on input parameters */\r
662 strcpy (&rmInst->name[0], initCfg->instName);\r
663 rmInst->instType = initCfg->instType;\r
664 rmInst->registeredWithDelegateOrServer = false;\r
665 \r
666 /* Initialize the transport routing map linked list pointer to NULL. The linked list\r
667 * nodes will be created when the application registers transports */\r
668 rmInst->routeMap = NULL;\r
669 \r
670 /* Initialize the transaction queue elements. */\r
671 rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
672 rmInst->transactionQueue= NULL;\r
673 \r
674 /* RM Server specific actions */\r
675 if (rmInst->instType == Rm_instType_SERVER)\r
676 {\r
677 /* parse DTB, etc */\r
678 }\r
679 \r
680 /* Instance startup policies are only used for Servers and Client Delegates */\r
681 if (rmInst->instType != Rm_instType_CLIENT)\r
682 {\r
683 rmInst->instPolicy = initCfg->startupPolicy;\r
684 \r
685 /* Store policy via policy APIs ... */\r
686 }\r
687 \r
688 /* Return the RM Handle */\r
689 return ((Rm_Handle) rmInst);\r
690 }\r
691 \r
692 uint32_t Rm_getVersion (void)\r
693 {\r
694 return RM_VERSION_ID;\r
695 }\r
696 \r
697 \r
698 const char* Rm_getVersionStr (void)\r
699 {\r
700 return rmVersionStr;\r
701 }\r
702 \r
703 /**\r
704 @}\r
705 */\r