1 /* $Id: memory.c,v 1.5 1999/08/31 06:55:04 davem Exp $
2 * memory.c: Prom routine for acquiring various bits of information
3 * about RAM on the machine, both virtual and physical.
5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
6 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
9 #include <linux/kernel.h>
10 #include <linux/init.h>
12 #include <asm/openprom.h>
13 #include <asm/oplib.h>
15 /* This routine, for consistency, returns the ram parameters in the
16 * V0 prom memory descriptor format. I choose this format because I
17 * think it was the easiest to work with. I feel the religious
18 * arguments now... ;) Also, I return the linked lists sorted to
19 * prevent paging_init() upset stomach as I have not yet written
20 * the pepto-bismol kernel module yet.
23 struct linux_prom64_registers prom_reg_memlist
[64];
24 struct linux_prom64_registers prom_reg_tmp
[64];
26 struct linux_mlist_p1275 prom_phys_total
[64];
27 struct linux_mlist_p1275 prom_prom_taken
[64];
28 struct linux_mlist_p1275 prom_phys_avail
[64];
30 struct linux_mlist_p1275
*prom_ptot_ptr
= prom_phys_total
;
31 struct linux_mlist_p1275
*prom_ptak_ptr
= prom_prom_taken
;
32 struct linux_mlist_p1275
*prom_pavl_ptr
= prom_phys_avail
;
34 struct linux_mem_p1275 prom_memlist
;
37 /* Internal Prom library routine to sort a linux_mlist_p1275 memory
38 * list. Used below in initialization.
41 prom_sortmemlist(struct linux_mlist_p1275
*thislist
)
45 unsigned long tmpaddr
, tmpsize
;
48 for(i
=0; thislist
[i
].theres_more
; i
++) {
49 lowest
= thislist
[i
].start_adr
;
50 for(mitr
= i
+1; thislist
[mitr
-1].theres_more
; mitr
++)
51 if(thislist
[mitr
].start_adr
< lowest
) {
52 lowest
= thislist
[mitr
].start_adr
;
55 if(lowest
== thislist
[i
].start_adr
) continue;
56 tmpaddr
= thislist
[swapi
].start_adr
;
57 tmpsize
= thislist
[swapi
].num_bytes
;
58 for(mitr
= swapi
; mitr
> i
; mitr
--) {
59 thislist
[mitr
].start_adr
= thislist
[mitr
-1].start_adr
;
60 thislist
[mitr
].num_bytes
= thislist
[mitr
-1].num_bytes
;
62 thislist
[i
].start_adr
= tmpaddr
;
63 thislist
[i
].num_bytes
= tmpsize
;
67 /* Initialize the memory lists based upon the prom version. */
68 void __init
prom_meminit(void)
71 unsigned int iter
, num_regs
;
73 node
= prom_finddevice("/memory");
74 num_regs
= prom_getproperty(node
, "available",
75 (char *) prom_reg_memlist
,
76 sizeof(prom_reg_memlist
));
77 num_regs
= (num_regs
/sizeof(struct linux_prom64_registers
));
78 for(iter
=0; iter
<num_regs
; iter
++) {
79 prom_phys_avail
[iter
].start_adr
=
80 prom_reg_memlist
[iter
].phys_addr
;
81 prom_phys_avail
[iter
].num_bytes
=
82 prom_reg_memlist
[iter
].reg_size
;
83 prom_phys_avail
[iter
].theres_more
=
84 &prom_phys_avail
[iter
+1];
86 prom_phys_avail
[iter
-1].theres_more
= NULL
;
88 num_regs
= prom_getproperty(node
, "reg",
89 (char *) prom_reg_memlist
,
90 sizeof(prom_reg_memlist
));
91 num_regs
= (num_regs
/sizeof(struct linux_prom64_registers
));
92 for(iter
=0; iter
<num_regs
; iter
++) {
93 prom_phys_total
[iter
].start_adr
=
94 prom_reg_memlist
[iter
].phys_addr
;
95 prom_phys_total
[iter
].num_bytes
=
96 prom_reg_memlist
[iter
].reg_size
;
97 prom_phys_total
[iter
].theres_more
=
98 &prom_phys_total
[iter
+1];
100 prom_phys_total
[iter
-1].theres_more
= NULL
;
102 node
= prom_finddevice("/virtual-memory");
103 num_regs
= prom_getproperty(node
, "available",
104 (char *) prom_reg_memlist
,
105 sizeof(prom_reg_memlist
));
106 num_regs
= (num_regs
/sizeof(struct linux_prom64_registers
));
108 /* Convert available virtual areas to taken virtual
109 * areas. First sort, then convert.
111 for(iter
=0; iter
<num_regs
; iter
++) {
112 prom_prom_taken
[iter
].start_adr
=
113 prom_reg_memlist
[iter
].phys_addr
;
114 prom_prom_taken
[iter
].num_bytes
=
115 prom_reg_memlist
[iter
].reg_size
;
116 prom_prom_taken
[iter
].theres_more
=
117 &prom_prom_taken
[iter
+1];
119 prom_prom_taken
[iter
-1].theres_more
= NULL
;
121 prom_sortmemlist(prom_prom_taken
);
123 /* Finally, convert. */
124 for(iter
=0; iter
<num_regs
; iter
++) {
125 prom_prom_taken
[iter
].start_adr
=
126 prom_prom_taken
[iter
].start_adr
+
127 prom_prom_taken
[iter
].num_bytes
;
128 prom_prom_taken
[iter
].num_bytes
=
129 prom_prom_taken
[iter
+1].start_adr
-
130 prom_prom_taken
[iter
].start_adr
;
132 prom_prom_taken
[iter
-1].num_bytes
=
133 -1UL - prom_prom_taken
[iter
-1].start_adr
;
135 /* Sort the other two lists. */
136 prom_sortmemlist(prom_phys_total
);
137 prom_sortmemlist(prom_phys_avail
);
139 /* Link all the lists into the top-level descriptor. */
140 prom_memlist
.p1275_totphys
=&prom_ptot_ptr
;
141 prom_memlist
.p1275_prommap
=&prom_ptak_ptr
;
142 prom_memlist
.p1275_available
=&prom_pavl_ptr
;
145 /* This returns a pointer to our libraries internal p1275 format
148 struct linux_mem_p1275
*
151 return &prom_memlist
;