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.

538 lines
14 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. eisac.c
  5. Abstract:
  6. This module implements routines to get EISA configuration information.
  7. Author:
  8. Shie-Lin Tzong (shielint) 10-June-1991
  9. Environment:
  10. 16-bit real mode.
  11. Revision History:
  12. John Vert (jvert) 5-Sep-1991
  13. Moved into the SU module of portable bootloader
  14. --*/
  15. #include "su.h"
  16. #include "eisa.h"
  17. //
  18. // HACKHACK - John Vert (jvert) 12-Sep-1991
  19. // We have to initialize this or else it gets stuck in our BSS section
  20. // which is right in the middle of the osloader.exe header
  21. //
  22. extern BTEISA_FUNCTION_INFORMATION FunctionInformation;
  23. BOOLEAN
  24. FindFunctionInformation (
  25. IN UCHAR SlotFlags,
  26. IN UCHAR FunctionFlags,
  27. OUT PBTEISA_FUNCTION_INFORMATION Buffer,
  28. IN BOOLEAN FromBeginning
  29. )
  30. /*++
  31. Routine Description:
  32. This routine finds function information that matches the specified
  33. flags. It starts, either where it left off last time, or at the
  34. beginning (slot 0, function 0)
  35. Arguments:
  36. Flags - Flags to check against EISA function and slot information.
  37. Buffer - pointer to buffer to store EISA information in.
  38. FromBeginning - if TRUE, search starts at slot 0, function 0.
  39. else continue from where it left off last time.
  40. Return Value:
  41. TRUE - If the operation is success (Buffer is filled in.)
  42. FALSE - Request fails.
  43. Notes: The buffer is always changed, reguardless of the success
  44. of the function. When failure is returned, the info is invalid.
  45. --*/
  46. {
  47. static UCHAR Slot=0;
  48. static UCHAR Function=0;
  49. BTEISA_SLOT_INFORMATION SlotInformation;
  50. UCHAR Flags;
  51. UCHAR ReturnCode;
  52. if (FromBeginning) {
  53. Slot = 0;
  54. Function = 0;
  55. }
  56. BtGetEisaSlotInformation(&SlotInformation, Slot);
  57. while (SlotInformation.ReturnCode != EISA_INVALID_SLOT) {
  58. //
  59. // insure that the slot is not empty, and all of the flags are set.
  60. // the flags are tested by performing the following logic:
  61. //
  62. // -- (RequestSlotFlags XOR (SlotFlags AND RequestSlotFlags)) --
  63. //
  64. // if all the requested flags are set, the result will be zero
  65. //
  66. if ((SlotInformation.ReturnCode != EISA_EMPTY_SLOT) &&
  67. (!(SlotFlags ^ (SlotInformation.FunctionInformation & SlotFlags)))) {
  68. while (SlotInformation.NumberFunctions > Function) {
  69. ReturnCode = BtGetEisaFunctionInformation(Buffer, Slot, Function);
  70. Function++;
  71. //
  72. // if function call succeeded
  73. //
  74. if (!ReturnCode){
  75. Flags = Buffer->FunctionFlags;
  76. //
  77. // Function Enable/Disable bit reversed.
  78. //
  79. Flags |= (~Flags & EISA_FUNCTION_ENABLED);
  80. //
  81. // insure that all the function flags are set.
  82. // the flags are tested by performing the following logic:
  83. //
  84. // -- (ReqFuncFlags XOR (FuncFlags AND ReqFuncFlags)) --
  85. //
  86. // if all the requested flags are set, the result will
  87. // be zero
  88. //
  89. if (!(FunctionFlags ^ (Flags & FunctionFlags))) {
  90. return TRUE;
  91. }
  92. }
  93. }
  94. }
  95. Slot++;
  96. Function = 0;
  97. BtGetEisaSlotInformation(&SlotInformation, Slot);
  98. }
  99. Slot = 0;
  100. Function = 0;
  101. return FALSE;
  102. }
  103. VOID
  104. InsertDescriptor (
  105. ULONG Address,
  106. ULONG Size
  107. )
  108. /*++
  109. Routine Description:
  110. This routine inserts a descriptor into the correct place in the
  111. memory descriptor list.
  112. Arguments:
  113. Address - Starting address of the memory block.
  114. Size - Size of the memory block to be inserted.
  115. Return Value:
  116. None.
  117. --*/
  118. {
  119. MEMORY_LIST_ENTRY _far *CurrentEntry;
  120. #ifdef DEBUG1
  121. BlPrint("Inserting descriptor %lx at %lx\n",Size,Address);
  122. _asm {
  123. push ax
  124. mov ax, 0
  125. int 16h
  126. pop ax
  127. }
  128. #endif
  129. //
  130. // Search the spot to insert the new descriptor.
  131. //
  132. CurrentEntry = MemoryDescriptorList;
  133. while (CurrentEntry->BlockSize > 0) {
  134. //
  135. // Check to see if this memory descriptor is contiguous with
  136. // the current one. If so, coalesce them. (yes, some machines
  137. // will return memory descriptors that look like this. Compaq
  138. // Prosignia machines)
  139. //
  140. if (Address+Size == CurrentEntry->BlockBase) {
  141. #ifdef DEBUG1
  142. BlPrint(" coalescing with descriptor at %lx (%lx)\n",
  143. CurrentEntry->BlockBase,
  144. CurrentEntry->BlockSize);
  145. #endif
  146. CurrentEntry->BlockBase = Address;
  147. CurrentEntry->BlockSize += Size;
  148. #ifdef DEBUG1
  149. BlPrint(" new descriptor at %lx (%lx)\n",
  150. CurrentEntry->BlockBase,
  151. CurrentEntry->BlockSize);
  152. #endif
  153. break;
  154. }
  155. if (Address == (CurrentEntry->BlockBase + CurrentEntry->BlockSize)) {
  156. #ifdef DEBUG1
  157. BlPrint(" coalescing with descriptor at %lx (%lx)\n",
  158. CurrentEntry->BlockBase,
  159. CurrentEntry->BlockSize);
  160. #endif
  161. CurrentEntry->BlockSize += Size;
  162. #ifdef DEBUG1
  163. BlPrint(" new descriptor at %lx (%lx)\n",
  164. CurrentEntry->BlockBase,
  165. CurrentEntry->BlockSize);
  166. #endif
  167. break;
  168. }
  169. CurrentEntry++;
  170. }
  171. if (CurrentEntry->BlockSize == 0) {
  172. //
  173. // If CurrentEntry->BlockSize == 0, we have reached the end of the list
  174. // So, insert the new descriptor here, and create a new end-of-list entry
  175. //
  176. CurrentEntry->BlockBase = Address;
  177. CurrentEntry->BlockSize = Size;
  178. ++CurrentEntry;
  179. //
  180. // Create a new end-of-list marker
  181. //
  182. CurrentEntry->BlockBase = 0L;
  183. CurrentEntry->BlockSize = 0L;
  184. }
  185. #ifdef DEBUG1
  186. //
  187. // Wait for a keypress
  188. //
  189. _asm {
  190. push ax
  191. mov ax, 0
  192. int 16h
  193. pop ax
  194. }
  195. #endif
  196. }
  197. ULONG
  198. EisaConstructMemoryDescriptors (
  199. VOID
  200. )
  201. /*++
  202. Routine Description:
  203. This routine gets the information EISA memory function above 16M
  204. and creates entries in the memory Descriptor array for them.
  205. Arguments:
  206. None.
  207. Return Value:
  208. Number of pages of usable memory.
  209. --*/
  210. {
  211. BOOLEAN Success;
  212. PBTEISA_MEMORY_CONFIGURATION MemoryConfiguration;
  213. ULONG Address;
  214. ULONG EndAddress;
  215. ULONG Size;
  216. ULONG MemorySize=0;
  217. ULONG IsaMemUnder1Mb=0xffffffff;
  218. MEMORY_LIST_ENTRY _far *CurrentEntry;
  219. //
  220. // HACKHACK John Vert (jvert) 5-Mar-1993
  221. //
  222. // See if there is already a memory descriptor for the 640k under
  223. // 1Mb. If so, we will believe it instead of the EISA routine. This
  224. // is because many EISA routines will always return 640k, even if
  225. // the disk parameter table is in the last 1k. The ISA routines will
  226. // always account for the disk parameter tables. If we believe the
  227. // EISA routines, we can overwrite the disk parameter tables, causing
  228. // much grief.
  229. //
  230. CurrentEntry = MemoryDescriptorList;
  231. while (CurrentEntry->BlockSize > 0) {
  232. if (CurrentEntry->BlockBase == 0) {
  233. //
  234. // found a descriptor starting at zero with a size > 0, so
  235. // this is the one we want to override the EISA information.
  236. //
  237. IsaMemUnder1Mb = CurrentEntry->BlockSize;
  238. break;
  239. }
  240. ++CurrentEntry;
  241. }
  242. //
  243. // Initialize the first entry in the list to zero (end-of-list)
  244. //
  245. MemoryDescriptorList->BlockSize = 0;
  246. MemoryDescriptorList->BlockBase = 0;
  247. Success = FindFunctionInformation(
  248. EISA_HAS_MEMORY_ENTRY,
  249. EISA_FUNCTION_ENABLED | EISA_HAS_MEMORY_ENTRY,
  250. &FunctionInformation,
  251. TRUE
  252. );
  253. //
  254. // while there are more memory functions, and more free descriptors
  255. //
  256. while (Success) {
  257. MemoryConfiguration = &FunctionInformation.EisaMemory[0];
  258. do {
  259. //
  260. // Get physical address of the memory.
  261. // Note: physical address is stored divided by 100h
  262. //
  263. Address = (((ULONG)MemoryConfiguration->AddressHighByte << 16)
  264. + MemoryConfiguration->AddressLowWord) * 0x100;
  265. //
  266. // Get the size of the memory block.
  267. // Note: Size is stored divided by 400h with the value of 0
  268. // meaning a size of 64M
  269. //
  270. if (MemoryConfiguration->MemorySize) {
  271. Size = ((ULONG)MemoryConfiguration->MemorySize) * 0x400;
  272. } else {
  273. Size = (_64MEGB);
  274. }
  275. #ifdef DEBUG1
  276. BlPrint("EISA memory at %lx Size=%lx Type=%x ",
  277. Address,
  278. Size,
  279. MemoryConfiguration->ConfigurationByte);
  280. if ((MemoryConfiguration->ConfigurationByte.Type == EISA_SYSTEM_MEMORY) &&
  281. (MemoryConfiguration->ConfigurationByte.ReadWrite == EISA_MEMORY_TYPE_RAM) ) {
  282. BlPrint(" (USED BY NT)\n");
  283. } else {
  284. BlPrint(" (not used)\n");
  285. }
  286. #endif
  287. //
  288. // Compute end address to determine if any part of the block
  289. // is above 16M
  290. //
  291. EndAddress = Address + Size;
  292. //
  293. // If it is SYSTEM memory and RAM, add the descriptor to the list.
  294. //
  295. if ((MemoryConfiguration->ConfigurationByte.Type == EISA_SYSTEM_MEMORY) &&
  296. (MemoryConfiguration->ConfigurationByte.ReadWrite == EISA_MEMORY_TYPE_RAM) ) {
  297. if (Address==0) {
  298. //
  299. // This is the descriptor for the memory under 1Mb.
  300. // Compare it with the ISA routine's result, and see
  301. // if the ISA one is smaller. If it is, use the ISA
  302. // answer.
  303. //
  304. if (Size > IsaMemUnder1Mb) {
  305. Size = IsaMemUnder1Mb;
  306. }
  307. }
  308. InsertDescriptor(Address, Size);
  309. MemorySize += (Size >> 12);
  310. }
  311. } while (MemoryConfiguration++->ConfigurationByte.MoreEntries);
  312. Success = FindFunctionInformation(
  313. EISA_HAS_MEMORY_ENTRY,
  314. EISA_FUNCTION_ENABLED | EISA_HAS_MEMORY_ENTRY,
  315. &FunctionInformation,
  316. FALSE
  317. );
  318. }
  319. #ifdef DEBUG1
  320. //
  321. // Wait for a keypress
  322. //
  323. _asm {
  324. push ax
  325. mov ax, 0
  326. int 16h
  327. pop ax
  328. }
  329. #endif
  330. return(MemorySize);
  331. }
  332. BOOLEAN
  333. Int15E820 (
  334. E820Frame *Frame
  335. );
  336. BOOLEAN
  337. ConstructMemoryDescriptors (
  338. VOID
  339. )
  340. /*++
  341. Routine Description:
  342. Arguments:
  343. Return Value:
  344. --*/
  345. {
  346. ULONG BAddr, EAddr;
  347. E820Frame Frame;
  348. //
  349. // Initialize the first entry in the list to zero (end-of-list)
  350. //
  351. MemoryDescriptorList->BlockSize = 0;
  352. MemoryDescriptorList->BlockBase = 0;
  353. //
  354. // Any entries returned for E820?
  355. //
  356. Frame.Key = 0;
  357. Frame.Size = sizeof (Frame.Descriptor);
  358. Int15E820 (&Frame);
  359. if (Frame.ErrorFlag || Frame.Size < sizeof (Frame.Descriptor)) {
  360. return FALSE;
  361. }
  362. //
  363. // Found memory in table, use the reported memory
  364. //
  365. Frame.Key = 0;
  366. do {
  367. Frame.Size = sizeof (Frame.Descriptor);
  368. Int15E820 (&Frame);
  369. if (Frame.ErrorFlag || Frame.Size < sizeof (Frame.Descriptor)) {
  370. break ;
  371. }
  372. #ifdef DEBUG1
  373. BlPrint("E820: %lx %lx:%lx %lx:%lx %lx %lx\n",
  374. Frame.Size,
  375. Frame.Descriptor.BaseAddrHigh, Frame.Descriptor.BaseAddrLow,
  376. Frame.Descriptor.SizeHigh, Frame.Descriptor.SizeLow,
  377. Frame.Descriptor.MemoryType,
  378. Frame.Key
  379. );
  380. _asm {
  381. push ax
  382. mov ax, 0
  383. int 16h
  384. pop ax
  385. }
  386. #endif
  387. BAddr = Frame.Descriptor.BaseAddrLow;
  388. EAddr = Frame.Descriptor.BaseAddrLow + Frame.Descriptor.SizeLow - 1;
  389. //
  390. // All the processors we have right now only support 32 bits
  391. // If the upper 32 bits of the Base Address is non-zero, then
  392. // this range is entirely above the 4g mark and can be ignored
  393. //
  394. if (Frame.Descriptor.BaseAddrHigh == 0) {
  395. if (EAddr < BAddr) {
  396. //
  397. // address wrapped - truncate the Ending address to
  398. // 32 bits of address space
  399. //
  400. EAddr = 0xFFFFFFFF;
  401. }
  402. //
  403. // Based upon the address range descriptor type, find the
  404. // available memory and add it to the descriptor list
  405. //
  406. switch (Frame.Descriptor.MemoryType) {
  407. case 1:
  408. //
  409. // This is a memory descriptor
  410. //
  411. InsertDescriptor (BAddr, EAddr - BAddr + 1);
  412. break;
  413. }
  414. }
  415. } while (Frame.Key) ;
  416. return TRUE;
  417. }
  418.