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 <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)
176 {
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(¶ms);
260 obj->chunks = List_create(¶ms);
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;
305 }
307 // allocate any addr
308 Int Chunk_allocate (RscTable_Object *obj, UInt32 size, UInt32 * pa)
309 {
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;
379 }
381 Int
382 RscTable_process (UInt16 procId, Bool tryAlloc, UInt32 * numBlocks,
383 Processor_Handle procHandle, ProcMgr_BootMode bootMode)
384 {
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, pa);
560 if (vringVA != MAP_DEVICE_FAILED) {
561 /* Zero-init the vring */
562 Memory_set((Ptr)vringVA, 0, vringSize);
563 munmap_device_io(vringVA, vringSize);
564 }
565 else {
566 GT_0trace(curTrace, GT_4CLASS,
567 "RscTable_alloc: "
568 "Warning - Unable to zero-init vring mem");
569 }
570 #endif
571 /*
572 * Override the vring 'da' field in resource table.
573 * This allows the slave to look it up when creating
574 * the VirtQueues
575 */
576 for (j = 0; j < vdev->num_of_vrings; j++) {
577 vring = (struct fw_rsc_vdev_vring *)
578 ((UInt32)vdev + sizeof(*vdev) +
579 (sizeof(*vring) * j));
580 vring->da = obj->vringPa + (j *
581 vr_size / vdev->num_of_vrings);
582 }
584 /*
585 * Override the physical address provided by the
586 * entry with the physical locations of the vrings
587 * as allocated when we processed the vdev entry
588 * (or as allocated by external loader for late
589 * attach mode)
590 */
591 dmem->pa = obj->vringPa;
592 }
593 }
594 }
595 if (!ret) {
596 if (obj->numMemEntries == SYSLINK_MAX_MEMENTRIES) {
597 ret = -1;
598 }
599 else {
600 obj->memEntries[obj->numMemEntries].slaveVirtAddr =
601 dmem->da;
602 obj->memEntries[obj->numMemEntries].masterPhysAddr =
603 dmem->pa;
604 obj->memEntries[obj->numMemEntries].size = dmem->len;
605 obj->memEntries[obj->numMemEntries].map = TRUE;
606 obj->memEntries[obj->numMemEntries].mapMask =
607 ProcMgr_SLAVEVIRT;
608 obj->memEntries[obj->numMemEntries].isCached = FALSE;
609 obj->memEntries[obj->numMemEntries].isValid = TRUE;
610 obj->numMemEntries++;
611 }
612 }
614 // TODO: need to make sure this mem exists/is set aside, or allocate it
615 printf ("RscTable_process: devmem [%s] @ da [0x%08x] pa [0x%08x] len [0x%x]\n", dmem->name, dmem->da, dmem->pa, dmem->len);
616 break;
617 }
618 case TYPE_TRACE :
619 {
620 // TODO: save da for future use
621 struct fw_rsc_trace * trace = (struct fw_rsc_trace *)entry;
622 Memory_copy(&obj->trace, trace, sizeof(*trace));
623 printf ("RscTable_process: trace [%s] @ da [0x%08x] len [0x%x]\n", trace->name, trace->da, trace->len);
624 break;
625 }
626 case TYPE_VDEV :
627 {
628 // TODO: save vring info for future use
629 UInt32 vr_bufs_size = 0;
630 UInt32 pa = 0;
632 vdev = (struct fw_rsc_vdev *)entry;
633 obj->numVrings = vdev->num_of_vrings;
634 obj->vrings = Memory_alloc(NULL,
635 sizeof (*vring) * obj->numVrings, 0,
636 NULL);
637 if (!obj->vrings)
638 ret = -1;
639 for (j = 0; j < vdev->num_of_vrings && !ret; j++) {
640 vring = (struct fw_rsc_vdev_vring *)
641 ((UInt32)vdev + sizeof(*vdev) +
642 (sizeof(*vring) * j));
643 /*
644 * Making a copy of original vring, given obj->vrings[j].da
645 * is used as slave virtual address in RscTable_getInfo(),
646 * and that is what the original vring definition contains.
647 */
648 Memory_copy (&obj->vrings[j], vring, sizeof (*vring));
649 printf ("RscTable_process: vring [%d] @ [0x%08x]\n",
650 vring->num, vring->da);
651 // Hack, we know this is the size alignment
652 if (vring->num != MessageQCopy_NUMBUFS ||
653 vring->align != MessageQCopy_VRINGALIGN) {
654 printf ("RscTable_process: warning size mis-match!\n");
655 ret = -1;
656 }
657 vr_size += ROUND_UP(MessageQCopy_RINGSIZE, 0x4000);
658 vr_bufs_size += (vring->num) * RPMSG_BUF_SIZE;
659 }
660 if ((!ret) && (bootMode != ProcMgr_BootMode_NoBoot)) {
661 // HACK: round up to multiple of 1MB, because we know this
662 // is the size of the remote entry
663 ret = Chunk_allocate(obj,
664 ROUND_UP(vr_size + vr_bufs_size, 0x100000),
665 &pa);
666 }
668 if (!ret) {
669 #if !ZEROINIT_CHUNKS
670 vringSize = vr_size + vr_bufs_size;
671 #endif
672 if (bootMode != ProcMgr_BootMode_NoBoot) {
673 obj->vringPa = pa;
674 obj->vringBufsPa = pa + vr_size;
675 }
676 }
677 else if (obj->vrings) {
678 Memory_free (NULL, obj->vrings,
679 sizeof(*vring) * obj->numVrings);
680 obj->vrings = NULL;
681 }
683 break;
684 }
685 default :
686 break;
687 }
688 }
690 if (ret) {
691 status = RSCTABLE_E_FAIL;
692 GT_setFailureReason (curTrace,
693 GT_4CLASS,
694 "RscTable_process",
695 status,
696 "Failure happened in processing table");
697 if (obj->vrings)
698 Memory_free(NULL, obj->vrings,
699 sizeof(*obj->vrings) * obj->numVrings);
700 obj->vrings = NULL;
701 obj->numMemEntries = 0;
702 }
703 *numBlocks = obj->numMemEntries;
705 return status;
706 }
708 Int
709 RscTable_getMemEntries (UInt16 procId, SysLink_MemEntry *memEntries,
710 UInt32 * numMemEntries)
711 {
712 Int status = 0;
713 RscTable_Object *obj = NULL;
715 // Find the table for this procId, if not found, return an error
716 if (procId >= MultiProc_MAXPROCESSORS || !RscTable_state.handles[procId]) {
717 status = RSCTABLE_E_INVALIDARG;
718 GT_setFailureReason (curTrace,
719 GT_4CLASS,
720 "RscTable_getMemEntries",
721 status,
722 "Invalid ProcId specified");
723 return status;
724 }
726 obj = (RscTable_Object *)RscTable_state.handles[procId];
728 if (obj->memEntries && obj->numMemEntries &&
729 *numMemEntries >= obj->numMemEntries) {
730 *numMemEntries = obj->numMemEntries;
731 Memory_copy(memEntries, obj->memEntries,
732 sizeof(*memEntries) * obj->numMemEntries);
733 }
734 else {
735 status = RSCTABLE_E_INVALIDARG;
736 GT_setFailureReason (curTrace,
737 GT_4CLASS,
738 "RscTable_getMemEntries",
739 status,
740 "Invalid num of memEntries or memEntries is NULL");
741 }
743 return status;
744 }
746 Int
747 RscTable_getInfo (UInt16 procId, UInt32 type, UInt32 extra, UInt32 * da,
748 UInt32 *pa, UInt32 * len)
749 {
750 Int status = 0;
751 RscTable_Object *obj = NULL;
753 // Find the table for this procId, if not found, return an error
754 if (procId >= MultiProc_MAXPROCESSORS || !RscTable_state.handles[procId]) {
755 status = RSCTABLE_E_INVALIDARG;
756 GT_setFailureReason (curTrace,
757 GT_4CLASS,
758 "RscTable_getInfo",
759 status,
760 "Invalid procId specified");
761 return status;
762 }
764 obj = (RscTable_Object *)RscTable_state.handles[procId];
766 if (type == TYPE_TRACE) {
767 if (da && len) {
768 *da = obj->trace.da;
769 *len = obj->trace.len;
770 }
771 else {
772 status = RSCTABLE_E_INVALIDARG;
773 GT_setFailureReason (curTrace,
774 GT_4CLASS,
775 "RscTable_getInfo",
776 status,
777 "Invalid pointer passed");
778 }
779 }
780 else if (type == TYPE_VDEV) {
781 if (extra == 0 && len) {
782 *len = obj->numVrings;
783 }
784 else if (extra < obj->numVrings && da) {
785 *da = obj->vrings[extra-1].da;
786 }
787 else {
788 status = RSCTABLE_E_INVALIDARG;
789 GT_setFailureReason (curTrace,
790 GT_4CLASS,
791 "RscTable_getInfo",
792 status,
793 "Invalid pointer passed");
794 }
795 }
796 else {
797 // type not supported
798 status = -1;
799 }
801 return status;
802 // Retrieve the info for a certain resource type (ex. Vring info)
803 }
805 Int
806 RscTable_update (UInt16 procId, ProcMgr_Handle procHandle)
807 {
808 // Updates the table to physical memory so that phys addrs are available to
809 // the remote cores. This should be called only after loading the remote
810 // cores.
811 Int status = 0;
812 RscTable_Object *obj = NULL;
813 UInt32 rscTableVA = 0, rscTablePA = 0;
815 // Find the table for this procId, if not found, return an error
816 if (procId >= MultiProc_MAXPROCESSORS || !RscTable_state.handles[procId]) {
817 status = RSCTABLE_E_INVALIDARG;
818 GT_setFailureReason (curTrace,
819 GT_4CLASS,
820 "RscTable_update",
821 status,
822 "Invalid ProcId specified");
823 return status;
824 }
826 obj = (RscTable_Object *)RscTable_state.handles[procId];
828 status = ProcMgr_translateAddr(procHandle, (Ptr *)&rscTablePA,
829 ProcMgr_AddrType_MasterPhys,
830 (Ptr)obj->rscTableDA,
831 ProcMgr_AddrType_SlaveVirt);
832 if (status < 0) {
833 status = RSCTABLE_E_FAIL;
834 GT_setFailureReason (curTrace,
835 GT_4CLASS,
836 "RscTable_update",
837 status,
838 "Unable to get the Master PA for RscTable");
839 }
840 else {
841 /* Map the phys mem to local */
842 rscTableVA = (UInt32)mmap_device_io(obj->rscTableLen, rscTablePA);
843 if (rscTableVA != MAP_DEVICE_FAILED) {
844 /* Copy the updated table to the memory */
845 Memory_copy((Ptr)rscTableVA, obj->rscTable, obj->rscTableLen);
846 munmap_device_io(rscTableVA, obj->rscTableLen);
847 }
848 else {
849 status = RSCTABLE_E_FAIL;
850 GT_setFailureReason (curTrace,
851 GT_4CLASS,
852 "RscTable_update",
853 status,
854 "Unable to map memory");
855 }
856 }
858 return status;
859 }
861 Int
862 RscTable_free (RscTable_Handle * handle)
863 {
864 Int status = 0;
865 RscTable_Object * obj = NULL;
866 Int i = 0;
867 List_Elem * elem;
869 // Remove resource table from coreId-Handle pair list
870 if (handle && *handle) {
871 // sanity check
872 for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
873 if (RscTable_state.handles[i] == *handle)
874 break;
875 }
876 if (i < MultiProc_MAXPROCESSORS) {
877 obj = (RscTable_Object *)(*handle);
878 // Additional sanity check
879 if (obj->procId == i) {
880 // Free vrings, memEntries, etc.
881 if (obj->chunks) {
882 while ((elem = List_get(obj->chunks))) {
883 Carveout_Elem * co_elem = (Carveout_Elem *)elem;
884 munmap((Void *)co_elem->addr, co_elem->size);
885 Memory_free(NULL, co_elem, sizeof(Carveout_Elem));
886 }
887 List_delete(&obj->chunks);
888 obj->chunks = NULL;
889 }
890 if (obj->vrings)
891 Memory_free(NULL, obj->vrings,
892 sizeof(*obj->vrings) * obj->numVrings);
893 obj->vrings = NULL;
894 obj->numMemEntries = 0;
896 if (obj->rscTable)
897 Memory_free(NULL, obj->rscTable, obj->rscTableLen);
898 obj->rscTableDA = 0;
899 Memory_free(NULL, obj, sizeof (RscTable_Object));
900 *handle = NULL;
901 RscTable_state.handles[i] = NULL;
902 }
903 }
904 else {
905 status = RSCTABLE_E_INVALIDARG;
906 GT_setFailureReason (curTrace,
907 GT_4CLASS,
908 "RscTable_free",
909 status,
910 "Invalid handle passed");
911 }
912 }
913 else {
914 status = RSCTABLE_E_INVALIDARG;
915 GT_setFailureReason (curTrace,
916 GT_4CLASS,
917 "RscTable_free",
918 status,
919 "Invalid handle passed");
920 }
922 return status;
923 }
925 Int RscTable_setStatus(UInt16 procId, UInt32 value)
926 {
927 Int i;
928 Int status = 0;
930 RscTable_Object * obj = (RscTable_Object *)RscTable_state.handles[procId];
931 RscTable_Header * table = (RscTable_Header *)obj->rscTable;
933 /* Look for the vdev entry and update the status */
934 for (i = 0; i < table->num; i++) {
935 RscTable_MemEntry * entry =
936 (RscTable_MemEntry *)((UInt32)table + table->offset[i]);
937 if (entry->type == TYPE_VDEV) {
938 struct fw_rsc_vdev *vdev = (struct fw_rsc_vdev *)entry;
939 vdev->status = value;
940 break;
941 }
942 }
944 if (i == table->num) {
945 status = RSCTABLE_E_FAIL;
946 }
948 return status;
949 }
951 #if defined (__cplusplus)
952 }
953 #endif /* defined (__cplusplus) */