237 lines
4.7 KiB
C
237 lines
4.7 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1991 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
ixreboot.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Provides the interface to the firmware for x86. Since there is no
|
||
|
firmware to speak of on x86, this is just reboot support.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
John Vert (jvert) 12-Aug-1991
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
//
|
||
|
// This module is compatible with PAE mode and therefore treats physical
|
||
|
// addresses as 64-bit entities.
|
||
|
//
|
||
|
|
||
|
#if !defined(_PHYS64_)
|
||
|
#define _PHYS64_
|
||
|
#endif
|
||
|
|
||
|
#include "halp.h"
|
||
|
#include "pci.h"
|
||
|
|
||
|
#ifdef ACPI_HAL
|
||
|
#include "acpitabl.h"
|
||
|
#include "xxacpi.h"
|
||
|
extern UCHAR HalpPiix4;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
//
|
||
|
// Defines to let us diddle the CMOS clock and the keyboard
|
||
|
//
|
||
|
|
||
|
#define CMOS_CTRL (PUCHAR )0x70
|
||
|
#define CMOS_DATA (PUCHAR )0x71
|
||
|
|
||
|
#define RESET 0xfe
|
||
|
#define KEYBPORT (PUCHAR )0x64
|
||
|
|
||
|
//
|
||
|
// Private function prototypes
|
||
|
//
|
||
|
|
||
|
VOID
|
||
|
HalpReboot (
|
||
|
VOID
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This procedure resets the CMOS clock to the standard timer settings
|
||
|
so the bios will work, and then issues a reset command to the keyboard
|
||
|
to cause a warm boot.
|
||
|
|
||
|
It is very machine dependent, this implementation is intended for
|
||
|
PC-AT like machines.
|
||
|
|
||
|
This code copied from the "old debugger" sources.
|
||
|
|
||
|
N.B.
|
||
|
|
||
|
Will NOT return.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
UCHAR Scratch;
|
||
|
PUSHORT Magic;
|
||
|
PUCHAR ResetAddress;
|
||
|
PHYSICAL_ADDRESS zeroPhysical;
|
||
|
PCI_SLOT_NUMBER slot;
|
||
|
|
||
|
//
|
||
|
// By sticking 0x1234 at physical location 0x472, we can bypass the
|
||
|
// memory check after a reboot.
|
||
|
//
|
||
|
|
||
|
zeroPhysical.QuadPart = 0;
|
||
|
Magic = HalpMapPhysicalMemory(zeroPhysical, 1);
|
||
|
if (Magic) {
|
||
|
Magic[0x472 / sizeof(USHORT)] = 0x1234;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Turn off interrupts
|
||
|
//
|
||
|
|
||
|
HalpAcquireCmosSpinLock();
|
||
|
HalpDisableInterrupts();
|
||
|
|
||
|
//
|
||
|
// Reset the cmos clock to a standard value
|
||
|
// (We are setting the periodic interrupt control on the MC147818)
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Disable periodic interrupt
|
||
|
//
|
||
|
|
||
|
WRITE_PORT_UCHAR(CMOS_CTRL, 0x0b); // Set up for control reg B.
|
||
|
KeStallExecutionProcessor(1);
|
||
|
|
||
|
Scratch = READ_PORT_UCHAR(CMOS_DATA);
|
||
|
KeStallExecutionProcessor(1);
|
||
|
|
||
|
Scratch &= 0xbf; // Clear periodic interrupt enable
|
||
|
|
||
|
WRITE_PORT_UCHAR(CMOS_DATA, Scratch);
|
||
|
KeStallExecutionProcessor(1);
|
||
|
|
||
|
//
|
||
|
// Set "standard" divider rate
|
||
|
//
|
||
|
|
||
|
WRITE_PORT_UCHAR(CMOS_CTRL, 0x0a); // Set up for control reg A.
|
||
|
KeStallExecutionProcessor(1);
|
||
|
|
||
|
Scratch = READ_PORT_UCHAR(CMOS_DATA);
|
||
|
KeStallExecutionProcessor(1);
|
||
|
|
||
|
Scratch &= 0xf0; // Clear rate setting
|
||
|
Scratch |= 6; // Set default rate and divider
|
||
|
|
||
|
WRITE_PORT_UCHAR(CMOS_DATA, Scratch);
|
||
|
KeStallExecutionProcessor(1);
|
||
|
|
||
|
//
|
||
|
// Set a "neutral" cmos address to prevent weirdness
|
||
|
// (Why is this needed? Source this was copied from doesn't say)
|
||
|
//
|
||
|
|
||
|
WRITE_PORT_UCHAR(CMOS_CTRL, 0x15);
|
||
|
KeStallExecutionProcessor(1);
|
||
|
|
||
|
HalpResetAllProcessors();
|
||
|
|
||
|
#ifdef ACPI_HAL
|
||
|
|
||
|
if ((HalpFixedAcpiDescTable.Header.Revision > 1) &&
|
||
|
(HalpFixedAcpiDescTable.flags & RESET_CAP)) {
|
||
|
|
||
|
switch (HalpFixedAcpiDescTable.reset_reg.AddressSpaceID) {
|
||
|
case 0: // Memory
|
||
|
|
||
|
ResetAddress =
|
||
|
HalpMapPhysicalMemory(HalpFixedAcpiDescTable.reset_reg.Address, 1);
|
||
|
|
||
|
WRITE_REGISTER_UCHAR(ResetAddress,
|
||
|
HalpFixedAcpiDescTable.reset_val);
|
||
|
break;
|
||
|
|
||
|
case 1: // I/O
|
||
|
|
||
|
WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)HalpFixedAcpiDescTable.reset_reg.Address.LowPart,
|
||
|
HalpFixedAcpiDescTable.reset_val);
|
||
|
break;
|
||
|
|
||
|
case 2: // PCI Config
|
||
|
|
||
|
slot.u.AsULONG = 0;
|
||
|
slot.u.bits.DeviceNumber =
|
||
|
HalpFixedAcpiDescTable.reset_reg.Address.HighPart;
|
||
|
slot.u.bits.FunctionNumber =
|
||
|
HalpFixedAcpiDescTable.reset_reg.Address.LowPart >> 16;
|
||
|
|
||
|
HalSetBusDataByOffset(PCIBus,
|
||
|
0,
|
||
|
slot.u.AsULONG,
|
||
|
&HalpFixedAcpiDescTable.reset_val,
|
||
|
HalpFixedAcpiDescTable.reset_reg.Address.LowPart & 0xff,
|
||
|
1);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// If we return, send the reset command to the keyboard controller
|
||
|
//
|
||
|
|
||
|
WRITE_PORT_UCHAR(KEYBPORT, RESET);
|
||
|
|
||
|
HalpHalt();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
#ifndef ACPI_HAL
|
||
|
|
||
|
VOID
|
||
|
HaliHaltSystem (
|
||
|
VOID
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This procedure is called when the machine has crashed and is to be
|
||
|
halted
|
||
|
|
||
|
N.B.
|
||
|
|
||
|
Will NOT return.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
_asm {
|
||
|
cli
|
||
|
hlt
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
HalpCheckPowerButton (
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
#endif
|