EMILE/second/bank.c

362 lines
7.1 KiB
C
Raw Normal View History

/*
*
* (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
2005-11-08 02:06:40 +00:00
#include "macos/lowmem.h"
#include "macos/gestalt.h"
2005-05-10 21:49:28 +00:00
#include "misc.h"
2004-02-26 22:56:39 +00:00
#include "arch.h"
2005-05-10 21:49:28 +00:00
#ifdef ARCH_M68K
2004-03-04 22:47:09 +00:00
#include "MMU030.h"
#include "MMU040.h"
2005-05-10 21:49:28 +00:00
#endif
#include "bank.h"
#include "vga.h"
2004-02-26 22:56:39 +00:00
/* MacOS nanokernel data structures (nubus powerPC only)
* found in Boot/X, thank you Ben ;-)
*/
2005-05-10 21:49:28 +00:00
#ifdef ARCH_PPC
2004-02-26 22:56:39 +00:00
#define MACOS_MEMMAP_PTR_ADDR 0x5FFFEFF0
#define MACOS_MEMMAP_SIZE_ADDR 0x5FFFEFF6
#define MACOS_MEMMAP_BANK_0FFSET 48
2005-05-10 21:49:28 +00:00
#endif
2004-02-26 22:56:39 +00:00
memory_map_t memory_map;
2004-02-19 13:09:41 +00:00
static void bank_add_mem(unsigned long logiAddr,
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++)
{
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 13:09:41 +00:00
memory_map.bank[i].size += size;
/* can we merge 2 banks */
2004-02-19 13:09:41 +00:00
for (j = 0; j < memory_map.bank_number; j++)
{
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 13:09:41 +00:00
memory_map.bank[i].size += memory_map.bank[j].size;
/* 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;
return;
}
}
return;
}
else if ( (physAddr + size == memory_map.bank[i].physAddr) &&
(logiAddr + size == memory_map.bank[i].logiAddr) )
{
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;
return;
}
}
/* not found, create new bank */
2004-02-19 13:09:41 +00:00
if (memory_map.bank_number >= MAX_MEM_MAP_SIZE)
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++;
}
2005-05-10 21:49:28 +00:00
#ifdef ARCH_M68K
2004-02-26 22:56:39 +00:00
void m68k_init_memory_map()
{
2005-10-20 21:12:13 +00:00
#ifdef USE_MMU
unsigned long logical;
unsigned long physical;
2004-02-26 22:56:39 +00:00
int ps;
2005-10-20 21:12:13 +00:00
#endif
memory_map.bank_number = 0;
2004-02-26 22:56:39 +00:00
if (mmu_type == gestaltNoMMU)
{
if (cpu_type == gestalt68000)
{
unsigned long start = KERNEL_BASEADDR;
unsigned long end = ScrnBase - 0x8000;
bank_add_mem(start, start, end - start);
}
else
bank_add_mem(0, 0, MemTop);
}
2005-10-20 21:12:13 +00:00
#ifdef USE_MMU040
2004-03-04 22:47:09 +00:00
else if (mmu_type == gestalt68040MMU)
{
ps = MMU040_get_page_size();
logical = 0;
for (logical = 0; logical < MemTop ; logical += ps)
{
if (MMU040_logical2physical(logical, &physical) == 0)
{
bank_add_mem(logical, physical, ps);
}
}
}
2005-10-20 21:12:13 +00:00
#endif /* USE_MMU040 */
#ifdef USE_MMU030
2004-02-26 22:56:39 +00:00
else
{
2004-03-04 22:47:09 +00:00
ps = MMU030_get_page_size();
2004-02-26 22:56:39 +00:00
logical = 0;
for (logical = 0; logical < MemTop ; logical += ps)
{
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);
}
}
}
2005-10-20 21:12:13 +00:00
#endif /* USE_MMU030 */
}
2005-05-10 21:49:28 +00:00
#endif /* ARCH_M68K */
2004-02-19 13:09:41 +00:00
2005-05-10 21:49:28 +00:00
#ifdef ARCH_PPC
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;
if (len <= MACOS_MEMMAP_BANK_0FFSET)
return;
2005-05-09 23:37:28 +00:00
base = (unsigned long*)((char*)base + MACOS_MEMMAP_BANK_0FFSET);
2004-02-26 22:56:39 +00:00
len -= MACOS_MEMMAP_BANK_0FFSET;
2005-05-09 23:37:28 +00:00
memory_map.bank_number = 0;
2004-02-26 22:56:39 +00:00
while(len >= 8)
{
2005-05-09 23:37:28 +00:00
unsigned long addr = *(unsigned long*)base++;
unsigned long size = *(unsigned long*)base++;
2004-02-26 22:56:39 +00:00
if (size)
bank_add_mem(addr, addr, size);
len -= 8;
}
}
2005-05-10 21:49:28 +00:00
#endif /* ARCH_PPC */
2004-02-26 22:56:39 +00:00
void init_memory_map()
{
2005-05-10 21:49:28 +00:00
if (arch_type == gestaltPowerPC) {
#ifdef ARCH_PPC
2004-02-26 22:56:39 +00:00
ppc_init_memory_map();
2005-05-10 21:49:28 +00:00
#else
error("This version of EMILE doesn't support PowePC\n");
#endif
}
else {
#ifdef ARCH_M68K
2004-02-26 22:56:39 +00:00
m68k_init_memory_map();
2005-05-10 21:49:28 +00:00
#else
error("This version of EMILE doesn't support Motorola 680x0\n");
#endif
}
2004-02-26 22:56:39 +00:00
}
2005-10-20 21:12:13 +00:00
#ifdef USE_MMU
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;
}
2005-10-20 21:12:13 +00:00
#if defined(ARCH_M68K)
#ifdef USE_MMU040
2004-03-04 22:47:09 +00:00
else if (mmu_type == gestalt68040MMU)
{
return MMU040_logical2physical(logical, physical);
}
2005-10-20 21:12:13 +00:00
#endif
#ifdef USE_MMU030
2004-03-04 22:47:09 +00:00
return MMU030_logical2physical(logical, physical);
2005-10-20 21:12:13 +00:00
#endif
2005-05-10 22:05:06 +00:00
#else
return 0;
2005-05-10 21:49:28 +00:00
#endif
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;
}
2005-10-20 21:12:13 +00:00
int check_full_in_bank(unsigned long start, unsigned long size)
{
int bank0;
int bank1;
bank0 = bank_find_by_logical(start);
bank1 = bank_find_by_logical(start + size);
return (bank0 == bank1);
}
#endif /* USE_MMU */
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;
}
2005-10-20 21:12:13 +00:00
#ifdef USE_MMU
2004-07-12 21:32:44 +00:00
void *malloc_contiguous(size_t size)
{
void* tmp;
void* contiguous;
int bank;
size_t part_size;
tmp = malloc(size);
if (tmp == NULL)
return NULL;
2004-07-12 21:32:44 +00:00
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_contiguous(size);
2004-07-12 21:32:44 +00:00
free(tmp);
return contiguous;
2004-06-16 17:23:12 +00:00
}
2005-10-20 21:12:13 +00:00
#endif
2004-06-16 17:23:12 +00:00
void *malloc_top(size_t size)
{
void *top;
void* tmp;
long bubble;
bubble = bank_mem_avail() - size;
do {
tmp = malloc_contiguous(bubble);
if (tmp)
{
top = malloc(size);
free(tmp);
if (top)
return top;
}
bubble -= 1024 * 1024; /* decrease of 1 MB */
} while (bubble > 0);
return NULL;
}
#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++)
{
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,
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;
}
}
#endif