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 $
9 #include <linux/init.h>
10 #include <linux/kernel.h>
11 #include <linux/types.h>
12 #include <linux/sched.h>
14 #include <linux/bootmem.h>
15 #include <linux/swap.h>
17 #include <asm/sgialib.h>
19 #include <asm/pgtable.h>
20 #include <asm/bootinfo.h>
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] = {
39 "Standlong Program Pages",
40 "ARCS Temp Storage Area",
41 "ARCS Permanent Storage Area"
44 static char *arc_mtypes
[8] = {
46 "SystemParameterBlock",
54 #define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] : arc_mtypes[a.arc]
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
)
76 return MEMTYPE_DONTUSE
;
80 while(1); /* Nuke warning. */
83 static inline int memtype_classify_arc (union linux_memtypes type
)
96 return MEMTYPE_DONTUSE
;
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
;
118 while (p
->size
!= 0) {
119 if (!highest
|| p
->base
> highest
->base
)
124 pfn
= (highest
->base
+ highest
->size
) >> PAGE_SHIFT
;
126 prom_printf("find_max_low_pfn: 0x%lx pfns.\n", pfn
);
131 static inline struct prom_pmemblock
*find_largest_memblock(void)
133 struct prom_pmemblock
*p
, *largest
;
137 while (p
->size
!= 0) {
138 if (!largest
|| p
->size
> largest
->size
)
146 void __init
prom_meminit(void)
148 struct prom_pmemblock
*largest
;
149 unsigned long bootmap_size
;
150 struct linux_mdesc
*p
;
155 prom_printf("ARCS MEMORY DESCRIPTOR dump:\n");
156 p
= ArcGetMemoryDescriptor(PROM_NULL_MDESC
);
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
);
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
) {
175 totram
+= pblocks
[i
].size
;
177 prom_printf("free_chunk[%d]: base=%08lx size=%x\n",
185 prom_printf("prom_chunk[%d]: base=%08lx size=%x\n",
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");
211 reserve_bootmem(largest
->base
, bootmap_size
);
213 printk("PROMLIB: Total free ram %dK / %dMB.\n",
214 totram
>> 10, totram
>> 20);
218 prom_free_prom_memory (void)
220 struct prom_pmemblock
*p
;
221 unsigned long freed
= 0;
224 for (p
= pblocks
; p
->size
!= 0; p
++) {
225 if (p
->type
!= MEMTYPE_PROM
)
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);
237 printk("Freeing prom memory: %ldkb freed\n", freed
>> 10);