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
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>
21 #include <linux/bootmem.h>
22 #include <linux/swap.h>
24 #include <asm/sgialib.h>
26 #include <asm/pgtable.h>
27 #include <asm/bootinfo.h>
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] = {
46 "Standlong Program Pages",
47 "ARCS Temp Storage Area",
48 "ARCS Permanent Storage Area"
51 static char *arc_mtypes
[8] = {
53 "SystemParameterBlock",
61 #define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] : arc_mtypes[a.arc]
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
)
83 return MEMTYPE_DONTUSE
;
87 while(1); /* Nuke warning. */
90 static inline int memtype_classify_arc (union linux_memtypes type
)
103 return MEMTYPE_DONTUSE
;
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
;
125 while (p
->size
!= 0) {
126 if (!highest
|| p
->base
> highest
->base
)
131 pfn
= (highest
->base
+ highest
->size
) >> PAGE_SHIFT
;
133 prom_printf("find_max_low_pfn: 0x%lx pfns.\n", pfn
);
138 static inline struct prom_pmemblock
*find_largest_memblock(void)
140 struct prom_pmemblock
*p
, *largest
;
144 while (p
->size
!= 0) {
145 if (!largest
|| p
->size
> largest
->size
)
153 void __init
prom_meminit(void)
155 struct prom_pmemblock
*largest
;
156 unsigned long bootmap_size
;
157 struct linux_mdesc
*p
;
162 prom_printf("ARCS MEMORY DESCRIPTOR dump:\n");
163 p
= ArcGetMemoryDescriptor(PROM_NULL_MDESC
);
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
);
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
) {
182 totram
+= pblocks
[i
].size
;
184 prom_printf("free_chunk[%d]: base=%08lx size=%x\n",
192 prom_printf("prom_chunk[%d]: base=%08lx size=%x\n",
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");
218 reserve_bootmem(largest
->base
, bootmap_size
);
220 printk("PROMLIB: Total free ram %dK / %dMB.\n",
221 totram
>> 10, totram
>> 20);
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
)
235 addr
= PAGE_OFFSET
+ (unsigned long) (long) p
->base
;
236 end
= addr
+ (unsigned long) (long) p
->size
;
238 ClearPageReserved(mem_map
+ MAP_NR(addr
));
239 set_page_count(mem_map
+ MAP_NR(addr
), 1);
245 printk("Freeing prom memory: %ldkb freed\n", freed
>> 10);