memory.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:7k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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