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.

236 lines
4.7 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. ixreboot.c
  5. Abstract:
  6. Provides the interface to the firmware for x86. Since there is no
  7. firmware to speak of on x86, this is just reboot support.
  8. Author:
  9. John Vert (jvert) 12-Aug-1991
  10. Revision History:
  11. --*/
  12. //
  13. // This module is compatible with PAE mode and therefore treats physical
  14. // addresses as 64-bit entities.
  15. //
  16. #if !defined(_PHYS64_)
  17. #define _PHYS64_
  18. #endif
  19. #include "halp.h"
  20. #include "pci.h"
  21. #ifdef ACPI_HAL
  22. #include "acpitabl.h"
  23. #include "xxacpi.h"
  24. extern UCHAR HalpPiix4;
  25. #endif
  26. //
  27. // Defines to let us diddle the CMOS clock and the keyboard
  28. //
  29. #define CMOS_CTRL (PUCHAR )0x70
  30. #define CMOS_DATA (PUCHAR )0x71
  31. #define RESET 0xfe
  32. #define KEYBPORT (PUCHAR )0x64
  33. //
  34. // Private function prototypes
  35. //
  36. VOID
  37. HalpReboot (
  38. VOID
  39. )
  40. /*++
  41. Routine Description:
  42. This procedure resets the CMOS clock to the standard timer settings
  43. so the bios will work, and then issues a reset command to the keyboard
  44. to cause a warm boot.
  45. It is very machine dependent, this implementation is intended for
  46. PC-AT like machines.
  47. This code copied from the "old debugger" sources.
  48. N.B.
  49. Will NOT return.
  50. --*/
  51. {
  52. UCHAR Scratch;
  53. PUSHORT Magic;
  54. PUCHAR ResetAddress;
  55. PHYSICAL_ADDRESS zeroPhysical;
  56. PCI_SLOT_NUMBER slot;
  57. //
  58. // By sticking 0x1234 at physical location 0x472, we can bypass the
  59. // memory check after a reboot.
  60. //
  61. zeroPhysical.QuadPart = 0;
  62. Magic = HalpMapPhysicalMemory(zeroPhysical, 1);
  63. if (Magic) {
  64. Magic[0x472 / sizeof(USHORT)] = 0x1234;
  65. }
  66. //
  67. // Turn off interrupts
  68. //
  69. HalpAcquireCmosSpinLock();
  70. HalpDisableInterrupts();
  71. //
  72. // Reset the cmos clock to a standard value
  73. // (We are setting the periodic interrupt control on the MC147818)
  74. //
  75. //
  76. // Disable periodic interrupt
  77. //
  78. WRITE_PORT_UCHAR(CMOS_CTRL, 0x0b); // Set up for control reg B.
  79. KeStallExecutionProcessor(1);
  80. Scratch = READ_PORT_UCHAR(CMOS_DATA);
  81. KeStallExecutionProcessor(1);
  82. Scratch &= 0xbf; // Clear periodic interrupt enable
  83. WRITE_PORT_UCHAR(CMOS_DATA, Scratch);
  84. KeStallExecutionProcessor(1);
  85. //
  86. // Set "standard" divider rate
  87. //
  88. WRITE_PORT_UCHAR(CMOS_CTRL, 0x0a); // Set up for control reg A.
  89. KeStallExecutionProcessor(1);
  90. Scratch = READ_PORT_UCHAR(CMOS_DATA);
  91. KeStallExecutionProcessor(1);
  92. Scratch &= 0xf0; // Clear rate setting
  93. Scratch |= 6; // Set default rate and divider
  94. WRITE_PORT_UCHAR(CMOS_DATA, Scratch);
  95. KeStallExecutionProcessor(1);
  96. //
  97. // Set a "neutral" cmos address to prevent weirdness
  98. // (Why is this needed? Source this was copied from doesn't say)
  99. //
  100. WRITE_PORT_UCHAR(CMOS_CTRL, 0x15);
  101. KeStallExecutionProcessor(1);
  102. HalpResetAllProcessors();
  103. #ifdef ACPI_HAL
  104. if ((HalpFixedAcpiDescTable.Header.Revision > 1) &&
  105. (HalpFixedAcpiDescTable.flags & RESET_CAP)) {
  106. switch (HalpFixedAcpiDescTable.reset_reg.AddressSpaceID) {
  107. case 0: // Memory
  108. ResetAddress =
  109. HalpMapPhysicalMemory(HalpFixedAcpiDescTable.reset_reg.Address, 1);
  110. WRITE_REGISTER_UCHAR(ResetAddress,
  111. HalpFixedAcpiDescTable.reset_val);
  112. break;
  113. case 1: // I/O
  114. WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)HalpFixedAcpiDescTable.reset_reg.Address.LowPart,
  115. HalpFixedAcpiDescTable.reset_val);
  116. break;
  117. case 2: // PCI Config
  118. slot.u.AsULONG = 0;
  119. slot.u.bits.DeviceNumber =
  120. HalpFixedAcpiDescTable.reset_reg.Address.HighPart;
  121. slot.u.bits.FunctionNumber =
  122. HalpFixedAcpiDescTable.reset_reg.Address.LowPart >> 16;
  123. HalSetBusDataByOffset(PCIBus,
  124. 0,
  125. slot.u.AsULONG,
  126. &HalpFixedAcpiDescTable.reset_val,
  127. HalpFixedAcpiDescTable.reset_reg.Address.LowPart & 0xff,
  128. 1);
  129. break;
  130. }
  131. }
  132. #endif
  133. //
  134. // If we return, send the reset command to the keyboard controller
  135. //
  136. WRITE_PORT_UCHAR(KEYBPORT, RESET);
  137. HalpHalt();
  138. }
  139. #ifndef ACPI_HAL
  140. VOID
  141. HaliHaltSystem (
  142. VOID
  143. )
  144. /*++
  145. Routine Description:
  146. This procedure is called when the machine has crashed and is to be
  147. halted
  148. N.B.
  149. Will NOT return.
  150. --*/
  151. {
  152. _asm {
  153. cli
  154. hlt
  155. }
  156. }
  157. VOID
  158. HalpCheckPowerButton (
  159. VOID
  160. )
  161. {
  162. }
  163. #endif