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