diff options
Diffstat (limited to 'arch/ia64/sn/fprom/fpmem.c')
-rw-r--r-- | arch/ia64/sn/fprom/fpmem.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/arch/ia64/sn/fprom/fpmem.c b/arch/ia64/sn/fprom/fpmem.c new file mode 100644 index 000000000..14f62bfc3 --- /dev/null +++ b/arch/ia64/sn/fprom/fpmem.c @@ -0,0 +1,200 @@ +/* + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 by Jack Steiner (steiner@sgi.com) + */ + + +/* + * FPROM EFI memory descriptor build routines + * + * - Routines to build the EFI memory descriptor map + * - Should also be usable by the SGI SN1 prom to convert + * klconfig to efi_memmap + */ + +#include <asm/efi.h> +#include "fpmem.h" + +/* + * args points to a layout in memory like this + * + * 32 bit 32 bit + * + * numnodes numcpus + * + * 16 bit 16 bit 32 bit + * nasid0 cpuconf membankdesc0 + * nasid1 cpuconf membankdesc1 + * . + * . + * . + * . + * . + */ + +sn_memmap_t *sn_memmap ; +sn_config_t *sn_config ; + +/* + * There is a hole in the node 0 address space. Dont put it + * in the memory map + */ +#define NODE0_HOLE_SIZE (20*MB) +#define NODE0_HOLE_END (4UL*GB) + +#define MB (1024*1024) +#define GB (1024*MB) +#define KERNEL_SIZE (4*MB) +#define PROMRESERVED_SIZE (1*MB) +#define MD_BANK_SHFT 30 + +#define TO_NODE(_n, _x) (((long)_n<<33L) | (long)_x) + +/* + * For SN, this may not take an arg and gets the numnodes from + * the prom variable or by traversing klcfg or promcfg + */ +int +GetNumNodes(void) +{ + return sn_config->nodes; +} + +int +GetNumCpus(void) +{ + return sn_config->cpus; +} + +/* For SN1, get the index th nasid */ + +int +GetNasid(int index) +{ + return sn_memmap[index].nasid ; +} + +node_memmap_t +GetMemBankInfo(int index) +{ + return sn_memmap[index].node_memmap ; +} + +int +IsCpuPresent(int cnode, int cpu) +{ + return sn_memmap[cnode].cpuconfig & (1<<cpu); +} + + +/* + * Made this into an explicit case statement so that + * we can assign specific properties to banks like bank0 + * actually disabled etc. + */ + +int +IsBankPresent(int index, node_memmap_t nmemmap) +{ + switch (index) { + case 0:return nmemmap.b0; + case 1:return nmemmap.b1; + case 2:return nmemmap.b2; + case 3:return nmemmap.b3; + case 4:return nmemmap.b4; + case 5:return nmemmap.b5; + case 6:return nmemmap.b6; + case 7:return nmemmap.b7; + default:return -1 ; + } +} + +int +GetBankSize(int index, node_memmap_t nmemmap) +{ + switch (index) { + case 0: + case 1:return nmemmap.b01size; + case 2: + case 3:return nmemmap.b23size; + case 4: + case 5:return nmemmap.b45size; + case 6: + case 7:return nmemmap.b67size; + default:return -1 ; + } +} + +void +build_mem_desc(efi_memory_desc_t *md, int type, long paddr, long numbytes) +{ + md->type = type; + md->phys_addr = paddr; + md->virt_addr = 0; + md->num_pages = numbytes >> 12; + md->attribute = EFI_MEMORY_WB; +} + +int +build_efi_memmap(void *md, int mdsize) +{ + int numnodes = GetNumNodes() ; + int cnode,bank ; + int nasid ; + node_memmap_t membank_info ; + int bsize; + int count = 0 ; + long paddr, hole, numbytes; + + + for (cnode=0;cnode<numnodes;cnode++) { + nasid = GetNasid(cnode) ; + membank_info = GetMemBankInfo(cnode) ; + for (bank=0;bank<SN1_MAX_BANK_PER_NODE;bank++) { + if (IsBankPresent(bank, membank_info)) { + bsize = GetBankSize(bank, membank_info) ; + paddr = TO_NODE(nasid, (long)bank<<MD_BANK_SHFT); + numbytes = BankSizeBytes(bsize); + + /* + * Check for the node 0 hole. Since banks cant + * span the hole, we only need to check if the end of + * the range is the end of the hole. + */ + if (paddr+numbytes == NODE0_HOLE_END) + numbytes -= NODE0_HOLE_SIZE; + /* + * UGLY hack - we must skip overr the kernel and + * PROM runtime services but we dont exactly where it is. + * So lets just reserve 0-12MB. + */ + if (bank == 0) { + hole = (cnode == 0) ? KERNEL_SIZE : PROMRESERVED_SIZE; + numbytes -= hole; + build_mem_desc(md, EFI_RUNTIME_SERVICES_DATA, paddr, hole); + paddr += hole; + count++ ; + md += mdsize; + } + build_mem_desc(md, EFI_CONVENTIONAL_MEMORY, paddr, numbytes); + + md += mdsize ; + count++ ; + } + } + } + return count ; +} + +void +build_init(unsigned long args) +{ + sn_config = (sn_config_t *) (args); + sn_memmap = (sn_memmap_t *)(args + 8) ; /* SN equiv for this is */ + /* init to klconfig start */ +} |