diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2009-05-06 20:08:01 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2009-05-06 20:08:01 +0000 |
commit | c52e153b4f274e8abfebe4cd275cacce3aee3f2f (patch) | |
tree | 04a957c802b85f7cea9293e1f3e5cd00f3681e97 /sys/arch | |
parent | f43a8dafabdc74e1ac673eb9227e4276e1b60357 (diff) |
IP27 and IP35 do not layout physical memory the same way, IP35 is much
simpler; use two different routines to register memory depending on the
system type.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/sgi/sgi/sginode.c | 122 |
1 files changed, 111 insertions, 11 deletions
diff --git a/sys/arch/sgi/sgi/sginode.c b/sys/arch/sgi/sgi/sginode.c index a7f5e1423a2..c2be0b76f91 100644 --- a/sys/arch/sgi/sgi/sginode.c +++ b/sys/arch/sgi/sgi/sginode.c @@ -1,4 +1,5 @@ -/* $OpenBSD: sginode.c,v 1.3 2009/05/02 21:26:05 miod Exp $ */ +#define DEBUG +/* $OpenBSD: sginode.c,v 1.4 2009/05/06 20:08:00 miod Exp $ */ /* * Copyright (c) 2008, 2009 Miodrag Vallat. * @@ -56,7 +57,8 @@ int nextcpu = 0; void kl_do_boardinfo(lboard_t *); -void kl_add_memory(int16_t *, unsigned int); +void kl_add_memory_ip27(int16_t *, unsigned int); +void kl_add_memory_ip35(int16_t *, unsigned int); #ifdef DEBUG #define DB_PRF(x) bios_printf x @@ -156,9 +158,11 @@ kl_do_boardinfo(lboard_t *boardinfo) case KLSTRUCT_MEMBNK: memcomp_m = (klmembnk_m_t *)comp; memcomp_n = (klmembnk_n_t *)comp; - DB_PRF(("\tmemory %dMB, select %x\n", + DB_PRF(("\tmemory %dMB, select %x flags %x\n", memcomp_m->membnk_memsz, - memcomp_m->membnk_dimm_select)); + memcomp_m->membnk_dimm_select, + kl_n_mode ? + memcomp_n->membnk_attr : memcomp_m->membnk_attr)); if (kl_n_mode) { for (j = 0; j < MD_MEM_BANKS_N; j++) { @@ -178,8 +182,14 @@ kl_do_boardinfo(lboard_t *boardinfo) } } - kl_add_memory(memcomp_m->membnk_bnksz, - kl_n_mode ? MD_MEM_BANKS_N : MD_MEM_BANKS_M); + if (sys_config.system_type == SGI_O200) + kl_add_memory_ip27(memcomp_m->membnk_bnksz, + kl_n_mode ? + MD_MEM_BANKS_N : MD_MEM_BANKS_M); + else + kl_add_memory_ip35(memcomp_m->membnk_bnksz, + kl_n_mode ? + MD_MEM_BANKS_N : MD_MEM_BANKS_M); break; @@ -218,9 +228,12 @@ kl_get_console_base() /* * Process memory bank information. + * There are two different routines, because IP27 and IP35 do not + * layout memory the same way. */ + void -kl_add_memory(int16_t *sizes, unsigned int cnt) +kl_add_memory_ip27(int16_t *sizes, unsigned int cnt) { int16_t nasid = 0; /* XXX */ paddr_t basepa; @@ -229,8 +242,8 @@ kl_add_memory(int16_t *sizes, unsigned int cnt) struct phys_mem_desc *md; /* - * Access to each DIMM is interleaved, which cause it to map - * to four banks on 128MB boundaries. + * On IP27, access to each DIMM is interleaved, which cause it to + * map to four banks on 128MB boundaries. * DIMMs of 128MB or smaller map everything in the first bank, * though. */ @@ -253,8 +266,8 @@ kl_add_memory(int16_t *sizes, unsigned int cnt) lp = fp + np; /* - * ARCBios provided us with information on the - * first 32MB, so skip them here if necessary. + * We do not manage the first 32MB, so skip them here + * if necessary. */ if (fp < atop(32 << 20)) { fp = atop(32 << 20); @@ -312,3 +325,90 @@ kl_add_memory(int16_t *sizes, unsigned int cnt) } } } + +void +kl_add_memory_ip35(int16_t *sizes, unsigned int cnt) +{ + int16_t nasid = 0; /* XXX */ + paddr_t basepa; + uint32_t fp, lp, np; + unsigned int descno; + struct phys_mem_desc *md; + + /* + * On IP35, the smallest memory DIMMs are 256MB, and the + * largest is 1GB. Memory is reported at 1GB intervals. + */ + + basepa = nasid << (32 - kl_n_mode); + while (cnt-- != 0) { + np = *sizes++; + if (np != 0) { + DB_PRF(("memory from %p to %p (%u MB)\n", + basepa, basepa + (np << 20), np)); + + fp = atop(basepa); + np = atop(np << 20); /* MB to pages */ + lp = fp + np; + + /* + * We do not manage the first 64MB, so skip them here + * if necessary. + */ + if (fp < atop(64 << 20)) { + fp = atop(64 << 20); + if (fp >= lp) + continue; + np = lp - fp; + physmem += atop(64 << 20); + } + + /* + * Walk the existing segment list to find if we + * are adjacent to an existing segment, or the + * next free segment to use if not. + * + * Note that since we do not know in which order + * we'll find our nodes, we have to check for + * both boundaries, despite adding a given node's + * memory in increasing pa order. + */ + for (descno = 0, md = mem_layout; descno < MAXMEMSEGS; + descno++, md++) { + if (md->mem_first_page == 0) + break; + + if (md->mem_first_page == lp) { + md->mem_first_page = fp; + physmem += np; + md = NULL; + break; + } + + if (md->mem_last_page == fp) { + md->mem_last_page = lp; + physmem += np; + md = NULL; + break; + } + } + if (descno != MAXMEMSEGS && md != NULL) { + md->mem_first_page = fp; + md->mem_last_page = lp; + physmem += np; + md = NULL; + } + + if (md != NULL) { + /* + * We could hijack the smallest segment here. + * But is it really worth doing? + */ + bios_printf("%u MB of memory could not be " + "managed, increase MAXMEMSEGS\n", + atop(np) >> 20); + } + } + basepa += 1 << 30; /* 1 GB */ + } +} |