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