90cbf6dfaff7fae02c964eb8c1bd8bd52889de65
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / resources / RscTable.c
1 /*
2  *  @file       RscTable.c
3  *
4  *  @brief      Resource Table parser.
5  *
6  *  ============================================================================
7  *
8  *  Copyright (c) 2012, Texas Instruments Incorporated
9  *
10  *  Redistribution and use in source and binary forms, with or without
11  *  modification, are permitted provided that the following conditions
12  *  are met:
13  *
14  *  *  Redistributions of source code must retain the above copyright
15  *     notice, this list of conditions and the following disclaimer.
16  *
17  *  *  Redistributions in binary form must reproduce the above copyright
18  *     notice, this list of conditions and the following disclaimer in the
19  *     documentation and/or other materials provided with the distribution.
20  *
21  *  *  Neither the name of Texas Instruments Incorporated nor the names of
22  *     its contributors may be used to endorse or promote products derived
23  *     from this software without specific prior written permission.
24  *
25  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
27  *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28  *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
29  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
32  *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33  *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34  *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35  *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  *  Contact information for paper mail:
37  *  Texas Instruments
38  *  Post Office Box 655303
39  *  Dallas, Texas 75265
40  *  Contact information:
41  *  http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm?
42  *  DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact
43  *  ============================================================================
44  *
45  */
48 #if defined (__cplusplus)
49 extern "C" {
50 #endif
52 #include <ti/syslink/Std.h>
53 #include <ti/syslink/utils/List.h>
54 #include <ti/syslink/utils/Memory.h>
55 #include <ti/syslink/utils/Trace.h>
56 #include <RscTable.h>
57 #include <OsalKfile.h>
58 #include <_MultiProc.h>
59 #include <dload_api.h>
60 #include <ti/syslink/ProcMgr.h>
61 #include <Bitops.h>
62 #include <_MessageQCopyDefs.h>
63 #include <ProcDefs.h>
64 #include <sys/mman.h>
66 /* =============================================================================
67  *  Macros and types
68  * =============================================================================
69  */
70 /*
71  * ZEROINIT_CHUNKS - Set to 1 to zero-init chunk allocations for
72  *                   dynamically allocated remote core memory carveout
73  *                   sections. Default is 0 to achieve better startup
74  *                   performance.
75  */
76 #define ZEROINIT_CHUNKS 0
78 #define RSC_TABLE_STRING ".resource_table"
79 #define DDR_MEM 0x80000000
81 typedef struct Carveout_Elem_tag {
82     List_Elem  elem;
83     UInt32     addr;
84     UInt32     size;
85 } Carveout_Elem;
87 typedef struct Carveout_Object_tag {
88     UInt32      addr;
89     UInt32      size;
90     List_Handle freeBlocks;
91 } Carveout_Object;
93 /*!
94  *  @brief  RscTable Header
95  */
96 typedef struct RscTable_Header_tag {
97     UInt32 ver;
98     UInt32 num;
99     UInt32 reserved[2];
100     UInt32 offset[];
101 } RscTable_Header;
103 /*!
104  *  @brief  RscTable Entry
105  */
106 typedef struct RscTable_MemEntry_tag {
107     UInt32 type;
108     UInt32 da;       /* Device Virtual Address */
109     UInt32 pa;       /* Physical Address */
110     UInt32 len;
111     UInt32 flags;
112     UInt32 reserved;
113     Char   name[32];
114 } RscTable_MemEntry;
116 /*!
117  *  @brief  RscTable Module state object
118  */
119 typedef struct RscTable_ModuleObject_tag {
120     RscTable_Handle       handles [MultiProc_MAXPROCESSORS];
121     /*!< Array of Handles of RscTable instances */
122 } RscTable_ModuleObject;
124 /*!
125  *  @brief  RscTable instance object
126  */
127 struct RscTable_Object_tag {
128     UInt16                 procId;
129     /*!< Processor ID associated with this RscTable. */
130     Char *                 fileName;
131     /*!< File name associated with this RscTable. */
132     Void *                 rscTable;
133     /*!< Pointer to the resource table. */
134     UInt32                 rscTableLen;
135     /*!< Resource table length. */
136     UInt32                 rscTableDA;
137     /*!< Resource table device address. */
138     Carveout_Object *      carveout[SYSLINK_MAX_MEMENTRIES];
139     /*!< Carveouts for this table. */
140     UInt32                 numCarveouts;
141     /*!< Carveouts for this table. */
142     SysLink_MemEntry       memEntries[SYSLINK_MAX_MEMENTRIES];
143     /*!< Memory Entries for the remote processor. */
144     UInt32                 numMemEntries;
145     /*!< Number of Memory Entries in the memEntries array. */
146     struct fw_rsc_vdev_vring * vrings;
147     /*!< Vring info for the remote processor. */
148     UInt32                 numVrings;
149     /*!< Number of vrings. */
150     UInt32                 vringPa;
151     /*!< PAddr of vrings space. */
152     UInt32                 vringBufsPa;
153     /*!< PAddr of vring bufs space. */
154     struct fw_rsc_trace    trace;
155     /*!< Trace info. */
156     List_Handle            chunks;
157     /*!< Allocated Chunks. */
158 } ;
160 /* Defines the RscTable_Object type. */
161 typedef struct RscTable_Object_tag RscTable_Object;
163 /* =============================================================================
164  *  Globals
165  * =============================================================================
166  */
167 /*!
168  *  @var    RscTable_state
169  *
170  *  @brief  RscTable state object variable
171  */
172 #if !defined(SYSLINK_BUILD_DEBUG)
173 static
174 #endif /* if !defined(SYSLINK_BUILD_DEBUG) */
175 RscTable_ModuleObject RscTable_state;
178 /* =============================================================================
179  *  APIs
180  * =============================================================================
181  */
183 RscTable_Handle
184 RscTable_alloc (Char * fileName, UInt16 procId)
186     Int status = 0;
187     RscTable_Object * obj = NULL;
188     OsalKfile_Handle fileDesc  = NULL;
189     UInt32 res_offs = 0, res_addr = 0, res_size = 0;
190     List_Params params;
192     // Check if this one is already registered
193     if (RscTable_state.handles[procId]) {
194         /* Not setting status here since this function does not return status.*/
195         GT_setFailureReason (curTrace,
196                              GT_4CLASS,
197                              "RscTable_alloc",
198                              RSCTABLE_E_INVALIDARG,
199                              "Invalid procId specified");
200         return NULL;
201     }
203     // Find the resource table in the file
204     status = OsalKfile_open (fileName, "r", &fileDesc);
205     if (status < 0) {
206         /* Not setting status here since this function does not return status.*/
207         GT_setFailureReason (curTrace,
208                              GT_4CLASS,
209                              "RscTable_alloc",
210                              RSCTABLE_E_INVALIDARG,
211                              "Invalid fileDesc specified");
212         return NULL;
213     }
215     status = DLOAD_get_section_offset((LOADER_FILE_DESC *)fileDesc,
216                                       RSC_TABLE_STRING, &res_offs, &res_size,
217                                       &res_addr);
218     if (status >= 0) {
219         obj = Memory_calloc(NULL, sizeof (RscTable_Object), 0, NULL);
220         if (obj != NULL) {
221             // Allocate memory to hold the table
222             obj->rscTable = Memory_alloc(NULL, res_size, 0, NULL);
223             if (obj->rscTable == NULL) {
224                 /* Not setting status here since this function does not return
225                  * status.*/
226                 GT_setFailureReason (curTrace,
227                                      GT_4CLASS,
228                                      "RscTable_alloc",
229                                      RSCTABLE_E_MEMORY,
230                                      "Unable to allocate rscTable");
231                 Memory_free(NULL, obj, sizeof (RscTable_Object));
232                 obj = NULL;
233             }
234             else {
235                 obj->rscTableLen = res_size;
236                 status = OsalKfile_seek(fileDesc, res_offs,
237                                         OsalKfile_Pos_SeekSet);
238                 if (status < 0) {
239                     /* Not setting status here since this function does not
240                      * return status.*/
241                     GT_setFailureReason (curTrace,
242                                          GT_4CLASS,
243                                          "RscTable_alloc",
244                                          RSCTABLE_E_FAIL,
245                                          "Unable to seek to rsctable in file");
246                     Memory_free(NULL, obj->rscTable, res_size);
247                     Memory_free(NULL, obj, sizeof (RscTable_Object));
248                     obj = NULL;
249                 }
250                 else {
251                     // Copy the table to the allocated memory
252                     status = OsalKfile_read(fileDesc, (char *)obj->rscTable, 1,
253                                             res_size);
254                     if (status < 0) {
255                         /* Not setting status here since this function does not
256                          * return status.*/
257                         GT_setFailureReason (curTrace,
258                                              GT_4CLASS,
259                                              "RscTable_alloc",
260                                              RSCTABLE_E_FAIL,
261                                              "Unable to read rsctable in file");
262                         Memory_free(NULL, obj->rscTable, res_size);
263                         Memory_free(NULL, obj, sizeof (RscTable_Object));
264                         obj = NULL;
265                     }
266                     else {
267                         obj->rscTableDA = res_addr;
268                         List_Params_init(&params);
269                         obj->chunks = List_create(&params);
270                         if (obj->chunks == NULL) {
271                             /* Not setting status here since this function does
272                              * not return status.*/
273                             GT_setFailureReason (curTrace,
274                                                  GT_4CLASS,
275                                                  "RscTable_alloc",
276                                                  RSCTABLE_E_FAIL,
277                                                  "Unable to create list");
278                             Memory_free(NULL, obj->rscTable, res_size);
279                             Memory_free(NULL, obj, sizeof (RscTable_Object));
280                             obj = NULL;
281                         }
282                     }
283                 }
284             }
285         }
286         else {
287             /* Not setting status here since this function does not return
288              * status.*/
289             GT_setFailureReason (curTrace,
290                                  GT_4CLASS,
291                                  "RscTable_alloc",
292                                  RSCTABLE_E_MEMORY,
293                                  "Unable to allocate obj");
294         }
295     }
296     else {
297         /* Not setting status here since this function does not return status.*/
298         GT_setFailureReason (curTrace,
299                              GT_4CLASS,
300                              "RscTable_alloc",
301                              RSCTABLE_E_FAIL,
302                              "Unable to find resource table in file");
303     }
305     OsalKfile_close(&fileDesc);
307     // If successful, save coreId-handle pair for later access
308     if (obj) {
309         obj->procId = procId;
310         RscTable_state.handles[procId] = (RscTable_Handle)obj;
311     }
313     return (RscTable_Handle)obj;
316 /* Helper functions for processing carveout */
317 Int Carveout_register (RscTable_Object *obj, UInt32 id, Ptr carveOut,
318                        UInt32 carveOutLen)
320     Int status = 0;
321     Carveout_Object * cout = NULL;
322     List_Params params;
324     cout = Memory_alloc(NULL, sizeof(Carveout_Object), 0, NULL);
325     if (cout) {
326         cout->addr = (UInt32)carveOut;
327         cout->size = carveOutLen;
328         List_Params_init(&params);
329         cout->freeBlocks = List_create(&params);
330         if (cout->freeBlocks == NULL) {
331             status = RSCTABLE_E_MEMORY;
332             GT_setFailureReason (curTrace,
333                                  GT_4CLASS,
334                                  "Carveout_register",
335                                  status,
336                                  "Unable to create free list");
337             Memory_free(NULL, cout, sizeof(Carveout_Object));
338             cout = NULL;
339         }
340         else {
341             // Add the whole of the memory to the free list
342             Carveout_Elem * elem = Memory_alloc(NULL, sizeof(Carveout_Elem),
343                                                 0, NULL);
344             if (elem) {
345                 elem->addr = cout->addr;
346                 elem->size = cout->size;
347                 List_put(cout->freeBlocks, (List_Elem *)elem);
348             }
349             else {
350                 status = RSCTABLE_E_MEMORY;
351                 GT_setFailureReason (curTrace,
352                                      GT_4CLASS,
353                                      "Carveout_register",
354                                      status,
355                                      "Unable to allocate elem");
356                 List_delete(&cout->freeBlocks);
357                 Memory_free(NULL, cout, sizeof(Carveout_Object));
358                 cout = NULL;
359             }
360         }
361     }
362     else {
363         status = RSCTABLE_E_MEMORY;
364         GT_setFailureReason (curTrace,
365                              GT_4CLASS,
366                              "Carveout_register",
367                              status,
368                              "Unable to allocate carveout structure");
369     }
371     obj->carveout[id] = cout;
372     obj->numCarveouts++;
373     return status;
376 Int Carveout_unregister (RscTable_Object *obj, UInt32 id)
378     Int status = 0;
379     List_Elem * elem = NULL;
381     if (obj->carveout[id]) {
382         if (obj->carveout[id]->freeBlocks) {
383             while ((elem = List_get(obj->carveout[id]->freeBlocks)))
384                 Memory_free(NULL, elem, sizeof(Carveout_Elem));
385             List_delete(&obj->carveout[id]->freeBlocks);
386         }
388         Memory_free(NULL, obj->carveout[id], sizeof(Carveout_Object));
389         obj->carveout[id] = NULL;
390         obj->numCarveouts--;
391     }
392     else {
393         status = RSCTABLE_E_INVALIDARG;
394         GT_setFailureReason (curTrace,
395                              GT_4CLASS,
396                              "Carveout_unregister",
397                              status,
398                              "No carveout associated with obj");
399     }
401     return status;
404 // allocate any addr
405 Int Chunk_allocate (RscTable_Object *obj, UInt32 size, UInt32 * pa)
407     Int status = 0;
408     List_Elem * elem = NULL;
409     Void * da;
410     long long paddr;
411     UInt32 len;
413     if (!pa || !obj || !obj->chunks) {
414         status = RSCTABLE_E_INVALIDARG;
415         GT_setFailureReason (curTrace,
416                              GT_4CLASS,
417                              "Chunk_allocate",
418                              status,
419                              "Invalid arg passed");
420         GT_3trace(curTrace, GT_4CLASS, "obj [0x%x] obj->chunks [0x%x] pa [0x%x]", obj, obj ? obj->chunks : NULL, pa);
421     }
422     else {
423         // first try to allocate contiguous mem
424         da = mmap64(NULL, size,
425                     PROT_NOCACHE | PROT_READ | PROT_WRITE,
426 #if ZEROINIT_CHUNKS
427                     MAP_ANON | MAP_PHYS | MAP_SHARED,
428 #else
429                     MAP_ANON | MAP_PHYS | MAP_SHARED | MAP_NOINIT,
430 #endif
431                     NOFD,
432                     0);
433         if (da == MAP_FAILED) {
434             // TODO: try to allocate non-contigous mem then get the pages
435             status = RSCTABLE_E_MEMORY;
436             GT_setFailureReason (curTrace,
437                                  GT_4CLASS,
438                                  "Chunk_allocate",
439                                  status,
440                                  "Unable to allocate chunk");
441         }
442         else {
443             /* Make sure the memory is contiguous */
444             status = mem_offset64(da, NOFD, size, &paddr, &len);
445             if (status || (len != size)) {
446                 munmap(da, size);
447                 status = RSCTABLE_E_MEMORY;
448                 GT_setFailureReason (curTrace,
449                                      GT_4CLASS,
450                                      "Chunk_allocate",
451                                      status,
452                                      "mem_offset64 failed");
453             }
454             else {
455                 *pa = (UInt32)paddr;
456                 // save the memory so that it can be freed later
457                 elem = Memory_alloc(NULL, sizeof(Carveout_Elem), 0, NULL);
458                 if (elem == NULL) {
459                     munmap(da, size);
460                     status = RSCTABLE_E_MEMORY;
461                     GT_setFailureReason (curTrace,
462                                          GT_4CLASS,
463                                          "Chunk_allocate",
464                                          status,
465                                          "Memory_alloc failed");
466                 }
467                 else {
468                     ((Carveout_Elem *)elem)->addr = (UInt32)da;
469                     ((Carveout_Elem *)elem)->size = size;
470                     List_put(obj->chunks, elem);
471                 }
472             }
473         }
474     }
475     return status;
478 // allocate any addr from a specified carveout
479 Int Carveout_allocate (RscTable_Object *obj, UInt32 size, UInt32 * pa)
481     Int status = 0;
482     Carveout_Object * cout = NULL;
483     List_Elem * elem = NULL;
484     Bool found = FALSE;
485     UInt i = 0;
487     if (!pa || !obj || !obj->numCarveouts) {
488         status = RSCTABLE_E_INVALIDARG;
489         GT_setFailureReason (curTrace,
490                              GT_4CLASS,
491                              "Carveout_allocate",
492                              status,
493                              "Invalid arg passed");
494     }
495     else {
496         for (i = 0; i < obj->numCarveouts; i++) {
497             *pa = 0;
498             cout = obj->carveout[i];
500             // search for a free block with sufficient size
501             List_traverse(elem, cout->freeBlocks) {
502                 if (((Carveout_Elem *)elem)->size >= size) {
503                     found = TRUE;
504                     break;
505                 }
506             }
507             if (found) {
508                 UInt32 rem = 0;
509                 UInt32 addr = 0;
511                 // found a spot for our request
512                 addr = ((Carveout_Elem *)elem)->addr;
513                 rem = ((Carveout_Elem *)elem)->size - size;
514                 if (rem) {
515                     ((Carveout_Elem *)elem)->addr += size;
516                     ((Carveout_Elem *)elem)->size = rem;
517                 }
518                 else {
519                     List_remove(cout->freeBlocks, elem);
520                     Memory_free (NULL, elem, sizeof(Carveout_Elem));
521                 }
522                 *pa = addr;
523                 break;
524             }
525         }
526         if (i == obj->numCarveouts) {
527             status = RSCTABLE_E_MEMORY;
528             GT_setFailureReason (curTrace,
529                                  GT_4CLASS,
530                                  "Carveout_allocate",
531                                  status,
532                                  "Not enough room in carveout");
533         }
534     }
535     return status;
538 // allocate specific addr
539 Int Carveout_reserve (RscTable_Object *obj, UInt32 size, UInt32 pa)
541     Int status = 0;
542     Carveout_Object * cout = NULL;
543     List_Elem * elem = NULL;
544     Bool found = FALSE;
545     UInt i = 0;
547     if (!pa || !obj || !obj->numCarveouts) {
548         status = RSCTABLE_E_INVALIDARG;
549         GT_setFailureReason (curTrace,
550                              GT_4CLASS,
551                              "Carveout_reserve",
552                              status,
553                              "Invalid arg passed");
554     }
555     else {
556         for (i = 0; i < obj->numCarveouts; i++) {
557             cout = obj->carveout[i];
559             // search for a free block with sufficient size
560             List_traverse(elem, cout->freeBlocks) {
561                 if ((((Carveout_Elem *)elem)->addr <= pa) &&
562                     ((((Carveout_Elem *)elem)->addr +
563                       ((Carveout_Elem *)elem)->size) >= (pa + size))) {
564                     found = TRUE;
565                     break;
566                 }
567             }
568             if (found) {
569                 UInt32 rem_start = 0;
570                 UInt32 rem_end = 0;
572                 // found a spot for our request
573                 if (((Carveout_Elem *)elem)->addr < pa) {
574                     // there is free mem at the beginning of the block
575                     rem_start = pa - ((Carveout_Elem *)elem)->addr;
576                 }
577                 if (((Carveout_Elem *)elem)->addr + ((Carveout_Elem *)elem)->size >
578                     (pa + size)) {
579                     // there is free mem at the end of the block
580                     rem_end = ((Carveout_Elem *)elem)->addr +
581                               ((Carveout_Elem *)elem)->size - (pa + size);
582                 }
583                 // now carve up the block
584                 if (rem_start) {
585                     ((Carveout_Elem *)elem)->size = rem_start;
586                 }
587                 else if (rem_end) {
588                     ((Carveout_Elem *)elem)->size = rem_end;
589                     ((Carveout_Elem *)elem)->addr = pa + size;
590                 }
591                 else {
592                     List_remove(cout->freeBlocks, elem);
593                     Memory_free (NULL, elem, sizeof(Carveout_Elem));
594                 }
595                 if (rem_start && rem_end) {
596                     Carveout_Elem * c_elem = NULL;
597                     c_elem = Memory_alloc (NULL, sizeof(Carveout_Elem), 0, NULL);
598                     if (c_elem) {
599                         c_elem->size = rem_end;
600                         c_elem->addr = pa + size;
601                         List_insert(cout->freeBlocks, (List_Elem *)&c_elem->elem,
602                                     elem->next);
603                     }
604                     else {
605                         /* add mem back to free block */
606                         ((Carveout_Elem *)elem)->size += (size + rem_end);
607                         status = RSCTABLE_E_MEMORY;
608                         GT_setFailureReason (curTrace,
609                                              GT_4CLASS,
610                                              "Carveout_reserve",
611                                              status,
612                                              "Unable to allocate elem");
613                     }
614                 }
615                 break;
616             }
617         }
618         if (i == obj->numCarveouts) {
619             status = RSCTABLE_E_MEMORY;
620             GT_setFailureReason (curTrace,
621                                  GT_4CLASS,
622                                  "Carveout_reserve",
623                                  status,
624                                  "Specified addr/size not available");
626         }
627     }
628     return status;
631 Int
632 RscTable_process (UInt16 procId, Bool mmuEnabled, UInt32 numCarveouts,
633                   Ptr carveOut[], UInt32 carveOutLen[], Bool tryAlloc,
634                   UInt32 * numBlocks)
636     Int status = 0;
637     Int ret = 0;
638     RscTable_Object * obj = NULL;
639     RscTable_Header * table = NULL;
640     UInt i = 0, j = 0;
641     UInt dmem_num = 0;
642 #if !ZEROINIT_CHUNKS
643     UInt32 vringVA = 0, vringSize = 0;
644 #endif
646     // Find the table for this coreId, if not found, return an error
647     if (procId >= MultiProc_MAXPROCESSORS || !RscTable_state.handles[procId]) {
648         status = RSCTABLE_E_INVALIDARG;
649         GT_setFailureReason (curTrace,
650                              GT_4CLASS,
651                              "RscTable_process",
652                              status,
653                              "Invalid procId specified");
654         return status;
655     }
657     obj = (RscTable_Object *)RscTable_state.handles[procId];
658     table = (RscTable_Header *)obj->rscTable;
660     obj->numMemEntries = 0;
662     // Register carveout mem regions if provided
663     if (numCarveouts && carveOut && carveOutLen) {
664         for (i = 0; i < numCarveouts; i++) {
665             status = Carveout_register(obj, i, carveOut[i], carveOutLen[i]);
666             if (status < 0) {
667                 GT_setFailureReason (curTrace,
668                                      GT_4CLASS,
669                                      "RscTable_process",
670                                      status,
671                                      "Carveout_register failed");
672                 return status;
673             }
674         }
675     }
677     // TODO: Check the version
678     printf("RscTable_process: RscTable version is [%d]\n", table->ver);
680     // Process the table for this core, allocating carveout memory if necessary
681     for (i = 0; i < table->num && !ret; i++) {
682         RscTable_MemEntry * entry =
683                 (RscTable_MemEntry *)((UInt32)table + table->offset[i]);
684         switch (entry->type) {
685             case TYPE_CARVEOUT :
686             {
687                 // TODO: need to allocate this mem from carveout
688                 struct fw_rsc_carveout * cout = (struct fw_rsc_carveout *)entry;
689                 UInt32 pa = 0;
690                 if (cout->pa == 0)
691                     if (mmuEnabled)
692                         ret = Chunk_allocate (obj, cout->len, &pa);
693                     else {
694                         ret = Carveout_reserve (obj, cout->len, cout->da);
695                         pa = cout->da;
696                     }
697                 else
698                     ret = Carveout_reserve (obj, cout->len, cout->pa);
699                 if (!ret) {
700                     cout->pa = pa;
701                     if (obj->numMemEntries == SYSLINK_MAX_MEMENTRIES) {
702                         ret = -1;
703                     }
704                     else {
705                         obj->memEntries[obj->numMemEntries].slaveVirtAddr =
706                                 cout->da;
707                         obj->memEntries[obj->numMemEntries].masterPhysAddr =
708                                 cout->pa;
709                         obj->memEntries[obj->numMemEntries].size = cout->len;
710                         //if (mmuEnabled) {
711                             obj->memEntries[obj->numMemEntries].map = TRUE;
712                             obj->memEntries[obj->numMemEntries].mapMask =
713                                 ProcMgr_SLAVEVIRT;
714                         //}
715                         //else
716                         //    obj->memEntries[obj->numMemEntries].map = FALSE;
717                         obj->memEntries[obj->numMemEntries].isCached = FALSE;
718                         obj->memEntries[obj->numMemEntries].isValid = TRUE;
719                         obj->numMemEntries++;
720                     }
721                 }
722                 printf ("RscTable_process: carveout [%s] @ da [0x%08x] pa [0x%08x] len [0x%x]\n", cout->name, cout->da, cout->pa, cout->len);
723                 break;
724             }
725             case TYPE_DEVMEM :
726             {
727                 // only care about mem in DDR for now
728                 struct fw_rsc_devmem * dmem = (struct fw_rsc_devmem *)entry;
729                 UInt32 pa = 0;
730                 if (dmem->pa >= DDR_MEM) {
731                     // HACK: treat vring mem specially, vring is always the
732                     //       first devmem entry, may change in future
733                     if (dmem_num++ == 0) {
734                         // memory should already be reserved for vring
735                         if (obj->vringPa == 0) {
736                             // vdev must have been defined first
737                             GT_setFailureReason (curTrace,
738                                                  GT_4CLASS,
739                                                  "RscTable_process",
740                                                  status,
741                                                  "Vring Must be Defined First");
743                             ret = -1;
744                         }
745                         else if (obj->vringPa != dmem->pa &&
746                                  (!tryAlloc || !mmuEnabled)) {
747                             // defined pa does not match allocated pa, and
748                             // either the mmu is disabled or the platform has
749                             // not given permission to allocate on our own
750                             ret = -1;
751                             GT_setFailureReason (curTrace,
752                                                  GT_4CLASS,
753                                                  "RscTable_process",
754                                                  status,
755                                                  "Vring PA Mis-match");
757                             GT_2trace (curTrace, GT_4CLASS,
758                                        "vringPa is 0x%x, dmem->pa is 0x%x",
759                                        obj->vringPa, dmem->pa);
760                         }
761                         else {
762                             dmem->pa = obj->vringPa;
763                         }
764                     }
765                     else {
766                         ret = Carveout_reserve (obj, dmem->len, dmem->pa);
767                         if (ret && mmuEnabled && tryAlloc) {
768                             ret = Carveout_allocate (obj, dmem->len, &pa);
769                             if (!ret) dmem->pa = pa;
770                         }
771                     }
772                 }
773                 if (!ret) {
774                     if (obj->numMemEntries == SYSLINK_MAX_MEMENTRIES) {
775                         ret = -1;
776                     }
777                     else {
778                         obj->memEntries[obj->numMemEntries].slaveVirtAddr =
779                                 dmem->da;
780                         obj->memEntries[obj->numMemEntries].masterPhysAddr =
781                                 dmem->pa;
782                         obj->memEntries[obj->numMemEntries].size = dmem->len;
783                         //if (mmuEnabled) {
784                             obj->memEntries[obj->numMemEntries].map = TRUE;
785                             obj->memEntries[obj->numMemEntries].mapMask =
786                                 ProcMgr_SLAVEVIRT;
787                         //}
788                         //else
789                         //    obj->memEntries[obj->numMemEntries].map = FALSE;
790                         obj->memEntries[obj->numMemEntries].isCached = FALSE;
791                         obj->memEntries[obj->numMemEntries].isValid = TRUE;
792                         obj->numMemEntries++;
793                     }
794                 }
796                 // TODO: need to make sure this mem exists/is set aside, or allocate it
797                 printf ("RscTable_process: devmem [%s] @ da [0x%08x] pa [0x%08x] len [0x%x]\n", dmem->name, dmem->da, dmem->pa, dmem->len);
798                 break;
799             }
800             case TYPE_TRACE :
801             {
802                 // TODO: save da for future use
803                 struct fw_rsc_trace * trace = (struct fw_rsc_trace *)entry;
804                 Memory_copy(&obj->trace, trace, sizeof(*trace));
805                 printf ("RscTable_process: trace [%s] @ da [0x%08x] len [0x%x]\n", trace->name, trace->da, trace->len);
806                 break;
807             }
808             case TYPE_VDEV :
809             {
810                 // TODO: save vring info for future use
811                 struct fw_rsc_vdev *vdev = (struct fw_rsc_vdev *)entry;
812                 struct fw_rsc_vdev_vring * vring = NULL;
813                 UInt32 vr_size = 0;
814                 UInt32 vr_bufs_size = 0;
815                 UInt32 pa = 0;
816                 obj->numVrings = vdev->num_of_vrings;
817                 obj->vrings = Memory_alloc(NULL,
818                                            sizeof (*vring) * obj->numVrings, 0,
819                                            NULL);
820                 if (!obj->vrings)
821                     ret = -1;
822                 for (j = 0; j < vdev->num_of_vrings && !ret; j++) {
823                     vring = (struct fw_rsc_vdev_vring *)
824                                 ((UInt32)vdev + sizeof(*vdev) +
825                                  (sizeof(*vring) * j));
826                     Memory_copy (&obj->vrings[j], vring, sizeof (*vring));
827                     printf ("RscTable_process: vring [%d] @ [0x%08x]\n",
828                             vring->num, vring->da);
829                     // Hack, we know this is the size alignment
830                     if (vring->num != MessageQCopy_NUMBUFS ||
831                         vring->align != MessageQCopy_VRINGALIGN) {
832                         printf ("RscTable_process: warning size mis-match!\n");
833                         ret = -1;
834                     }
835                     vr_size += ROUND_UP(MessageQCopy_RINGSIZE, 0x4000);
836                     vr_bufs_size += (vring->num) * RPMSG_BUF_SIZE;
837                 }
838                 if (!ret)
839                     // HACK: round up to multiple of 1MB, because we know this
840                     //       is the size of the remote entry
841                     if (mmuEnabled)
842                         ret = Chunk_allocate(obj,
843                                      ROUND_UP(vr_size + vr_bufs_size, 0x100000),
844                                      &pa);
845                     else
846                         ret = Carveout_allocate(obj,
847                                      ROUND_UP(vr_size + vr_bufs_size, 0x100000),
848                                      &pa);
849                 else if (obj->vrings) {
850                     Memory_free (NULL, obj->vrings,
851                                  sizeof(*vring) * obj->numVrings);
852                     obj->vrings = NULL;
853                 }
855                 if (!ret) {
856 #if !ZEROINIT_CHUNKS
857                     /* Map the phys mem to local */
858                     vringSize = vr_size + vr_bufs_size;
859                     vringVA = (UInt32)mmap_device_io(vringSize, pa);
860                     if (vringVA != MAP_DEVICE_FAILED) {
861                         /* Zero-init the vring */
862                         Memory_set((Ptr)vringVA, 0, vringSize);
863                         munmap_device_io(vringVA, vringSize);
864                     }
865                     else {
866                         GT_0trace(curTrace, GT_4CLASS,
867                                   "RscTable_alloc: "
868                                   "Warning - Unable to zero-init vring mem");
869                     }
870 #endif
872                     obj->vringPa = pa;
873                     obj->vringBufsPa = pa + vr_size;
874                 }
875                 break;
876             }
877             case TYPE_CRASHDUMP :
878                 // what to do with this?
879                 break;
880             default :
881                 break;
882         }
883     }
885     if (ret) {
886         status = RSCTABLE_E_FAIL;
887         GT_setFailureReason (curTrace,
888                              GT_4CLASS,
889                              "RscTable_process",
890                              status,
891                              "Failure happened in processing table");
892         if (obj->vrings)
893             Memory_free(NULL, obj->vrings,
894                         sizeof(*obj->vrings) * obj->numVrings);
895         obj->vrings = NULL;
896         obj->numMemEntries = 0;
897     }
898     *numBlocks = obj->numMemEntries;
899     // Can un-register the carveout now? Don't need it anymore?
900     for (i = 0; i < numCarveouts; i++)
901         Carveout_unregister(obj, i);
903     return status;
906 Int
907 RscTable_getMemEntries (UInt16 procId, SysLink_MemEntry *memEntries,
908                         UInt32 * numMemEntries)
910     Int status = 0;
911     RscTable_Object *obj = NULL;
913     // Find the table for this procId, if not found, return an error
914     if (procId >= MultiProc_MAXPROCESSORS || !RscTable_state.handles[procId]) {
915         status = RSCTABLE_E_INVALIDARG;
916         GT_setFailureReason (curTrace,
917                              GT_4CLASS,
918                              "RscTable_getMemEntries",
919                              status,
920                              "Invalid ProcId specified");
921         return status;
922     }
924     obj = (RscTable_Object *)RscTable_state.handles[procId];
926     if (obj->memEntries && obj->numMemEntries &&
927         *numMemEntries >= obj->numMemEntries) {
928         *numMemEntries = obj->numMemEntries;
929         Memory_copy(memEntries, obj->memEntries,
930                     sizeof(*memEntries) * obj->numMemEntries);
931     }
932     else {
933         status = RSCTABLE_E_INVALIDARG;
934         GT_setFailureReason (curTrace,
935                              GT_4CLASS,
936                              "RscTable_getMemEntries",
937                              status,
938                              "Invalid num of memEntries or memEntries is NULL");
939     }
941     return status;
944 Int
945 RscTable_getInfo (UInt16 procId, UInt32 type, UInt32 extra, UInt32 * da,
946                   UInt32 *pa, UInt32 * len)
948     Int status = 0;
949     RscTable_Object *obj = NULL;
951     // Find the table for this procId, if not found, return an error
952     if (procId >= MultiProc_MAXPROCESSORS || !RscTable_state.handles[procId]) {
953         status = RSCTABLE_E_INVALIDARG;
954         GT_setFailureReason (curTrace,
955                              GT_4CLASS,
956                              "RscTable_getInfo",
957                              status,
958                              "Invalid procId specified");
959         return status;
960     }
962     obj = (RscTable_Object *)RscTable_state.handles[procId];
964     if (type == TYPE_TRACE) {
965         if (da && len) {
966             *da = obj->trace.da;
967             *len = obj->trace.len;
968         }
969         else {
970             status = RSCTABLE_E_INVALIDARG;
971             GT_setFailureReason (curTrace,
972                                  GT_4CLASS,
973                                  "RscTable_getInfo",
974                                  status,
975                                  "Invalid pointer passed");
976         }
977     }
978     else if (type == TYPE_VDEV) {
979         if (extra == 0 && len) {
980             *len = obj->numVrings;
981         }
982         else if (extra < obj->numVrings && da) {
983             *da = obj->vrings[extra-1].da;
984         }
985         else {
986             status = RSCTABLE_E_INVALIDARG;
987             GT_setFailureReason (curTrace,
988                                  GT_4CLASS,
989                                  "RscTable_getInfo",
990                                  status,
991                                  "Invalid pointer passed");
992         }
993     }
994     else {
995         // type not supported
996         status = -1;
997     }
999     return status;
1000     // Retrieve the info for a certain resource type (ex. Vring info)
1003 Int
1004 RscTable_update (UInt16 procId, ProcMgr_Handle procHandle)
1006     // Updates the table to physical memory so that phys addrs are available to
1007     // the remote cores.  This should be called only after loading the remote
1008     // cores.
1009     Int status = 0;
1010     RscTable_Object *obj = NULL;
1011     UInt32 rscTableVA = 0, rscTablePA = 0;
1013     // Find the table for this procId, if not found, return an error
1014     if (procId >= MultiProc_MAXPROCESSORS || !RscTable_state.handles[procId]) {
1015         status = RSCTABLE_E_INVALIDARG;
1016         GT_setFailureReason (curTrace,
1017                              GT_4CLASS,
1018                              "RscTable_update",
1019                              status,
1020                              "Invalid ProcId specified");
1021         return status;
1022     }
1024     obj = (RscTable_Object *)RscTable_state.handles[procId];
1026     status = ProcMgr_translateAddr(procHandle, (Ptr *)&rscTablePA,
1027                                    ProcMgr_AddrType_MasterPhys,
1028                                    (Ptr)obj->rscTableDA,
1029                                    ProcMgr_AddrType_SlaveVirt);
1030     if (status < 0) {
1031         status = RSCTABLE_E_FAIL;
1032         GT_setFailureReason (curTrace,
1033                              GT_4CLASS,
1034                              "RscTable_update",
1035                              status,
1036                              "Unable to get the Master PA for RscTable");
1037     }
1038     else {
1039         /* Map the phys mem to local */
1040         rscTableVA = (UInt32)mmap_device_io(obj->rscTableLen, rscTablePA);
1041         if (rscTableVA != MAP_DEVICE_FAILED) {
1042             /* Copy the updated table to the memory */
1043             Memory_copy((Ptr)rscTableVA, obj->rscTable, obj->rscTableLen);
1044             munmap_device_io(rscTableVA, obj->rscTableLen);
1045         }
1046         else {
1047             status = RSCTABLE_E_FAIL;
1048             GT_setFailureReason (curTrace,
1049                                  GT_4CLASS,
1050                                  "RscTable_update",
1051                                  status,
1052                                  "Unable to map memory");
1053         }
1054     }
1056     return status;
1059 Int
1060 RscTable_free (RscTable_Handle * handle)
1062     Int status = 0;
1063     RscTable_Object * obj = NULL;
1064     Int i = 0;
1065     List_Elem * elem;
1067     // Remove resource table from coreId-Handle pair list
1068     if (handle && *handle) {
1069         // sanity check
1070         for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
1071             if (RscTable_state.handles[i] == *handle)
1072                 break;
1073         }
1074         if (i < MultiProc_MAXPROCESSORS) {
1075             obj = (RscTable_Object *)(*handle);
1076             // Additional sanity check
1077             if (obj->procId == i) {
1078                 // Free vrings, memEntries, etc.
1079                 if (obj->chunks) {
1080                     while ((elem = List_get(obj->chunks))) {
1081                         Carveout_Elem * co_elem = (Carveout_Elem *)elem;
1082                         munmap((Void *)co_elem->addr, co_elem->size);
1083                         Memory_free(NULL, co_elem, sizeof(Carveout_Elem));
1084                     }
1085                     List_delete(&obj->chunks);
1086                     obj->chunks = NULL;
1087                 }
1088                 if (obj->vrings)
1089                     Memory_free(NULL, obj->vrings,
1090                                 sizeof(*obj->vrings) * obj->numVrings);
1091                 obj->vrings = NULL;
1092                 obj->numMemEntries = 0;
1094                 if (obj->rscTable)
1095                     Memory_free(NULL, obj->rscTable, obj->rscTableLen);
1096                 obj->rscTableDA = 0;
1097                 Memory_free(NULL, obj, sizeof (RscTable_Object));
1098                 *handle = NULL;
1099                 RscTable_state.handles[i] = NULL;
1100             }
1101         }
1102         else {
1103             status = RSCTABLE_E_INVALIDARG;
1104             GT_setFailureReason (curTrace,
1105                                  GT_4CLASS,
1106                                  "RscTable_free",
1107                                  status,
1108                                  "Invalid handle passed");
1109         }
1110     }
1111     else {
1112         status = RSCTABLE_E_INVALIDARG;
1113         GT_setFailureReason (curTrace,
1114                              GT_4CLASS,
1115                              "RscTable_free",
1116                              status,
1117                              "Invalid handle passed");
1118     }
1120     return status;
1123 Int RscTable_setStatus(UInt16 procId, UInt32 value)
1125     Int i;
1126     Int status = 0;
1128     RscTable_Object * obj = (RscTable_Object *)RscTable_state.handles[procId];
1129     RscTable_Header * table = (RscTable_Header *)obj->rscTable;
1131     /* Look for the vdev entry and update the status */
1132     for (i = 0; i < table->num; i++) {
1133         RscTable_MemEntry * entry =
1134                 (RscTable_MemEntry *)((UInt32)table + table->offset[i]);
1135         if (entry->type == TYPE_VDEV) {
1136             struct fw_rsc_vdev *vdev = (struct fw_rsc_vdev *)entry;
1137             vdev->status = value;
1138             break;
1139         }
1140     }
1142     if (i == table->num) {
1143         status = RSCTABLE_E_FAIL;
1144     }
1146     return status;
1149 #if defined (__cplusplus)
1151 #endif /* defined (__cplusplus) */