memory.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /* $Id: memory.c,v 1.15 2000/01/29 01:09:12 anton Exp $
  2. * memory.c: Prom routine for acquiring various bits of information
  3. * about RAM on the machine, both virtual and physical.
  4. *
  5. * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  6. * Copyright (C) 1997 Michael A. Griffith (grif@acm.org)
  7. */
  8. #include <linux/kernel.h>
  9. #include <linux/init.h>
  10. #include <asm/openprom.h>
  11. #include <asm/sun4prom.h>
  12. #include <asm/oplib.h>
  13. /* This routine, for consistency, returns the ram parameters in the
  14. * V0 prom memory descriptor format. I choose this format because I
  15. * think it was the easiest to work with. I feel the religious
  16. * arguments now... ;) Also, I return the linked lists sorted to
  17. * prevent paging_init() upset stomach as I have not yet written
  18. * the pepto-bismol kernel module yet.
  19. */
  20. struct linux_prom_registers prom_reg_memlist[64];
  21. struct linux_prom_registers prom_reg_tmp[64];
  22. struct linux_mlist_v0 prom_phys_total[64];
  23. struct linux_mlist_v0 prom_prom_taken[64];
  24. struct linux_mlist_v0 prom_phys_avail[64];
  25. struct linux_mlist_v0 *prom_ptot_ptr = prom_phys_total;
  26. struct linux_mlist_v0 *prom_ptak_ptr = prom_prom_taken;
  27. struct linux_mlist_v0 *prom_pavl_ptr = prom_phys_avail;
  28. struct linux_mem_v0 prom_memlist;
  29. /* Internal Prom library routine to sort a linux_mlist_v0 memory
  30. * list. Used below in initialization.
  31. */
  32. static void __init
  33. prom_sortmemlist(struct linux_mlist_v0 *thislist)
  34. {
  35. int swapi = 0;
  36. int i, mitr, tmpsize;
  37. char *tmpaddr;
  38. char *lowest;
  39. for(i=0; thislist[i].theres_more; i++) {
  40. lowest = thislist[i].start_adr;
  41. for(mitr = i+1; thislist[mitr-1].theres_more; mitr++)
  42. if(thislist[mitr].start_adr < lowest) {
  43. lowest = thislist[mitr].start_adr;
  44. swapi = mitr;
  45. }
  46. if(lowest == thislist[i].start_adr) continue;
  47. tmpaddr = thislist[swapi].start_adr;
  48. tmpsize = thislist[swapi].num_bytes;
  49. for(mitr = swapi; mitr > i; mitr--) {
  50. thislist[mitr].start_adr = thislist[mitr-1].start_adr;
  51. thislist[mitr].num_bytes = thislist[mitr-1].num_bytes;
  52. }
  53. thislist[i].start_adr = tmpaddr;
  54. thislist[i].num_bytes = tmpsize;
  55. }
  56. return;
  57. }
  58. /* Initialize the memory lists based upon the prom version. */
  59. void __init prom_meminit(void)
  60. {
  61. int node = 0;
  62. unsigned int iter, num_regs;
  63. struct linux_mlist_v0 *mptr; /* ptr for traversal */
  64. switch(prom_vers) {
  65. case PROM_V0:
  66. /* Nice, kind of easier to do in this case. */
  67. /* First, the total physical descriptors. */
  68. for(mptr = (*(romvec->pv_v0mem.v0_totphys)), iter=0;
  69. mptr; mptr=mptr->theres_more, iter++) {
  70. prom_phys_total[iter].start_adr = mptr->start_adr;
  71. prom_phys_total[iter].num_bytes = mptr->num_bytes;
  72. prom_phys_total[iter].theres_more = &prom_phys_total[iter+1];
  73. }
  74. prom_phys_total[iter-1].theres_more = NULL;
  75. /* Second, the total prom taken descriptors. */
  76. for(mptr = (*(romvec->pv_v0mem.v0_prommap)), iter=0;
  77. mptr; mptr=mptr->theres_more, iter++) {
  78. prom_prom_taken[iter].start_adr = mptr->start_adr;
  79. prom_prom_taken[iter].num_bytes = mptr->num_bytes;
  80. prom_prom_taken[iter].theres_more = &prom_prom_taken[iter+1];
  81. }
  82. prom_prom_taken[iter-1].theres_more = NULL;
  83. /* Last, the available physical descriptors. */
  84. for(mptr = (*(romvec->pv_v0mem.v0_available)), iter=0;
  85. mptr; mptr=mptr->theres_more, iter++) {
  86. prom_phys_avail[iter].start_adr = mptr->start_adr;
  87. prom_phys_avail[iter].num_bytes = mptr->num_bytes;
  88. prom_phys_avail[iter].theres_more = &prom_phys_avail[iter+1];
  89. }
  90. prom_phys_avail[iter-1].theres_more = NULL;
  91. /* Sort all the lists. */
  92. prom_sortmemlist(prom_phys_total);
  93. prom_sortmemlist(prom_prom_taken);
  94. prom_sortmemlist(prom_phys_avail);
  95. break;
  96. case PROM_V2:
  97. case PROM_V3:
  98. /* Grrr, have to traverse the prom device tree ;( */
  99. node = prom_getchild(prom_root_node);
  100. node = prom_searchsiblings(node, "memory");
  101. num_regs = prom_getproperty(node, "available",
  102. (char *) prom_reg_memlist,
  103. sizeof(prom_reg_memlist));
  104. num_regs = (num_regs/sizeof(struct linux_prom_registers));
  105. for(iter=0; iter<num_regs; iter++) {
  106. prom_phys_avail[iter].start_adr =
  107. (char *) prom_reg_memlist[iter].phys_addr;
  108. prom_phys_avail[iter].num_bytes =
  109. (unsigned long) prom_reg_memlist[iter].reg_size;
  110. prom_phys_avail[iter].theres_more =
  111. &prom_phys_avail[iter+1];
  112. }
  113. prom_phys_avail[iter-1].theres_more = NULL;
  114. num_regs = prom_getproperty(node, "reg",
  115. (char *) prom_reg_memlist,
  116. sizeof(prom_reg_memlist));
  117. num_regs = (num_regs/sizeof(struct linux_prom_registers));
  118. for(iter=0; iter<num_regs; iter++) {
  119. prom_phys_total[iter].start_adr =
  120. (char *) prom_reg_memlist[iter].phys_addr;
  121. prom_phys_total[iter].num_bytes =
  122. (unsigned long) prom_reg_memlist[iter].reg_size;
  123. prom_phys_total[iter].theres_more =
  124. &prom_phys_total[iter+1];
  125. }
  126. prom_phys_total[iter-1].theres_more = NULL;
  127. node = prom_getchild(prom_root_node);
  128. node = prom_searchsiblings(node, "virtual-memory");
  129. num_regs = prom_getproperty(node, "available",
  130. (char *) prom_reg_memlist,
  131. sizeof(prom_reg_memlist));
  132. num_regs = (num_regs/sizeof(struct linux_prom_registers));
  133. /* Convert available virtual areas to taken virtual
  134. * areas. First sort, then convert.
  135. */
  136. for(iter=0; iter<num_regs; iter++) {
  137. prom_prom_taken[iter].start_adr =
  138. (char *) prom_reg_memlist[iter].phys_addr;
  139. prom_prom_taken[iter].num_bytes =
  140. (unsigned long) prom_reg_memlist[iter].reg_size;
  141. prom_prom_taken[iter].theres_more =
  142. &prom_prom_taken[iter+1];
  143. }
  144. prom_prom_taken[iter-1].theres_more = NULL;
  145. prom_sortmemlist(prom_prom_taken);
  146. /* Finally, convert. */
  147. for(iter=0; iter<num_regs; iter++) {
  148. prom_prom_taken[iter].start_adr =
  149. prom_prom_taken[iter].start_adr +
  150. prom_prom_taken[iter].num_bytes;
  151. prom_prom_taken[iter].num_bytes =
  152. prom_prom_taken[iter+1].start_adr -
  153. prom_prom_taken[iter].start_adr;
  154. }
  155. prom_prom_taken[iter-1].num_bytes =
  156. 0xffffffff - (unsigned long) prom_prom_taken[iter-1].start_adr;
  157. /* Sort the other two lists. */
  158. prom_sortmemlist(prom_phys_total);
  159. prom_sortmemlist(prom_phys_avail);
  160. break;
  161. case PROM_SUN4:
  162. #ifdef CONFIG_SUN4
  163. /* how simple :) */
  164. prom_phys_total[0].start_adr = NULL;
  165. prom_phys_total[0].num_bytes = *(sun4_romvec->memorysize);
  166. prom_phys_total[0].theres_more = NULL;
  167. prom_prom_taken[0].start_adr = NULL;
  168. prom_prom_taken[0].num_bytes = 0x0;
  169. prom_prom_taken[0].theres_more = NULL;
  170. prom_phys_avail[0].start_adr = NULL;
  171. prom_phys_avail[0].num_bytes = *(sun4_romvec->memoryavail);
  172. prom_phys_avail[0].theres_more = NULL;
  173. #endif
  174. break;
  175. default:
  176. break;
  177. };
  178. /* Link all the lists into the top-level descriptor. */
  179. prom_memlist.v0_totphys=&prom_ptot_ptr;
  180. prom_memlist.v0_prommap=&prom_ptak_ptr;
  181. prom_memlist.v0_available=&prom_pavl_ptr;
  182. return;
  183. }
  184. /* This returns a pointer to our libraries internal v0 format
  185. * memory descriptor.
  186. */
  187. struct linux_mem_v0 *
  188. prom_meminfo(void)
  189. {
  190. return &prom_memlist;
  191. }