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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: SCCS/s.mem_pieces.c 1.5 05/17/01 18:14:23 cort
  3.  */
  4. /*
  5.  *    Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
  6.  *      Changes to accomodate Power Macintoshes.
  7.  *    Cort Dougan <cort@cs.nmt.edu>
  8.  *      Rewrites.
  9.  *    Grant Erickson <grant@lcse.umn.edu>
  10.  *      General rework and split from mm/init.c.
  11.  *
  12.  *    Module name: mem_pieces.c
  13.  *
  14.  *    Description:
  15.  *      Routines and data structures for manipulating and representing
  16.  *      phyiscal memory extents (i.e. address/length pairs).
  17.  *
  18.  */
  19. #include <linux/config.h>
  20. #include <linux/kernel.h>
  21. #include <linux/stddef.h>
  22. #include <linux/blk.h>
  23. #include <linux/init.h>
  24. #include "mem_pieces.h"
  25. extern struct mem_pieces phys_avail;
  26. static void mem_pieces_print(struct mem_pieces *);
  27. /*
  28.  * Scan a region for a piece of a given size with the required alignment.
  29.  */
  30. void __init *
  31. mem_pieces_find(unsigned int size, unsigned int align)
  32. {
  33. int i;
  34. unsigned a, e;
  35. struct mem_pieces *mp = &phys_avail;
  36. for (i = 0; i < mp->n_regions; ++i) {
  37. a = mp->regions[i].address;
  38. e = a + mp->regions[i].size;
  39. a = (a + align - 1) & -align;
  40. if (a + size <= e) {
  41. mem_pieces_remove(mp, a, size, 1);
  42. return __va(a);
  43. }
  44. }
  45. panic("Couldn't find %u bytes at %u alignmentn", size, align);
  46. return NULL;
  47. }
  48. /*
  49.  * Remove some memory from an array of pieces
  50.  */
  51. void __init 
  52. mem_pieces_remove(struct mem_pieces *mp, unsigned int start, unsigned int size,
  53.   int must_exist)
  54. {
  55. int i, j;
  56. unsigned int end, rs, re;
  57. struct reg_property *rp;
  58. end = start + size;
  59. for (i = 0, rp = mp->regions; i < mp->n_regions; ++i, ++rp) {
  60. if (end > rp->address && start < rp->address + rp->size)
  61. break;
  62. }
  63. if (i >= mp->n_regions) {
  64. if (must_exist)
  65. printk("mem_pieces_remove: [%x,%x) not in any regionn",
  66.        start, end);
  67. return;
  68. }
  69. for (; i < mp->n_regions && end > rp->address; ++i, ++rp) {
  70. rs = rp->address;
  71. re = rs + rp->size;
  72. if (must_exist && (start < rs || end > re)) {
  73. printk("mem_pieces_remove: bad overlap [%x,%x) with",
  74.        start, end);
  75. mem_pieces_print(mp);
  76. must_exist = 0;
  77. }
  78. if (start > rs) {
  79. rp->size = start - rs;
  80. if (end < re) {
  81. /* need to split this entry */
  82. if (mp->n_regions >= MEM_PIECES_MAX)
  83. panic("eek... mem_pieces overflow");
  84. for (j = mp->n_regions; j > i + 1; --j)
  85. mp->regions[j] = mp->regions[j-1];
  86. ++mp->n_regions;
  87. rp[1].address = end;
  88. rp[1].size = re - end;
  89. }
  90. } else {
  91. if (end < re) {
  92. rp->address = end;
  93. rp->size = re - end;
  94. } else {
  95. /* need to delete this entry */
  96. for (j = i; j < mp->n_regions - 1; ++j)
  97. mp->regions[j] = mp->regions[j+1];
  98. --mp->n_regions;
  99. --i;
  100. --rp;
  101. }
  102. }
  103. }
  104. }
  105. static void __init
  106. mem_pieces_print(struct mem_pieces *mp)
  107. {
  108. int i;
  109. for (i = 0; i < mp->n_regions; ++i)
  110. printk(" [%x, %x)", mp->regions[i].address,
  111.        mp->regions[i].address + mp->regions[i].size);
  112. printk("n");
  113. }
  114. #if defined(CONFIG_APUS) || defined(CONFIG_ALL_PPC)
  115. /*
  116.  * Add some memory to an array of pieces
  117.  */
  118. void __init
  119. mem_pieces_append(struct mem_pieces *mp, unsigned int start, unsigned int size)
  120. {
  121. struct reg_property *rp;
  122. if (mp->n_regions >= MEM_PIECES_MAX)
  123. return;
  124. rp = &mp->regions[mp->n_regions++];
  125. rp->address = start;
  126. rp->size = size;
  127. }
  128. #endif /* CONFIG_APUS || CONFIG_ALL_PPC */
  129. void __init
  130. mem_pieces_sort(struct mem_pieces *mp)
  131. {
  132. unsigned long a, s;
  133. int i, j;
  134. for (i = 1; i < mp->n_regions; ++i) {
  135. a = mp->regions[i].address;
  136. s = mp->regions[i].size;
  137. for (j = i - 1; j >= 0; --j) {
  138. if (a >= mp->regions[j].address)
  139. break;
  140. mp->regions[j+1] = mp->regions[j];
  141. }
  142. mp->regions[j+1].address = a;
  143. mp->regions[j+1].size = s;
  144. }
  145. }
  146. void __init
  147. mem_pieces_coalesce(struct mem_pieces *mp)
  148. {
  149. unsigned long a, s, ns;
  150. int i, j, d;
  151. d = 0;
  152. for (i = 0; i < mp->n_regions; i = j) {
  153. a = mp->regions[i].address;
  154. s = mp->regions[i].size;
  155. for (j = i + 1; j < mp->n_regions
  156.      && mp->regions[j].address - a <= s; ++j) {
  157. ns = mp->regions[j].address + mp->regions[j].size - a;
  158. if (ns > s)
  159. s = ns;
  160. }
  161. mp->regions[d].address = a;
  162. mp->regions[d].size = s;
  163. ++d;
  164. }
  165. mp->n_regions = d;
  166. }