- Finish the work around for the Pentium cmpxchg8b lock errata: We detected the errat...
[reactos.git] / reactos / hal / halx86 / generic / reboot.c
index 4e07b2c..fe822ac 100644 (file)
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/hal/x86/reboot.c
- * PURPOSE:         Reboot functions.
- * PROGRAMMER:      Eric Kohl (ekohl@abo.rhein-zeitung.de)
- * UPDATE HISTORY:
- *                  Created 11/10/99
+/*
+ * PROJECT:         ReactOS HAL
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            hal/halx86/generic/reboot.c
+ * PURPOSE:         Reboot functions
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ *                  Eric Kohl (ekohl@abo.rhein-zeitung.de)
  */
 
-#define NDEBUG
+/* INCLUDES ******************************************************************/
+
 #include <hal.h>
+#define NDEBUG
+#include <debug.h>
 
+#define GetPteAddress(x) (PHARDWARE_PTE)(((((ULONG_PTR)(x)) >> 12) << 2) + 0xC0000000)
 
-static VOID
-HalReboot (VOID)
+/* PRIVATE FUNCTIONS *********************************************************/
+
+VOID
+NTAPI
+HalpWriteResetCommand(VOID)
 {
-    char data;
-    extern PVOID HalpZeroPageMapping;
+    /* Generate RESET signal via keyboard controller */
+    WRITE_PORT_UCHAR((PUCHAR)0x64, 0xFE);
+};
+
+VOID
+NTAPI
+HalpReboot(VOID)
+{
+    UCHAR Data;
+    PVOID ZeroPageMapping;
+    PHARDWARE_PTE Pte;
+
+    /* Get a PTE in the HAL reserved region */
+    ZeroPageMapping = (PVOID)(0xFFC00000 + PAGE_SIZE);
+    Pte = GetPteAddress(ZeroPageMapping);
+
+    /* Make it valid and map it to the first physical page */
+    Pte->Valid = 1;
+    Pte->Write = 1;
+    Pte->Owner = 1;
+    Pte->PageFrameNumber = 0;
+
+    /* Flush the TLB by resetting CR3 */
+    __writecr3(__readcr3());
 
-    /* enable warm reboot */
-    ((PUCHAR)HalpZeroPageMapping)[0x472] = 0x34;
-    ((PUCHAR)HalpZeroPageMapping)[0x473] = 0x12;
+    /* Enable warm reboot */
+    ((PUSHORT)ZeroPageMapping)[0x239] = 0x1234;
 
-    /* disable interrupts */
-    Ki386DisableInterrupts();
+    /* Lock CMOS Access (and disable interrupts) */
+    HalpAcquireSystemHardwareSpinLock();
 
+    /* Setup control register B */
+    WRITE_PORT_UCHAR((PUCHAR)0x70, 0x0B);
+    KeStallExecutionProcessor(1);
 
-    /* disable periodic interrupt (RTC) */
-    WRITE_PORT_UCHAR((PUCHAR)0x70, 0x0b);
-    data = READ_PORT_UCHAR((PUCHAR)0x71);
-    WRITE_PORT_UCHAR((PUCHAR)0x71, (UCHAR)(data & 0xbf));
+    /* Read periodic register and clear the interrupt enable */
+    Data = READ_PORT_UCHAR((PUCHAR)0x71);
+    WRITE_PORT_UCHAR((PUCHAR)0x71, Data & ~0x40);
+    KeStallExecutionProcessor(1);
 
-    /* */
-    WRITE_PORT_UCHAR((PUCHAR)0x70, 0x0a);
-    data = READ_PORT_UCHAR((PUCHAR)0x71);
-    WRITE_PORT_UCHAR((PUCHAR)0x71, (UCHAR)((data & 0xf0) | 0x06));
+    /* Setup control register A */
+    WRITE_PORT_UCHAR((PUCHAR)0x70, 0x0A);
+    KeStallExecutionProcessor(1);
 
-    /* */
+    /* Read divider rate and reset it */
+    Data = READ_PORT_UCHAR((PUCHAR)0x71);
+    WRITE_PORT_UCHAR((PUCHAR)0x71, (Data & ~0x9) | 0x06);
+    KeStallExecutionProcessor(1);
+
+    /* Reset neutral CMOS address */
     WRITE_PORT_UCHAR((PUCHAR)0x70, 0x15);
+    KeStallExecutionProcessor(1);
 
-    /* generate RESET signal via keyboard controller */
-    WRITE_PORT_UCHAR((PUCHAR)0x64, 0xfe);
+    /* Flush write buffers and send the reset command */
+    KeFlushWriteBuffer();
+    HalpWriteResetCommand();
 
-    /* stop the processor */
-#if 1
-    Ki386HaltProcessor();
-    for(;;);
-#endif   
+    /* Halt the CPU */
+    __halt();
 }
 
+/* PUBLIC FUNCTIONS **********************************************************/
 
-VOID STDCALL
-HalReturnToFirmware (
-       ULONG   Action
-       )
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+HalReturnToFirmware(IN FIRMWARE_REENTRY Action)
 {
-    if (Action == HalHaltRoutine)
-    {
-        DbgPrint ("HalReturnToFirmware called!\n");
-        DbgBreakPoint ();
-    }
-    else if (Action == HalRebootRoutine)
+    /* Check what kind of action this is */
+    switch (Action)
     {
-        HalReleaseDisplayOwnership();
-        HalReboot ();
+        /* All recognized actions */
+        case HalHaltRoutine:
+        case HalRebootRoutine:
+
+            /* Acquire the display */
+            InbvAcquireDisplayOwnership();
+
+            /* Call the internal reboot function */
+            HalpReboot();
+
+        /* Anything else */
+        default:
+
+            /* Print message and break */
+            DbgPrint("HalReturnToFirmware called!\n");
+            DbgBreakPoint();
     }
 }