Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

242 lines
6.1 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. XNSUMB.C
  5. Abstract:
  6. Routines to service XMS Request UMB and Release UMB functions.
  7. Also includes UMB initialization routine
  8. Author:
  9. William Hsieh (williamh) Created 23-Sept-1992
  10. [Environment:]
  11. User mode, running in the MVDM context (bop from 16bits)
  12. [Notes:]
  13. Revision History:
  14. --*/
  15. #include <xms.h>
  16. #include "umb.h"
  17. #include "softpc.h"
  18. // This global variable points to the first node(lowest address) UMB list
  19. static PXMSUMB xmsUMBHead;
  20. static BOOL xmsIsON = FALSE;
  21. // ------------------------------------------------------------------
  22. // Initialization for UMB support. It create a single direction linked
  23. // list and allocate all available UMBs.
  24. // Input: client (AX:BX) = segment:offset of himem.sys A20State variable
  25. //
  26. // Output: list header, xmsUMBHead set.
  27. //-------------------------------------------------------------------
  28. VOID xmsInitUMB(VOID)
  29. {
  30. PVOID Address;
  31. ULONG Size;
  32. PXMSUMB xmsUMB, xmsUMBNew;
  33. xmsUMBHead = NULL;
  34. while (ReserveUMB(UMB_OWNER_XMS, &Address, &Size) &&
  35. (xmsUMBNew = (PXMSUMB) malloc(sizeof(XMSUMB))) != NULL) {
  36. // convert size in bytes to paragraphs
  37. xmsUMBNew->Size = (WORD) (Size >> 4);
  38. // convert linear address to paragraphs segment
  39. xmsUMBNew->Segment = (WORD)((DWORD)Address >> 4);
  40. xmsUMBNew->Owner = 0;
  41. if (xmsUMBHead == NULL) {
  42. xmsUMBHead = xmsUMBNew;
  43. xmsUMBHead->Next = NULL;
  44. }
  45. else {
  46. xmsUMBNew->Next = xmsUMB->Next;
  47. xmsUMB->Next = xmsUMBNew;
  48. }
  49. xmsUMB = xmsUMBNew;
  50. }
  51. xmsIsON = TRUE;
  52. pHimemA20State = (PBYTE) GetVDMAddr(getAX(), getBX());
  53. xmsEnableA20Wrapping();
  54. }
  55. // This function receives control whenever there has been an UMB released
  56. // Input: PVOID Address = the block address
  57. // ULONG Size = the block size
  58. VOID xmsReleaseUMBNotify(
  59. PVOID Address,
  60. DWORD Size
  61. )
  62. {
  63. // If the block is good and xms driver is ON,
  64. // grab the block and insert it into our xms UMB list
  65. if (Address != NULL && Size > 0 && xmsIsON &&
  66. ReserveUMB(UMB_OWNER_XMS, &Address, &Size)){
  67. xmsInsertUMB(Address, Size);
  68. }
  69. }
  70. // ------------------------------------------------------------------
  71. // Insert a given UMB into the list
  72. // Input: PVOID Address = linear address of the block to be inserted
  73. // ULONG Size = size in byte of the block
  74. // Output: TRUE if the block was inserted to the list successfully
  75. // FALSE if the block wasn't inserted
  76. //-------------------------------------------------------------------
  77. VOID xmsInsertUMB(
  78. PVOID Address,
  79. ULONG Size
  80. )
  81. {
  82. PXMSUMB xmsUMB, xmsUMBNew;
  83. WORD Segment;
  84. Segment = (WORD) ((DWORD)Address >> 4);
  85. Size >>= 4;
  86. xmsUMB = xmsUMBNew = xmsUMBHead;
  87. while (xmsUMBNew != NULL && xmsUMBNew->Segment < Segment) {
  88. xmsUMB = xmsUMBNew;
  89. xmsUMBNew = xmsUMBNew->Next;
  90. }
  91. // merge it with previous block if possible
  92. if (xmsUMB != NULL &&
  93. xmsUMB->Owner == 0 &&
  94. Segment == xmsUMB->Segment + xmsUMB->Size) {
  95. xmsUMB->Size += (WORD) Size;
  96. return;
  97. }
  98. // merge it with the after block if possible
  99. if (xmsUMBNew != NULL &&
  100. xmsUMBNew->Owner == 0 &&
  101. xmsUMBNew->Segment == Segment + Size) {
  102. xmsUMBNew->Size += (WORD) Size;
  103. xmsUMBNew->Segment = Segment;
  104. return;
  105. }
  106. // create a new node for the block
  107. if ((xmsUMBNew = (PXMSUMB)malloc(sizeof(XMSUMB))) != NULL) {
  108. xmsUMBNew->Size = (WORD) Size;
  109. xmsUMBNew->Segment = Segment;
  110. xmsUMBNew->Owner = 0;
  111. if (xmsUMBHead == NULL) {
  112. xmsUMBHead = xmsUMBNew;
  113. xmsUMBNew->Next = NULL;
  114. }
  115. else {
  116. xmsUMBNew->Next = xmsUMB->Next;
  117. xmsUMB->Next = xmsUMBNew;
  118. }
  119. }
  120. }
  121. // ------------------------------------------------------------------
  122. // XMS function 16, Request UMB.
  123. // Input: (DX) = requested size in paragraphs
  124. // Output: (AX) = 1 if succeed and
  125. // (BX) has segment address(number) of the block
  126. // (DX) has actual allocated size in paragraphs
  127. // (AX) = 0 if failed and
  128. // (BL) = 0xB0, (DX) = largest size available
  129. // or
  130. // (BL) = 0xB1 if no UMBs are available
  131. //-------------------------------------------------------------------
  132. VOID xmsRequestUMB(VOID)
  133. {
  134. PXMSUMB xmsUMB, xmsUMBNew;
  135. WORD SizeRequested, SizeLargest;
  136. xmsUMB = xmsUMBHead;
  137. SizeRequested = getDX();
  138. SizeLargest = 0;
  139. while (xmsUMB != NULL) {
  140. if (xmsUMB->Owner == 0) {
  141. if (xmsUMB->Size >= SizeRequested) {
  142. if((xmsUMB->Size - SizeRequested) >= XMSUMB_THRESHOLD &&
  143. (xmsUMBNew = (PXMSUMB) malloc(sizeof(XMSUMB))) != NULL) {
  144. xmsUMBNew->Segment = xmsUMB->Segment + SizeRequested;
  145. xmsUMBNew->Size = xmsUMB->Size - SizeRequested;
  146. xmsUMBNew->Next = xmsUMB->Next;
  147. xmsUMB->Next = xmsUMBNew;
  148. xmsUMBNew->Owner = 0;
  149. xmsUMB->Size -= xmsUMBNew->Size;
  150. }
  151. xmsUMB->Owner = 0xFFFF;
  152. setAX(1);
  153. setBX(xmsUMB->Segment);
  154. setDX(xmsUMB->Size);
  155. return;
  156. }
  157. else {
  158. if (xmsUMB->Size > SizeLargest)
  159. SizeLargest = xmsUMB->Size;
  160. }
  161. }
  162. xmsUMB = xmsUMB->Next;
  163. }
  164. setAX(0);
  165. setDX(SizeLargest);
  166. if (SizeLargest > 0)
  167. setBL(0xB0);
  168. else
  169. setBL(0xB1);
  170. }
  171. //------------------------------------------------------------------
  172. // XMS function 17, Release UMB.
  173. // Input : (DX) = segment to be released
  174. // Output: (AX) = 1 if succeed
  175. // (AX) = 0 if failed and
  176. // (BL) = 0xB2 if segment not found in the list
  177. //------------------------------------------------------------------
  178. VOID xmsReleaseUMB(VOID)
  179. {
  180. PXMSUMB xmsUMB, xmsUMBNext;
  181. WORD Segment;
  182. xmsUMB = xmsUMBHead;
  183. Segment = getDX();
  184. while (xmsUMB != NULL && xmsUMB->Segment != Segment) {
  185. xmsUMB = xmsUMB->Next;
  186. }
  187. if (xmsUMB != NULL && xmsUMB->Owner != 0) {
  188. xmsUMB->Owner = 0;
  189. // no walk through the entire list to combine consecutive
  190. // blocks together
  191. xmsUMB = xmsUMBHead;
  192. while (xmsUMB != NULL) {
  193. while (xmsUMB->Owner == 0 &&
  194. (xmsUMBNext = xmsUMB->Next) != NULL &&
  195. xmsUMBNext->Owner == 0 &&
  196. (WORD)(xmsUMB->Segment + xmsUMB->Size) == xmsUMBNext->Segment){
  197. xmsUMB->Size += xmsUMBNext->Size;
  198. xmsUMB->Next = xmsUMBNext->Next;
  199. free(xmsUMBNext);
  200. }
  201. xmsUMB = xmsUMB->Next;
  202. }
  203. setAX(1);
  204. }
  205. else {
  206. setBL(0xB2);
  207. setAX(0);
  208. }
  209. }