File: /usr/src/linux/arch/ia64/sn/fprom/fpmem.c
1 /*
2 *
3 * This file is subject to the terms and conditions of the GNU General Public
4 * License. See the file "COPYING" in the main directory of this archive
5 * for more details.
6 *
7 * Copyright (C) 2000 Silicon Graphics, Inc.
8 * Copyright (C) 2000 by Jack Steiner (steiner@sgi.com)
9 */
10
11
12 /*
13 * FPROM EFI memory descriptor build routines
14 *
15 * - Routines to build the EFI memory descriptor map
16 * - Should also be usable by the SGI SN1 prom to convert
17 * klconfig to efi_memmap
18 */
19
20 #include <asm/efi.h>
21 #include "fpmem.h"
22
23 /*
24 * args points to a layout in memory like this
25 *
26 * 32 bit 32 bit
27 *
28 * numnodes numcpus
29 *
30 * 16 bit 16 bit 32 bit
31 * nasid0 cpuconf membankdesc0
32 * nasid1 cpuconf membankdesc1
33 * .
34 * .
35 * .
36 * .
37 * .
38 */
39
40 sn_memmap_t *sn_memmap ;
41 sn_config_t *sn_config ;
42
43 /*
44 * There is a hole in the node 0 address space. Dont put it
45 * in the memory map
46 */
47 #define NODE0_HOLE_SIZE (20*MB)
48 #define NODE0_HOLE_END (4UL*GB)
49
50 #define MB (1024*1024)
51 #define GB (1024*MB)
52 #define KERNEL_SIZE (4*MB)
53 #define PROMRESERVED_SIZE (1*MB)
54 #define MD_BANK_SHFT 30
55
56 #define TO_NODE(_n, _x) (((long)_n<<33L) | (long)_x)
57
58 /*
59 * For SN, this may not take an arg and gets the numnodes from
60 * the prom variable or by traversing klcfg or promcfg
61 */
62 int
63 GetNumNodes(void)
64 {
65 return sn_config->nodes;
66 }
67
68 int
69 GetNumCpus(void)
70 {
71 return sn_config->cpus;
72 }
73
74 /* For SN1, get the index th nasid */
75
76 int
77 GetNasid(int index)
78 {
79 return sn_memmap[index].nasid ;
80 }
81
82 node_memmap_t
83 GetMemBankInfo(int index)
84 {
85 return sn_memmap[index].node_memmap ;
86 }
87
88 int
89 IsCpuPresent(int cnode, int cpu)
90 {
91 return sn_memmap[cnode].cpuconfig & (1<<cpu);
92 }
93
94
95 /*
96 * Made this into an explicit case statement so that
97 * we can assign specific properties to banks like bank0
98 * actually disabled etc.
99 */
100
101 int
102 IsBankPresent(int index, node_memmap_t nmemmap)
103 {
104 switch (index) {
105 case 0:return nmemmap.b0;
106 case 1:return nmemmap.b1;
107 case 2:return nmemmap.b2;
108 case 3:return nmemmap.b3;
109 case 4:return nmemmap.b4;
110 case 5:return nmemmap.b5;
111 case 6:return nmemmap.b6;
112 case 7:return nmemmap.b7;
113 default:return -1 ;
114 }
115 }
116
117 int
118 GetBankSize(int index, node_memmap_t nmemmap)
119 {
120 switch (index) {
121 case 0:
122 case 1:return nmemmap.b01size;
123 case 2:
124 case 3:return nmemmap.b23size;
125 case 4:
126 case 5:return nmemmap.b45size;
127 case 6:
128 case 7:return nmemmap.b67size;
129 default:return -1 ;
130 }
131 }
132
133 void
134 build_mem_desc(efi_memory_desc_t *md, int type, long paddr, long numbytes)
135 {
136 md->type = type;
137 md->phys_addr = paddr;
138 md->virt_addr = 0;
139 md->num_pages = numbytes >> 12;
140 md->attribute = EFI_MEMORY_WB;
141 }
142
143 int
144 build_efi_memmap(void *md, int mdsize)
145 {
146 int numnodes = GetNumNodes() ;
147 int cnode,bank ;
148 int nasid ;
149 node_memmap_t membank_info ;
150 int bsize;
151 int count = 0 ;
152 long paddr, hole, numbytes;
153
154
155 for (cnode=0;cnode<numnodes;cnode++) {
156 nasid = GetNasid(cnode) ;
157 membank_info = GetMemBankInfo(cnode) ;
158 for (bank=0;bank<SN1_MAX_BANK_PER_NODE;bank++) {
159 if (IsBankPresent(bank, membank_info)) {
160 bsize = GetBankSize(bank, membank_info) ;
161 paddr = TO_NODE(nasid, (long)bank<<MD_BANK_SHFT);
162 numbytes = BankSizeBytes(bsize);
163
164 /*
165 * Check for the node 0 hole. Since banks cant
166 * span the hole, we only need to check if the end of
167 * the range is the end of the hole.
168 */
169 if (paddr+numbytes == NODE0_HOLE_END)
170 numbytes -= NODE0_HOLE_SIZE;
171 /*
172 * UGLY hack - we must skip overr the kernel and
173 * PROM runtime services but we dont exactly where it is.
174 * So lets just reserve 0-12MB.
175 */
176 if (bank == 0) {
177 hole = (cnode == 0) ? KERNEL_SIZE : PROMRESERVED_SIZE;
178 numbytes -= hole;
179 build_mem_desc(md, EFI_RUNTIME_SERVICES_DATA, paddr, hole);
180 paddr += hole;
181 count++ ;
182 md += mdsize;
183 }
184 build_mem_desc(md, EFI_CONVENTIONAL_MEMORY, paddr, numbytes);
185
186 md += mdsize ;
187 count++ ;
188 }
189 }
190 }
191 return count ;
192 }
193
194 void
195 build_init(unsigned long args)
196 {
197 sn_config = (sn_config_t *) (args);
198 sn_memmap = (sn_memmap_t *)(args + 8) ; /* SN equiv for this is */
199 /* init to klconfig start */
200 }
201