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