/*++

Copyright (c) 2009  Microsoft Corporation

Module Name:

    nthalext.h

Abstract:

    Header file containing the HAL Extensions API. This file should be included
    by each HAL Extension.

    N.B. Avoid making breaking changes to the structures and enumerations in
         this file, as HAL Extensions may have been compiled with an old header.

Author:

    Andy Raffman (andyraf) 20-Sep-2010

--*/

//
// -------------------------------------------------------------------- Pragmas
//

#pragma once

//
// ------------------------------------------------------------------- Includes
//

#include <wdm.h>
#include <acpitabl.h>

//
// ---------------------------------------------------------------- Definitions
//

#define DMA_INITIALIZATION_VERSION 1
#define DMA_CHANNEL_INITIALIZATION_VERSION 1

#define INITIALIZE_DMA_HEADER(_Pointer)                                     \
    ((_Pointer)->Header.TableVersion = DMA_INITIALIZATION_VERSION),         \
    ((_Pointer)->Header.TableSize = sizeof(DMA_INITIALIZATION_BLOCK))

#define INITIALIZE_DMA_CHANNEL_HEADER(_Pointer)                             \
    ((_Pointer)->Header.TableVersion = DMA_CHANNEL_INITIALIZATION_VERSION), \
    ((_Pointer)->Header.TableSize = sizeof(DMA_CHANNEL_INITIALIZATION_BLOCK))

// begin_ntoshvp

#define TIMER_INITIALIZATION_VERSION 1

#define INITIALIZE_TIMER_HEADER(_Pointer)                                   \
    ((_Pointer)->Header.TableVersion = TIMER_INITIALIZATION_VERSION),       \
    ((_Pointer)->Header.TableSize = sizeof(TIMER_INITIALIZATION_BLOCK))

//
// This bit is set if the timer hardware is duplicated across each processor.
// That is, the actual timer hardware being interacted with depends on which
// processor the code is being executed on. Per-processor timers are expected
// to have the same attributes on all processors.
//

#define TIMER_PER_PROCESSOR 0x00000001

//
// This bit is set if the timer's counter is readable by the HAL. If this bit
// is set, then the QueryCounter function is mandatory. It is expected that
// once initialized, the counter will operate in increasing free-running mode
// from 0 to its maximum bit width. When it reaches its maximum bit width, it
// will roll over to 0 and continue counting. Actions performed on other timers
// should not affect this timer's counter. If arming or querying other
// registered timers affects this timer's counter, it should not have this
// bit set.
//

#define TIMER_COUNTER_READABLE 0x00000002

//
// Set if the counter can be written to. It's fine if the counter has to be
// stopped to write to it.
//

#define TIMER_COUNTER_WRITABLE 0x00000004

//
// Set if the timer has a configurable input clock divisor. If this bit is set,
// the SetDivisor function is mandatory.
//

#define TIMER_HAS_DIVISOR 0x00000008

//
// This bit is set if the timer is capable of generating a periodic interval by
// continually rearming the timer in one-shot mode. If the timer supports this
// mode, it must not introduce additional delay by the re-armings. Only
// deadline-based timers or timers that run off a match register are known to
// support this mode, as other forms of timers introduce delay in the process
// of re-setting the timer.
//

#define TIMER_PSEUDO_PERIODIC_CAPABLE 0x00000010

//
// This bit is set if the timer is capable of generating one-shot interrupts.
// A one-shot interrupt is an interrupt that will fire once after the specified
// number of ticks, but does not automatically rearm itself to fire
// periodically at that rate.
//

#define TIMER_ONE_SHOT_CAPABLE 0x00000020

//
// This bit is set if the timer is capable of generating periodic interrupts.
// A periodic interrupt is an interrupt that will come in at a regular
// interval after a certain number of ticks. The only difference between
// periodic and pseudo-periodic mode is the implied amount of work the timer
// has to do in the acknowledge interrupt routine. It is assumed that
// re-arming the timer for a new one-shot tick is more expensive in terms of
// hardware access than setting the timer in periodic mode. The HAL will also
// not attempt lossless rate changes on a timer armed in pseudo-periodic mode.
//

#define TIMER_PERIODIC_CAPABLE 0x00000040

//
// This bit is set if the timer cannot generate interrupts at an arbitrary tick
// count, but is only capable of generating interrupts when the timer rolls
// over from its maximum value to 0. The ACPI PM timer is an example of such a
// timer.
//

#define TIMER_ROLLOVER_INTERRUPTS_ONLY 0x00000080

//
// This bit is set if the timer is connected to one of the dual 8259 interrupt
// controllers on a PC/AT system. This bit should never be set on ARM.
//

#define TIMER_GENERATES_8259_INTERRUPTS 0x00000100

//
// This bit is set if the timer generates interrupts connected to a line of the
// interrupt controller. This line may be a normal device line or processor
// local line. If this bit is set, the GSI field is used to determine which
// line the timer's interrupt is connected to.
//

#define TIMER_GENERATES_LINE_BASED_INTERRUPTS 0x00000200

//
// This bit is set if the timer can generate MSI interrupts. If this bit is
// set, the SetMessageInterruptRouting function is mandatory.
//

#define TIMER_GENERATES_MSI_INTERRUPTS 0x00000400

//
// This bit is set if the timer's interrupt is generated internally by the
// interrupt controller. These timers have no interrupt line and generally
// vector to the set location automatically. Timers that generate internal
// interrupts are generally built directly into the interrupt controller. The
// Local APIC timer on the PC is an example of such a timer. At this time, no
// known ARM timers fit this category.
//

#define TIMER_GENERATES_INTERNAL_INTERRUPTS 0x00000800

//
// Used to determine if the timer is capable of generating any sort of
// interrupt.
//

#if defined(_AMD64_) || defined(_X86_)

#define TIMER_INTERRUPT_MASK (TIMER_GENERATES_8259_INTERRUPTS |       \
                              TIMER_GENERATES_LINE_BASED_INTERRUPTS | \
                              TIMER_GENERATES_MSI_INTERRUPTS |        \
                              TIMER_GENERATES_INTERNAL_INTERRUPTS)

#elif defined(_ARM_) || defined(_ARM64_)

#define TIMER_INTERRUPT_MASK (TIMER_GENERATES_LINE_BASED_INTERRUPTS | \
                              TIMER_GENERATES_INTERNAL_INTERRUPTS)

#endif

//
// This bit is set if the timer is capable of changing from one periodic rate
// to another without introducing arbitrary delay. Currently this feature is
// only known to exist on deadline-based timers. This bit is optional, but if
// it is set then the LosslessRateChange function is mandatory.
//
// N.B. Use of this flag is deprecated.
//

#define TIMER_LOSSLESS_RATE_CHANGE 0x00001000

//
// Set if the timer's counter frequency may change with performance states
// (Dynamic Voltage and Frequency Scaling).
//

#define TIMER_PERFORMANCE_STATE_VARIANT 0x00002000

//
// Set if the timer's counter frequency may change with processor core idle
// states.
//

#define TIMER_IDLE_STATE_VARIANT 0x00004000

//
// Set if the timer frequency may vary with deep processor idle states or
// performance states. This value is equivalent to specifying the Performance
// State Variant and Idle State Variant flags.
//

#define TIMER_VARIANT (TIMER_PERFORMANCE_STATE_VARIANT | \
                       TIMER_IDLE_STATE_VARIANT)

//
// Defines the mask of capabilities that can be updated post-registration.
//

#define TIMER_UPDATABLE_CAPABILITIES (TIMER_VARIANT)

//
// Set if the timer remains on through the deepest of idle transitions. Note
// that there *must* be at least one timer with this bit set in a platform.
//

#define TIMER_ALWAYS_ON 0x00008000

//
// Set for per-processor timers that require internal data to be mirrored for
// each processor.
//

#define TIMER_PER_PROCESSOR_INTERNAL_DATA 0x00010000

//
// Set for timers which can generate a reset.
//

#define TIMER_GENERATES_RESET 0x00020000

//
// Set if the timer generated a reset during the last boot.
//

#define TIMER_GENERATED_LAST_RESET 0x00040000

//
// Set for timers which can generate a pre-reset interrupt.
//

#define TIMER_GENERATES_PRE_RESET_LINE_BASED_INTERRUPTS 0x00080000

//
// Set to indicate hardware is in support of special auxiliary counter.
//

#define TIMER_AUXILIARY 0x00100000

//
// Set to indicate that a timer does not require calls to initialize after
// being stopped.
//

#define TIMER_SINGLE_INIT 0x00200000

//
// Set to indicate that a timer arms against its counter. Timers which set
// this flag _must_ provide a method to query their counter.
//

#define TIMER_REQUIRES_ABSOLUTE_ARMING 0x00400000

//
// Set to indicate that this timer is subject to ARM A73 rollover errata.
//

#define TIMER_HAS_ROLLOVER_ERRATA 0x00800000

//
// Set to indicate that the timer supports advanced querying.
// In the case of the TSC, this indicates that rdtscp is available.
//

#define TIMER_SUPPORTS_ADVANCED_QUERY 0x01000000

//
// Defines the total valid timer capability flags. Timer plugins must not set
// flags outside this mask, as they are reserved for future use.
//

#define TIMER_VALID_CAPABILITIES 0x01FFFFFF

// end_ntoshvp

//
// Flags used for DMA Port Widths.
//

#define DMA_UNLIMITED_PORT_WIDTH 1
#define DMA_8_BIT_PORT_WIDTH     2
#define DMA_16_BIT_PORT_WIDTH    4
#define DMA_32_BIT_PORT_WIDTH    8
#define DMA_64_BIT_PORT_WIDTH    16

//
// ------------------------------------------------- Data Structure Definitions
//

// begin_ntoshvp

typedef struct _SOC_INITIALIZATION_HEADER {
    ULONG TableVersion;
    ULONG TableSize;
} SOC_INITIALIZATION_HEADER, *PSOC_INITIALIZATION_HEADER;

/*++

SoC Initialization Header Description:

    Stores the header for the SoC initialization block that is passed from a
    SoC module to the HAL.

Fields:

    TableVersion - Stores the version of the table.

    TableSize - Stores the total size, including the header, of the table.

--*/

typedef enum _TIMER_MODE {
    TimerModeInvalid,
    TimerModePseudoPeriodic,
    TimerModePeriodic,
    TimerModeOneShot,
    MaxTimerModes
} TIMER_MODE, *PTIMER_MODE;

typedef enum _KNOWN_TIMER_TYPE {
    TimerInvalid,
    TimerAcpi,
    TimerCmosRtc,
    TimerHpet,
    Timer8254,
    TimerProcessor,
    TimerSfi,
    TimerApic,
    TimerHypervisor,
    TimerBrokenAcpi,
    TimerCycleCounter,
    TimerGit,
    TimerVPPT,
    TimerWDAT,
    TimerGitWatchdog,
    TimerART,
    TimerGitAux,
    TimerUnknown = 0x1000
} KNOWN_TIMER_TYPE, *PKNOWN_TIMER_TYPE;

//
// Routines that need to be implemented by each timer implementation.
//

typedef
_Function_class_(TIMER_INITIALIZE)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
NTSTATUS
TIMER_INITIALIZE (
    _In_ PVOID TimerData
    );

/*++

Routine Description:

    This routine is responsible for initializing the timer hardware. This is
    guaranteed to be the first timer routine called by the HAL. It must prepare
    the timer for use by beginning the timer's counter ticking if the counter
    is readable, setting the intial input clock divisor to 1 if applicable,
    and masking all interrupts. If the timer's stop routine is called, this
    routine will be called before the timer is queried or armed again. It will
    not be called between every rearming of the timer.

    This routine will not be called concurrently with any other calls to
    this HAL Timer extension. For per-processor timers, this routine will be
    called once on each processor. A failure on any processor blocks the timer's
    use on all processors.

Arguments:

    TimerData - Supplies a pointer to the timer's private context. The contents
        of this pointer were specified when the timer was initially registered,
        and may be modified inside this routine. The HAL does not interpret any
        data deferenced from this pointer.

Return Value:

    Returns an NT status code indicating success or failure. If a successful
    status code is returned then the HAL may subsequently call further routines
    in this HAL extension to query or arm the timer. If a failure code is
    returned, this HAL extension will not attempt to use this timer unless the
    Initialize routine is called again and succeeds.

--*/

typedef TIMER_INITIALIZE *PTIMER_INITIALIZE;

typedef
_Function_class_(TIMER_QUERY_COUNTER)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
ULONGLONG
TIMER_QUERY_COUNTER (
    _In_ PVOID TimerData
    );

/*++

Routine Description:

    This routine queries the timer hardware and retrieves the current counter
    value.

    Timers are assumed to always count *up*. If the actual timer hardware counts
    down, then this routine should subtract the current count from the maximum
    counter value so that values appear to count up. This routine may be called
    concurrently on multiple processors and must be reentrant. This routine is
    extremely performance sensitive, as it may be used to back the system
    performance counter.

Arguments:

    TimerData - Supplies a pointer to the timer's private context, whose
        initial content was supplied when the timer was registered.

Return Value:

    Returns the hardware's current count.

--*/

typedef TIMER_QUERY_COUNTER *PTIMER_QUERY_COUNTER;

typedef
_Function_class_(TIMER_ACKNOWLEDGE_INTERRUPT)
_IRQL_requires_same_
_IRQL_requires_max_(CLOCK_LEVEL)
VOID
TIMER_ACKNOWLEDGE_INTERRUPT (
    _In_ PVOID TimerData
    );

/*++

Routine Description:

    This routine performs any actions necessary to acknowledge and quiesce a
    timer interrupt. For per-processor timers, this routine may be called
    concurrently on multiple processors. This routine will be called on every
    timer interrupt at the hardware priority level of that interrupt, so this
    routine is extremely performance sensitive. For timers running in
    pseudo-periodic mode, this routine must rearm the timer for the same
    interval as it was armed with without introducing delay into the interrupt
    interval. Only deadline-based timers support pseudo-periodic mode.

Arguments:

    TimerData - Supplies a pointer to the timer's private context, whose
        initial content was supplied when the timer was registered.

Return Value:

    None.

--*/

typedef TIMER_ACKNOWLEDGE_INTERRUPT *PTIMER_ACKNOWLEDGE_INTERRUPT;

typedef
_Function_class_(TIMER_SET_DIVISOR)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
VOID
TIMER_SET_DIVISOR (
    _In_ PVOID TimerData,
    _In_ ULONG NewDivisor
    );

/*++

Routine Description:

    This routine set's the counter's input frequency divisor, controlling the
    speed at which the counter updates. The Timer Initialize routine sets this
    divisor to 1, so if this is the appropriate value then this routine will
    not get called during initialization. This routine will not get called
    concurrently with other timer routines, but may be called after the timer
    has already been armed to fire an interrupt. On per-processor timers,
    this routine may get called concurrently on different processors. The
    counter is expected to be ticking at the new divisor rate by the time this
    routine returns.

Arguments:

    TimerData - Supplies a pointer to the timer's private context, whose
        initial content was supplied when the timer was registered.

    NewDivisor - Supplies the new divisor rate to set. This value will be a
        power of two and will be less than or equal to the timer's specified
        maximum divisor.

Return Value:

    None.

--*/

typedef TIMER_SET_DIVISOR *PTIMER_SET_DIVISOR;

typedef
_Function_class_(TIMER_ARM_TIMER)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
NTSTATUS
TIMER_ARM_TIMER (
    _In_ PVOID TimerData,
    _In_ TIMER_MODE Mode,
    _In_ ULONGLONG TickCount
    );

/*++

Routine Description:

    This routine arms a timer to fire an interrupt after the given number of
    timer ticks. For timers that only interrupt on rollovers, this simply
    enables the interrupt, the tick count parameter is ignored. If the timer
    is currently armed for a different mode or tick count, this call is
    expected to replace that programming. This routine will not get called
    concurrently with other timer calls, except on per-processor timers, where
    it may get called concurrently on different processors.

Arguments:

    TimerData - Supplies a pointer to the timer's private context, whose
        initial content was supplied when the timer was registered.

    Mode - Supplies the mode to arm the timer in, which will be one of the
        modes the HAL extension advertised support for when registering the
        timer. The modes are as follows:

        OneShot - Arms the timer to fire the given number of ticks from now.
            Only one interrupt is expected to come in. The HAL does not make
            assumptions on whether or not the expiration of this interrupt
            causes the counter to stop. The Query Counter routine will not be
            called while a timer is armed to fire an interrupt.

        Periodic - Arms the timer to fire periodically with an interval of the
            given number of ticks. The first interrupt should happen
            approximately the given number of ticks from when the arm timer
            function was invoked.

        PseudoPeriodic - Arms the timer with the same functional behavior as
            periodic mode, with the knowledge that the timer will have to rearm
            itself during the acknowledge interrupt routine. This mode is
            expected to have slightly worse performance than pure periodic mode,
            but is expected to generate periodic interrupts at the exact rate
            specified.

    TickCount - Supplies the number of ticks from now that the timer should
        assert its interrupt in. For timers that are only capable of
        interrupting on rollovers from their maximum value to 0, this parameter
        is ignored.

Return Value:

    Returns and NTSTATUS code indicating success or failure. If the timer
    returns success, then the interrupt is expected to come in the specified
    number of ticks from when the function was called, with a tolerance of
    however long the function took to execute. If the routine fails, then no
    timer routines will be called again until the timer Initialize routine is
    called again and succeeds. In most cases, returning a failure code results
    in a system bugcheck.

--*/

typedef TIMER_ARM_TIMER *PTIMER_ARM_TIMER;

typedef
_Function_class_(TIMER_SET_MESSAGE_INTERRUPT_ROUTING)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
NTSTATUS
TIMER_SET_MESSAGE_INTERRUPT_ROUTING (
    _In_ PVOID TimerData,
    _In_ BOOLEAN Enable,
    _In_ PHYSICAL_ADDRESS MessageAddress,
    _In_ ULONG MessageData
    );

/*++

Routine Description:

    This routine enables or disables message signalled interrupts on the given
    timer and configures the address and data of the message to generate on
    interrupts. This function only needs to be implemented on timers that have
    indicated they are capable of generating message signalled interrupts.

Arguments:

    TimerData - Supplies a pointer to the timer's private context, whose
        initial content was supplied when the timer was registered.

    Enable - Supplies a flag indicating whether or not MSI delivery mode should
        be enabled (TRUE) or disabled (FALSE). For timers that can generate
        both line based and MSI-based interrupts, this parameter determines
        which type should be used.

    MessageAddress - Supplies the physical address to send the message to.
        This parameter should be ignored when MSIs are being disabled.

    MessageData - Supplies the value to write to the specified address. This
        parameter should be ignored when MSIs are being disabled.

Return Value:

    Returns an NT status code indicating success or failure. If a failure is
    returned, the timer is expected to be left with the interrupt configuration
    it had before this call occurred.

--*/

typedef TIMER_SET_MESSAGE_INTERRUPT_ROUTING *PTIMER_SET_MESSAGE_INTERRUPT_ROUTING;

typedef
_Function_class_(TIMER_CHANGE_LOSSLESS_RATE)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
ULONG
TIMER_CHANGE_LOSSLESS_RATE (
    _In_ PVOID TimerData,
    _In_ ULONGLONG NewTickCount
    );

/*++

Routine Description:

    This routine changes the rate of a timer that is already operating in
    periodic mode. If this function is implemented, it must support changing
    the periodic interrupt rate without introducing any delay/skew during the
    programming of the new rate. Currently only deadline-based timers are known
    to support this capability. This function should not be implemented if not
    supported, and is mandatory for timers that advertise support for this
    capability.

Arguments:

    TimerData - Supplies a pointer to the timer's private context, whose
        initial content was supplied when the timer was registered.

    NewTickCount - Supplies the new periodic rate, in hardware counter
        ticks.

Return Value:

    Returns the number of interrupts that will occur at the old rate.
    Usually the equivalent of the "periodic interval" register is buffered in
    hardware, this is mechanism the HAL extension can use to indicate that the
    rate change is buffered and the 'depth' of that buffer.

--*/

typedef TIMER_CHANGE_LOSSLESS_RATE *PTIMER_CHANGE_LOSSLESS_RATE;

typedef
_Function_class_(TIMER_SET_INTERRUPT_VECTOR)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
VOID
TIMER_SET_INTERRUPT_VECTOR (
    _In_ PVOID TimerData,
    _In_ ULONG Vector
    );

/*++

Routine Description:

    This routine informs the timer of the vector it's going to be generating
    interrupts on. Most timers do not need to implement this function, it is
    only necessary for timers built in to interrupt controllers.

Arguments:

    TimerData - Supplies a pointer to the timer's private context, whose
        initial content was supplied when the timer was registered.

    Vector - Supplies the vector that the timer should configure itself to
        generate interrupts on.

Return Value:

    None.

--*/

typedef TIMER_SET_INTERRUPT_VECTOR *PTIMER_SET_INTERRUPT_VECTOR;

typedef
_Function_class_(TIMER_FIXED_STALL)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
ULONGLONG
TIMER_FIXED_STALL (
    _In_ PVOID TimerData,
    _In_ ULONGLONG MinimumStallIn100ns
    );

/*++

Routine Description:

    This routine accurately stalls execution for timers that cannot directly
    expose the timer's counter. This routine is used when the timer is capable
    of being an accurate stall source but its counter is unreadable or its
    stall durations cannot be arbitrary lengths of time. An example of this is
    the CMOS RTC on the PC, which can generate accurate stalls of 1Hz by
    polling the "Update In Progress" bit. This routine will always be called
    twice in immediate succession: once to allow the timer to potentially
    adjust to its fixed-stall cadence, and then once to actually perform the
    stall. The return value from the first call is always ignored. This routine
    is only used once during boot to measure the frequency of the processor if
    no other timers with known frequencies are available. All interrupts are
    disabled at this time. It is not used during normal stall execution calls,
    for that a readable counter is used.

Arguments:

    TimerData - Supplies a pointer to the timer's private context, whose
        initial content was supplied when the timer was registered.

    MinimumStallIn100ns - Supplies the minimum amount of time to stall for in
        100 nanosecond units (10^-7 seconds), or 0 to indicate this is the
        "warm-up" call to allow the timer to adjust to its potentially fixed
        stall cadence. When this parameter is 0, the return value of this
        routine is ignored.

Return Value:

    This routine should return 0 if 0 is passed into the minimum stall
    duration.

    Returns the number of 100ns units that the stall lasted. This number should
    be no less than the minimum stall parameter.

--*/

typedef TIMER_FIXED_STALL *PTIMER_FIXED_STALL;

typedef
_Function_class_(TIMER_STOP)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
VOID
TIMER_STOP (
    _In_ PVOID TimerData
    );

/*++

Routine Description:

    This routine stops a timer from ticking. After this function returns, the
    timer should not generate any more interrupts, and reads to its counter
    might return the same value every time.

Arguments:

    TimerData - Supplies a pointer to the timer's private context, whose
        initial content was supplied when the timer was registered.

Return Value:

    None, this function must succeed.

--*/

typedef TIMER_STOP *PTIMER_STOP;

typedef struct _TIMER_FUNCTION_TABLE {
    PTIMER_INITIALIZE Initialize;
    PTIMER_QUERY_COUNTER QueryCounter;
    PTIMER_ACKNOWLEDGE_INTERRUPT AcknowledgeInterrupt;
    PTIMER_ARM_TIMER ArmTimer;
    PTIMER_STOP Stop;
    PTIMER_SET_DIVISOR SetDivisor;
    PTIMER_SET_MESSAGE_INTERRUPT_ROUTING SetMessageInterruptRouting;
    PTIMER_CHANGE_LOSSLESS_RATE LosslessRateChange;
    PTIMER_SET_INTERRUPT_VECTOR SetInterruptVector;
    PTIMER_FIXED_STALL FixedStall;
} TIMER_FUNCTION_TABLE, *PTIMER_FUNCTION_TABLE;

/*++

Timer Function Table Description :

    Exposes a set of basic operations that can be performed on timer hardware.
    For a detailed explanation of each function, see the definition of each
    member's type.

Fields:

    Initialize - Stores a pointer to the initialization function, which performs
        any actions necessary to get the timer to an operable state.

    QueryCounter - Stores a pointer to the query count routine, which returns
        the current hardware counter value.

    AcknowledgeInterrupt - Stores a pointer to the acknowledge interrupt
        routine, which performs any actions necessary to quiesce an interrupt.

    ArmTimer - Stores a pointer to the timer arming routine, which programs the
        timer to fire an interrupt after the specified number of ticks (if
        supported).

    Stop - Stores a pointer to a function that stops the timer.

    SetDivisor - Stores a pointer to the set divisor routine, which reprograms
        the hardware counter's divisor rate.

    SetMessageInterruptRouting - Stores a pointer to the routine for
        configuring a timer to generate message based interrupts. This function
        only needs to be implemented for timers that have indicated they can
        generate MSIs.

    LosslessRateChange - Stores a pointer to the routine that allows the
        system to change the clock rate without introducing timer programming
        delay.

    SetInterruptVector - Stores a pointer to the routine that configures the
        timer to generate an interrupt at a certain vector.

    FixedStall - Stores a pointer to the routine that generates stalls of
        fixed increments of time.

--*/

typedef struct _TIMER_INTERRUPT {
    LONG LegacyIrq;
    LONG Gsi;
    KINTERRUPT_POLARITY Polarity;
    KINTERRUPT_MODE Mode;
} TIMER_INTERRUPT, *PTIMER_INTERRUPT;

/*++

Timer Interrupt Block Description:

    Stores the information required to describe a timer's interrupt.

Fields:

    LegacyIrq - Stores the IRQ pin the timer's interrupt comes in on if it
        generates interrupts on a legacy 8259 interrupt controller.

    Gsi - Stores the global system interrupt number of the interrupt this timer
        generates, if it generates line-based interrupts.

    Polarity - Stores the polarity of the interrupt this timer generates, if it
        generates interrupts.

    Mode - Stores whether or not this timer generates edge or levelctriggered
        interrupts, if it generates interrupts at all.

--*/

typedef struct _TIMER_INITIALIZATION_BLOCK {
    SOC_INITIALIZATION_HEADER Header;
    TIMER_FUNCTION_TABLE FunctionTable;
    PVOID InternalData;
    ULONG InternalDataSize;
    ULONG CounterBitWidth;
    ULONGLONG CounterFrequency;
    ULONG MaxDivisor;
    ULONG Capabilities;
    TIMER_INTERRUPT Interrupt;
    KNOWN_TIMER_TYPE KnownType;
    ULONG Identifier;
} TIMER_INITIALIZATION_BLOCK, *PTIMER_INITIALIZATION_BLOCK;

/*++

Timer Initialization Block Description:

    Stores the information required of the timer module by the HAL for the HAL
    to register a new timer source.

Fields:

    Header - Stores the structure size and version number. Do not fill in these
        members directly. Use the INITIALIZE_TIMER_HEADER macro to ensure these
        values are set correctly. Pass a pointer to the
        TIMER_INITIALIZATION_BLOCK as the only argument to the macro. The HAL
        will fail the registration call if it does not recognize this header.

    FunctionTable - Stores pointers to all implemented timer functions. The HAL
        will call these functions to interact with the timer extension during
        the initialization, use, and shutdown phases. Not all functions are
        mandatory, the mandatory functions are governed by which capabilities
        are set.

    InternalData - Stores a pointer to the initial value of the timer's
        internal data. This pointer is not referenced after the call to
        register the timer returns, as it is assumed to be a pointer to a local
        variable. A copy of this data is made and passed to the extension on
        each function call.

    InternalDataSize - Stores the number of bytes in the internal data
        structure. The contents of the Internal Data are never read or
        interpreted by the HAL. This allocation size is expected to be only a
        few bytes, allocating too much space may cause the system not to boot
        due to the limited ability to allocate memory before the memory manager
        is online.

    CounterBitWidth - Stores the number of bits in the timer's internal counter.
        Even if the timer's counter is not directly accessible to the HAL or
        the extension, this parameter must be filled in, as it is used in
        calculations for arming the timer and configuring its divisor.

    CounterFrequency - Stores the frequency of the counter, in Hertz. Even if
        the timer's counter is not directly accessible to the HAL or the
        extension, this parameter must be filled in, as it is used in
        calculations for arming the timer and configuring its divisor. If the
        timer is variant, this must be set to its fastest speed. This parameter
        may be set to 0 to indicate that the HAL extension does not have
        enough information to determine the counter's frequency. The HAL will
        then use another registered timer whose frequency parameter is filled
        in or the processor cycle counter itself to measure the frequency of
        this timer. This measured frequency is never reported back to the HAL
        extension, as the HAL arms the timer in terms of "ticks", not seconds.

    MaxDivisor - Stores the highest counter divisor supported by the hardware.
        Some timers implement a divisor on the input clock that drives the
        counter. Setting the divisor to 2 for instance causes the counter to
        count at half its normal frequency. If the timer can be configured at
        runtime for an arbitrary power of 2 divisor between 1 and N, then the
        MaxDivisor field can be set to N. The HAL may attempt to change the
        divisor after the timer has been initialized to any power of 2 between
        1 and MaxDivisor. If the timer does not implement a power of 2 divisor,
        set this field to 1. The HAL assumes that the initial divisor
        configured in the timer at initialization is 1.

    Capabilities - Stores the capabilities of the current timer, such as the
        ability to generate interrupts, the ability to have its counter read or
        written, etc.

    Interrupt - Stores information about the interrupt this timer generates,
        if applicable.

    KnownType - Stores an identifier that marks this as a known timer type to
        the HAL. The HAL may choose to make certain decisions differently if it
        is familiar with this type of timer.

    Identifier - Stores a 32-bit integer used to uniquely identify this timer.
        Set this to the same value as the UID for the Resource Descriptor.

--*/

// end_ntoshvp

typedef enum _DMA_INTERRUPT_TYPE {
    InterruptTypeCompletion,
    InterruptTypeError,
    InterruptTypeCancelled
} DMA_INTERRUPT_TYPE, *PDMA_INTERRUPT_TYPE;

typedef struct _DMA_REQUEST_LINE_BINDING_DESCRIPTION {
    ULONG RequestLine;
    ULONG ChannelNumber;
} DMA_REQUEST_LINE_BINDING_DESCRIPTION, *PDMA_REQUEST_LINE_BINDING_DESCRIPTION;

typedef struct _DMA_SCATTER_GATHER_ELEMENT {
    PHYSICAL_ADDRESS Address;
    ULONG Length;
    ULONG_PTR Reserved;
} DMA_SCATTER_GATHER_ELEMENT, *PDMA_SCATTER_GATHER_ELEMENT;

#pragma warning(push)
#pragma warning(disable:4200)

typedef struct _DMA_SCATTER_GATHER_LIST {
    ULONG NumberOfElements;
    ULONG_PTR Reserved;
    SCATTER_GATHER_ELEMENT Elements[];
} DMA_SCATTER_GATHER_LIST, *PDMA_SCATTER_GATHER_LIST;

#pragma warning(pop)

//
// Prototypes for routines used by DMA extension modules.
//

typedef
_Function_class_(DMA_INITIALIZE_CONTROLLER)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
VOID
DMA_INITIALIZE_CONTROLLER (
    _In_ PVOID ControllerContext
    );

/*++

Routine Description:

    This routine provides an opportunity for DMA controllers to initialize.

Arguments:

    ControllerContext - Supplies a pointer to the controller's internel data.

Return Value:

    None.

--*/

typedef DMA_INITIALIZE_CONTROLLER *PDMA_INITIALIZE_CONTROLLER;

typedef
_Function_class_(DMA_VALIDATE_REQUEST_LINE_BINDING)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
BOOLEAN
DMA_VALIDATE_REQUEST_LINE_BINDING (
    _In_ PVOID ControllerContext,
    _In_ PDMA_REQUEST_LINE_BINDING_DESCRIPTION BindingDescription
    );

/*++

Routine Description:

    This routine queries a DMA controller extension to test the validity of a
    request line binding.

Arguments:

    ControllerContext - Supplies a pointer to the controller's internal data.

    DeviceDescription - Supplies a pointer to the request information.

Return Value:

    TRUE if the request line binding is valid and supported by the controller.

    FALSE if the binding is invalid.

Environment:

    PASSIVE_LEVEL.

--*/

typedef DMA_VALIDATE_REQUEST_LINE_BINDING *PDMA_VALIDATE_REQUEST_LINE_BINDING;

typedef
_Function_class_(DMA_QUERY_MAX_FRAGMENTS)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
ULONG
DMA_QUERY_MAX_FRAGMENTS (
    _In_ PVOID ControllerContext,
    _In_ ULONG ChannelNumber,
    _In_ ULONG MaxFragmentsRequested
    );

/*++

Routine Description:

    This routine queries the DMA extension to determine the number of
    scatter gather fragments that the next transfer can support.

Arguments:

    ControllerContext - Supplies a pointer to the controller's internal data.

    ChannelNumber - Supplies the number of the channel to program.

    MaxFragmentsRequested - Supplies a hint to the maximum fragments useful to
        this transfer.

Return Value:

    Number of fragments the next transfer on this channel can support.

--*/

typedef DMA_QUERY_MAX_FRAGMENTS *PDMA_QUERY_MAX_FRAGMENTS;

typedef
_Function_class_(DMA_PROGRAM_CHANNEL)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
VOID
DMA_PROGRAM_CHANNEL (
    _In_ PVOID ControllerContext,
    _In_ ULONG ChannelNumber,
    _In_ ULONG RequestLine,
    _In_ PDMA_SCATTER_GATHER_LIST MemoryAddress,
    _In_ PHYSICAL_ADDRESS DeviceAddress,
    _In_ BOOLEAN WriteToDevice,
    _In_ BOOLEAN LoopTransfer
    );

/*++

Routine Description:

    This routine programs a DMA controller channel for a specific transfer.

Arguments:

    ControllerContext - Supplies a pointer to the controller's internal data.

    ChannelNumber - Supplies the number of the channel to program.

    RequestLine - Supplies the request line number to program.  This request
        line number is system-unique (as provided to the HAL during
        registration) and must be translated by the extension.

    MemoryAddress - Supplies the address to be programmed into the memory
        side of the channel configuration.

    DeviceAddress - Supplies the address to be programmed into the device
        side of the channel configuration.

    WriteToDevice - Supplies the direction of the transfer.

    LoopTransfer - Supplies whether AutoInitialize has been set in the
        adapter making this request.

Return Value:

    None.

--*/

typedef DMA_PROGRAM_CHANNEL *PDMA_PROGRAM_CHANNEL;

typedef
_Function_class_(DMA_CONFIGURE_CHANNEL)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
NTSTATUS
DMA_CONFIGURE_CHANNEL (
    _In_ PVOID ControllerContext,
    _In_ ULONG ChannelNumber,
    _In_ ULONG FunctionNumber,
    _In_ PVOID Context
    );

/*++

Routine Description:

    This routine configures the channel for a DMA extension specific operation.

Arguments:

    ControllerContext - Supplies a pointer to the controller's internal data.

    ChannelNumber - Supplies the channel to configure.

    FunctionNumber - Supplies the ID of the operation to perform.

    Context - Supplies parameters for this operation.

Return Value:

    NTSTATUS code.

--*/

typedef DMA_CONFIGURE_CHANNEL *PDMA_CONFIGURE_CHANNEL;

typedef
_Function_class_(DMA_FLUSH_CHANNEL)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
VOID
DMA_FLUSH_CHANNEL (
    _In_ PVOID ControllerContext,
    _In_ ULONG ChannelNumber
    );

/*++

Routine Description:

    This routine resets the state of a channel and returns the
    channel to a state ready for the next ProgramChannel call.

Arguments:

    ControllerContext - Supplies a pointer to the controller's internal data.

    ChannelNumber - Supplies the channel to flush.

Return Value:

    None.

--*/

typedef DMA_FLUSH_CHANNEL *PDMA_FLUSH_CHANNEL;

typedef
_Function_class_(DMA_HANDLE_INTERRUPT)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
BOOLEAN
DMA_HANDLE_INTERRUPT (
    _In_ PVOID ControllerContext,
    _Out_ PULONG ChannelNumber,
    _Out_ PDMA_INTERRUPT_TYPE InterruptType
    );

/*++

Routine Description:

    This routine probes a controller for interrupts, clears any interrupts
    found, fills in channel and interrupt type information.  This routine
    will be called repeatedly until FALSE is returned.

Arguments:

    ControllerContext - Supplies a pointer to the controller's internal data.

    ChannelNumber - Supplies a placeholder for the extension to fill in which
        channel is interrupting.

    InterruptType - Supplies a placeholder for the extension to fill in the
        interrupt type.

Return Value:

    TRUE if an interrupt was found on this controller.

    FALSE otherwise.

--*/

typedef DMA_HANDLE_INTERRUPT *PDMA_HANDLE_INTERRUPT;

typedef
_Function_class_(DMA_READ_DMA_COUNTER)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
ULONG
DMA_READ_DMA_COUNTER (
    _In_ PVOID ControllerContext,
    _In_ ULONG ChannelNumber
    );

/*++

Routine Description:

    This routine determines how many bytes remain to be transferred on the
    given channel.  If the current transfer is set to loop, this routine
    will return the number of bytes remaining in the current iteration.

Arguments:

    ControllerContext - Supplies a pointer to the controller's internal data.

    ChannelNumber - Supplies the channel number.

Return Value:

    Returns the number of bytes remaining to be transferred on the given
    channel.

--*/

typedef DMA_READ_DMA_COUNTER *PDMA_READ_DMA_COUNTER;

typedef
_Function_class_(DMA_REPORT_COMMON_BUFFER)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
VOID
DMA_REPORT_COMMON_BUFFER (
    _In_ PVOID ControllerContext,
    _In_ ULONG ChannelNumber,
    _In_ PVOID VirtualAddress,
    _In_ PHYSICAL_ADDRESS LogicalAddress
    );

/*++

Routine Description:

    This routine allows the HAL to report to the extension information about
    a common buffer alloated on behalf of a channel.  This allocation is the
    result of a requirement listed in the channel initialization block.
    The buffer is non-cached.

Arguments:

    ControllerContext - Supplies a pointer to the controller's internal data.

    ChannelNumber - Supplies the channel number.

    VirtualAddress - Supplies the virtual address of the common buffer.

    LogicalAddress - Supplies the DMA controller visible address of the common
        buffer.

Return Value:

    None.

--*/

typedef DMA_REPORT_COMMON_BUFFER *PDMA_REPORT_COMMON_BUFFER;

typedef
_Function_class_(DMA_CANCEL_TRANSFER)
_IRQL_requires_same_
_IRQL_requires_max_(HIGH_LEVEL)
BOOLEAN
DMA_CANCEL_TRANSFER (
    _In_ PVOID ControllerContext,
    _In_ ULONG ChannelNumber
    );

/*++

Routine Description:

    This routine must disable the selected channel.  The channel must not be
    capable of interrupting for this transfer after being cleared in this way.

Arguments:

    ControllerContext - Supplies a pointer to the controller's internal data.

    ChannelNumber - Supplies the channel number.

Return Value:

    FALSE if the channel is already idle or if the channel is already asserting
    an interrupt.  TRUE is the channel is active and no interrupt is asserted.

--*/

typedef DMA_CANCEL_TRANSFER *PDMA_CANCEL_TRANSFER;

//
// Define the DMA Extension interface table.
//

typedef struct _DMA_FUNCTION_TABLE {
    PDMA_INITIALIZE_CONTROLLER InitializeController;
    PDMA_VALIDATE_REQUEST_LINE_BINDING ValidateRequestLineBinding;
    PDMA_QUERY_MAX_FRAGMENTS QueryMaxFragments;
    PDMA_PROGRAM_CHANNEL ProgramChannel;
    PDMA_CONFIGURE_CHANNEL ConfigureChannel;
    PDMA_FLUSH_CHANNEL FlushChannel;
    PDMA_HANDLE_INTERRUPT HandleInterrupt;
    PDMA_READ_DMA_COUNTER ReadDmaCounter;
    PDMA_REPORT_COMMON_BUFFER ReportCommonBuffer;
    PDMA_CANCEL_TRANSFER CancelTransfer;
} DMA_FUNCTION_TABLE, *PDMA_FUNCTION_TABLE;

/*++

DMA Function Table Description :

    Exposes a set of basic operations that can be performed by a DMA
    controller.

Fields:

    InitializeController - Perform any one-time initialization needed
        by the DMA controller.

    ValidateRequestLineBinding - Validate the request to bind a request
        line.

    ProgramChannel - Program a DMA channel and ready it for transfer.

    ConfigureChannel - Provides mechanism for DMA controller custom features.

    FlushChannel - Flushes the specified channel and returns the channel to a
        state ready to be programmed.

    HandleInterrupt - Probe DMA controller for interrupt.  Acknowledge the
        interrupt and return which channel interrupted.

    ReadDmaCounter - Determine how many bytes remain in a transfer on the given
        channel.  If the current transfer is set to loop, then this routine
        will return the number of bytes remaining in the current iteration.

    ReportCommonBuffer - This routine is optional iff all channels report a
        zero length common buffer requirement.  This routine is called by
        the HAL to report the virtual and logical addresses of a common buffer
        usable by the DMA controller channel.

--*/

typedef struct _DMA_INITIALIZATION_BLOCK {
    SOC_INITIALIZATION_HEADER Header;
    ULONG ControllerId;
    ULONG ChannelCount;
    BOOLEAN CacheCoherent;
    ULONG DmaAddressWidth;
    ULONG SupportedPortWidths;
    ULONG MinimumTransferUnit;
    ULONG MinimumRequestLine;
    ULONG MaximumRequestLine;
    BOOLEAN GeneratesInterrupt;
    LONG Gsi;
    KINTERRUPT_POLARITY InterruptPolarity;
    KINTERRUPT_MODE InterruptMode;
    PVOID InternalData;
    ULONG InternalDataSize;
    PDMA_FUNCTION_TABLE Operations;
} DMA_INITIALIZATION_BLOCK, *PDMA_INITIALIZATION_BLOCK;

/*++

DMA Controller Initialization Block Description:

    Stores the information required of the DMA controller module by the
    HAL for the HAL to register a new DMA controller unit.

Fields:

    ControllerId - System-wide unique ID identifying controller.

    ChannelCount - Number of channels supported by teh controller.

    CacheCoherent - Describes whether this controller is cache coherent.

    DmaAddressWidth - Describes the width of this controller's address bus.
        This determiens the maximum address accessible by this controller.

    SupportedPortWidths - Describes which wrapping modes are supported by this
        controller.  This is a bitfield.

    MaximumRequestLine - System-unique maximum request line supported by
        this controller.

    MinimumRequestLine - System-unique minimum request line supported by this
        controller.

    GeneratesInterrupt - Describes whether this controller generates an
        interrupt to signal DMA completion.

    Gsi - Stores the global system interrupt number of the interrupt this DMA
        controller generates, if it generates line-based interrupts.

    InterruptPolarity - Stores the polarity of the interrupt this DMA
        controller generates, if it generates interrupts.

    InterruptMode - Stores whether or not this DMA controller generates edge
        or level triggered interrupts, if it generates interrupts at all.

    InternalData - Stores a pointer to the individual DMA controller's
        internal data. This pointer is passed to the DMA controller
        module at each of its function table calls.

    InternalDataSize - Stores the size, in bytes, of the DMA module's
        internal data strucuture.

--*/

typedef struct _DMA_CHANNEL_INITIALIZATION_BLOCK {
    SOC_INITIALIZATION_HEADER Header;
    ULONG ControllerId;
    BOOLEAN GeneratesInterrupt;
    LONG Gsi;
    KINTERRUPT_POLARITY InterruptPolarity;
    KINTERRUPT_MODE InterruptMode;
    ULONG CommonBufferLength;
    ULONG ChannelNumber;
} DMA_CHANNEL_INITIALIZATION_BLOCK, *PDMA_CHANNEL_INITIALIZATION_BLOCK;

/*++

DMA Channel Initialization Block Description:

    Stores the information required of the DMA channel module by the
    HAL for the HAL to register a new DMA channel.

Fields:

    ControllerId - System-wide unique ID identifying controller which
        implements channel..

    GeneratesInterrupt - Describes whether this channel generates an
        interrupt to signal DMA completion.

    Gsi - Stores the global system interrupt number of the interrupt this DMA
        channel generates, if it generates line-based interrupts.

    InterruptPolarity - Stores the polarity of the interrupt this DMA channel
        generates, if it generates interrupts.

    InterruptMode - Stores whether or not this DMA channel generates edge or
        level triggered interrupts, if it generates interrupts at all.

    ChannelNumber - The number of the channel being described.  Channel numbers
        must be zero-based and not contain holes.

    CommonBufferLength - Allows the extension to specify that this channel
        requires a buffer accessible both by the extension and it's hardware.
        If this value is non-zero, the HAL will report virtual and logical
        addresses for this buffer to the extension with the ReportCommonBuffer
        routine.  If this value is non-zero, ReportCommonBuffer must be
        implemented.

--*/

//
// -------------------------------------------------------- Function Prototypes
//

//
// Functions exported from the HAL Extension to the HAL
//

NTSTATUS
AddResourceGroup (
    _In_ ULONG Handle,
    _In_ PCSRT_RESOURCE_GROUP_HEADER ResourceGroup
    );

/*++

Routine Description:

    This routine identifies and registers all of the Resource Descriptors
    in the specified Resource Group.

Arguments:

    Handle - Supplies the HAL Extension handle which must be passed to other
        HAL Extension APIs.

    ResourceGroup - Supplies a pointer to the Resource Group which the
        HAL Extension has been installed on.

Return Value:

    NTSTATUS code.

--*/

//
// Functions exported from the HAL to the HAL Extension
//

NTSTATUS
RegisterResourceDescriptor (
    _In_ ULONG Handle,
    _In_ PCSRT_RESOURCE_GROUP_HEADER ResourceGroup,
    _In_ PCSRT_RESOURCE_DESCRIPTOR_HEADER ResourceDescriptor,
    _In_opt_ PVOID ResourceDescriptorInfo
    );

/*++

Routine Description:

    This routine registers a Resource Descriptor, forwarding the request to
    the appropriate registration routine based on the Resource Descriptor type.

Arguments:

     Handle - Supplies the HAL Extension handle passed into the extension via
        AddResourceGroup.

    ResourceGroup - Supplies a pointer to the Resource Group passed into the
        extension via AddResourceGroup.

    ResourceDescriptor - Supplies a pointer to the Resource Descriptor
        to be registered.

    ResourceDescriptorInfo - Supplies a pointer to a resource-specific data
        structure.

Return Value:

    NTSTATUS code.

--*/

PCSRT_RESOURCE_DESCRIPTOR_HEADER
GetNextResourceDescriptor (
    _In_ ULONG Handle,
    _In_ PCSRT_RESOURCE_GROUP_HEADER ResourceGroup,
    _In_opt_ PCSRT_RESOURCE_DESCRIPTOR_HEADER ResourceDescriptor,
    _In_ USHORT ResourceType,
    _In_ USHORT ResourceSubtype,
    _In_ ULONG ResourceID
    );

/*++

Routine Description:

    This routine returns the next Resource Descriptor within a Resource Group,
    filtered by ResourceType and ResourceId.

Arguments:

    Handle - Supplies the HAL Extension handle passed into the extension via
       AddResourceGroup.

    ResourceGroup - Supplies a pointer to the Resource Group being enumerated.

    ResourceDescriptor - Supplies a pointer to the Resource Descriptor returned
        by the previous invocation of this API. This parameter should be set
        to NULL to start the iteration at the first Resource Descriptor.

    ResourceType - Supplies a filter specifying the Resource Type being
        requested. The value CSRT_RD_TYPE_ANY will match any Resource Type.

    ResourceSubtype - Supplies a filter specifying the Resource Subtype being
        requested. The value CSRT_RD_SUBTYPE_ANY will match any Resource Subtype.

    ResourceId - Supplies a filter specifying the Resource Id being
        requested. The value CSRT_RD_UID_ANY will match any Resource Id.

Return Value:

    A pointer to a Resource Descriptor, or NULL if no additional descriptors are
    available.

--*/

PVOID
GetAcpiTable (
    _In_ ULONG Handle,
    _In_ ULONG Signature,
    _In_opt_ PCSTR OemId,
    _In_opt_ PCSTR OemTableId
    );

/*++

Routine Description:

    This routine returns the requested ACPI table.

Arguments:

    Handle - Supplies the HAL Extension handle passed into the extension via
       AddResourceGroup.

    Signature - The signature of the table required by the caller.

    OemId - The optional OemId of the table required by the caller.

    OemTableId - The optional OemTableId of the table required by the caller.

Return Value:

    A pointer to the table requested by the caller, or NULL if the table doesn't
    exist.  The caller must under no circumstances attempt to free or unmap the
    memory referred to by the result of this function, as it is cached by the
    HAL.

--*/


PVOID
HalMapIoSpace (
    _In_ PHYSICAL_ADDRESS PhysicalAddress,
    _In_ SIZE_T NumberOfBytes,
    _In_ MEMORY_CACHING_TYPE CacheType
    );

/*++

Routine Description:

    This routine maps physical memory into the area of virtual memory
    reserved for the HAL.  It does this by directly inserting the PTE
    into the Page Table which the OS Loader has provided.

Arguments:

    PhysicalAddress - Supplies the physical address of the start of the
        area of physical memory to be mapped.

    NumberOfBytes - Supplies the number of bytes that should be mapped.

    CacheType - Supplies the caching attributes of the mapping.

Return Value:

    PVOID - Virtual address at which the requested block of physical memory
            was mapped

    NULL - The requested block of physical memory could not be mapped.

--*/

VOID
HalUnmapIoSpace (
    _In_ PVOID VirtualAddress,
    _In_ SIZE_T NumberOfBytes
    );

/*++

Routine Description:

    This routine unmaps a virtual address.

Arguments:

    VirtualAddress  - Supplies a valid virtual address to be unmapped.

    NumberOfBytes - Supplies the number of bytes to unmap.

Return Value:

    None.

--*/

NTSTATUS
HalRegisterPermanentAddressUsage (
    _In_ PHYSICAL_ADDRESS PhysicalAddress,
    _In_ ULONG SizeInBytes
    );

/*++

Routine Description:

    This routine permanently stakes out a piece of physical memory for use by
    the SoC module. This routine does not map that memory anywhere, it just
    claims it. This registration cannot be undone.

Arguments:

    PhysicalAddress - Supplies the physical address to register.

    SizeInBytes - Supplies the size of the physical allocation, in byte.

Return Value:

    STATUS_SUCCESS on success.

    STATUS_NO_MEMORY if the allocation could not be reserved.

    STATUS_TOO_LATE if the call is made after the HAL initialization phase is
    complete.

--*/

