Bool Mem32DevIns(CMemRange *tmpmr) { CMemRange *tmpmr1 = dev.mem32_head.next, *tmpmr2; while (tmpmr1 != &dev.mem32_head) { if (!tmpmr1->type && tmpmr->base >= tmpmr1->base && tmpmr->base + tmpmr->size <= tmpmr1->base + tmpmr1->size) { if (tmpmr->base > tmpmr1->base) { tmpmr2 = SysMAlloc(sizeof(CMemRange)); tmpmr2->type = MRT_UNUSED; tmpmr2->flags = 0; tmpmr2->base = tmpmr1->base; tmpmr2->size = tmpmr->base - tmpmr1->base; QueueInsertRev(tmpmr2, tmpmr1); } QueueInsertRev(tmpmr, tmpmr1); tmpmr1->size = tmpmr1->base + tmpmr1->size - (tmpmr->base + tmpmr->size); tmpmr1->base = tmpmr->base + tmpmr->size; if (!tmpmr1->size) { QueueRemove(tmpmr1); Free(tmpmr1); } return TRUE; } tmpmr1 = tmpmr1->next; } return FALSE; } U0 Mem32DevInit() { CMemRange *tmpmr; CMemE820 *m20 = MEM_E820; QueueInit(&dev.mem32_head); tmpmr = SysMAlloc(sizeof(CMemRange)); tmpmr->type = MRT_UNUSED; tmpmr->flags = 0; //Maybe !!! Change this to 0xF0000000 !!! tmpmr->base = 0xE0000000; tmpmr->size = 0x10000000; QueueInsert(tmpmr, dev.mem32_head.last); if (m20->type) { while (m20->type) { tmpmr = SysMAlloc(sizeof(CMemRange)); tmpmr->type = m20->type; tmpmr->flags = 0; tmpmr->base = m20->base; tmpmr->size = m20->len; if (!Mem32DevIns(tmpmr)) Free(tmpmr); m20++; } } } U8 *Mem32DevAlloc(I64 size, I64 alignment) {//Alloc 32-bit address space for device. (Doesn't work.) Not used. //For this to work the BIOS E820 map must be searched for gaps in //the 32-bit range and the pool initialized to the gaps. U8 *base, *limit; CMemRange *tmpmr, *tmpmr1; while (LBts(&sys_semas[SEMA_DEV_MEM], 0)) Yield; tmpmr1 = dev.mem32_head.next; while (tmpmr1 != &dev.mem32_head) { base = (tmpmr1->base + alignment - 1) & ~(alignment - 1); limit = base + size - 1; if (!tmpmr1->type && limit < tmpmr1->base + tmpmr1->size) { tmpmr = SysMAlloc(sizeof(CMemRange)); tmpmr->type = MRT_DEV; tmpmr->flags = 0; tmpmr->base = base; tmpmr->size = size; if (!Mem32DevIns(tmpmr)) { Free(tmpmr); LBtr(&sys_semas[SEMA_DEV_MEM], 0); return NULL; } LBtr(&sys_semas[SEMA_DEV_MEM], 0); return tmpmr->base; } tmpmr1 = tmpmr1->next; } LBtr(&sys_semas[SEMA_DEV_MEM], 0); return NULL; } U0 Mem32DevFree(U8 *base) {//Free 32-bit device address space. CMemRange *tmpmr; if (!base) return; while (LBts(&sys_semas[SEMA_DEV_MEM], 0)) Yield; tmpmr = dev.mem32_head.next; while (tmpmr != &dev.mem32_head) { if (tmpmr->base == base) { tmpmr->type = MRT_UNUSED; break; } tmpmr = tmpmr->next; } LBtr(&sys_semas[SEMA_DEV_MEM], 0); } U8 *Mem64DevAlloc(I64 *_pages1Gig) {//Alloc 64-bit address space for device. U8 *a; I64 i = *_pages1Gig, *pte; while (LBts(&sys_semas[SEMA_DEV_MEM], 0)) Yield; while (i--) { a = dev.mem64_ptr -= 1 << 30; do { pte = MemPageTable(a); *pte = *pte & ~0x18 | 0x11; //Uncached and present InvalidatePage(dev.mem64_ptr); a += mem_page_size; } while (a - dev.mem64_ptr < 1 << 30); } LBtr(&sys_semas[SEMA_DEV_MEM], 0); return dev.mem64_ptr; } U0 Mem64DevFree(U8 *base, I64 pages1Gig) {//Free 64-bit device address space. if (!base) return; while (LBts(&sys_semas[SEMA_DEV_MEM], 0)) Yield; if (base == dev.mem64_ptr) dev.mem64_ptr += pages1Gig * 1 << 30; //else not freed LBtr(&sys_semas[SEMA_DEV_MEM], 0); } U0 UncachedAliasAlloc() //Make uncached alias for 4 lowest Gig. { I64 i = 4, *pte; U8 *a; a = dev.uncached_alias = Mem64DevAlloc(&i); do { pte = MemPageTable(a); *pte = 0x197 + a - dev.uncached_alias; InvalidatePage(a); a += mem_page_size; } while (a - dev.uncached_alias < 1 << 32); } I64 MemBIOSTotal() {//Returns max of either E801 or E820 mem map. I64 total01 = 0x100000, total20 = 0; U16 *mem01 = MEM_E801; CMemE820 *mem20 = MEM_E820; total01 += mem01[0] * 1024; //First U16 is mem between 1MiB and 16 MiB in KiB. total01 += mem01[1] * 64 * 1024;//Second U16 is mem above 16MiB (until it encounters a hole) in 64KiB blocks. if (mem20->type) { while (mem20->type) { if (mem20->type == MEM_E820t_USABLE) total20 += mem20->len; mem20++; } } return MaxI64(total01, total20); } I64 Scale2Mem(I64 min, I64 max, I64 limit=2*1024*1024*1024) {//Helps pick DiskCache and RAMDisk sizes. //Can be used in BootHDIns() config scripts. I64 i; if (sys_data_bp) i = sys_data_bp->alloced_u8s; else i = sys_code_bp->alloced_u8s; if (i >= limit) return max; else return min + (max - min) * i / limit; } I64 Seg2Linear(U32 *ptr) {//Convert 32-bit segmented far pointer to linear address. Modify in place. *ptr = *ptr >> 16 << 4 + *ptr & 0xFFFF; return *ptr; }