summaryrefslogblamecommitdiffstats
path: root/private/ntos/nthals/halalpha/fwreturn.c
blob: bf11d8c2777847154bccc25f886a25faa5ccefbb (plain) (tree)






























































































































































































































































                                                                                
/*++

Copyright (c) 1991  Microsoft Corporation
Copyright (c) 1992, 1993  Digital Equipment Corporation

Module Name:

    fwreturn.c

Abstract:

    This module implements the HAL return to firmware function.

    Stolen wholesale from s3return.c in ../mips.
    Assumes that the firmware entry vector defined in the HAL spec has
    been set up and is reachable through the System Parameter Block.

Author:

    David N. Cutler (davec) 21-Aug-1991
    Miche Baker-Harvey (miche) 4-Jun-1992

Revision History:

    14-Dec-1993 Joe Notarangelo
        Add MP support, use reboot encoding to return to firmware

--*/

#include "halp.h"

#if !defined(NT_UP)


VOID                                    // #definition of KiIpiSendPacket
KiIpiSendPacket(                        // not in ntmp.h. Define here
    IN KAFFINITY TargetProcessors,
    IN PKIPI_WORKER WorkerFunction,
    IN PVOID Parameter1,
    IN PVOID Parameter2,
    IN PVOID Parameter3
    );
#endif

VOID
HalpResetHAERegisters(
    VOID
    );

VOID
HalpShutdownSystem(
    ULONG HaltReasonCode
    );


VOID
HalReturnToFirmware(
    IN FIRMWARE_REENTRY Routine
    )

/*++

Routine Description:

    This function returns control to the specified firmware routine.

Arguments:

    Routine - Supplies a value indicating which firmware routine to invoke.

Return Value:

    Does not return.

Revision History:

    09-Jul-1992 Jeff McLeman (mcleman)
      In all cases, except for ArcEnterInteractiveMode, invoke a
      halt to restart the firmware. (Enter PAL)
    04-Mar-1993 Joe Mitchell (DEC)
      Invoke a routine to call halt in ALL cases. Before calling this routine,
      pass a value to the firmware indicating the desired function via
      the Restart Block save area.

--*/

{

    //
    // Case on the type of return.
    //

    switch (Routine)
    {
      case HalHaltRoutine:
        HalpShutdownSystem( AXP_HALT_REASON_POWEROFF );
        break;
      case HalPowerDownRoutine:
        HalpShutdownSystem( AXP_HALT_REASON_POWERFAIL );
        break;
      case HalRestartRoutine:
        HalpShutdownSystem( AXP_HALT_REASON_RESTART );
        break;
      case HalRebootRoutine:
        HalpShutdownSystem( AXP_HALT_REASON_REBOOT );
        break;
      case HalInteractiveModeRoutine:
        HalpShutdownSystem( AXP_HALT_REASON_HALT );
        break;
      default:
        HalDisplayString("Unknown ARCS restart function.\n");
        DbgBreakPoint();
    }

    /* NOTREACHED */
    HalDisplayString("Illegal return from ARCS restart function.\n");
    DbgBreakPoint();
}

VOID
HalpShutdownSystem(
    ULONG HaltReasonCode
    )
/*++

Routine Description:

    This function causes a system shutdown so that each processor in
    the system will return to the firmware.  A processor returns to
    the firmware by executing the reboot call pal function.

Arguments:

    HaltReasonCode - Supplies the reason code for the halt.

Return Value:

    None.

--*/
{
    PRESTART_BLOCK RestartBlock;                // Boot Master Restart Block
#if !defined(NT_UP)
    KAFFINITY TargetProcessors;
    KIRQL OldIrql;
    PKPRCB Prcb = PCR->Prcb;
    ULONG Wait;
#endif

    //
    // Reset video using NT driver's HwResetHw routine
    //

    HalpVideoReboot();

    //
    // Reset the HAE Registers to 0
    //

    HalpResetHAERegisters();

    //
    // Write the halt reason code into the restart block of the
    // boot master processor.
    //

    RestartBlock = SYSTEM_BLOCK->RestartBlock;
    if( RestartBlock != NULL ){
        RestartBlock->u.Alpha.HaltReason = HaltReasonCode;
    }

#if !defined(NT_UP)

#define REBOOT_WAIT_LIMIT (5 * 1000)            // loop count for 5 second wait

    //
    // Raise Irql to block all interrupts except errors and IPIs.
    //

    KeRaiseIrql( CLOCK_LEVEL, &OldIrql );

    //
    // Send an IPI to each processor.
    //
    TargetProcessors = HalpActiveProcessors;
    TargetProcessors &= ~Prcb->SetMember;

#if HALDBG

    DbgPrint( "HalpShutdown: TargetProcessors = %x, Active = %x\n",
               TargetProcessors, HalpActiveProcessors );

#endif //HALDBG


    KiIpiSendPacket( TargetProcessors,
                     (PKIPI_WORKER) HalpReboot,
                     NULL,
                     NULL,
                     NULL );


    //
    // If the current processor is the primary, it must reboot and handle
    // the firmware restart. If a secondary processor is executing this
    // shutdown, then it waits to verify that the primary has shutdown so
    // that the restart can be performed. If the primary doesn't reach the
    // firmware, the system is toasted and a message is printed.
    //
    if ( Prcb->Number == HAL_PRIMARY_PROCESSOR )
    {
        HalpReboot;                // Never to return
    }

    //
    // Wait until the primary processor has rebooted and signalled that
    // it has returned to the firmware by indicating that the processor
    // is not started in the BootStatus of its restart block. (ProcessorStart=0)
    // However, put a timeout on the check in case the primary processor
    // is currently wedged (it may not be able to receive the IPI).
    //

    Wait = 0;
    while( RestartBlock->BootStatus.ProcessorStart == 0 &&
                                        Wait < REBOOT_WAIT_LIMIT ) {
        //
        // The Primary processor is still running.  Stall for a while
        // and increment the wait count.
        //

        KeStallExecutionProcessor( 1000 );      // 1000000 );
        Wait ++;

    } //end  while( Wait < REBOOT_WAIT_LIMIT )


    //
    // if the wait timed out print messages to alert the user.
    //
    if ( Wait >= REBOOT_WAIT_LIMIT )
    {
        HalDisplayString( "The Primary Processor was not shutdown.\n" );
        HalDisplayString( "Power off your system before restarting.\n" );
    }

#endif //!NT_UP

    //
    // Reboot this processor.
    //

    HalpReboot();

}