Import 2.3.49pre2
[davej-history.git] / arch / mips64 / arc / memory.c
blob58d4835eaafd5c9fe84d4ed05bdd9847b65f4576
1 /* $Id: memory.c,v 1.5 2000/01/27 23:21:57 ralf Exp $
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.
7 * Copyright (C) 1996 by David S. Miller
8 * Copyright (C) 1999, 2000 by Ralf Baechle
9 * Copyright (C) 1999, 2000 by Silicon Graphics, Inc.
11 * PROM library functions for acquiring/using memory descriptors given to us
12 * from the ARCS firmware. This is only used when CONFIG_ARC_MEMORY is set
13 * because on some machines like SGI IP27 the ARC memory configuration data
14 * completly bogus and alternate easier to use mechanisms are available.
16 #include <linux/init.h>
17 #include <linux/kernel.h>
18 #include <linux/types.h>
19 #include <linux/sched.h>
20 #include <linux/mm.h>
21 #include <linux/bootmem.h>
22 #include <linux/swap.h>
24 #include <asm/sgialib.h>
25 #include <asm/page.h>
26 #include <asm/pgtable.h>
27 #include <asm/bootinfo.h>
29 #undef DEBUG
31 extern char _end;
33 struct linux_mdesc * __init
34 ArcGetMemoryDescriptor(struct linux_mdesc *Current)
36 return (struct linux_mdesc *) ARC_CALL1(get_mdesc, Current);
39 #ifdef DEBUG /* convenient for debugging */
40 static char *arcs_mtypes[8] = {
41 "Exception Block",
42 "ARCS Romvec Page",
43 "Free/Contig RAM",
44 "Generic Free RAM",
45 "Bad Memory",
46 "Standlong Program Pages",
47 "ARCS Temp Storage Area",
48 "ARCS Permanent Storage Area"
51 static char *arc_mtypes[8] = {
52 "Exception Block",
53 "SystemParameterBlock",
54 "FreeMemory",
55 "Bad Memory",
56 "LoadedProgram",
57 "FirmwareTemporary",
58 "FirmwarePermanent",
59 "FreeContigiuous"
61 #define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] : arc_mtypes[a.arc]
62 #endif
64 static struct prom_pmemblock pblocks[PROM_MAX_PMEMBLOCKS];
66 #define MEMTYPE_DONTUSE 0
67 #define MEMTYPE_PROM 1
68 #define MEMTYPE_FREE 2
70 static inline int memtype_classify_arcs (union linux_memtypes type)
72 switch (type.arcs) {
73 case arcs_fcontig:
74 case arcs_free:
75 return MEMTYPE_FREE;
76 case arcs_atmp:
77 return MEMTYPE_PROM;
78 case arcs_eblock:
79 case arcs_rvpage:
80 case arcs_bmem:
81 case arcs_prog:
82 case arcs_aperm:
83 return MEMTYPE_DONTUSE;
84 default:
85 BUG();
87 while(1); /* Nuke warning. */
90 static inline int memtype_classify_arc (union linux_memtypes type)
92 switch (type.arc) {
93 case arc_free:
94 case arc_fcontig:
95 return MEMTYPE_FREE;
96 case arc_atmp:
97 return MEMTYPE_PROM;
98 case arc_eblock:
99 case arc_rvpage:
100 case arc_bmem:
101 case arc_prog:
102 case arc_aperm:
103 return MEMTYPE_DONTUSE;
104 default:
105 BUG();
107 while(1); /* Nuke warning. */
110 static int __init prom_memtype_classify (union linux_memtypes type)
112 if (prom_flags & PROM_FLAG_ARCS) /* SGI is ``different'' ... */
113 return memtype_classify_arcs(type);
115 return memtype_classify_arc(type);
118 static inline unsigned long find_max_low_pfn(void)
120 struct prom_pmemblock *p, *highest;
121 unsigned long pfn;
123 p = pblocks;
124 highest = 0;
125 while (p->size != 0) {
126 if (!highest || p->base > highest->base)
127 highest = p;
128 p++;
131 pfn = (highest->base + highest->size) >> PAGE_SHIFT;
132 #ifdef DEBUG
133 prom_printf("find_max_low_pfn: 0x%lx pfns.\n", pfn);
134 #endif
135 return pfn;
138 static inline struct prom_pmemblock *find_largest_memblock(void)
140 struct prom_pmemblock *p, *largest;
142 p = pblocks;
143 largest = 0;
144 while (p->size != 0) {
145 if (!largest || p->size > largest->size)
146 largest = p;
147 p++;
150 return largest;
153 void __init prom_meminit(void)
155 struct prom_pmemblock *largest;
156 unsigned long bootmap_size;
157 struct linux_mdesc *p;
158 int totram;
159 int i = 0;
161 #ifdef DEBUG
162 prom_printf("ARCS MEMORY DESCRIPTOR dump:\n");
163 p = ArcGetMemoryDescriptor(PROM_NULL_MDESC);
164 while(p) {
165 prom_printf("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n",
166 i, p, p->base, p->pages, mtypes(p->type));
167 p = ArcGetMemoryDescriptor(p);
168 i++;
170 #endif
172 totram = 0;
173 i = 0;
174 p = PROM_NULL_MDESC;
175 while ((p = ArcGetMemoryDescriptor(p))) {
176 pblocks[i].type = prom_memtype_classify(p->type);
177 pblocks[i].base = p->base << PAGE_SHIFT;
178 pblocks[i].size = p->pages << PAGE_SHIFT;
180 switch (pblocks[i].type) {
181 case MEMTYPE_FREE:
182 totram += pblocks[i].size;
183 #ifdef DEBUG
184 prom_printf("free_chunk[%d]: base=%08lx size=%x\n",
185 i, pblocks[i].base,
186 pblocks[i].size);
187 #endif
188 i++;
189 break;
190 case MEMTYPE_PROM:
191 #ifdef DEBUG
192 prom_printf("prom_chunk[%d]: base=%08lx size=%x\n",
193 i, pblocks[i].base,
194 pblocks[i].size);
195 #endif
196 i++;
197 break;
198 default:
199 break;
202 pblocks[i].size = 0;
204 max_low_pfn = find_max_low_pfn();
205 largest = find_largest_memblock();
206 bootmap_size = init_bootmem(largest->base >> PAGE_SHIFT, max_low_pfn);
208 for (i = 0; pblocks[i].size; i++)
209 if (pblocks[i].type == MEMTYPE_FREE)
210 free_bootmem(pblocks[i].base, pblocks[i].size);
212 /* This test is simpleminded. It will fail if the bootmem bitmap
213 falls into multiple adjacent ARC memory areas. */
214 if (bootmap_size > largest->size) {
215 prom_printf("CRITIAL: overwriting PROM data.\n");
216 BUG();
218 reserve_bootmem(largest->base, bootmap_size);
220 printk("PROMLIB: Total free ram %dK / %dMB.\n",
221 totram >> 10, totram >> 20);
224 void __init
225 prom_free_prom_memory (void)
227 struct prom_pmemblock *p;
228 unsigned long freed = 0;
229 unsigned long addr, end;
231 for (p = pblocks; p->size != 0; p++) {
232 if (p->type != MEMTYPE_PROM)
233 continue;
235 addr = PAGE_OFFSET + (unsigned long) (long) p->base;
236 end = addr + (unsigned long) (long) p->size;
237 while (addr < end) {
238 ClearPageReserved(mem_map + MAP_NR(addr));
239 set_page_count(mem_map + MAP_NR(addr), 1);
240 free_page(addr);
241 addr += PAGE_SIZE;
242 freed += PAGE_SIZE;
245 printk("Freeing prom memory: %ldkb freed\n", freed >> 10);