2004-02-19 11:34:18 +00:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* (c) 2004 Laurent Vivier <LaurentVivier@wanadoo.fr>
|
|
|
|
*
|
|
|
|
* portion from penguin booter
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2004-02-19 13:09:41 +00:00
|
|
|
#include <stdio.h>
|
2004-07-12 21:32:44 +00:00
|
|
|
#include <malloc.h>
|
2004-02-19 13:09:41 +00:00
|
|
|
|
2004-02-26 22:56:39 +00:00
|
|
|
#include "arch.h"
|
2004-02-19 11:34:18 +00:00
|
|
|
#include "lowmem.h"
|
2004-03-04 22:47:09 +00:00
|
|
|
#include "MMU030.h"
|
|
|
|
#include "MMU040.h"
|
2004-02-19 11:34:18 +00:00
|
|
|
#include "bank.h"
|
|
|
|
|
2004-02-26 22:56:39 +00:00
|
|
|
/* MacOS nanokernel data structures (nubus powerPC only)
|
|
|
|
* found in Boot/X, thank you Ben ;-)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define MACOS_MEMMAP_PTR_ADDR 0x5FFFEFF0
|
|
|
|
#define MACOS_MEMMAP_SIZE_ADDR 0x5FFFEFF6
|
|
|
|
#define MACOS_MEMMAP_BANK_0FFSET 48
|
|
|
|
|
2004-05-25 23:30:31 +00:00
|
|
|
memory_map_t memory_map;
|
2004-02-19 13:09:41 +00:00
|
|
|
|
|
|
|
static void bank_add_mem(unsigned long logiAddr,
|
2004-02-19 11:34:18 +00:00
|
|
|
unsigned long physAddr, unsigned long size)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int j;
|
|
|
|
|
2004-02-19 13:09:41 +00:00
|
|
|
for (i = 0; i < memory_map.bank_number; i++)
|
2004-02-19 11:34:18 +00:00
|
|
|
{
|
2004-02-21 01:48:52 +00:00
|
|
|
if ( (memory_map.bank[i].physAddr +
|
|
|
|
memory_map.bank[i].size == physAddr) &&
|
|
|
|
(memory_map.bank[i].logiAddr +
|
|
|
|
memory_map.bank[i].size == logiAddr) )
|
2004-02-19 11:34:18 +00:00
|
|
|
{
|
2004-02-19 13:09:41 +00:00
|
|
|
memory_map.bank[i].size += size;
|
2004-02-19 11:34:18 +00:00
|
|
|
|
|
|
|
/* can we merge 2 banks */
|
|
|
|
|
2004-02-19 13:09:41 +00:00
|
|
|
for (j = 0; j < memory_map.bank_number; j++)
|
2004-02-19 11:34:18 +00:00
|
|
|
{
|
2004-02-21 01:48:52 +00:00
|
|
|
if ( (memory_map.bank[i].physAddr +
|
|
|
|
memory_map.bank[i].size ==
|
|
|
|
memory_map.bank[j].physAddr) &&
|
|
|
|
(memory_map.bank[i].logiAddr +
|
|
|
|
memory_map.bank[i].size ==
|
|
|
|
memory_map.bank[j].logiAddr) )
|
2004-02-19 11:34:18 +00:00
|
|
|
{
|
2004-02-19 13:09:41 +00:00
|
|
|
memory_map.bank[i].size += memory_map.bank[j].size;
|
2004-02-19 11:34:18 +00:00
|
|
|
|
|
|
|
/* remove bank */
|
|
|
|
|
2004-02-19 13:09:41 +00:00
|
|
|
memory_map.bank_number--;
|
|
|
|
memory_map.bank[j].physAddr = memory_map.bank[memory_map.bank_number].physAddr;
|
|
|
|
memory_map.bank[j].logiAddr = memory_map.bank[memory_map.bank_number].logiAddr;
|
|
|
|
memory_map.bank[j].size = memory_map.bank[memory_map.bank_number].size;
|
2004-02-19 11:34:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2004-02-21 01:48:52 +00:00
|
|
|
else if ( (physAddr + size == memory_map.bank[i].physAddr) &&
|
|
|
|
(logiAddr + size == memory_map.bank[i].logiAddr) )
|
2004-02-19 11:34:18 +00:00
|
|
|
{
|
2004-02-19 13:09:41 +00:00
|
|
|
memory_map.bank[i].physAddr = physAddr;
|
|
|
|
memory_map.bank[i].logiAddr = logiAddr;
|
|
|
|
memory_map.bank[i].size += size;
|
2004-02-19 11:34:18 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* not found, create new bank */
|
|
|
|
|
2004-02-19 13:09:41 +00:00
|
|
|
if (memory_map.bank_number >= MAX_MEM_MAP_SIZE)
|
2004-02-19 11:34:18 +00:00
|
|
|
return;
|
|
|
|
|
2004-02-19 13:09:41 +00:00
|
|
|
memory_map.bank[memory_map.bank_number].physAddr = physAddr;
|
|
|
|
memory_map.bank[memory_map.bank_number].logiAddr = logiAddr;
|
|
|
|
memory_map.bank[memory_map.bank_number].size = size;
|
|
|
|
memory_map.bank_number++;
|
2004-02-19 11:34:18 +00:00
|
|
|
}
|
|
|
|
|
2004-02-26 22:56:39 +00:00
|
|
|
void m68k_init_memory_map()
|
2004-02-19 11:34:18 +00:00
|
|
|
{
|
|
|
|
unsigned long logical;
|
|
|
|
unsigned long physical;
|
2004-02-26 22:56:39 +00:00
|
|
|
int ps;
|
2004-02-19 11:34:18 +00:00
|
|
|
|
2004-02-26 22:56:39 +00:00
|
|
|
if (mmu_type == gestaltNoMMU)
|
2004-02-19 11:34:18 +00:00
|
|
|
{
|
2004-02-26 22:56:39 +00:00
|
|
|
bank_add_mem(0, 0, MemTop);
|
2004-02-19 11:34:18 +00:00
|
|
|
}
|
2004-03-04 22:47:09 +00:00
|
|
|
else if (mmu_type == gestalt68040MMU)
|
|
|
|
{
|
|
|
|
ps = MMU040_get_page_size();
|
|
|
|
memory_map.bank_number = 0;
|
|
|
|
logical = 0;
|
|
|
|
for (logical = 0; logical < MemTop ; logical += ps)
|
|
|
|
{
|
|
|
|
if (MMU040_logical2physical(logical, &physical) == 0)
|
|
|
|
{
|
|
|
|
bank_add_mem(logical, physical, ps);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-02-26 22:56:39 +00:00
|
|
|
else
|
2004-02-19 11:34:18 +00:00
|
|
|
{
|
2004-03-04 22:47:09 +00:00
|
|
|
ps = MMU030_get_page_size();
|
2004-02-26 22:56:39 +00:00
|
|
|
memory_map.bank_number = 0;
|
|
|
|
logical = 0;
|
|
|
|
for (logical = 0; logical < MemTop ; logical += ps)
|
2004-02-19 11:34:18 +00:00
|
|
|
{
|
2004-03-04 22:47:09 +00:00
|
|
|
if (MMU030_logical2physical(logical, &physical) == 0)
|
2004-02-26 22:56:39 +00:00
|
|
|
{
|
|
|
|
bank_add_mem(logical, physical, ps);
|
|
|
|
}
|
2004-02-19 11:34:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-02-19 13:09:41 +00:00
|
|
|
|
2004-02-26 22:56:39 +00:00
|
|
|
void ppc_init_memory_map()
|
|
|
|
{
|
|
|
|
/* Nubus powerPC */
|
|
|
|
|
|
|
|
unsigned long *base = *(unsigned long**)MACOS_MEMMAP_PTR_ADDR;
|
|
|
|
unsigned long len = *(unsigned short*)MACOS_MEMMAP_SIZE_ADDR;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (len <= MACOS_MEMMAP_BANK_0FFSET)
|
|
|
|
return;
|
|
|
|
|
|
|
|
base += MACOS_MEMMAP_BANK_0FFSET;
|
|
|
|
len -= MACOS_MEMMAP_BANK_0FFSET;
|
|
|
|
i = 0;
|
|
|
|
|
|
|
|
while(len >= 8)
|
|
|
|
{
|
|
|
|
unsigned long addr = *(unsigned long*)base;
|
|
|
|
unsigned long size = *(unsigned long*)(base+4);
|
|
|
|
|
|
|
|
if (size)
|
|
|
|
bank_add_mem(addr, addr, size);
|
|
|
|
|
|
|
|
base += 8;
|
|
|
|
len -= 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void init_memory_map()
|
|
|
|
{
|
|
|
|
if (arch_type == gestaltPowerPC)
|
|
|
|
ppc_init_memory_map();
|
|
|
|
else
|
|
|
|
m68k_init_memory_map();
|
|
|
|
}
|
|
|
|
|
2004-02-19 13:09:41 +00:00
|
|
|
static int bank_find_by_physical(unsigned long physical)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < memory_map.bank_number; i++)
|
|
|
|
{
|
|
|
|
if ( (memory_map.bank[i].physAddr <= physical) &&
|
|
|
|
( physical < memory_map.bank[i].physAddr + memory_map.bank[i].size) )
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2004-07-12 21:32:44 +00:00
|
|
|
static int bank_find_by_logical(unsigned long logical)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < memory_map.bank_number; i++)
|
|
|
|
{
|
|
|
|
if ( (memory_map.bank[i].logiAddr <= logical) &&
|
|
|
|
( logical < memory_map.bank[i].logiAddr + memory_map.bank[i].size) )
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2004-02-26 22:56:39 +00:00
|
|
|
int logical2physical(unsigned long logical, unsigned long *physical)
|
|
|
|
{
|
|
|
|
if ( (mmu_type == gestaltNoMMU) || (mmu_type == gestaltEMMU1) )
|
|
|
|
{
|
|
|
|
*physical = logical;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2004-03-04 22:47:09 +00:00
|
|
|
else if (mmu_type == gestalt68040MMU)
|
|
|
|
{
|
|
|
|
return MMU040_logical2physical(logical, physical);
|
|
|
|
}
|
2004-02-26 22:56:39 +00:00
|
|
|
|
2004-03-04 22:47:09 +00:00
|
|
|
return MMU030_logical2physical(logical, physical);
|
2004-02-26 22:56:39 +00:00
|
|
|
}
|
|
|
|
|
2004-02-19 13:09:41 +00:00
|
|
|
int physical2logical(unsigned long physical, unsigned long *logical)
|
|
|
|
{
|
|
|
|
int bank;
|
|
|
|
|
|
|
|
bank = bank_find_by_physical(physical);
|
|
|
|
|
|
|
|
if (bank == -1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (memory_map.bank[bank].physAddr > memory_map.bank[bank].logiAddr)
|
|
|
|
*logical = physical - (memory_map.bank[bank].physAddr -
|
|
|
|
memory_map.bank[bank].logiAddr);
|
|
|
|
else
|
|
|
|
*logical = physical + (memory_map.bank[bank].logiAddr -
|
|
|
|
memory_map.bank[bank].physAddr);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-02-23 00:24:05 +00:00
|
|
|
unsigned long bank_mem_avail()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
unsigned long size = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < memory_map.bank_number; i++)
|
|
|
|
{
|
|
|
|
size += memory_map.bank[i].size;
|
|
|
|
}
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2004-06-16 17:23:12 +00:00
|
|
|
int check_full_in_bank(unsigned long start, unsigned long size)
|
|
|
|
{
|
2004-07-12 21:32:44 +00:00
|
|
|
int bank0;
|
|
|
|
int bank1;
|
2004-06-16 17:23:12 +00:00
|
|
|
|
2004-07-12 21:32:44 +00:00
|
|
|
bank0 = bank_find_by_logical(start);
|
|
|
|
bank1 = bank_find_by_logical(start + size);
|
|
|
|
|
|
|
|
return (bank0 == bank1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *malloc_contiguous(size_t size)
|
|
|
|
{
|
|
|
|
void* tmp;
|
|
|
|
void* contiguous;
|
|
|
|
int bank;
|
|
|
|
size_t part_size;
|
|
|
|
|
|
|
|
tmp = malloc(size);
|
|
|
|
|
|
|
|
if (check_full_in_bank((unsigned long)tmp, size))
|
|
|
|
return tmp;
|
|
|
|
|
|
|
|
/* not in one contiguous block */
|
|
|
|
|
|
|
|
bank = bank_find_by_logical((unsigned long)tmp);
|
|
|
|
|
|
|
|
part_size = memory_map.bank[bank].size -
|
|
|
|
((unsigned long)tmp - memory_map.bank[bank].logiAddr);
|
|
|
|
free(tmp);
|
|
|
|
|
|
|
|
tmp = malloc(part_size);
|
|
|
|
contiguous = malloc(size);
|
|
|
|
free(tmp);
|
|
|
|
|
|
|
|
if (!check_full_in_bank((unsigned long)contiguous, size))
|
2004-06-16 17:23:12 +00:00
|
|
|
{
|
2004-07-12 21:32:44 +00:00
|
|
|
free(contiguous);
|
|
|
|
return NULL;
|
2004-06-16 17:23:12 +00:00
|
|
|
}
|
2004-07-12 21:32:44 +00:00
|
|
|
|
|
|
|
return contiguous;
|
2004-06-16 17:23:12 +00:00
|
|
|
}
|
|
|
|
|
2004-02-23 23:29:59 +00:00
|
|
|
#ifdef BANK_DUMP
|
2004-02-19 13:09:41 +00:00
|
|
|
void bank_dump()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
unsigned long size = 0;
|
|
|
|
|
|
|
|
printf("Physical memory map:\n");
|
|
|
|
for (i = 0; i < memory_map.bank_number; i++)
|
|
|
|
{
|
2004-02-21 01:48:52 +00:00
|
|
|
printf("%d: 0x%08lx -> 0x%08lx mapped at 0x%08lx -> 0x%08lx\n",
|
|
|
|
i,
|
2004-02-19 13:09:41 +00:00
|
|
|
memory_map.bank[i].physAddr,
|
|
|
|
memory_map.bank[i].physAddr + memory_map.bank[i].size,
|
2004-02-21 01:48:52 +00:00
|
|
|
memory_map.bank[i].logiAddr,
|
|
|
|
memory_map.bank[i].logiAddr + memory_map.bank[i].size);
|
2004-02-19 13:09:41 +00:00
|
|
|
size += memory_map.bank[i].size;
|
|
|
|
}
|
|
|
|
}
|
2004-02-23 23:29:59 +00:00
|
|
|
#endif
|