static inline void _select_largest_contiguous(void){ int i; int contig_start, this_start; seL4_Word contig_size, this_size; int contig_end; assert(_ut.count); contig_start = 0; contig_size = 0; contig_end = 0; this_start = 0; this_size = 0; for(i = 0; i < _ut.count; i++){ this_size += 1 << UT_SIZEBITS(i); if(i + 1 >= _ut.count || UT_PEND(i) != UT_PSTART(i + 1)){ if(contig_size < this_size){ contig_size = this_size; contig_start = this_start; contig_end = i + 1; } this_start = i + 1; this_size = 0; } } i = 0; while(contig_start < contig_end){ _ut.map[i++] = _ut.map[contig_start++]; } _ut.count = i; }
static inline void _print_table(void){ int i; dprintf(0, "\n" "+-----------------------------------------------+\n" "| Untyped Table |\n" "|-----------------------------------------------|\n" "| ut(bi) | start -> end | size bits |\n" "|-----------------------------------------------|\n"); for(i = 0; i < _ut.count; i++){ dprintf(0, "| %2d(%2d) | 0x%08x -> 0x%08x | %9d |\n", i, _ut.map[i], UT_PSTART(i), UT_PEND(i), UT_SIZEBITS(i)); if(i != _ut.count - 1 && UT_PEND(i) != UT_PSTART(i + 1)){ dprintf(0, "|-----------------------------------------------|\n"); } } dprintf(0, "+-----------------------------------------------+\n"); }
int ut_translate(seL4_Word addr, seL4_Untyped* ret_cptr, seL4_Word* ret_offset){ int start, end; start = 0; end = _ut.count; while(start < end){ int index; index = (start + end) >> 1; if(addr < UT_PSTART(index)){ end = index; }else if(UT_PEND(index) <= addr){ start = index + 1; }else{ *ret_cptr = UT_CAP(index); *ret_offset = addr - UT_PSTART(index); return 0; } } /* Check if the address matches a device */ return ut_translate_device(addr, ret_cptr, ret_offset); }
int ut_table_init(const seL4_BootInfo *bi){ if(!bi){ return !0; } _fill_table(bi); _reduce_table(MIN_UT_SIZE_BITS, 0); _sort_table(); _select_largest_contiguous(); _low = UT_PSTART(0); _high = UT_PEND(_ut.count - 1); _print_table(); return 0; }