b8c597ec305787038d496029436f816ef637d6d3
[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-2015, 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 <Processor.h>
62 #include <Bitops.h>
63 #include <_MessageQCopyDefs.h>
64 #include <ProcDefs.h>
65 #include <sys/mman.h>
67 /* =============================================================================
68  *  Macros and types
69  * =============================================================================
70  */
71 /*
72  * ZEROINIT_CHUNKS - Set to 1 to zero-init chunk allocations for
73  *                   dynamically allocated remote core memory carveout
74  *                   sections. Default is 0 to achieve better startup
75  *                   performance.
76  */
77 #define ZEROINIT_CHUNKS 0
79 #define RSC_TABLE_STRING ".resource_table"
80 #define DDR_MEM 0x80000000
82 typedef struct Carveout_Elem_tag {
83     List_Elem  elem;
84     UInt32     addr;
85     UInt32     size;
86 } Carveout_Elem;
88 /*!
89  *  @brief  RscTable Header
90  */
91 typedef struct RscTable_Header_tag {
92     UInt32 ver;
93     UInt32 num;
94     UInt32 reserved[2];
95     UInt32 offset[];
96 } RscTable_Header;
98 /*!
99  *  @brief  RscTable Entry
100  */
101 typedef struct RscTable_MemEntry_tag {
102     UInt32 type;
103     UInt32 da;       /* Device Virtual Address */
104     UInt32 pa;       /* Physical Address */
105     UInt32 len;
106     UInt32 flags;
107     UInt32 reserved;
108     Char   name[32];
109 } RscTable_MemEntry;
111 /*!
112  *  @brief  RscTable Module state object
113  */
114 typedef struct RscTable_ModuleObject_tag {
115     RscTable_Handle       handles [MultiProc_MAXPROCESSORS];
116     /*!< Array of Handles of RscTable instances */
117 } RscTable_ModuleObject;
119 /*!
120  *  @brief  RscTable instance object
121  */
122 struct RscTable_Object_tag {
123     UInt16                 procId;
124     /*!< Processor ID associated with this RscTable. */
125     Char *                 fileName;
126     /*!< File name associated with this RscTable. */
127     Void *                 rscTable;
128     /*!< Pointer to the resource table. */
129     UInt32                 rscTableLen;
130     /*!< Resource table length. */
131     UInt32                 rscTableDA;
132     /*!< Resource table device address. */
133     SysLink_MemEntry       memEntries[SYSLINK_MAX_MEMENTRIES];
134     /*!< Memory Entries for the remote processor. */
135     UInt32                 numMemEntries;
136     /*!< Number of Memory Entries in the memEntries array. */
137     struct fw_rsc_vdev_vring * vrings;
138     /*!< Vring info for the remote processor. */
139     UInt32                 numVrings;
140     /*!< Number of vrings. */
141     UInt32                 vringPa;
142     /*!< PAddr of vrings space. */
143     UInt32                 vringBufsPa;
144     /*!< PAddr of vring bufs space. */
145     struct fw_rsc_trace    trace;
146     /*!< Trace info. */
147     List_Handle            chunks;
148     /*!< Allocated Chunks. */
149 } ;
151 /* Defines the RscTable_Object type. */
152 typedef struct RscTable_Object_tag RscTable_Object;
154 /* =============================================================================
155  *  Globals
156  * =============================================================================
157  */
158 /*!
159  *  @var    RscTable_state
160  *
161  *  @brief  RscTable state object variable
162  */
163 #if !defined(SYSLINK_BUILD_DEBUG)
164 static
165 #endif /* if !defined(SYSLINK_BUILD_DEBUG) */
166 RscTable_ModuleObject RscTable_state;
169 /* =============================================================================
170  *  APIs
171  * =============================================================================
172  */
174 RscTable_Handle
175 RscTable_alloc (Char * fileName, UInt16 procId)
177     Int status = 0;
178     RscTable_Object * obj = NULL;
179     OsalKfile_Handle fileDesc  = NULL;
180     UInt32 res_offs = 0, res_addr = 0, res_size = 0;
181     List_Params params;
183     // Check if this one is already registered
184     if (RscTable_state.handles[procId]) {
185         /* Not setting status here since this function does not return status.*/
186         GT_setFailureReason (curTrace,
187                              GT_4CLASS,
188                              "RscTable_alloc",
189                              RSCTABLE_E_INVALIDARG,
190                              "Invalid procId specified");
191         return NULL;
192     }
194     // Find the resource table in the file
195     status = OsalKfile_open (fileName, "r", &fileDesc);
196     if (status < 0) {
197         /* Not setting status here since this function does not return status.*/
198         GT_setFailureReason (curTrace,
199                              GT_4CLASS,
200                              "RscTable_alloc",
201                              RSCTABLE_E_INVALIDARG,
202                              "Invalid fileDesc specified");
203         return NULL;
204     }
206     status = DLOAD_get_section_offset((LOADER_FILE_DESC *)fileDesc,
207                                       RSC_TABLE_STRING, &res_offs, &res_size,
208                                       &res_addr);
209     if (status >= 0) {
210         obj = Memory_calloc(NULL, sizeof (RscTable_Object), 0, NULL);
211         if (obj != NULL) {
212             // Allocate memory to hold the table
213             obj->rscTable = Memory_alloc(NULL, res_size, 0, NULL);
214             if (obj->rscTable == NULL) {
215                 /* Not setting status here since this function does not return
216                  * status.*/
217                 GT_setFailureReason (curTrace,
218                                      GT_4CLASS,
219                                      "RscTable_alloc",
220                                      RSCTABLE_E_MEMORY,
221                                      "Unable to allocate rscTable");
222                 Memory_free(NULL, obj, sizeof (RscTable_Object));
223                 obj = NULL;
224             }
225             else {
226                 obj->rscTableLen = res_size;
227                 status = OsalKfile_seek(fileDesc, res_offs,
228                                         OsalKfile_Pos_SeekSet);
229                 if (status < 0) {
230                     /* Not setting status here since this function does not
231                      * return status.*/
232                     GT_setFailureReason (curTrace,
233                                          GT_4CLASS,
234                                          "RscTable_alloc",
235                                          RSCTABLE_E_FAIL,
236                                          "Unable to seek to rsctable in file");
237                     Memory_free(NULL, obj->rscTable, res_size);
238                     Memory_free(NULL, obj, sizeof (RscTable_Object));
239                     obj = NULL;
240                 }
241                 else {
242                     // Copy the table to the allocated memory
243                     status = OsalKfile_read(fileDesc, (char *)obj->rscTable, 1,
244                                             res_size);
245                     if (status < 0) {
246                         /* Not setting status here since this function does not
247                          * return status.*/
248                         GT_setFailureReason (curTrace,
249                                              GT_4CLASS,
250                                              "RscTable_alloc",
251                                              RSCTABLE_E_FAIL,
252                                              "Unable to read rsctable in file");
253                         Memory_free(NULL, obj->rscTable, res_size);
254                         Memory_free(NULL, obj, sizeof (RscTable_Object));
255                         obj = NULL;
256                     }
257                     else {
258                         obj->rscTableDA = res_addr;
259                         List_Params_init(&params);
260                         obj->chunks = List_create(&params);
261                         if (obj->chunks == NULL) {
262                             /* Not setting status here since this function does
263                              * not return status.*/
264                             GT_setFailureReason (curTrace,
265                                                  GT_4CLASS,
266                                                  "RscTable_alloc",
267                                                  RSCTABLE_E_FAIL,
268                                                  "Unable to create list");
269                             Memory_free(NULL, obj->rscTable, res_size);
270                             Memory_free(NULL, obj, sizeof (RscTable_Object));
271                             obj = NULL;
272                         }
273                     }
274                 }
275             }
276         }
277         else {
278             /* Not setting status here since this function does not return
279              * status.*/
280             GT_setFailureReason (curTrace,
281                                  GT_4CLASS,
282                                  "RscTable_alloc",
283                                  RSCTABLE_E_MEMORY,
284                                  "Unable to allocate obj");
285         }
286     }
287     else {
288         /* Not setting status here since this function does not return status.*/
289         GT_setFailureReason (curTrace,
290                              GT_4CLASS,
291                              "RscTable_alloc",
292                              RSCTABLE_E_FAIL,
293                              "Unable to find resource table in file");
294     }
296     OsalKfile_close(&fileDesc);
298     // If successful, save coreId-handle pair for later access
299     if (obj) {
300         obj->procId = procId;
301         RscTable_state.handles[procId] = (RscTable_Handle)obj;
302     }
304     return (RscTable_Handle)obj;
307 // allocate any addr
308 Int Chunk_allocate (RscTable_Object *obj, UInt32 size, UInt32 * pa)
310     Int status = 0;
311     List_Elem * elem = NULL;
312     Void * da;
313     long long paddr;
314     UInt32 len;
316     if (!pa || !obj || !obj->chunks) {
317         status = RSCTABLE_E_INVALIDARG;
318         GT_setFailureReason (curTrace,
319                              GT_4CLASS,
320                              "Chunk_allocate",
321                              status,
322                              "Invalid arg passed");
323         GT_3trace(curTrace, GT_4CLASS, "obj [0x%x] obj->chunks [0x%x] pa [0x%x]", obj, obj ? obj->chunks : NULL, pa);
324     }
325     else {
326         // first try to allocate contiguous mem
327         da = mmap64(NULL, size,
328                     PROT_NOCACHE | PROT_READ | PROT_WRITE,
329 #if ZEROINIT_CHUNKS
330                     MAP_ANON | MAP_PHYS | MAP_SHARED,
331 #else
332                     MAP_ANON | MAP_PHYS | MAP_SHARED | MAP_NOINIT,
333 #endif
334                     NOFD,
335                     0);
336         if (da == MAP_FAILED) {
337             // TODO: try to allocate non-contigous mem then get the pages
338             status = RSCTABLE_E_MEMORY;
339             GT_setFailureReason (curTrace,
340                                  GT_4CLASS,
341                                  "Chunk_allocate",
342                                  status,
343                                  "Unable to allocate chunk");
344         }
345         else {
346             /* Make sure the memory is contiguous */
347             status = mem_offset64(da, NOFD, size, &paddr, &len);
348             if (status || (len != size)) {
349                 munmap(da, size);
350                 status = RSCTABLE_E_MEMORY;
351                 GT_setFailureReason (curTrace,
352                                      GT_4CLASS,
353                                      "Chunk_allocate",
354                                      status,
355                                      "mem_offset64 failed");
356             }
357             else {
358                 *pa = (UInt32)paddr;
359                 // save the memory so that it can be freed later
360                 elem = Memory_alloc(NULL, sizeof(Carveout_Elem), 0, NULL);
361                 if (elem == NULL) {
362                     munmap(da, size);
363                     status = RSCTABLE_E_MEMORY;
364                     GT_setFailureReason (curTrace,
365                                          GT_4CLASS,
366                                          "Chunk_allocate",
367                                          status,
368                                          "Memory_alloc failed");
369                 }
370                 else {
371                     ((Carveout_Elem *)elem)->addr = (UInt32)da;
372                     ((Carveout_Elem *)elem)->size = size;
373                     List_put(obj->chunks, elem);
374                 }
375             }
376         }
377     }
378     return status;
381 Int
382 RscTable_process (UInt16 procId, Bool tryAlloc, UInt32 * numBlocks,
383     Processor_Handle procHandle, ProcMgr_BootMode bootMode)
385     Int status = 0;
386     Int ret = 0;
387     RscTable_Object * obj = NULL;
388     RscTable_Header * table = NULL;
389     UInt i = 0, j = 0;
390     UInt dmem_num = 0;
391     struct fw_rsc_vdev *vdev = NULL;
392     struct fw_rsc_vdev_vring * vring = NULL;
393     UInt32 vr_size = 0;
394 #if !ZEROINIT_CHUNKS
395     UInt32 vringVA = 0, vringSize = 0;
396 #endif
398     // Find the table for this coreId, if not found, return an error
399     if (procId >= MultiProc_MAXPROCESSORS || !RscTable_state.handles[procId]) {
400         status = RSCTABLE_E_INVALIDARG;
401         GT_setFailureReason (curTrace,
402                              GT_4CLASS,
403                              "RscTable_process",
404                              status,
405                              "Invalid procId specified");
406         return status;
407     }
409     obj = (RscTable_Object *)RscTable_state.handles[procId];
410     table = (RscTable_Header *)obj->rscTable;
412     obj->numMemEntries = 0;
414     // TODO: Check the version
415     printf("RscTable_process: RscTable version is [%d]\n", table->ver);
417     // Process the table for this core, allocating carveout memory if necessary
418     for (i = 0; i < table->num && !ret; i++) {
419         RscTable_MemEntry * entry =
420                 (RscTable_MemEntry *)((UInt32)table + table->offset[i]);
421         switch (entry->type) {
422             case TYPE_CARVEOUT :
423             {
424                 // TODO: need to allocate this mem from carveout
425                 struct fw_rsc_carveout * cout =
426                     (struct fw_rsc_carveout *)entry;
427                 UInt32 pa = 0;
429                 if (bootMode == ProcMgr_BootMode_NoBoot) {
430                     /* Lookup physical address of carveout from page table */
431                     if (Processor_translateFromPte(procHandle,
432                         &cout->pa, cout->da) != ProcMgr_S_SUCCESS) {
433                         status = RSCTABLE_E_FAIL;
434                         GT_setFailureReason (curTrace,
435                              GT_4CLASS,
436                              "RscTable_process",
437                              status,
438                              "Failed to lookup address from page table");
439                         ret = -1;
440                     }
441                 }
442                 else {
443                     if (cout->pa == 0) {
444                         ret = Chunk_allocate (obj, cout->len, &pa);
445                     }
446                     if (!ret) {
447                         cout->pa = pa;
448                     }
449                 }
451                 if (ret == 0) {
452                     if (obj->numMemEntries == SYSLINK_MAX_MEMENTRIES) {
453                         ret = -1;
454                     }
455                     else {
456                         obj->memEntries[obj->numMemEntries].slaveVirtAddr =
457                             cout->da;
458                         obj->memEntries[obj->numMemEntries].masterPhysAddr =
459                             cout->pa;
460                         obj->memEntries[obj->numMemEntries].size =
461                             cout->len;
462                         obj->memEntries[obj->numMemEntries].map = TRUE;
463                         obj->memEntries[obj->numMemEntries].mapMask =
464                             ProcMgr_SLAVEVIRT;
465                         obj->memEntries[obj->numMemEntries].isCached =
466                             FALSE;
467                         obj->memEntries[obj->numMemEntries].isValid = TRUE;
468                         obj->numMemEntries++;
469                     }
470                 }
471                 printf ("RscTable_process: carveout [%s] @ da [0x%08x] pa [0x%08x] len [0x%x]\n", cout->name, cout->da, cout->pa, cout->len);
472                 break;
473             }
474             case TYPE_INTMEM :
475             {
476                 struct fw_rsc_intmem * cout = (struct fw_rsc_intmem *)entry;
478                 if (obj->numMemEntries == SYSLINK_MAX_MEMENTRIES) {
479                     ret = -1;
480                 }
481                 else {
482                     obj->memEntries[obj->numMemEntries].slaveVirtAddr =
483                             cout->da;
484                     obj->memEntries[obj->numMemEntries].masterPhysAddr =
485                             cout->pa;
486                     obj->memEntries[obj->numMemEntries].size = cout->len;
487                     /* do not map to slave MMU */
488                     obj->memEntries[obj->numMemEntries].map = FALSE;
489                     obj->memEntries[obj->numMemEntries].mapMask =
490                         ProcMgr_SLAVEVIRT;
491                     obj->memEntries[obj->numMemEntries].isCached = FALSE;
492                     obj->memEntries[obj->numMemEntries].isValid = TRUE;
493                     obj->numMemEntries++;
494                 }
495                 printf ("RscTable_process: intmem [%s] @ da [0x%08x]"
496                     " pa [0x%08x] len [0x%x]\n", cout->name, cout->da,
497                     cout->pa, cout->len);
498                 break;
499             }
500             case TYPE_DEVMEM :
501             {
502                 // only care about mem in DDR for now
503                 struct fw_rsc_devmem * dmem = (struct fw_rsc_devmem *)entry;
504                 UInt32 pa = 0;
506                 if (dmem->pa >= DDR_MEM) {
507                     // HACK: treat vring mem specially, vring is always the
508                     //       first devmem entry, may change in future
509                     if (dmem_num++ == 0) {
510                         if (bootMode == ProcMgr_BootMode_NoBoot) {
511                             /*
512                              * Lookup physical address of vrings from page
513                              * table
514                              */
515                             if (Processor_translateFromPte(procHandle,
516                                 &pa, dmem->da) != ProcMgr_S_SUCCESS) {
517                                 status = RSCTABLE_E_FAIL;
518                                 GT_setFailureReason (curTrace,
519                                     GT_4CLASS,
520                                     "RscTable_process",
521                                     status,
522                                     "Failed to lookup address from page table");
523                                 ret = -1;
524                             }
525                             obj->vringPa = pa;
526                             obj->vringBufsPa = pa + vr_size;
527                         }
528                         else {
529                             // memory should already be reserved for vring
530                             if (obj->vringPa == 0) {
531                                 // vdev must have been defined first
532                                 GT_setFailureReason (curTrace,
533                                                  GT_4CLASS,
534                                                  "RscTable_process",
535                                                  status,
536                                                  "Vring Must be Defined First");
538                                 ret = -1;
539                             }
540                             else if (obj->vringPa != dmem->pa && (!tryAlloc)) {
541                                 // defined pa does not match allocated pa, and
542                                 // either the mmu is disabled or the platform has
543                                 // not given permission to allocate on our own
544                                 ret = -1;
545                                 GT_setFailureReason (curTrace,
546                                                  GT_4CLASS,
547                                                  "RscTable_process",
548                                                  status,
549                                                  "Vring PA Mis-match");
551                                 GT_2trace (curTrace, GT_4CLASS,
552                                        "vringPa is 0x%x, dmem->pa is 0x%x",
553                                        obj->vringPa, dmem->pa);
554                             }
555                         }
556                         if (ret == 0) {
557 #if !ZEROINIT_CHUNKS
558                             /* Map the phys mem to local */
559                             vringVA = (UInt32)mmap_device_io(vringSize,
560                                 obj->vringPa);
561                             if (vringVA != MAP_DEVICE_FAILED) {
562                                 /* Zero-init the vring */
563                                 Memory_set((Ptr)vringVA, 0, vringSize);
564                                 munmap_device_io(vringVA, vringSize);
565                             }
566                             else {
567                                 GT_0trace(curTrace, GT_4CLASS,
568                                     "RscTable_alloc: "
569                                     "Warning - Unable to zero-init vring mem");
570                             }
571 #endif
572                             /*
573                              * Override the vring 'da' field in resource table.
574                              * This allows the slave to look it up when creating
575                              * the VirtQueues
576                              */
577                             for (j = 0; j < vdev->num_of_vrings; j++) {
578                                 vring = (struct fw_rsc_vdev_vring *)
579                                     ((UInt32)vdev + sizeof(*vdev) +
580                                      (sizeof(*vring) * j));
581                                 vring->da = obj->vringPa + (j *
582                                     vr_size / vdev->num_of_vrings);
583                             }
585                             /*
586                              * Override the physical address provided by the
587                              * entry with the physical locations of the vrings
588                              * as allocated when we processed the vdev entry
589                              * (or as allocated by external loader for late
590                              * attach mode)
591                              */
592                             dmem->pa = obj->vringPa;
593                         }
594                     }
595                 }
596                 if (!ret) {
597                     if (obj->numMemEntries == SYSLINK_MAX_MEMENTRIES) {
598                         ret = -1;
599                     }
600                     else {
601                         obj->memEntries[obj->numMemEntries].slaveVirtAddr =
602                                 dmem->da;
603                         obj->memEntries[obj->numMemEntries].masterPhysAddr =
604                                 dmem->pa;
605                         obj->memEntries[obj->numMemEntries].size = dmem->len;
606                         obj->memEntries[obj->numMemEntries].map = TRUE;
607                         obj->memEntries[obj->numMemEntries].mapMask =
608                             ProcMgr_SLAVEVIRT;
609                         obj->memEntries[obj->numMemEntries].isCached = FALSE;
610                         obj->memEntries[obj->numMemEntries].isValid = TRUE;
611                         obj->numMemEntries++;
612                     }
613                 }
615                 // TODO: need to make sure this mem exists/is set aside, or allocate it
616                 printf ("RscTable_process: devmem [%s] @ da [0x%08x] pa [0x%08x] len [0x%x]\n", dmem->name, dmem->da, dmem->pa, dmem->len);
617                 break;
618             }
619             case TYPE_TRACE :
620             {
621                 // TODO: save da for future use
622                 struct fw_rsc_trace * trace = (struct fw_rsc_trace *)entry;
623                 Memory_copy(&obj->trace, trace, sizeof(*trace));
624                 printf ("RscTable_process: trace [%s] @ da [0x%08x] len [0x%x]\n", trace->name, trace->da, trace->len);
625                 break;
626             }
627             case TYPE_VDEV :
628             {
629                 // TODO: save vring info for future use
630                 UInt32 vr_bufs_size = 0;
631                 UInt32 pa = 0;
633                 vdev = (struct fw_rsc_vdev *)entry;
634                 obj->numVrings = vdev->num_of_vrings;
635                 obj->vrings = Memory_alloc(NULL,
636                                            sizeof (*vring) * obj->numVrings, 0,
637                                            NULL);
638                 if (!obj->vrings)
639                     ret = -1;
640                 for (j = 0; j < vdev->num_of_vrings && !ret; j++) {
641                     vring = (struct fw_rsc_vdev_vring *)
642                                 ((UInt32)vdev + sizeof(*vdev) +
643                                  (sizeof(*vring) * j));
644                     /*
645                      * Making a copy of original vring, given obj->vrings[j].da
646                      * is used as slave virtual address in RscTable_getInfo(),
647                      * and that is what the original vring definition contains.
648                      */
649                     Memory_copy (&obj->vrings[j], vring, sizeof (*vring));
650                     printf ("RscTable_process: vring [%d] @ [0x%08x]\n",
651                             vring->num, vring->da);
652                     // Hack, we know this is the size alignment
653                     if (vring->num != MessageQCopy_NUMBUFS ||
654                         vring->align != MessageQCopy_VRINGALIGN) {
655                         printf ("RscTable_process: warning size mis-match!\n");
656                         ret = -1;
657                     }
658                     vr_size += ROUND_UP(MessageQCopy_RINGSIZE, 0x4000);
659                     vr_bufs_size += (vring->num) * RPMSG_BUF_SIZE;
660                 }
661                 if ((!ret) && (bootMode != ProcMgr_BootMode_NoBoot)) {
662                     // HACK: round up to multiple of 1MB, because we know this
663                     //       is the size of the remote entry
664                     ret = Chunk_allocate(obj,
665                         ROUND_UP(vr_size + vr_bufs_size, 0x100000),
666                         &pa);
667                 }
669                 if (!ret) {
670 #if !ZEROINIT_CHUNKS
671                     vringSize = vr_size + vr_bufs_size;
672 #endif
673                     if (bootMode != ProcMgr_BootMode_NoBoot) {
674                         obj->vringPa = pa;
675                         obj->vringBufsPa = pa + vr_size;
676                     }
677                 }
678                 else if (obj->vrings) {
679                     Memory_free (NULL, obj->vrings,
680                                  sizeof(*vring) * obj->numVrings);
681                     obj->vrings = NULL;
682                 }
684                 break;
685             }
686             default :
687                 break;
688         }
689     }
691     if (ret) {
692         status = RSCTABLE_E_FAIL;
693         GT_setFailureReason (curTrace,
694                              GT_4CLASS,
695                              "RscTable_process",
696                              status,
697                              "Failure happened in processing table");
698         if (obj->vrings)
699             Memory_free(NULL, obj->vrings,
700                         sizeof(*obj->vrings) * obj->numVrings);
701         obj->vrings = NULL;
702         obj->numMemEntries = 0;
703     }
704     *numBlocks = obj->numMemEntries;
706     return status;
709 Int
710 RscTable_getMemEntries (UInt16 procId, SysLink_MemEntry *memEntries,
711                         UInt32 * numMemEntries)
713     Int status = 0;
714     RscTable_Object *obj = NULL;
716     // Find the table for this procId, if not found, return an error
717     if (procId >= MultiProc_MAXPROCESSORS || !RscTable_state.handles[procId]) {
718         status = RSCTABLE_E_INVALIDARG;
719         GT_setFailureReason (curTrace,
720                              GT_4CLASS,
721                              "RscTable_getMemEntries",
722                              status,
723                              "Invalid ProcId specified");
724         return status;
725     }
727     obj = (RscTable_Object *)RscTable_state.handles[procId];
729     if (obj->memEntries && obj->numMemEntries &&
730         *numMemEntries >= obj->numMemEntries) {
731         *numMemEntries = obj->numMemEntries;
732         Memory_copy(memEntries, obj->memEntries,
733                     sizeof(*memEntries) * obj->numMemEntries);
734     }
735     else {
736         status = RSCTABLE_E_INVALIDARG;
737         GT_setFailureReason (curTrace,
738                              GT_4CLASS,
739                              "RscTable_getMemEntries",
740                              status,
741                              "Invalid num of memEntries or memEntries is NULL");
742     }
744     return status;
747 Int
748 RscTable_getInfo (UInt16 procId, UInt32 type, UInt32 extra, UInt32 * da,
749                   UInt32 *pa, UInt32 * len)
751     Int status = 0;
752     RscTable_Object *obj = NULL;
754     // Find the table for this procId, if not found, return an error
755     if (procId >= MultiProc_MAXPROCESSORS || !RscTable_state.handles[procId]) {
756         status = RSCTABLE_E_INVALIDARG;
757         GT_setFailureReason (curTrace,
758                              GT_4CLASS,
759                              "RscTable_getInfo",
760                              status,
761                              "Invalid procId specified");
762         return status;
763     }
765     obj = (RscTable_Object *)RscTable_state.handles[procId];
767     if (type == TYPE_TRACE) {
768         if (da && len) {
769             *da = obj->trace.da;
770             *len = obj->trace.len;
771         }
772         else {
773             status = RSCTABLE_E_INVALIDARG;
774             GT_setFailureReason (curTrace,
775                                  GT_4CLASS,
776                                  "RscTable_getInfo",
777                                  status,
778                                  "Invalid pointer passed");
779         }
780     }
781     else if (type == TYPE_VDEV) {
782         if (extra == 0 && len) {
783             *len = obj->numVrings;
784         }
785         else if (extra < obj->numVrings && da) {
786             *da = obj->vrings[extra-1].da;
787         }
788         else {
789             status = RSCTABLE_E_INVALIDARG;
790             GT_setFailureReason (curTrace,
791                                  GT_4CLASS,
792                                  "RscTable_getInfo",
793                                  status,
794                                  "Invalid pointer passed");
795         }
796     }
797     else {
798         // type not supported
799         status = -1;
800     }
802     return status;
803     // Retrieve the info for a certain resource type (ex. Vring info)
806 Int
807 RscTable_update (UInt16 procId, ProcMgr_Handle procHandle)
809     // Updates the table to physical memory so that phys addrs are available to
810     // the remote cores.  This should be called only after loading the remote
811     // cores.
812     Int status = 0;
813     RscTable_Object *obj = NULL;
814     UInt32 rscTableVA = 0, rscTablePA = 0;
816     // Find the table for this procId, if not found, return an error
817     if (procId >= MultiProc_MAXPROCESSORS || !RscTable_state.handles[procId]) {
818         status = RSCTABLE_E_INVALIDARG;
819         GT_setFailureReason (curTrace,
820                              GT_4CLASS,
821                              "RscTable_update",
822                              status,
823                              "Invalid ProcId specified");
824         return status;
825     }
827     obj = (RscTable_Object *)RscTable_state.handles[procId];
829     status = ProcMgr_translateAddr(procHandle, (Ptr *)&rscTablePA,
830                                    ProcMgr_AddrType_MasterPhys,
831                                    (Ptr)obj->rscTableDA,
832                                    ProcMgr_AddrType_SlaveVirt);
833     if (status < 0) {
834         status = RSCTABLE_E_FAIL;
835         GT_setFailureReason (curTrace,
836                              GT_4CLASS,
837                              "RscTable_update",
838                              status,
839                              "Unable to get the Master PA for RscTable");
840     }
841     else {
842         /* Map the phys mem to local */
843         rscTableVA = (UInt32)mmap_device_io(obj->rscTableLen, rscTablePA);
844         if (rscTableVA != MAP_DEVICE_FAILED) {
845             /* Copy the updated table to the memory */
846             Memory_copy((Ptr)rscTableVA, obj->rscTable, obj->rscTableLen);
847             munmap_device_io(rscTableVA, obj->rscTableLen);
848         }
849         else {
850             status = RSCTABLE_E_FAIL;
851             GT_setFailureReason (curTrace,
852                                  GT_4CLASS,
853                                  "RscTable_update",
854                                  status,
855                                  "Unable to map memory");
856         }
857     }
859     return status;
862 Int
863 RscTable_free (RscTable_Handle * handle)
865     Int status = 0;
866     RscTable_Object * obj = NULL;
867     Int i = 0;
868     List_Elem * elem;
870     // Remove resource table from coreId-Handle pair list
871     if (handle && *handle) {
872         // sanity check
873         for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
874             if (RscTable_state.handles[i] == *handle)
875                 break;
876         }
877         if (i < MultiProc_MAXPROCESSORS) {
878             obj = (RscTable_Object *)(*handle);
879             // Additional sanity check
880             if (obj->procId == i) {
881                 // Free vrings, memEntries, etc.
882                 if (obj->chunks) {
883                     while ((elem = List_get(obj->chunks))) {
884                         Carveout_Elem * co_elem = (Carveout_Elem *)elem;
885                         munmap((Void *)co_elem->addr, co_elem->size);
886                         Memory_free(NULL, co_elem, sizeof(Carveout_Elem));
887                     }
888                     List_delete(&obj->chunks);
889                     obj->chunks = NULL;
890                 }
891                 if (obj->vrings)
892                     Memory_free(NULL, obj->vrings,
893                                 sizeof(*obj->vrings) * obj->numVrings);
894                 obj->vrings = NULL;
895                 obj->numMemEntries = 0;
897                 if (obj->rscTable)
898                     Memory_free(NULL, obj->rscTable, obj->rscTableLen);
899                 obj->rscTableDA = 0;
900                 Memory_free(NULL, obj, sizeof (RscTable_Object));
901                 *handle = NULL;
902                 RscTable_state.handles[i] = NULL;
903             }
904         }
905         else {
906             status = RSCTABLE_E_INVALIDARG;
907             GT_setFailureReason (curTrace,
908                                  GT_4CLASS,
909                                  "RscTable_free",
910                                  status,
911                                  "Invalid handle passed");
912         }
913     }
914     else {
915         status = RSCTABLE_E_INVALIDARG;
916         GT_setFailureReason (curTrace,
917                              GT_4CLASS,
918                              "RscTable_free",
919                              status,
920                              "Invalid handle passed");
921     }
923     return status;
926 Int RscTable_setStatus(UInt16 procId, UInt32 value)
928     Int i;
929     Int status = 0;
931     RscTable_Object * obj = (RscTable_Object *)RscTable_state.handles[procId];
932     RscTable_Header * table = (RscTable_Header *)obj->rscTable;
934     /* Look for the vdev entry and update the status */
935     for (i = 0; i < table->num; i++) {
936         RscTable_MemEntry * entry =
937                 (RscTable_MemEntry *)((UInt32)table + table->offset[i]);
938         if (entry->type == TYPE_VDEV) {
939             struct fw_rsc_vdev *vdev = (struct fw_rsc_vdev *)entry;
940             vdev->status = value;
941             break;
942         }
943     }
945     if (i == table->num) {
946         status = RSCTABLE_E_FAIL;
947     }
949     return status;
952 #if defined (__cplusplus)
954 #endif /* defined (__cplusplus) */