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 LIBFDT includes */\r
58 #include <ti/drv/rm/src/libfdt/libfdt.h>\r
59 \r
60 /* RM OSAL layer */\r
61 #include <rm_osal.h>\r
62 \r
63 /**********************************************************************\r
64 ************************** Globals ***********************************\r
65 **********************************************************************/\r
66 #if 0\r
67 /* Place QMSS PDSP permissions array */\r
68 #pragma DATA_SECTION (rmQmssPdspFirmwarePerms, ".rm");\r
69 #pragma DATA_ALIGN (rmQmssPdspFirmwarePerms, 128)\r
70 Rm_Perms rmQmssPdspFirmwarePerms[RM_ALIGN_PERMISSIONS_ARRAY(RM_QMSS_FIRMWARE_PDSPS, Rm_Perms)];\r
71 #endif\r
72 \r
73 /** @brief Global Variable which describes the RM Version Information */\r
74 const char rmVersionStr[] = RM_VERSION_STR ":" __DATE__ ":" __TIME__;\r
75 \r
76 /**********************************************************************\r
77 ********************** Internal Functions ****************************\r
78 **********************************************************************/\r
79 \r
80 /* At the very least the transaction ID needs to be provided to create a transaction */\r
81 Rm_Transaction *Rm_transactionQueueAdd(Rm_Inst *rmInst)\r
82 {\r
83 Rm_Transaction *transactionQueue = (Rm_Transaction *)rmInst->transactionQueue;\r
84 Rm_Transaction *newTransaction = NULL;\r
85 void *key;\r
86 \r
87 /* Lock access to the RM instance's transaction queue */\r
88 key = Rm_osalMtCsEnter();\r
89 \r
90 /* Get memory for a new transaction from local memory */\r
91 newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction));\r
92 \r
93 /* Return if the memory allocated for the transaction entry is NULL */\r
94 if (newTransaction == NULL)\r
95 {\r
96 Rm_osalMtCsExit(key);\r
97 return(newTransaction);\r
98 }\r
99 \r
100 /* Clear the transaction */\r
101 memset((void *)newTransaction, 0, sizeof(Rm_Transaction));\r
102 \r
103 /* Create an ID for the new transaction. The ID will be used for two purposes:\r
104 * 1) Matching responses from higher level RM agents to requests\r
105 * 2) Provided to the component that requested the service so that it can match its\r
106 * request with the response it receives via its callback function it provided */\r
107 newTransaction->localId = Rm_transactionGetSequenceNum(rmInst);\r
108 /* New transaction's nextTransaction pointer will always be NULL */\r
109 newTransaction->nextTransaction = NULL; \r
110 \r
111 /* Check if there are any transactions in the transaction queue */\r
112 if (transactionQueue)\r
113 {\r
114 /* At least one transaction in the transaction queue. Add the new entry to the \r
115 * end of the transaction queue */\r
116 while (transactionQueue->nextTransaction != NULL)\r
117 {\r
118 /* Traverse the list until arriving at the last transaction */\r
119 transactionQueue = transactionQueue->nextTransaction;\r
120 }\r
121 \r
122 /* Add the new transaction to the end of the queue */\r
123 transactionQueue->nextTransaction = newTransaction;\r
124 }\r
125 else\r
126 {\r
127 /* The transaction queue does not currently exist. The new transaction is the \r
128 * first transaction */\r
129 rmInst->transactionQueue = newTransaction;\r
130 }\r
131 \r
132 Rm_osalMtCsExit(key);\r
133 return (newTransaction);\r
134 }\r
135 \r
136 Rm_Transaction *Rm_transactionQueueFind(Rm_Inst *rmInst, uint32_t transactionId)\r
137 {\r
138 Rm_Transaction *transaction = (Rm_Transaction *)rmInst->transactionQueue;\r
139 \r
140 /* Make sure there is at least one transaction in the transaction queue */\r
141 if (transaction != NULL)\r
142 {\r
143 /* Find the transaction ID within the specified RM instance's transaction queue.\r
144 * If the end of the transaction queue is reached without finding the transaction the \r
145 * transaction pointer will be NULL */\r
146 while (transaction != NULL)\r
147 {\r
148 if (transaction->localId == transactionId)\r
149 {\r
150 /* Match: break out of loop and return the transaction */\r
151 break; \r
152 }\r
153 transaction = transaction->nextTransaction;\r
154 }\r
155 }\r
156 \r
157 return (transaction);\r
158 }\r
159 \r
160 int32_t Rm_transactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)\r
161 {\r
162 Rm_Transaction *transaction = (Rm_Transaction *) rmInst->transactionQueue;\r
163 Rm_Transaction *prevTransaction = NULL;\r
164 int32_t retVal = RM_SERVICE_STATE_OKAY;\r
165 void *key;\r
166 \r
167 /* Lock access to the RM instance's transaction queue */\r
168 key = Rm_osalMtCsEnter();\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->localId == 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 retVal = RM_SERVICE_ERROR_SERVICE_TRANSACTION_DOES_NOT_EXIST;\r
187 }\r
188 else\r
189 {\r
190 /* Delete the transaction */\r
191 if (prevTransaction == NULL)\r
192 {\r
193 /* Transaction to be deleted exists at start of transaction queue. Map second\r
194 * transaction to be start of transaction queue. This covers case where there is\r
195 * only one transaction in the queue since the nextTransaction will be NULL */\r
196 rmInst->transactionQueue = transaction->nextTransaction;\r
197 }\r
198 else\r
199 {\r
200 /* Transaction to be deleted is in the middle or at end of the queue. Adjust \r
201 * adjacent transaction pointers. This covers the case where the transaction to be \r
202 * removed is at the end of the queue. */\r
203 prevTransaction->nextTransaction = transaction->nextTransaction;\r
204 }\r
205 \r
206 /* Free the memory associated with the transaction. */\r
207 Rm_osalFree((void *)transaction, sizeof(Rm_Transaction), false);\r
208 }\r
209 \r
210 Rm_osalMtCsExit(key);\r
211 return (retVal);\r
212 }\r
213 \r
214 uint32_t Rm_transactionInitSequenceNum(void)\r
215 {\r
216 /* Sequence number can never have a value of zero so that there are no conflicts\r
217 * with transactions that have a remoteOriginatingId of zero */\r
218 return (1);\r
219 }\r
220 \r
221 uint32_t Rm_transactionGetSequenceNum(Rm_Inst *rmInst)\r
222 {\r
223 uint32_t sequenceNum = 0;\r
224 \r
225 /* Get the next sequence number and then increment. If there's an overflow\r
226 * assign the initial value instead of incrementing. */\r
227 if (rmInst->transactionSeqNum + 1 < rmInst->transactionSeqNum)\r
228 {\r
229 /* Overflow */\r
230 sequenceNum = rmInst->transactionSeqNum;\r
231 rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
232 }\r
233 else\r
234 {\r
235 sequenceNum = rmInst->transactionSeqNum++;\r
236 } \r
237 \r
238 return (sequenceNum);\r
239 }\r
240 \r
241 /* Function used to send RM response transactions to lower level agents */\r
242 void Rm_transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
243 {\r
244 Rm_TransportNode *dstTransportNode = NULL;\r
245 Rm_Packet *rmPkt = NULL;\r
246 \r
247 /* Find the transport for the RM instance that sent the request. */\r
248 dstTransportNode = Rm_transportNodeFindRemoteName(rmInst, transaction->sourceInstName);\r
249 \r
250 /* Create a RM packet using the service information */\r
251 switch (transaction->type)\r
252 {\r
253 case Rm_service_RESOURCE_ALLOCATE:\r
254 case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
255 case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
256 case Rm_service_RESOURCE_FREE:\r
257 case Rm_service_RESOURCE_BLOCK_FREE:\r
258 case Rm_service_RESOURCE_FREE_BY_NAME:\r
259 rmPkt = Rm_transportCreateResourceResponsePkt(rmInst, dstTransportNode, \r
260 transaction);\r
261 break;\r
262 case Rm_service_RESOURCE_MAP_TO_NAME:\r
263 case Rm_service_RESOURCE_UNMAP_NAME:\r
264 rmPkt = Rm_transportCreateNsResponsePkt(rmInst, dstTransportNode,\r
265 transaction);\r
266 break;\r
267 default:\r
268 /* Invalid service type. Flag the error and return */\r
269 transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
270 break;\r
271 }\r
272 \r
273 if (transaction->state <= RM_SERVICE_ERROR_BASE)\r
274 {\r
275 /* Delete the transaction and return immediately because an error occurred \r
276 * allocating the packet */\r
277 Rm_transactionQueueDelete(rmInst, transaction->localId);\r
278 return;\r
279 }\r
280 \r
281 /* Send the RM packet to the application transport */\r
282 if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL)\r
283 {\r
284 /* Negative value returned by transport send. An error occurred\r
285 * in the transport while attempting to send the packet.*/\r
286 transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
287 /* Clean up the packet */\r
288 if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\r
289 {\r
290 /* Non-NULL value returned by transport packet free. Flag the\r
291 * error */\r
292 transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
293 }\r
294 return;\r
295 }\r
296 \r
297 /* NEED TO DO SOMETHING IF GET AN ERROR IN THE transaction->state FIELD. CREATE\r
298 * NEW TRANSACTION WITH DATA FROM ORIGINAL? THEN TRY TO SEND FAILED REQUEST BACK\r
299 * TO REQUESTER??? KEEP RETRYING SEND OF RESPONSE??? */\r
300 \r
301 /* Delete the transaction */\r
302 Rm_transactionQueueDelete(rmInst, transaction->localId);\r
303 }\r
304 \r
305 void Rm_allocationHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
306 {\r
307 if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
308 {\r
309 #if 0 \r
310 /* Check local policy to see if the request can be satisfied with the\r
311 * resources stored locally */\r
312 Rm_policy...API()\r
313 \r
314 if (policy check approves the resource)\r
315 {\r
316 /* call the allocator to allocate the resource */\r
317 if (allocator returns resource)\r
318 {\r
319 /* Populate the transaction with the allocated resources and the result */\r
320 transaction->state = approve reason;\r
321 return ...\r
322 }\r
323 else\r
324 {\r
325 /* allocator ran out of resources, need to contact Server for more\r
326 * resources */\r
327 Rm_resourcePoolModRequest(...);\r
328 }\r
329 }\r
330 else if (policy check denies resource)\r
331 {\r
332 /* Policy check denied resource. */\r
333 transaction->state= deny reason;\r
334 return ...\r
335 }\r
336 else if (policy check says forward to Server for validation)\r
337 {\r
338 /* Forward the transaction to the Server */\r
339 Rm_transactionForwarder(rmInst, transaction);\r
340 }\r
341 #endif \r
342 }\r
343 else if (rmInst->instType == Rm_instType_SERVER)\r
344 {\r
345 #if 0 \r
346 /* Check global policy to see if resource can be allocated. return result\r
347 * no matter what */\r
348 Rm_policy...API()\r
349 \r
350 if (policy approves)\r
351 {\r
352 /* call allocator to allocate resource */\r
353 }\r
354 \r
355 transaction->state = approve or deny reason;\r
356 transaction->resourceInfo.base = ...;\r
357 transaction->resourceInfo.range = ...;\r
358 \r
359 /* If source instance name does not match the current instance\r
360 * name the allocation request came from a Client. The result\r
361 * must be sent back to the Client */\r
362 if (strcmp(transaction->sourceInstName, rmInst->name))\r
363 {\r
364 /* Names don't match. Send the transaction back to the Client */\r
365 Rm_transactionResponder(rmInst, transaction);\r
366 }\r
367 else\r
368 {\r
369 /* Resource allocation request originated locally on the active\r
370 * instance. Send the response via the service responder. */ \r
371 Rm_serviceResponder(rmInst, transaction); \r
372 }\r
373 #endif \r
374 } \r
375 }\r
376 \r
377 void Rm_freeHandler (Rm_Inst *rmInst, Rm_Transaction *transaction)\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 transaction->state = approve reason;\r
401 return ...\r
402 }\r
403 }\r
404 else if (policy check denies resource free)\r
405 {\r
406 /* Policy check denied resource. */\r
407 transaction->state = deny reason;\r
408 return ...\r
409 }\r
410 else if (policy check says forward to Server for validation)\r
411 {\r
412 /* Forward the transaction to the Server */\r
413 Rm_transactionForwarder(rmInst, transaction);\r
414 }\r
415 #endif \r
416 }\r
417 else if (rmInst->instType == Rm_instType_SERVER)\r
418 {\r
419 #if 0 \r
420 /* Check global policy to see if resource can be freed. return result\r
421 * no matter what */\r
422 Rm_policy...API()\r
423 if (policy approves)\r
424 {\r
425 /* call allocator to free resources */\r
426 }\r
427 \r
428 transaction->state = approve or deny reason;\r
429 transaction->resourceInfo.base = ...;\r
430 transaction->resourceInfo.range = ...;\r
431 \r
432 /* If source instance name does not match the current instance\r
433 * name the allocation request came from a client. The result\r
434 * must be sent back to the Client */\r
435 if (strcmp(transaction->sourceInstName, rmInst->name))\r
436 {\r
437 /* Names don't match. Send the transaction back to the Client Delegate or Client */\r
438 Rm_transactionResponder(rmInst, transaction);\r
439 }\r
440 else\r
441 {\r
442 /* Resource allocation request originated locally on the active\r
443 * instance. Send the response via the service responder. */\r
444 Rm_serviceResponder(rmInst, transaction); \r
445 }\r
446 #endif \r
447 } \r
448 }\r
449 \r
450 /* Function used to forward RM transactions to higher level agents */\r
451 void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
452 {\r
453 Rm_TransportNode *dstTransportNode = NULL;\r
454 Rm_Packet *rmPkt = NULL;\r
455 \r
456 /* Make sure the RM instance has a transport registered with a higher level agent */\r
457 if (rmInst->registeredWithDelegateOrServer == false)\r
458 {\r
459 transaction->state = RM_SERVICE_ERROR_NOT_REGISTERED_WITH_DEL_OR_SERVER;\r
460 return;\r
461 }\r
462 \r
463 /* Find the transport for the higher level agent. Check for a connection to a Client Delegate\r
464 * or a Server. Clients will be connected to either a Client Delegate or a Server. Client\r
465 * Delegates will be connected to a Server. */\r
466 if (rmInst->instType == Rm_instType_CLIENT)\r
467 {\r
468 dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_CLIENT_DELEGATE);\r
469 } \r
470 else if (rmInst->instType == Rm_instType_CLIENT_DELEGATE)\r
471 {\r
472 dstTransportNode = Rm_transportNodeFindRemoteInstType(rmInst, Rm_instType_SERVER);\r
473 }\r
474 \r
475 /* Create a RM packet using the service information */\r
476 switch (transaction->type)\r
477 {\r
478 case Rm_service_RESOURCE_ALLOCATE:\r
479 case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
480 case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
481 case Rm_service_RESOURCE_FREE:\r
482 case Rm_service_RESOURCE_BLOCK_FREE:\r
483 case Rm_service_RESOURCE_FREE_BY_NAME:\r
484 rmPkt = Rm_transportCreateResourceReqPkt(rmInst, dstTransportNode, \r
485 transaction);\r
486 break;\r
487 case Rm_service_RESOURCE_MAP_TO_NAME:\r
488 case Rm_service_RESOURCE_UNMAP_NAME:\r
489 rmPkt = Rm_transportCreateNsRequestPkt(rmInst, dstTransportNode,\r
490 transaction);\r
491 break;\r
492 default:\r
493 /* Invalid service type. Flag the error and return */\r
494 transaction->state = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;\r
495 break;\r
496 }\r
497 \r
498 if (transaction->state <= RM_SERVICE_ERROR_BASE)\r
499 {\r
500 /* Return immediately because an error occurred allocating the packet */\r
501 return;\r
502 }\r
503 \r
504 /* Send the RM packet to the application transport */\r
505 if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL)\r
506 {\r
507 /* Negative value returned by transport send. An error occurred\r
508 * in the transport while attempting to send the packet.*/\r
509 transaction->state = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
510 /* Clean up the packet */\r
511 if (rmInst->transport.rmFreePkt((Rm_TransportHandle) dstTransportNode, rmPkt))\r
512 {\r
513 /* Non-NULL value returned by transport packet free. Flag the\r
514 * error */\r
515 transaction->state = RM_SERVICE_ERROR_TRANSPORT_FREE_PKT_ERROR;\r
516 }\r
517 return;\r
518 }\r
519 \r
520 /* Transaction is not deleted because it is awaiting a response from the higher level\r
521 * RM instance */\r
522 }\r
523 \r
524 void Rm_transactionProcessor (Rm_Inst *rmInst, Rm_Transaction *transaction)\r
525 {\r
526 /* Handle auto-forwarded transactions. These transactions include:\r
527 * - All request transactions received on Clients are forwarded to the Client Delegate\r
528 * - NameServer requests received on the Client Delegate are forwarded to the Server */\r
529 if ((rmInst->instType == Rm_instType_CLIENT) ||\r
530 ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
531 (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME) ||\r
532 (transaction->type == Rm_service_RESOURCE_UNMAP_NAME)))\r
533 {\r
534 /* Check if the transaction is a transaction that received a response to its\r
535 * request. */\r
536 if (transaction->state != RM_SERVICE_PROCESSING)\r
537 {\r
538 \r
539 /* A transaction has received a response. Send the response to either the \r
540 * transaction or service responder based on the source instance */\r
541 if (strcmp(transaction->sourceInstName, rmInst->name))\r
542 {\r
543 /* Transaction originated from another instance. Use the \r
544 * transaction responder to send the result to the source instance. This\r
545 * is not possible on RM Clients since they can't forward RM services */\r
546 Rm_transactionResponder(rmInst, transaction);\r
547 }\r
548 else\r
549 {\r
550 /* Transaction originated on this instance. Send to the\r
551 * service responder */\r
552 Rm_serviceResponder(rmInst, transaction);\r
553 }\r
554 }\r
555 else\r
556 {\r
557 /* This is a new transaction that must be forwarded to a higher level RM instance. */\r
558 Rm_transactionForwarder(rmInst, transaction);\r
559 }\r
560 }\r
561 else\r
562 {\r
563 /* Client Delegate and Server transaction processors. */\r
564 switch (transaction->type)\r
565 {\r
566 case Rm_service_RESOURCE_ALLOCATE:\r
567 case Rm_service_RESOURCE_BLOCK_ALLOCATE:\r
568 case Rm_service_RESOURCE_ALLOCATE_BY_NAME:\r
569 case Rm_service_RESOURCE_FREE:\r
570 case Rm_service_RESOURCE_BLOCK_FREE:\r
571 case Rm_service_RESOURCE_FREE_BY_NAME: \r
572 /* Check if the transaction is fulfilled request */\r
573 if (transaction->state != RM_SERVICE_PROCESSING)\r
574 {\r
575 /* If source instance name does not match the current instance\r
576 * name the allocation request came from a client. The result\r
577 * must be sent back to the Client */\r
578 if (strcmp(transaction->sourceInstName, rmInst->name))\r
579 {\r
580 Rm_transactionResponder(rmInst, transaction);\r
581 }\r
582 else\r
583 {\r
584 /* Resource allocation request originated locally. Send the response\r
585 * via the service responder. */\r
586 Rm_serviceResponder(rmInst, transaction); \r
587 }\r
588 }\r
589 else\r
590 {\r
591 /* This is a new transaction request originating from an RM instance with fewer\r
592 * allocate/free privileges. Run the allocation or free handler to see if the resource\r
593 * request can be handled locally or if it needs to be forwarded to a higher level\r
594 * agent */\r
595 if ((transaction->type == Rm_service_RESOURCE_ALLOCATE) ||\r
596 (transaction->type == Rm_service_RESOURCE_BLOCK_ALLOCATE) ||\r
597 (transaction->type == Rm_service_RESOURCE_ALLOCATE_BY_NAME))\r
598 {\r
599 Rm_allocationHandler(rmInst, transaction);\r
600 }\r
601 else\r
602 {\r
603 Rm_freeHandler(rmInst, transaction);\r
604 }\r
605 }\r
606 break;\r
607 case Rm_service_RESOURCE_MAP_TO_NAME:\r
608 case Rm_service_RESOURCE_UNMAP_NAME: \r
609 /* Server is the only RM instance capable of adding NameServer objects */\r
610 if (rmInst->instType == Rm_instType_SERVER)\r
611 {\r
612 if (transaction->type == Rm_service_RESOURCE_MAP_TO_NAME)\r
613 {\r
614 /* Create a new NameServer object with the request transaction information.\r
615 * Transaction will contain the state result of the NameServer addition. */\r
616 Rm_nsAddObject(rmInst, transaction);\r
617 }\r
618 else\r
619 {\r
620 /* Delete an existing NameServer object with the request transaction information\r
621 * Transaction will contain the state result of the NameServer addition. */\r
622 Rm_nsDeleteObject(rmInst, transaction);\r
623 }\r
624 \r
625 /* If source instance name does not match the local instance\r
626 * name the NameServer request came from a Client or Client Delegate. The \r
627 * result must be sent back to the Client or Client Delegate. Just return if it does\r
628 * match since the NameServer transaction result can be returned immediately by the\r
629 * Rm_serviceHandler. */\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 void reverse_properties(void *fdt, int32_t offset)\r
645 {\r
646 int32_t len;\r
647 const char *name;\r
648 char nameTest[] = "resource-range";\r
649 const void *data;\r
650 uint32_t *dataPtr;\r
651 uint32_t i;\r
652 \r
653 data = fdt_getprop_by_offset(fdt, offset, &name, &len);\r
654 if (!data)\r
655 Rm_osalLog("Error traverse_properties fdt_getprop_by_offset: %d\n", len);\r
656 else\r
657 {\r
658 Rm_osalLog("Property name: %s with length: %d offset: %d and address: %x\n", name, len, offset, data);\r
659 Rm_osalLog("Property value: %s\n", (char *)data);\r
660 \r
661 if(strcmp(nameTest, name) == 0)\r
662 {\r
663 dataPtr = (uint32_t *)data;\r
664 Rm_osalLog("Range value: %d %d\n", dtb32_to_cpu(dataPtr[0]), dtb32_to_cpu(dataPtr[1]));\r
665 }\r
666 }\r
667 \r
668 offset = fdt_next_property_offset(fdt, offset);\r
669 if (offset >= 0)\r
670 reverse_properties(fdt, offset);\r
671 else if (offset != -FDT_ERR_NOTFOUND)\r
672 Rm_osalLog("Error traverse_properties fdt_next_property_offset: %d\n", offset);\r
673 }\r
674 \r
675 void reverse_node(void *fdt, int32_t nodeOffset);\r
676 \r
677 void reverse_children(void *fdt, int32_t offset)\r
678 {\r
679 const char *nodeName;\r
680 int32_t error;\r
681 int32_t nextOffset = offset;\r
682 int32_t depth = 1;\r
683 \r
684 do {\r
685 char path[256];\r
686 \r
687 nodeName = fdt_get_name(fdt, nextOffset, NULL);\r
688 error = fdt_get_path(fdt, nextOffset, path, sizeof(path));\r
689 if (error)\r
690 Rm_osalLog("Error reverse_children fdt_get_path: %d\n", error);\r
691 else\r
692 Rm_osalLog("Node path: %s with name %s\n", path, nodeName);\r
693 \r
694 \r
695 nextOffset = fdt_next_node(fdt, nextOffset, &depth);\r
696 if (error < 0)\r
697 Rm_osalLog("Error reverse_children fdt_next_node: %d\n", offset);\r
698 else\r
699 Rm_osalLog("Next node offset: %d with depth: %d\n", nextOffset, depth);\r
700 } while ((depth >= 0) && (depth != 1));\r
701 \r
702 if (depth == 1)\r
703 reverse_children(fdt, nextOffset);\r
704 \r
705 reverse_node(fdt, offset);\r
706 }\r
707 \r
708 void reverse_node(void *fdt, int32_t nodeOffset)\r
709 {\r
710 const char *nodeName = fdt_get_name(fdt, nodeOffset, NULL);\r
711 char path[256];\r
712 int32_t error;\r
713 int32_t offset;\r
714 int32_t depth = 0;\r
715 \r
716 error = fdt_get_path(fdt, nodeOffset, path, sizeof(path));\r
717 if (error)\r
718 Rm_osalLog("Error traverse_node fdt_get_path: %d\n", error);\r
719 else\r
720 Rm_osalLog("Node path: %s with name %s\n", path, nodeName);\r
721 \r
722 /* Get the properties for the node if any exist */\r
723 offset = fdt_first_property_offset(fdt, nodeOffset);\r
724 if (offset >= 0)\r
725 reverse_properties(fdt, offset);\r
726 else if (offset != -FDT_ERR_NOTFOUND)\r
727 Rm_osalLog("Error traverse_node fdt_first_property_offset: %d\n", offset);\r
728 \r
729 /* Get the next node */\r
730 offset = fdt_next_node(fdt, nodeOffset, &depth);\r
731 if (offset >= 0)\r
732 {\r
733 Rm_osalLog("Next node offset: %d with depth: %d\n", offset, depth);\r
734 }\r
735 else if (offset != -FDT_ERR_NOTFOUND)\r
736 Rm_osalLog("Error traverse_node fdt_next_node: %d\n", offset);\r
737 \r
738 if (depth == 1)\r
739 reverse_children(fdt, offset);\r
740 }\r
741 \r
742 void traverseFdt (void *fdt)\r
743 {\r
744 int32_t nodeOffset = 0; /* offset starts at 0, beginning of tree */\r
745 \r
746 reverse_node(fdt, nodeOffset);\r
747 }\r
748 \r
749 \r
750 /**********************************************************************\r
751 ********************** Application visible APIs **********************\r
752 **********************************************************************/\r
753 \r
754 Rm_Handle Rm_init(Rm_InitCfg *initCfg)\r
755 {\r
756 Rm_Inst *rmInst;\r
757 void *fdt = initCfg->globalResourceList; \r
758 \r
759 /* Instance creation checks. Add one to strlen calculation for null character */\r
760 if ((strlen(initCfg->instName) + 1) > RM_INSTANCE_NAME_MAX_CHARS)\r
761 {\r
762 /* Failure: Instance name is too big */\r
763 return (NULL);\r
764 }\r
765 \r
766 /* Get memory for RM instance from local memory */\r
767 rmInst = Rm_osalMalloc (sizeof(Rm_Inst));\r
768 /* Populate instance based on input parameters */\r
769 strcpy (&rmInst->name[0], initCfg->instName);\r
770 rmInst->instType = initCfg->instType;\r
771 rmInst->registeredWithDelegateOrServer = false;\r
772 \r
773 /* Initialize the transport routing map linked list pointer to NULL. The linked list\r
774 * nodes will be created when the application registers transports */\r
775 rmInst->routeMap = NULL;\r
776 \r
777 /* Initialize the transaction queue elements. */\r
778 rmInst->transactionSeqNum = Rm_transactionInitSequenceNum();\r
779 rmInst->transactionQueue= NULL;\r
780 \r
781 /* RM Server specific actions */\r
782 if (rmInst->instType == Rm_instType_SERVER)\r
783 {\r
784 /* Open the ResourceList file */\r
785 fdt_open_into(initCfg->globalResourceList, fdt, fdt_totalsize(initCfg->globalResourceList));\r
786 \r
787 /* TEST: Try to parse the entire fdt */\r
788 traverseFdt(fdt);\r
789 }\r
790 \r
791 /* Instance startup policies are only used for Servers and Client Delegates */\r
792 if (rmInst->instType != Rm_instType_CLIENT)\r
793 {\r
794 rmInst->instPolicy = initCfg->startupPolicy;\r
795 \r
796 /* Store policy via policy APIs ... */\r
797 }\r
798 \r
799 /* Return the RM Handle */\r
800 return ((Rm_Handle) rmInst);\r
801 }\r
802 \r
803 uint32_t Rm_getVersion (void)\r
804 {\r
805 return RM_VERSION_ID;\r
806 }\r
807 \r
808 \r
809 const char* Rm_getVersionStr (void)\r
810 {\r
811 return rmVersionStr;\r
812 }\r
813 \r
814 /**\r
815 @}\r
816 */\r