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