22a9835c35
Just about every architecture defines some macros to do operations on pfns. They're all virtually identical. This patch consolidates all of them. One minor glitch is that at least i386 uses them in a very skeletal header file. To keep away from #include dependency hell, I stuck the new definitions in a new, isolated header. Of all of the implementations, sh64 is the only one that varied by a bit. It used some masks to ensure that any sign-extension got ripped away before the arithmetic is done. This has been posted to that sh64 maintainers and the development list. Compiles on x86, x86_64, ia64 and ppc64. Signed-off-by: Dave Hansen <haveblue@us.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
184 lines
4.3 KiB
C
184 lines
4.3 KiB
C
/*
|
|
* Carsten Langgaard, carstenl@mips.com
|
|
* Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
|
|
*
|
|
* This program is free software; you can distribute it and/or modify it
|
|
* under the terms of the GNU General Public License (Version 2) as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
|
*
|
|
* PROM library functions for acquiring/using memory descriptors given to
|
|
* us from the YAMON.
|
|
*/
|
|
#include <linux/config.h>
|
|
#include <linux/init.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/bootmem.h>
|
|
#include <linux/string.h>
|
|
|
|
#include <asm/bootinfo.h>
|
|
#include <asm/page.h>
|
|
|
|
#include <asm/mips-boards/prom.h>
|
|
|
|
/*#define DEBUG*/
|
|
|
|
enum yamon_memtypes {
|
|
yamon_dontuse,
|
|
yamon_prom,
|
|
yamon_free,
|
|
};
|
|
struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
|
|
|
|
#ifdef DEBUG
|
|
static char *mtypes[3] = {
|
|
"Dont use memory",
|
|
"YAMON PROM memory",
|
|
"Free memmory",
|
|
};
|
|
#endif
|
|
|
|
/* References to section boundaries */
|
|
extern char _end;
|
|
|
|
struct prom_pmemblock * __init prom_getmdesc(void)
|
|
{
|
|
char *memsize_str;
|
|
unsigned int memsize;
|
|
char cmdline[CL_SIZE], *ptr;
|
|
|
|
/* Check the command line first for a memsize directive */
|
|
strcpy(cmdline, arcs_cmdline);
|
|
ptr = strstr(cmdline, "memsize=");
|
|
if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
|
|
ptr = strstr(ptr, " memsize=");
|
|
|
|
if (ptr) {
|
|
memsize = memparse(ptr + 8, &ptr);
|
|
}
|
|
else {
|
|
/* otherwise look in the environment */
|
|
memsize_str = prom_getenv("memsize");
|
|
if (!memsize_str) {
|
|
prom_printf("memsize not set in boot prom, set to default (32Mb)\n");
|
|
memsize = 0x02000000;
|
|
} else {
|
|
#ifdef DEBUG
|
|
prom_printf("prom_memsize = %s\n", memsize_str);
|
|
#endif
|
|
memsize = simple_strtol(memsize_str, NULL, 0);
|
|
}
|
|
}
|
|
memset(mdesc, 0, sizeof(mdesc));
|
|
|
|
mdesc[0].type = yamon_dontuse;
|
|
mdesc[0].base = 0x00000000;
|
|
mdesc[0].size = 0x00001000;
|
|
|
|
mdesc[1].type = yamon_prom;
|
|
mdesc[1].base = 0x00001000;
|
|
mdesc[1].size = 0x000ef000;
|
|
|
|
#ifdef CONFIG_MIPS_MALTA
|
|
/*
|
|
* The area 0x000f0000-0x000fffff is allocated for BIOS memory by the
|
|
* south bridge and PCI access always forwarded to the ISA Bus and
|
|
* BIOSCS# is always generated.
|
|
* This mean that this area can't be used as DMA memory for PCI
|
|
* devices.
|
|
*/
|
|
mdesc[2].type = yamon_dontuse;
|
|
mdesc[2].base = 0x000f0000;
|
|
mdesc[2].size = 0x00010000;
|
|
#else
|
|
mdesc[2].type = yamon_prom;
|
|
mdesc[2].base = 0x000f0000;
|
|
mdesc[2].size = 0x00010000;
|
|
#endif
|
|
|
|
mdesc[3].type = yamon_dontuse;
|
|
mdesc[3].base = 0x00100000;
|
|
mdesc[3].size = CPHYSADDR(PAGE_ALIGN(&_end)) - mdesc[3].base;
|
|
|
|
mdesc[4].type = yamon_free;
|
|
mdesc[4].base = CPHYSADDR(PAGE_ALIGN(&_end));
|
|
mdesc[4].size = memsize - mdesc[4].base;
|
|
|
|
return &mdesc[0];
|
|
}
|
|
|
|
static int __init prom_memtype_classify (unsigned int type)
|
|
{
|
|
switch (type) {
|
|
case yamon_free:
|
|
return BOOT_MEM_RAM;
|
|
case yamon_prom:
|
|
return BOOT_MEM_ROM_DATA;
|
|
default:
|
|
return BOOT_MEM_RESERVED;
|
|
}
|
|
}
|
|
|
|
void __init prom_meminit(void)
|
|
{
|
|
struct prom_pmemblock *p;
|
|
|
|
#ifdef DEBUG
|
|
prom_printf("YAMON MEMORY DESCRIPTOR dump:\n");
|
|
p = prom_getmdesc();
|
|
while (p->size) {
|
|
int i = 0;
|
|
prom_printf("[%d,%p]: base<%08lx> size<%08lx> type<%s>\n",
|
|
i, p, p->base, p->size, mtypes[p->type]);
|
|
p++;
|
|
i++;
|
|
}
|
|
#endif
|
|
p = prom_getmdesc();
|
|
|
|
while (p->size) {
|
|
long type;
|
|
unsigned long base, size;
|
|
|
|
type = prom_memtype_classify (p->type);
|
|
base = p->base;
|
|
size = p->size;
|
|
|
|
add_memory_region(base, size, type);
|
|
p++;
|
|
}
|
|
}
|
|
|
|
unsigned long __init prom_free_prom_memory(void)
|
|
{
|
|
unsigned long freed = 0;
|
|
unsigned long addr;
|
|
int i;
|
|
|
|
for (i = 0; i < boot_mem_map.nr_map; i++) {
|
|
if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
|
|
continue;
|
|
|
|
addr = boot_mem_map.map[i].addr;
|
|
while (addr < boot_mem_map.map[i].addr
|
|
+ boot_mem_map.map[i].size) {
|
|
ClearPageReserved(virt_to_page(__va(addr)));
|
|
init_page_count(virt_to_page(__va(addr)));
|
|
free_page((unsigned long)__va(addr));
|
|
addr += PAGE_SIZE;
|
|
freed += PAGE_SIZE;
|
|
}
|
|
}
|
|
printk("Freeing prom memory: %ldkb freed\n", freed >> 10);
|
|
|
|
return freed;
|
|
}
|