Import 2.3.49pre2
[davej-history.git] / arch / mips / arc / memory.c
blobd1c530fda4bf24a21809b61b871e7e01fae41c7d
1 /*
2 * memory.c: PROM library functions for acquiring/using memory descriptors
3 * given to us from the ARCS firmware.
5 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
7 * $Id: memory.c,v 1.10 2000/01/27 23:21:57 ralf Exp $
8 */
9 #include <linux/init.h>
10 #include <linux/kernel.h>
11 #include <linux/types.h>
12 #include <linux/sched.h>
13 #include <linux/mm.h>
14 #include <linux/bootmem.h>
15 #include <linux/swap.h>
17 #include <asm/sgialib.h>
18 #include <asm/page.h>
19 #include <asm/pgtable.h>
20 #include <asm/bootinfo.h>
22 #undef DEBUG
24 extern char _end;
26 struct linux_mdesc * __init
27 ArcGetMemoryDescriptor(struct linux_mdesc *Current)
29 return romvec->get_mdesc(Current);
32 #ifdef DEBUG /* convenient for debugging */
33 static char *arcs_mtypes[8] = {
34 "Exception Block",
35 "ARCS Romvec Page",
36 "Free/Contig RAM",
37 "Generic Free RAM",
38 "Bad Memory",
39 "Standlong Program Pages",
40 "ARCS Temp Storage Area",
41 "ARCS Permanent Storage Area"
44 static char *arc_mtypes[8] = {
45 "Exception Block",
46 "SystemParameterBlock",
47 "FreeMemory",
48 "Bad Memory",
49 "LoadedProgram",
50 "FirmwareTemporary",
51 "FirmwarePermanent",
52 "FreeContigiuous"
54 #define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] : arc_mtypes[a.arc]
55 #endif
57 static struct prom_pmemblock pblocks[PROM_MAX_PMEMBLOCKS];
59 #define MEMTYPE_DONTUSE 0
60 #define MEMTYPE_PROM 1
61 #define MEMTYPE_FREE 2
63 static inline int memtype_classify_arcs (union linux_memtypes type)
65 switch (type.arcs) {
66 case arcs_fcontig:
67 case arcs_free:
68 return MEMTYPE_FREE;
69 case arcs_atmp:
70 return MEMTYPE_PROM;
71 case arcs_eblock:
72 case arcs_rvpage:
73 case arcs_bmem:
74 case arcs_prog:
75 case arcs_aperm:
76 return MEMTYPE_DONTUSE;
77 default:
78 BUG();
80 while(1); /* Nuke warning. */
83 static inline int memtype_classify_arc (union linux_memtypes type)
85 switch (type.arc) {
86 case arc_free:
87 case arc_fcontig:
88 return MEMTYPE_FREE;
89 case arc_atmp:
90 return MEMTYPE_PROM;
91 case arc_eblock:
92 case arc_rvpage:
93 case arc_bmem:
94 case arc_prog:
95 case arc_aperm:
96 return MEMTYPE_DONTUSE;
97 default:
98 BUG();
100 while(1); /* Nuke warning. */
103 static int __init prom_memtype_classify (union linux_memtypes type)
105 if (prom_flags & PROM_FLAG_ARCS) /* SGI is ``different'' ... */
106 return memtype_classify_arcs(type);
108 return memtype_classify_arc(type);
111 static inline unsigned long find_max_low_pfn(void)
113 struct prom_pmemblock *p, *highest;
114 unsigned long pfn;
116 p = pblocks;
117 highest = 0;
118 while (p->size != 0) {
119 if (!highest || p->base > highest->base)
120 highest = p;
121 p++;
124 pfn = (highest->base + highest->size) >> PAGE_SHIFT;
125 #ifdef DEBUG
126 prom_printf("find_max_low_pfn: 0x%lx pfns.\n", pfn);
127 #endif
128 return pfn;
131 static inline struct prom_pmemblock *find_largest_memblock(void)
133 struct prom_pmemblock *p, *largest;
135 p = pblocks;
136 largest = 0;
137 while (p->size != 0) {
138 if (!largest || p->size > largest->size)
139 largest = p;
140 p++;
143 return largest;
146 void __init prom_meminit(void)
148 struct prom_pmemblock *largest;
149 unsigned long bootmap_size;
150 struct linux_mdesc *p;
151 int totram;
152 int i = 0;
154 #ifdef DEBUG
155 prom_printf("ARCS MEMORY DESCRIPTOR dump:\n");
156 p = ArcGetMemoryDescriptor(PROM_NULL_MDESC);
157 while(p) {
158 prom_printf("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n",
159 i, p, p->base, p->pages, mtypes(p->type));
160 p = ArcGetMemoryDescriptor(p);
161 i++;
163 #endif
165 totram = 0;
166 i = 0;
167 p = PROM_NULL_MDESC;
168 while ((p = ArcGetMemoryDescriptor(p))) {
169 pblocks[i].type = prom_memtype_classify(p->type);
170 pblocks[i].base = p->base << PAGE_SHIFT;
171 pblocks[i].size = p->pages << PAGE_SHIFT;
173 switch (pblocks[i].type) {
174 case MEMTYPE_FREE:
175 totram += pblocks[i].size;
176 #ifdef DEBUG
177 prom_printf("free_chunk[%d]: base=%08lx size=%x\n",
178 i, pblocks[i].base,
179 pblocks[i].size);
180 #endif
181 i++;
182 break;
183 case MEMTYPE_PROM:
184 #ifdef DEBUG
185 prom_printf("prom_chunk[%d]: base=%08lx size=%x\n",
186 i, pblocks[i].base,
187 pblocks[i].size);
188 #endif
189 i++;
190 break;
191 default:
192 break;
195 pblocks[i].size = 0;
197 max_low_pfn = find_max_low_pfn();
198 largest = find_largest_memblock();
199 bootmap_size = init_bootmem(largest->base >> PAGE_SHIFT, max_low_pfn);
201 for (i = 0; pblocks[i].size; i++)
202 if (pblocks[i].type == MEMTYPE_FREE)
203 free_bootmem(pblocks[i].base, pblocks[i].size);
205 /* This test is simpleminded. It will fail if the bootmem bitmap
206 falls into multiple adjacent ARC memory areas. */
207 if (bootmap_size > largest->size) {
208 prom_printf("CRITIAL: overwriting PROM data.\n");
209 BUG();
211 reserve_bootmem(largest->base, bootmap_size);
213 printk("PROMLIB: Total free ram %dK / %dMB.\n",
214 totram >> 10, totram >> 20);
217 void __init
218 prom_free_prom_memory (void)
220 struct prom_pmemblock *p;
221 unsigned long freed = 0;
222 unsigned long addr;
224 for (p = pblocks; p->size != 0; p++) {
225 if (p->type != MEMTYPE_PROM)
226 continue;
228 addr = PAGE_OFFSET + p->base;
229 while (addr < p->base + p->size) {
230 ClearPageReserved(mem_map + MAP_NR(addr));
231 set_page_count(mem_map + MAP_NR(addr), 1);
232 free_page(addr);
233 addr += PAGE_SIZE;
234 freed += PAGE_SIZE;
237 printk("Freeing prom memory: %ldkb freed\n", freed >> 10);