QNX: IPC: Handle Internal Memory Loading outside of Resource Table
[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-2016, 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     Ipc_MemEntry           memEntries[IPC_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(IPC_BUILD_DEBUG)
164 static
165 #endif /* if !defined(IPC_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 == TRUE) {
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 == IPC_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_DEVMEM :
475             {
476                 // only care about mem in DDR for now
477                 struct fw_rsc_devmem * dmem = (struct fw_rsc_devmem *)entry;
478                 UInt32 pa = 0;
480                 if (dmem->pa >= DDR_MEM) {
481                     // HACK: treat vring mem specially, vring is always the
482                     //       first devmem entry, may change in future
483                     if (dmem_num++ == 0) {
484                         if (bootMode == ProcMgr_BootMode_NoBoot) {
485                             /*
486                              * Lookup physical address of vrings from page
487                              * table
488                              */
489                             if (Processor_translateFromPte(procHandle,
490                                 &pa, dmem->da) != ProcMgr_S_SUCCESS) {
491                                 status = RSCTABLE_E_FAIL;
492                                 GT_setFailureReason (curTrace,
493                                     GT_4CLASS,
494                                     "RscTable_process",
495                                     status,
496                                     "Failed to lookup address from page table");
497                                 ret = -1;
498                             }
499                             obj->vringPa = pa;
500                             obj->vringBufsPa = pa + vr_size;
501                         }
502                         else {
503                             // memory should already be reserved for vring
504                             if (obj->vringPa == 0) {
505                                 // vdev must have been defined first
506                                 GT_setFailureReason (curTrace,
507                                                  GT_4CLASS,
508                                                  "RscTable_process",
509                                                  status,
510                                                  "Vring Must be Defined First");
512                                 ret = -1;
513                             }
514                             else if (obj->vringPa != dmem->pa && (!tryAlloc)) {
515                                 // defined pa does not match allocated pa, and
516                                 // either the mmu is disabled or the platform has
517                                 // not given permission to allocate on our own
518                                 ret = -1;
519                                 GT_setFailureReason (curTrace,
520                                                  GT_4CLASS,
521                                                  "RscTable_process",
522                                                  status,
523                                                  "Vring PA Mis-match");
525                                 GT_2trace (curTrace, GT_4CLASS,
526                                        "vringPa is 0x%x, dmem->pa is 0x%x",
527                                        obj->vringPa, dmem->pa);
528                             }
529                         }
530                         if (ret == 0) {
531 #if !ZEROINIT_CHUNKS
532                             /* Map the phys mem to local */
533                             vringVA = (UInt32)mmap_device_io(vringSize,
534                                 obj->vringPa);
535                             if (vringVA != MAP_DEVICE_FAILED) {
536                                 /* Zero-init the vring */
537                                 Memory_set((Ptr)vringVA, 0, vringSize);
538                                 munmap_device_io(vringVA, vringSize);
539                             }
540                             else {
541                                 GT_0trace(curTrace, GT_4CLASS,
542                                     "RscTable_alloc: "
543                                     "Warning - Unable to zero-init vring mem");
544                             }
545 #endif
546                             /*
547                              * Override the vring 'da' field in resource table.
548                              * This allows the slave to look it up when creating
549                              * the VirtQueues
550                              */
551                             for (j = 0; j < vdev->num_of_vrings; j++) {
552                                 vring = (struct fw_rsc_vdev_vring *)
553                                     ((UInt32)vdev + sizeof(*vdev) +
554                                      (sizeof(*vring) * j));
555                                 vring->da = obj->vringPa + (j *
556                                     vr_size / vdev->num_of_vrings);
557                             }
559                             /*
560                              * Override the physical address provided by the
561                              * entry with the physical locations of the vrings
562                              * as allocated when we processed the vdev entry
563                              * (or as allocated by external loader for late
564                              * attach mode)
565                              */
566                             dmem->pa = obj->vringPa;
567                         }
568                     }
569                 }
570                 if (!ret) {
571                     if (obj->numMemEntries == IPC_MAX_MEMENTRIES) {
572                         ret = -1;
573                     }
574                     else {
575                         obj->memEntries[obj->numMemEntries].slaveVirtAddr =
576                                 dmem->da;
577                         obj->memEntries[obj->numMemEntries].masterPhysAddr =
578                                 dmem->pa;
579                         obj->memEntries[obj->numMemEntries].size = dmem->len;
580                         obj->memEntries[obj->numMemEntries].map = TRUE;
581                         obj->memEntries[obj->numMemEntries].mapMask =
582                             ProcMgr_SLAVEVIRT;
583                         obj->memEntries[obj->numMemEntries].isCached = FALSE;
584                         obj->memEntries[obj->numMemEntries].isValid = TRUE;
585                         obj->numMemEntries++;
586                     }
587                 }
589                 // TODO: need to make sure this mem exists/is set aside, or allocate it
590                 printf ("RscTable_process: devmem [%s] @ da [0x%08x] pa [0x%08x] len [0x%x]\n", dmem->name, dmem->da, dmem->pa, dmem->len);
591                 break;
592             }
593             case TYPE_TRACE :
594             {
595                 // TODO: save da for future use
596                 struct fw_rsc_trace * trace = (struct fw_rsc_trace *)entry;
597                 Memory_copy(&obj->trace, trace, sizeof(*trace));
598                 printf ("RscTable_process: trace [%s] @ da [0x%08x] len [0x%x]\n", trace->name, trace->da, trace->len);
599                 break;
600             }
601             case TYPE_VDEV :
602             {
603                 // TODO: save vring info for future use
604                 UInt32 vr_bufs_size = 0;
605                 UInt32 pa = 0;
607                 vdev = (struct fw_rsc_vdev *)entry;
608                 obj->numVrings = vdev->num_of_vrings;
609                 obj->vrings = Memory_alloc(NULL,
610                                            sizeof (*vring) * obj->numVrings, 0,
611                                            NULL);
612                 if (!obj->vrings)
613                     ret = -1;
614                 for (j = 0; j < vdev->num_of_vrings && !ret; j++) {
615                     vring = (struct fw_rsc_vdev_vring *)
616                                 ((UInt32)vdev + sizeof(*vdev) +
617                                  (sizeof(*vring) * j));
618                     /*
619                      * Making a copy of original vring, given obj->vrings[j].da
620                      * is used as slave virtual address in RscTable_getInfo(),
621                      * and that is what the original vring definition contains.
622                      */
623                     Memory_copy (&obj->vrings[j], vring, sizeof (*vring));
624                     printf ("RscTable_process: vring [%d] @ [0x%08x]\n",
625                             vring->num, vring->da);
626                     // Hack, we know this is the size alignment
627                     if (vring->num != MessageQCopy_NUMBUFS ||
628                         vring->align != MessageQCopy_VRINGALIGN) {
629                         printf ("RscTable_process: warning size mis-match!\n");
630                         ret = -1;
631                     }
632                     vr_size += ROUND_UP(MessageQCopy_RINGSIZE, 0x4000);
633                     vr_bufs_size += (vring->num) * RPMSG_BUF_SIZE;
634                 }
635                 if ((!ret) && (bootMode != ProcMgr_BootMode_NoBoot)) {
636                     // HACK: round up to multiple of 1MB, because we know this
637                     //       is the size of the remote entry
638                     ret = Chunk_allocate(obj,
639                         ROUND_UP(vr_size + vr_bufs_size, 0x100000),
640                         &pa);
641                 }
643                 if (!ret) {
644 #if !ZEROINIT_CHUNKS
645                     vringSize = vr_size + vr_bufs_size;
646 #endif
647                     if (bootMode != ProcMgr_BootMode_NoBoot) {
648                         obj->vringPa = pa;
649                         obj->vringBufsPa = pa + vr_size;
650                     }
651                 }
652                 else if (obj->vrings) {
653                     Memory_free (NULL, obj->vrings,
654                                  sizeof(*vring) * obj->numVrings);
655                     obj->vrings = NULL;
656                 }
658                 break;
659             }
660             default :
661                 break;
662         }
663     }
665     if (ret) {
666         status = RSCTABLE_E_FAIL;
667         GT_setFailureReason (curTrace,
668                              GT_4CLASS,
669                              "RscTable_process",
670                              status,
671                              "Failure happened in processing table");
672         if (obj->vrings)
673             Memory_free(NULL, obj->vrings,
674                         sizeof(*obj->vrings) * obj->numVrings);
675         obj->vrings = NULL;
676         obj->numMemEntries = 0;
677     }
678     *numBlocks = obj->numMemEntries;
680     return status;
683 Int
684 RscTable_getMemEntries (UInt16 procId, Ipc_MemEntry *memEntries,
685                         UInt32 * numMemEntries)
687     Int status = 0;
688     RscTable_Object *obj = NULL;
690     // Find the table for this procId, if not found, return an error
691     if (procId >= MultiProc_MAXPROCESSORS || !RscTable_state.handles[procId]) {
692         status = RSCTABLE_E_INVALIDARG;
693         GT_setFailureReason (curTrace,
694                              GT_4CLASS,
695                              "RscTable_getMemEntries",
696                              status,
697                              "Invalid ProcId specified");
698         return status;
699     }
701     obj = (RscTable_Object *)RscTable_state.handles[procId];
703     if (obj->memEntries && obj->numMemEntries &&
704         *numMemEntries >= obj->numMemEntries) {
705         *numMemEntries = obj->numMemEntries;
706         Memory_copy(memEntries, obj->memEntries,
707                     sizeof(*memEntries) * obj->numMemEntries);
708     }
709     else {
710         status = RSCTABLE_E_INVALIDARG;
711         GT_setFailureReason (curTrace,
712                              GT_4CLASS,
713                              "RscTable_getMemEntries",
714                              status,
715                              "Invalid num of memEntries or memEntries is NULL");
716     }
718     return status;
721 Int
722 RscTable_getInfo (UInt16 procId, UInt32 type, UInt32 extra, UInt32 * da,
723                   UInt32 *pa, UInt32 * len)
725     Int status = 0;
726     RscTable_Object *obj = NULL;
728     // Find the table for this procId, if not found, return an error
729     if (procId >= MultiProc_MAXPROCESSORS || !RscTable_state.handles[procId]) {
730         status = RSCTABLE_E_INVALIDARG;
731         GT_setFailureReason (curTrace,
732                              GT_4CLASS,
733                              "RscTable_getInfo",
734                              status,
735                              "Invalid procId specified");
736         return status;
737     }
739     obj = (RscTable_Object *)RscTable_state.handles[procId];
741     if (type == TYPE_TRACE) {
742         if (da && len) {
743             *da = obj->trace.da;
744             *len = obj->trace.len;
745         }
746         else {
747             status = RSCTABLE_E_INVALIDARG;
748             GT_setFailureReason (curTrace,
749                                  GT_4CLASS,
750                                  "RscTable_getInfo",
751                                  status,
752                                  "Invalid pointer passed");
753         }
754     }
755     else if (type == TYPE_VDEV) {
756         if (extra == 0 && len) {
757             *len = obj->numVrings;
758         }
759         else if (extra < obj->numVrings && da) {
760             *da = obj->vrings[extra-1].da;
761         }
762         else {
763             status = RSCTABLE_E_INVALIDARG;
764             GT_setFailureReason (curTrace,
765                                  GT_4CLASS,
766                                  "RscTable_getInfo",
767                                  status,
768                                  "Invalid pointer passed");
769         }
770     }
771     else {
772         // type not supported
773         status = -1;
774     }
776     return status;
777     // Retrieve the info for a certain resource type (ex. Vring info)
780 Int
781 RscTable_update (UInt16 procId, ProcMgr_Handle procHandle)
783     // Updates the table to physical memory so that phys addrs are available to
784     // the remote cores.  This should be called only after loading the remote
785     // cores.
786     Int status = 0;
787     RscTable_Object *obj = NULL;
788     UInt32 rscTableVA = 0, rscTablePA = 0;
790     // Find the table for this procId, if not found, return an error
791     if (procId >= MultiProc_MAXPROCESSORS || !RscTable_state.handles[procId]) {
792         status = RSCTABLE_E_INVALIDARG;
793         GT_setFailureReason (curTrace,
794                              GT_4CLASS,
795                              "RscTable_update",
796                              status,
797                              "Invalid ProcId specified");
798         return status;
799     }
801     obj = (RscTable_Object *)RscTable_state.handles[procId];
803     status = ProcMgr_translateAddr(procHandle, (Ptr *)&rscTablePA,
804                                    ProcMgr_AddrType_MasterPhys,
805                                    (Ptr)obj->rscTableDA,
806                                    ProcMgr_AddrType_SlaveVirt);
807     if (status < 0) {
808         status = RSCTABLE_E_FAIL;
809         GT_setFailureReason (curTrace,
810                              GT_4CLASS,
811                              "RscTable_update",
812                              status,
813                              "Unable to get the Master PA for RscTable");
814     }
815     else {
816         /* Map the phys mem to local */
817         rscTableVA = (UInt32)mmap_device_io(obj->rscTableLen, rscTablePA);
818         if (rscTableVA != MAP_DEVICE_FAILED) {
819             /* Copy the updated table to the memory */
820             Memory_copy((Ptr)rscTableVA, obj->rscTable, obj->rscTableLen);
821             munmap_device_io(rscTableVA, obj->rscTableLen);
822         }
823         else {
824             status = RSCTABLE_E_FAIL;
825             GT_setFailureReason (curTrace,
826                                  GT_4CLASS,
827                                  "RscTable_update",
828                                  status,
829                                  "Unable to map memory");
830         }
831     }
833     return status;
836 Int
837 RscTable_free (RscTable_Handle * handle)
839     Int status = 0;
840     RscTable_Object * obj = NULL;
841     Int i = 0;
842     List_Elem * elem;
844     // Remove resource table from coreId-Handle pair list
845     if (handle && *handle) {
846         // sanity check
847         for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
848             if (RscTable_state.handles[i] == *handle)
849                 break;
850         }
851         if (i < MultiProc_MAXPROCESSORS) {
852             obj = (RscTable_Object *)(*handle);
853             // Additional sanity check
854             if (obj->procId == i) {
855                 // Free vrings, memEntries, etc.
856                 if (obj->chunks) {
857                     while ((elem = List_get(obj->chunks))) {
858                         Carveout_Elem * co_elem = (Carveout_Elem *)elem;
859                         munmap((Void *)co_elem->addr, co_elem->size);
860                         Memory_free(NULL, co_elem, sizeof(Carveout_Elem));
861                     }
862                     List_delete(&obj->chunks);
863                     obj->chunks = NULL;
864                 }
865                 if (obj->vrings)
866                     Memory_free(NULL, obj->vrings,
867                                 sizeof(*obj->vrings) * obj->numVrings);
868                 obj->vrings = NULL;
869                 obj->numMemEntries = 0;
871                 if (obj->rscTable)
872                     Memory_free(NULL, obj->rscTable, obj->rscTableLen);
873                 obj->rscTableDA = 0;
874                 Memory_free(NULL, obj, sizeof (RscTable_Object));
875                 *handle = NULL;
876                 RscTable_state.handles[i] = NULL;
877             }
878         }
879         else {
880             status = RSCTABLE_E_INVALIDARG;
881             GT_setFailureReason (curTrace,
882                                  GT_4CLASS,
883                                  "RscTable_free",
884                                  status,
885                                  "Invalid handle passed");
886         }
887     }
888     else {
889         status = RSCTABLE_E_INVALIDARG;
890         GT_setFailureReason (curTrace,
891                              GT_4CLASS,
892                              "RscTable_free",
893                              status,
894                              "Invalid handle passed");
895     }
897     return status;
900 Int RscTable_setStatus(UInt16 procId, UInt32 value)
902     Int i;
903     Int status = 0;
905     RscTable_Object * obj = (RscTable_Object *)RscTable_state.handles[procId];
906     RscTable_Header * table = (RscTable_Header *)obj->rscTable;
908     /* Look for the vdev entry and update the status */
909     for (i = 0; i < table->num; i++) {
910         RscTable_MemEntry * entry =
911                 (RscTable_MemEntry *)((UInt32)table + table->offset[i]);
912         if (entry->type == TYPE_VDEV) {
913             struct fw_rsc_vdev *vdev = (struct fw_rsc_vdev *)entry;
914             vdev->status = value;
915             break;
916         }
917     }
919     if (i == table->num) {
920         status = RSCTABLE_E_FAIL;
921     }
923     return status;
926 #if defined (__cplusplus)
928 #endif /* defined (__cplusplus) */