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