Developer Reference

Intel® Graphics for Linux* - Programmer's Reference Manuals

ID 772629
Date 4/12/2022
Public
Document Table of Contents

GuC KMD API

/****************************************************************************************
** Copyright © 2016 Intel® Corporation
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and associated documentation files (the "Software"),
** to deal in the Software without restriction, including without limitation
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
** and/or sell copies of the Software, and to permit persons to whom the
** Software is furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice (including the next
** paragraph) shall be included in all copies or substantial portions of the
** Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
** IN THE SOFTWARE.
**
****************************************************************************************/

/****************************************************************************************
** File Name    : UkGuckmdInterface.h
**
** Description  : Definitions for GuC to KMD interface
**
** Environment  : GuC
**
** Notes:
**
****************************************************************************************/

#ifndef UK_GUC_KMD_INTEFACE_H
#define UK_GUC_KMD_INTEFACE_H
#if defined (_MSC_VER)  
    #pragma pack(push, 1)
#else
    #pragma pack(1)
#endif
#include "types.h"

typedef ULONG64 ADDRESS64;
typedef ULONG   ADDRESS32;

//*****************************************************************************
// MACRO: KM_BIT_RANGE
// PURPOSE: Calculates the number of bits between the startbit and the endbit 
// and count is inclusive of both bits. The bits are 0 based.
//*****************************************************************************
#ifndef KM_BIT_RANGE
#define KM_BIT_RANGE(endbit, startbit)     ((endbit)-(startbit)+1)

//*****************************************************************************
// MACRO: KM_BIT
// PURPOSE: Used for clarity when defining bit structs
//*****************************************************************************
#define KM_BIT(bit)     (1)

#endif

//***********************************************************************************************
// Struct:  Render Power Clock State register definition
// PURPOSE: KMD/GuC uses this definition to program Render Power Clock State register in ring context
//          at Exec List Submit Port time.
//***********************************************************************************************
typedef struct _KM_UK_RENDER_PWR_CLK_STATE
{
    union
    {
        struct 
        {
            // 0010: 2 EUs
            // 0100: 4 EUs
            // 0110: 6 EUs
            // 1000 :8 EUs 
            DWORD EUmin                  : KM_BIT_RANGE(3,0); // Minimum number of EUs to power (per subslice if multiple subslices enabled)
            DWORD EUmax                  : KM_BIT_RANGE(7,4); // Maximum number of EUs to power (per subslice if multiple subslices enabled).
            //  To specify an exact number of subslices, set EUmax equal to EUmin

            // Number of subslices to power:
            // 001: 1 subslice
            // 010: 2 subslices
            // 011: 3 subslices
            // BXT only! This MBZ for SKL!
            DWORD SScount                : KM_BIT_RANGE(10,8); // sub-slice count
        
            // BXT only! This MBZ for SKL!
            DWORD SScountEn              : KM_BIT_RANGE(11,11); // Enable Subslice Count Request (1 = Use SliceCount from this register)

            DWORD                        : KM_BIT_RANGE(14,12); 

            // SKL only! This  MBZ for BXT!
            DWORD SliceCount             : KM_BIT_RANGE(17,15);
            // SKL only! This  MBZ for BXT!
            DWORD SCountEn               : KM_BIT_RANGE(18,18);

            DWORD                        : KM_BIT_RANGE(30,19);

            // Main trigger: Power Clock State Enable
            //  0: No specific power state set, no message/wait with PMunit
            //  1: CSunit sends the contents of this register to PMunit each time it is written, Send contents of this register to PMunit, wait for Ack.
            DWORD PowerClkStateEn        : KM_BIT_RANGE(31,31);
        };

        DWORD Data;
    };
}KM_UK_RENDER_PWR_CLK_STATE;

//*****************************************************************************
// Enum:  IGFX_ENGINE
// PURPOSE: Engine IDs available in the GFX HW
//*****************************************************************************
typedef enum
{
    // The Enum values are important as some macros and loops depend on them being sequential
    IGFX_RENDER_ENGINE       = 0,
    IGFX_VIDEO_ENGINE        = 1,
    IGFX_BLITTER_ENGINE      = 2,
    IGFX_VIDEOENHANCE_ENGINE = 3,
    IGFX_VIDEO_ENGINE2       = 4,
    IGFX_ABSOLUTE_MAX_ENGINES,
    IGFX_ENGINE_INVALID = IGFX_ABSOLUTE_MAX_ENGINES
}IGFX_ENGINE;


//*****************************************************************************
// Enum:  UK_ENGINES_USED
// PURPOSE: A bit flag for each engines used. Used for making some memory optimizations.
//*****************************************************************************
typedef struct UK_ENGINES_USED_REC
{
  union
  {
    struct 
    {
     // This sequence of engines (i.e bit positions) must match the corresponding IGFX_ENGINE enum value,
     UCHAR      RenderEngine      : KM_BIT       (   0 );
     UCHAR      VideoEngine       : KM_BIT       (   1 );
     UCHAR      BltEngine         : KM_BIT       (   2 );
     UCHAR      VEEngine          : KM_BIT       (   3 );
     UCHAR      VideoEngine2      : KM_BIT       (   4 );
     UCHAR                        : KM_BIT_RANGE (7, 5 );
    };
    UCHAR Value;
  };
} IGFX_ENGINES_USED;

//*****************************************************************************
// Enum:  UK_QUEUE_STATUS
// PURPOSE:  to indicate the status of a Micro Kernel's Work/Submit Queue.
//  TBD: Define what state means what...
//*****************************************************************************
typedef enum
{
    UK_QSTATUS_ACTIVE           = 1,    //Work queue will be serviced if doorbell is owned by app
    UK_QSTATUS_SUSPENDED        ,       //Work queue will not be serviced.
    UK_QSTATUS_CMD_ERROR        ,       //Error in work queue
    UK_QUEUE_STATUS_ENGINE_ID_NOT_USED,
    UK_QSTATUS_SUSPENDED_FROM_ENGINE_RESET, //Suspended due to engine reset. App must consider all work before WQ tail as in error and resubmit necessary work.
    UK_QSTATUS_INVALID_STATUS   
}UK_QUEUE_STATUS;


//*****************************************************************************
// Enum:  UK_CONTEXT_PRIORITY
// PURPOSE:  To indicate the priority of UK context.
//*****************************************************************************
typedef enum
{
    UK_CONTEXT_PRIORITY_KMD_HIGH     = 0,    // KMD priority is only for SKL+ 
    UK_CONTEXT_PRIORITY_HIGH         = 1,
    UK_CONTEXT_PRIORITY_KMD_NORMAL   = 2,    // KMD priority is only for SKL+ 
    UK_CONTEXT_PRIORITY_NORMAL       = 3,
    UK_CONTEXT_PRIORITY_ABSOLUTE_MAX_COUNT ,
    UK_CONTEXT_PRIORITY_INVALID            = UK_CONTEXT_PRIORITY_ABSOLUTE_MAX_COUNT
}UK_CONTEXT_PRIORITY;

#define UK_BDW_MAX_PRIORITIES (2)
#define UK_SKL_MAX_PRIORITIES (4)

//*****************************************************************************
// Enum:  UK_ENGINE_EXECLIST_CONTEXT
// PURPOSE:  State of the context - this is per engine.
//*****************************************************************************
typedef struct UK_ENGINE_CONTEXT_STATE_REC
{
    union
    {
        struct 
        {
            UCHAR    Submitted     : KM_BIT      (      0);
            UCHAR                  : KM_BIT_RANGE(  7,  1);
        };
        UCHAR SubmitValue;
    };
    union
    {
        struct 
        {
            UCHAR    WaitForDisplayEvent    : KM_BIT      (      0);
            UCHAR    WaitForSemaphore       : KM_BIT      (      1);
            UCHAR    WaitForFaultFulfill    : KM_BIT      (      2);
            UCHAR    CATError               : KM_BIT      (      3);
            UCHAR    ReEnqueueToSubmitQueue : KM_BIT      (      4);
            UCHAR                           : KM_BIT_RANGE(  7,  5);
        };
        UCHAR WaitValue;
    };

} UK_ENGINE_CONTEXT_STATE;

//*****************************************************************************
// Enum:  UK_SCHED_INSTRUCTION_TYPE
// PURPOSE:  These are instructions to the scheduler
//*****************************************************************************
typedef enum
{
    SCHED_INSTRUCTION_BATCH_BUFFER_START = 0x1,
    SCHED_INSTRUCTION_GUC_CMD_PSEUDO     = 0x2,
    SCHED_INSTRUCTION_GUC_CMD_KMD        = 0x3,  // This work item is issued by KMD (Windows mode)
    SCHED_INSTRUCTION_GUC_CMD_NOOP       = 0x4,  // Treat data following this WI header as no op (i.e. skip it). uKernel will not read the data.
    SCHED_INSTRUCTION_INVALID                 ,  // This must be the last-1 entry
    SCHED_INSTRUCTION_MAX                = 0xF,  // Currently this is the max value
}UK_SCHED_INSTRUCTION_TYPE;

//*****************************************************************************
// Enum:  UK_SCHED_WORK_QUEUE_WORKLOAD_TYPE
// PURPOSE:  Workload type information.
//*****************************************************************************
typedef enum
{
    SCHED_WORK_QUEUE_GENERAL_WORKLOAD   = 0,
    SCHED_WORK_QUEUE_GPGPU_WORKLOAD,
    SCHED_WORK_QUEUE_TOUCH_WORKLOAD,

    SCHED_WORK_QUEUE_MAX_WORKLOADS
}UK_SCHED_WORK_QUEUE_WORKLOAD_TYPE;

//*****************************************************************************
// Enum:  UK_SCHED_WORK_QUEUE_ITEM_HEADER
// PURPOSE: Header for every work item put in the work queue
//*****************************************************************************
typedef struct UK_SCHED_WORK_QUEUE_ITEM_HEADER_REC
{ 
    union
    {
      struct
       {
        ULONG  WorkInstructionType        : KM_BIT_RANGE( 7,  0); //UK_SCHED_INSTRUCTION_TYPE
        ULONG                             : KM_BIT_RANGE( 9,  8); //MBZ
        ULONG  TargetEngine               : KM_BIT_RANGE(13, 10); //IGFX_ENGINE
        ULONG                             : KM_BIT_RANGE(15, 14); //MBZ
        ULONG  CommandLengthDwords        : KM_BIT_RANGE(26, 16); //Length in number of Dwords following this header
        ULONG  DoNotInsertWCFlushWait     : KM_BIT_RANGE(27, 27);
        ULONG  IsPresentWorkload          : KM_BIT_RANGE(28, 28);
        ULONG  WorkloadType               : KM_BIT_RANGE(31, 29); // Enum UK_SCHED_WORK_QUEUE_WORKLOAD_TYPE
        //ULONG                             : KM_BIT_RANGE(31, 30); //Ignored on production build. On debug, UMD can use to put tracking number (16 max)
       };
      ULONG Value;
    };

}UK_SCHED_WORK_QUEUE_ITEM_HEADER;

//INFO: Work Queue Item
//
//              Work Queue Item
// V---------------------------------------V
// *****************************************
// *                   *                   *
// * WQ Item Header    *     Commands      *    
// *****************************************
// Commands are variable length so not included in any structure.


#define UK_MAX_WORK_QUEUE_ITEMS (128)
//Max size of WI (including header). This is used for security checks.
//If a single WI size increases more than this size, we need to evaluate use cases to increase this define 
#define UK_MAX_WI_SIZE_IN_DW (16) 
//*****************************************************************************
// Struct:  UK_KM_APP_DOORBELL_INFO
// PURPOSE: Doorbell cacheline description
//*****************************************************************************
typedef struct UK_KM_APP_DOORBELL_INFO_REC
{
        struct
        {
            ULONG      DoorBellStatus;    // 0 / 1
            ULONG      Cookie;            // Only KMD/uKernel should write 0 here. App should rollover to 1.
            ULONG      Reserved[14];      // Rest of the cache line.
        };
 
}UK_KM_APP_DOORBELL_INFO;

//*****************************************************************************
// Struct:  UK_DOORBELL_QW
// PURPOSE: Doorbell QW description
//*****************************************************************************
typedef struct UK_DOORBELL_QW_REC
{
    union
    {
        struct
        {
            ULONG      DoorBellStatus;    // 0 / 1
            ULONG      Cookie;            // Only KMD/uKernel should write 0 here. App should rollover to 1.
        };
        ULONG64 QuadPart;
    };
 
}UK_DOORBELL_QW;
#define KM_DOORBELL_ENABLED (1)
#define KM_DOORBELL_DISABLED (0)


//*****************************************************************************
// Struct:  SCHED_CONTEXT_ENGINE_PRESENCE
// PURPOSE: Per Context Engine Status
//*****************************************************************************
typedef struct SCHED_CONTEXT_ENGINE_PRESENCE_STRUCT
{
   union
   {
       struct
       {
           ULONG        IsContextInRcsSubmitQueue       : KM_BIT      (   0);
           ULONG        IsContextInVcsSubmitQueue       : KM_BIT      (   1);
           ULONG        IsContextInBcsSubmitQueue       : KM_BIT      (   2);
           ULONG        IsContextInVecsSubmitQueue      : KM_BIT      (   3);
           ULONG        IsContextInVcs2SubmitQueue      : KM_BIT      (   4);
           ULONG                                        : KM_BIT_RANGE(30,5);
           ULONG                                        : KM_BIT      (  31);   //Used to be IsSubmitQueueElementValid
       };
       ULONG    SubmitQueuePresenceValue;
   };
 
}SCHED_CONTEXT_ENGINE_PRESENCE;


//*****************************************************************************
// Struct:  UK_SCHED_PROCESS_DESCRIPTOR
// PURPOSE: A shared structure between app and uKernel communication.
//*****************************************************************************
typedef struct UK_SCHED_PROCESS_DESCRIPTOR_REC
{
   ULONG              ContextId;
   // Trigger / doorbell address for App - Reserved in uK space
   ADDRESS64          pDoorbell;                         // For Read-Write access by App. Ptr to UK_KM_APP_DOORBELL_INFO
   ULONG              HeadOffset;                        // Byte Offset - App must not write here.
   ULONG              TailOffset;                        // Byte Offset - uKernel will not write here.
   ULONG              ErrorOffsetByte;
   ADDRESS64          WQVBaseAddress;                    // pVirt in app - for use only by application
   ULONG              WQSizeBytes;
   UK_QUEUE_STATUS    WQStatus;                          // Read by App. Written by uKernel/KMD.
   SCHED_CONTEXT_ENGINE_PRESENCE  ContextEnginePresence; // Read by App. Written by uKernel. A snapshot of context descriptor's copy. Updates only at Context Complete and WI Process complete.
   UK_CONTEXT_PRIORITY PriorityAssigned;                 // Read only by app
   ULONG               Reserved[4];                      // Reserved
   
   //Tracking variables for debug
   ULONG              WorkItemTrackingEnabled;           // Status set by KMD, Read only for App. For speed reasons, tracking is enabled for all contexts or none.
   ULONG              AppTotalNumberOfWorkItemsAdded;    // App must set to 0 upon return from OpenGPU, before using it. Written only by Application - Total number of Work Items added to WQ so far (all Engines, monotonic increase)
   ULONG              AppReserved2[3];

   //uKernel side tracking for debug
   ULONG              TotalWorkItemsParsedByGuC;         // Written by uKernel at the time of parsing and successfull removed from WQ (implies ring tail was updated).
   ULONG              TotalWorkItemsCollapsedByGuC;      // Written by uKernel if a WI was collapsed if next WI is the same LRCA (optimization applies only to Secure/KMD contexts)
   ULONG              TotalWorkItemsCancelled;           // Written by uKernel if a WI was cancelled due to preempt.
   
   ULONG              IsContextInEngineReset;            // Tells if the context is affected in Engine Reset. UMD needs to clear it after taking appropriate Action(TBD).
   ULONG              EngineResetSampledWQTail;          // WQ Sampled tail at Engine Reset Time. Valid only if IsContextInEngineReset = TRUE
   ULONG              EngineResetSampledWQTailValid;     // Valid from Engine reset until all the affected Work Items are processed.
   ULONG              GuCReserved3[15];                  // Reserved

}UK_SCHED_PROCESS_DESCRIPTOR;

#define KM_MAX_PDP_REGISTERS    (4)
#define KM_PDP_REGISTER_DWORDS  (2)

#define MAX_GUC_GPU_CONTEXTS (1024)
#define MAX_GUC_BLOCKS_OF_16_GPU_CONTEXTS (64)
#define KM_GUC_INVALID_CONTEXT_ID (MAX_GUC_GPU_CONTEXTS)

//**************************************************************************************
// Struct:  KM_UK_POWER_GATING_TRANSPORT_STATE
// PURPOSE: Transport current programmed and requested power gating states in shared context
//**************************************************************************************
typedef struct KM_UK_POWER_GATING_TRANSPORT_STATE_REC
{
    KM_UK_RENDER_PWR_CLK_STATE CurrentState;
    KM_UK_RENDER_PWR_CLK_STATE RequestedState;

}KM_UK_POWER_GATING_TRANSPORT_STATE;

//*****************************************************************************
// Enum:  KM_PAGE_FAULT_MODE
// PURPOSE: Page fault mode. Must match "Context Descriptor Format" in BSpec
//*****************************************************************************
typedef enum KM_PAGE_FAULT_MODE_ENUM
{
    KM_PAGE_FAULT_MODE_FAULT_HANG     = 0x0,
    KM_PAGE_FAULT_MODE_FAULT_WAIT     = 0x1,  //aka Fault and Halt
    KM_PAGE_FAULT_MODE_FAULT_STREAM   = 0x2,
    KM_PAGE_FAULT_MODE_FAULT_CONTINUE = 0x3,  //SKL+

}KM_PAGE_FAULT_MODE;

//*****************************************************************************
// Enum:  KM_CONTEXT_ADDRESSING_MODE
// PURPOSE: Describes Addressing Mode & Legacy Context. Must match "Context Descriptor Format" in BSpec
//*****************************************************************************
typedef enum KM_CONTEXT_ADDRESSING_MODE_ENUM
{
    KM_CONTEXT_ADDRESSING_MODE_INVALID                = 0x0,
    KM_CONTEXT_ADDRESSING_MODE_LEGACY_NO_64BIT_VA     = 0x1,  //Legacy & DOESN'T support any SVM features. (32bit PPGGTT)
    KM_CONTEXT_ADDRESSING_MODE_ADVANCED               = 0x2,  //Advanced context mode and supports SVM features
    KM_CONTEXT_ADDRESSING_MODE_LEGACY_WITH_64BIT_VA   = 0x3,  //Legacy & DOESN'T support any SVM features. (64bit PPGTT)

}KM_CONTEXT_ADDRESSING_MODE;

//*****************************************************************************
// Struct: UK_KM_ADDRESS
// PURPOSE: Used to hold ptr to CPU virtual address and Ptr to Ukernel address
//*****************************************************************************
typedef struct UK_KM_ADDRESS_REC
{
    ADDRESS64  pCpuAddress; //Cpu / big core address (virtual)
    ADDRESS32  pUkAddress;  //uKernel address (gfx)
}UK_KM_ADDRESS;

//*****************************************************************************
// Struct:  UK_CONTEXT_ID_MAP
// PURPOSE: To represent the context ID structure and execlist/submit queues
//*****************************************************************************
typedef struct UK_CONTEXT_ID_MAP_REC
{
    union
    {
        struct
        {
            ULONG    ContextIndex          : KM_BIT_RANGE(  19,  0);  // NOTE: This can be index in the app context pool in direct submission case or LRCA itself in proxy submission case
            ULONG    SubmissionByProxy     : KM_BIT_RANGE(  20, 20);  // If KMD or other context submitted this context. This means, ContextID is LRCA[31:20]
            ULONG    Reserved              : KM_BIT_RANGE(  22, 21);  // Required by HW
            ULONG    SWCounter             : KM_BIT_RANGE(  28, 23);  // Used for tracking IOMMU group resubmits (or if submit by proxy is true, lower 6 bits QWIndex).
            ULONG    EngineId              : KM_BIT_RANGE(  31, 29);
        };
        ULONG                        ContextIdDword;
    };

}UK_CONTEXT_ID_MAP;
#define CONTEXT_ID_MAP_SWCOUNTER_NUM_BITS (6)

//*****************************************************************************
// Struct:  SCHED_CONTEXT_DESCRIPTOR_LD_REC
// PURPOSE: The default setting for Context Descriptor Format to be set in UK_ELEMENT_DESC
//*****************************************************************************
typedef struct SCHED_ELEMENT_DESC_REC
{
   union
    {
        struct
        {
            ULONG    Valid                  : KM_BIT      (      0);
            ULONG    ForcePDRestore         : KM_BIT      (      1);  //Force Page Directory
            ULONG    ForceRestore           : KM_BIT      (      2);
            ULONG    CtxtAddrMode           : KM_BIT_RANGE(  4,  3);  //Addressing Mode & Legacy Context (KM_CONTEXT_ADDRESSING_MODE)
            ULONG    L3LLCCoherencySupport  : KM_BIT      (      5);
            ULONG    FaultSupportType       : KM_BIT_RANGE(  7,  6);  //Type: KM_PAGE_FAULT_MODE
            ULONG    Privilege              : KM_BIT      (      8);
            ULONG                           : KM_BIT_RANGE( 11,  9);
            ULONG    LRCA                   : KM_BIT_RANGE( 31,  12);
        };
        ULONG Value;
    };

}SCHED_CONTEXT_DESCRIPTOR_LD;

//*****************************************************************************
// Struct:  UK_ELEMENT_DESC
// PURPOSE: The Execution list's element descriptor. Also in Submit Queue
//*****************************************************************************
typedef struct UK_ELEMENT_DESC_REC
{
    union
    {
        SCHED_CONTEXT_DESCRIPTOR_LD ContextDesc;
    };

    union
    {
        struct
        {
            UK_CONTEXT_ID_MAP    ContextId;
        };

        ULONG    HighDW;
    };

}UK_ELEMENT_DESC;

// Bit-flags used for storing information about each saved register
typedef union KM_MMIO_REGISTER_FLAGS
{
    ULONG FlagsValue;
    struct
    {
        ULONG PowerCycle            : KM_BIT_RANGE(0 ,  0);    //Restore at power cycle
        ULONG Masked                : KM_BIT_RANGE(1 ,  1);    //Register is masked
        ULONG EngineReset           : KM_BIT_RANGE(2 ,  2);    //Restore at Engine Reset
        ULONG SaveDefaultValue      : KM_BIT_RANGE(3 ,  3);    //Save default at init time
        ULONG SaveCurrentValue      : KM_BIT_RANGE(4 ,  4);    //Save current value just before reset/sleep
        ULONG                       : KM_BIT_RANGE(31,  5);    //Reserved
    };
}KM_MMIO_REGISTER_FLAGS;

#define KM_REGSET_FLAG_FLAGS_NONE                 0x00000000
#define KM_REGSET_FLAG_POWERCYCLE                 0x00000001 //(__BIT(0))
#define KM_REGSET_FLAG_MASKED                     0x00000002 //(__BIT(1))
#define KM_REGSET_FLAG_ENGINERESET                0x00000004 //(__BIT(2))
#define KM_REGSET_FLAG_SAVE_DEFAULT_VALUE         0x00000008 //(__BIT(3))
#define KM_REGSET_FLAG_SAVE_CURRENT_VALUE         0x00000010 //(__BIT(4))

// Note: this value will need to be increased if any register set exceeds it
#define KM_REGSET_MAX_REGISTERS_PER_SET (25)

#define KM_MMIO_WHITE_LIST_MAX_OFFSETS 12
typedef struct KM_MMIO_WHITE_LIST_REC
{
    ULONG                   MmioStart;
    ULONG                   Offsets[KM_MMIO_WHITE_LIST_MAX_OFFSETS];
    ULONG                   Count;
} KM_MMIO_WHITE_LIST;

// Structure used for storing register offset, current value, default value
// and flags
typedef struct KM_MMIO_REGISTER_REC
{
    ULONG                    Offset;       // Register offset
    ULONG                    Value;        // Current value
    KM_MMIO_REGISTER_FLAGS   Flags;
} KM_MMIO_REGISTER;

// Structure describing register set
typedef struct KM_MMIO_REGISTER_SET_REC
{
    KM_MMIO_REGISTER           Registers[KM_REGSET_MAX_REGISTERS_PER_SET];
    BOOL                       RegisterValuesValid;
    ULONG                      NumberOfRegisters;
} KM_MMIO_REGISTER_SET;

// Structure describing collection of register sets
typedef struct KM_MMIO_REGISTER_STATE_REC
{
    KM_MMIO_REGISTER_SET    GlobalRegisters;                                     // Registers that are not specific to a node
    KM_MMIO_REGISTER_SET    NodeRegisters[IGFX_ABSOLUTE_MAX_ENGINES];            // Node specific registers
    KM_MMIO_WHITE_LIST      MMIOWhiteList[IGFX_ABSOLUTE_MAX_ENGINES];            // List of MMIO registers that are set as non privileged 
} KM_MMIO_REGISTER_STATE;

#define UK_MAX_GUC_S3_SAVE_SPACE_PAGES (10)
//*****************************************************************************
// Struct:  KM_GUC_ADDITIONAL_DATA_STRUCTS
// PURPOSE: Pointers to other data structures used for various operations
//*****************************************************************************
typedef struct KM_GUC_ADDITIONAL_DATA_STRUCTS_REC
{
    ADDRESS32               GfxAddressMMIORegisterState;                         //Gfx ptr to KM_MMIO_REGISTER_STATE. Size is IGFX_ABSOLUTE_MAX_ENGINES (Gfx address must be persistent for life of GuC)
    ADDRESS32               GfxPtrToGuCSStateSaveBuffer;                         //Max of UK_MAX_GUC_S3_SAVE_SPACE_PAGES (Persistent)
    ADDRESS32               GfxGoldenContextLRCA;                                //LRCA addresses of golden contexts; (Persistent)
    ADDRESS32               GfxSchedulerPolicies;                                //GFX addresses of SCHED_SCHEDULING_POLICIES; (non-Persistent, may be released after initial load), NULL or valid=0 flag value will cause default policies to be loaded.
    DWORD                   Reserved0[2];
    DWORD                   Reserved1;                            
    DWORD                   GoldenContextEngStateSizeInBytes[IGFX_ABSOLUTE_MAX_ENGINES];
    DWORD                   Reserved2[2];
    DWORD                   Reserved3[2]; 
}KM_GUC_ADDITIONAL_DATA_STRUCTS;

#define KM_KBYTES_TO_DWORD_COUNT(a)     ((a * 1024) / sizeof(DWORD))

#define KM_SCHED_MAX_SUBMIT_DATA_ENTRIES (64)
#define KM_SCHED_MAX_PREMPT_REPORT_ENTRIES (16)

//*****************************************************************************
// Struct:  KM_SCHED_SUBMIT_DATA
// PURPOSE: Currently Reserved. (Future: used for extended KMD - GuC Communication)
//*****************************************************************************
typedef struct KM_SCHED_SUBMIT_DATA_REC
{
   ULONG    Reserved[KM_SCHED_MAX_SUBMIT_DATA_ENTRIES];
   ULONG    MaxSubmitDataEntriesCount;        // MBZ - For future use.
   ULONG    SubmitDataFreeIndex;              // MBZ
}KM_SCHED_SUBMIT_DATA;

//*****************************************************************************
// Enum:  KM_SCHED_CONTEXT_AFFECTED_TYPE
// PURPOSE: To indicate how a context was affected when involved in preempt/reset
//*****************************************************************************
typedef enum KM_SCHED_CONTEXT_AFFECTED_TYPE_ENUM
{
    KM_SCHED_CONTEXT_AFFECTED_NONE    = 0x0,
    KM_SCHED_CONTEXT_AFFECTED_IN_HW_EXECUTION     = 0x1,
    KM_SCHED_CONTEXT_AFFECTED_IN_WORK_QUEUE       = 0x2,
    KM_SCHED_CONTEXT_AFFECTED_IN_SUBMIT_QUEUE     = 0x3,
}KM_SCHED_CONTEXT_AFFECTED_TYPE;

//*****************************************************************************
// Enum:  KM_SCHED_AC_REPORT_STATUS
// PURPOSE: To indicate report status of the context when involved in preempt/reset
//*****************************************************************************
typedef enum KM_SCHED_AC_REPORT_STATUS_ENUM
{
    KM_SCHED_AC_REPORT_STATUS_UNKNOWN       = 0x0, //Unknown / un-acked.
    KM_SCHED_AC_REPORT_STATUS_REQUEST_ACKED = 0x1, // Got the request to preempt
    KM_SCHED_AC_REPORT_STATUS_ERROR         = 0x2,
    KM_SCHED_AC_REPORT_STATUS_COMPLETE      = 0x4  //Request to preempt was completed by CSB  = context complete for preempt context

}KM_SCHED_AC_REPORT_STATUS;
//KM_SCHED_AC_REPORT_STATUS_REACHED_CS    = 0x3, //[Currently not implemented due to perf] Request to preempt was acked by CS HW (idle -> active/switch)

// Types of Reset supported by GuC
typedef enum UK_KM_RESET_TYPE_ENUM
{
    UK_KM_RESET_TYPE_MEDIA_RESET,
    UK_KM_RESET_TYPE_WINDOWS_ENGINE_RESET,
    UK_KM_RESET_TYPE_PRIVATE_ENGINE_RESET, // TODO: find out what is needed for this?? To support this we may need to send UK_KM_RESET_TYPE from KMD 
    UK_KM_RESET_TYPE_GUC_INTERNAL_ENGINE_RESET

}UK_KM_RESET_TYPE;

//*****************************************************************************
// Struct:  KM_SCHED_AFFECTED_CONTEXT_REPORT
// PURPOSE: Used by GuC to report back on which contexts were affected by
//          preempt request by KMD
//*****************************************************************************
typedef struct KM_SCHED_AFFECTED_CONTEXT_REPORT_REC
{
    KM_SCHED_AC_REPORT_STATUS       ReportReturnStatus;  // KMD must request report in Options (see host->GuC interface doc)
                                                         // GuC sets this if a report is requested and was able to satisfy the request
    ULONG64                         ArrAffectedPtrExeclistContext[KM_SCHED_MAX_PREMPT_REPORT_ENTRIES];  // Kernel mode virtual address (pExeclistContext, from Backpointer in LRCA)
    KM_SCHED_CONTEXT_AFFECTED_TYPE  ArrAffectedType[KM_SCHED_MAX_PREMPT_REPORT_ENTRIES];                // How the context is affected.
    ULONG                           ArrAffectedFenceId[KM_SCHED_MAX_PREMPT_REPORT_ENTRIES];             // This is the submit fence ID as seen by GuC for debug. Should not use for reporting to OS.
    ULONG                           AffectExeclistCount;
    ULONG                           GuCInternal0;      // KMD should not write to this value as long as preemption is in progress with GuC
    ULONG                           GuCInternal1;      // KMD should not write to this value as long as preemption is in progress with GuC

}KM_SCHED_AFFECTED_CONTEXT_REPORT;

#define KM_UK_MAX_PREEMPTION_DEBUG_DWORDS 32

//*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// typedef:
//        SLPM_PER_CTX_STATE_INFO
//
// Description:
//      This structure provides per-context storage for SLPM related information.
//
// *** IMPORTANT *** Keep in sync with slpmosinterface.h and UkGucKmdInterface.h
//------------------------------------------------------------------------------*/
typedef struct KM_SLPM_PER_CTX_STATE_INFO_REC
{
    ULONG       EvaluationId;       // The evaluation id that this context last partipated in. 0 == This is a new context.
    ULONG       GtFreqRequest;      // The GT frequency request for this context. Opaque value of type SLPM_GT_FREQ_REQUEST.
    ULONG       GtFreqRequestId;    // The GT frequency request ID used by SLPM to decide if a new frequency change needs to be applied. 0 = There is not GT frequency request.
    ULONG       GtConfig;           // The recommended GT_CONFIG.
    ULONG       GtFreqLRI;          // Encoded GtFreqRequest ready for sending to pcode via LRI.
    UCHAR       AppMinGtFreqBins;   // Minimum GT frequency requested by application/KMD. Value is in bins (1 = 50MHz). Default = 0x0.
    UCHAR       AppMaxGtFreqBins;   // Maximum GT frequency requested by application/KMD. Value is in bins (1 = 50MHz). Default = 0xFF.
    UCHAR       GtHwMaxFreq;        // The maximum GT frequency for the recommended GT_CONFIG.
    
    // Last member of this structure.
    UCHAR       ChangeId;           // KMD/APP increments this value when a change is made to the data above. SLPM uses this to know if to reread the data in this structure
                                    // or if it's safe to use it's internally cached values.
                                    //     - 0x00 : means that this context is new.
                                    //     - 0xFF : forces SLPM to read the structure all the time.
}KM_SLPM_PER_CTX_STATE_INFO;

//*****************************************************************************
// Struct:  KM_SCHED_SHARED_CONTEXT_DATA_LOCK
// PURPOSE: Lock of KM_SCHED_SHARED_CONTEXT_DATA so that clients can access
//          this data even after the scheduler has submitted for execution.
//*****************************************************************************
typedef enum KM_SCHED_SHARED_CONTEXT_DATA_CLIENT_ENUM
{
    KM_SCHED_SHARED_CONTEXT_DATA_CLIENT_SLPM = 0,

    KM_SCHED_SHARED_CONTEXT_DATA_CLIENT_MAX
}KM_SCHED_SHARED_CONTEXT_DATA_CLIENT;
typedef struct KM_SCHED_SHARED_CONTEXT_DATA_LOCK_DATA
{
    union
    {
        ULONG Value;
        struct
        {
            UCHAR           Client[KM_SCHED_SHARED_CONTEXT_DATA_CLIENT_MAX];    // The value will be 1 or 0.
                                                                                // UCHAR is used rather than a bitfield
                                                                                // so that there is no need to read
                                                                                // the lock value into the GUC.
        };
    };
}KM_SCHED_SHARED_CONTEXT_DATA_LOCK;

//*****************************************************************************
// Struct:  KM_SCHED_SHARED_CONTEXT_DATA
// PURPOSE: Used for extended KMD - GuC Communication.
//          This is part of HW context allocation
//*****************************************************************************
typedef struct KM_SCHED_SHARED_CONTEXT_DATA_REC
{
    //Context specific address of dma buffer private data for tracking mid batch preemption
    ULONG       AddOfLastPreemptedPrivateDataLowPart;     // CPU address of private data for currently executing preemtable workload. Used to save BB preempt data.
    ULONG       AddOfLastPreemptedPrivateDataHighPart;    // If these are non-zero at Preempt Completion time, then this BB was preempted mid-batch or mid-thread

    ULONG       AddOfLastPreemptedPrivateDataHighPartTmp; // Used for WaPipeControlUpperDwordCorruption
    ULONG       :32; // Qword Padding

    ULONG       IsMappedToProxyContext;
    ULONG       ProxyContextID;

    ULONG       EngineResetContextId;

    ULONG       MediaResetCount;

    // Reserved Space
    ULONG     Reserved[8];

    ULONG     UkLastContextSwitchReason;
    ULONG     WasReset;
    ULONG     LRCAGfxAddress;          // Gfx Address of LRCA used as back pointer
    ULONG64   pExeclistContext;        // Back pointer to ExecList Context (KM_EXECLIST_CONTEXT)
    KM_SCHED_SUBMIT_DATA               SchedSubmitData;        // MBZ
    KM_SCHED_AFFECTED_CONTEXT_REPORT   PreemptedContextReport[IGFX_ABSOLUTE_MAX_ENGINES]; // MBZ prior to calling to GuC for this report TODO: Make this allocation per engine's shared area
    KM_SCHED_AFFECTED_CONTEXT_REPORT   EngResetContextReport[IGFX_ABSOLUTE_MAX_ENGINES];
    KM_UK_POWER_GATING_TRANSPORT_STATE PowerGatingStates; // SSEU payload to be transported to GuC
    ULONG                              ReservedPreemptDebugData[KM_UK_MAX_PREEMPTION_DEBUG_DWORDS];               // The structure is reserved for Intel use
    ULONG                              KmIdleContextId;
    BOOL                               IsIdleContextValid;

    KM_SCHED_SHARED_CONTEXT_DATA_LOCK  Lock;    // This is used to keep track of when clients need to prevent
                                                // this data from being destroyed. When not zero, KMD cannot
                                                // garabage clean this memory from GTT or system memory.

    // Fields for SLPM
    KM_SLPM_PER_CTX_STATE_INFO          SlpmPerContextState;

}KM_SCHED_SHARED_CONTEXT_DATA;

typedef enum UK_SLEEP_STATE_ENTER_STATUS_ENUM
{
    UK_SLEEP_STATE_ENTER_SUCCESS,
    UK_SLEEP_STATE_ENTER_PREEMPT_TO_IDLE_FAILED,
    UK_SLEEP_STATE_ENTER_ENG_RESET_FAILED,
}UK_SLEEP_STATE_ENTER_STATUS;

//*****************************************************************************
// Struct:  KM_SCHED_WORK_QUEUE_KMD_ELEMENT_INFO
// PURPOSE: Work item for submitting KMD workloads into work queue for GuC.
//*****************************************************************************
typedef struct KM_SCHED_WORK_QUEUE_KMD_ELEMENT_INFO_REC
{
    SCHED_CONTEXT_DESCRIPTOR_LD               ElementLowDW;             // 1 DW - Execlist context descriptor's lower DW.
    union
    {
        struct
        {
            ULONG                            : KM_BIT_RANGE(  19,  0);
            ULONG    RingTailQWIndex         : KM_BIT_RANGE(  30, 20);  // QW Aligned, TailValue <= 2048 (addresses 4 pages max)
            ULONG                            : KM_BIT_RANGE(  31, 31);
        };
        ULONG Value;
    } ElementHighDW;
} KM_SCHED_WORK_QUEUE_KMD_ELEMENT_INFO;

//KMD work Item looks like this:
//          KMD Work Queue Item ( KM_SCHED_WORK_QUEUE_ITEM)
// V------------------------------------------------------------------------------V
// ********************************************************************************
// |                   |          KmdSubmitInfo (2 DWs)             |             |
// | WQ Item Header    | TailValue  |    LRCA    |  ContextDescLD   |   RsvdDW    |
// ********************************************************************************

//*****************************************************************************
// Struct:  KM_SCHED_WORK_QUEUE_ITEM
// PURPOSE: Work item for submitting KMD workloads into work queue for GuC.
//*****************************************************************************
typedef struct KM_SCHED_WORK_QUEUE_ITEM_REC
{
   UK_SCHED_WORK_QUEUE_ITEM_HEADER      Header;                 // 1 DW
   KM_SCHED_WORK_QUEUE_KMD_ELEMENT_INFO KmdSubmitElementInfo;   // 2 DW - Contains Ring Tail and LRCA, ContextDescLD
   ULONG                                FenceId;                // 1 DW Fence ID from OS (used for debug tracing). Bit 31, says its preempt or not
} KM_SCHED_WORK_QUEUE_ITEM;



// If we don't have  KM_MAX_ELEMENTS_PER_EXEC_LIST defined we are
// in non-windows gfx driver environment  (like fulsim/GuC code itself...)
// So, define these stuctures.
#ifndef KM_MAX_ELEMENTS_PER_EXEC_LIST
#ifndef __IGFXFMID_H__

//*****************************************************************************
// Enum:  GTTYPE
// PURPOSE: To GT type of the device
//*****************************************************************************
typedef enum __GTTYPE
{
    GTTYPE_GT1 = 0x0,
    GTTYPE_GT2,
    GTTYPE_GT2_FUSED_TO_GT1,
    GTTYPE_GT2_FUSED_TO_GT1_6, //IVB
    GTTYPE_GTL, // HSW
    GTTYPE_GTM, // HSW
    GTTYPE_GTH, // HSW
    GTTYPE_GT3, // BDW
    GTTYPE_GT4, // BDW
    GTTYPE_GT0, // BDW
    GTTYPE_GTA, // BXT
    GTTYPE_GTC, // BXT
    GTTYPE_UNDEFINED,//Always at the end.
}GTTYPE;

//*****************************************************************************
// Enum:  GFXCORE_FAMILY
// PURPOSE: Identify the family
//*****************************************************************************
typedef enum
{
    IGFX_GEN8_CORE       = 11,  //Gen8 Family
    IGFX_GEN9_CORE       = 12,  //Gen9 Family
    IGFX_GENNEXT_CORE    = 13,  //GenNext Family
    GFXCORE_FAMILY_FORCE_ULONG = 0x7fffffff
} GFXCORE_FAMILY;

//*****************************************************************************
// Enum:  PRODUCT_FAMILY
// PURPOSE: Identify the product
//*****************************************************************************

typedef enum
{
    IGFX_UNKNOWN        =  0,
    IGFX_BROADWELL      = 16,
    IGFX_CHERRYVIEW     = 17,
    IGFX_SKYLAKE        = 18,
    IGFX_WILLOWVIEW     = 19,
    IGFX_BROXTON        = 20,

    IGFX_GENNEXT               = 0x7ffffffe,
    PRODUCT_FAMILY_FORCE_ULONG = 0x7fffffff
} PRODUCT_FAMILY;

//*****************************************************************************
// Enum:  SKU_STEPPING_ID
// PURPOSE: Stepping ID for use for use with GuC
//*****************************************************************************
typedef enum SKU_STEPPING_ID_ENUM
{
    SKU_STEPPING_ID_A0 = 0x0,
    // Add Ax steppings here

    SKU_STEPPING_ID_B0 = 0x10,
    // Add Bx steppings here

    SKU_STEPPING_ID_C0 = 0x20,
    // Add Cx stepping here

    SKU_STEPPING_ID_D0 = 0x30,
    // Add Dx stepping here

    SKU_STEPPING_ID_E0 = 0x40
    // Add Ex stepping here

}SKU_STEPPING_ID;

#endif // ifndef __IGFXFMID_H__

/******************************
KM_EXECLIST_RING_CONTEXT_REGISTER - Must Match BSpec
******************************/
#define KM_MAX_ELEMENTS_PER_EXEC_LIST  (2)

typedef struct
{
    ULONG   Offset;
    ULONG   Data;
} KM_EXECLIST_RING_CONTEXT_REGISTER;

/******************************
KM_EXECLIST_RING_CONTEXT - Must Match BSpec
******************************/

typedef struct KM_EXECLIST_RING_CONTEXT_REC
{
    ULONG   Noop;
    ULONG   RingInfoLriHeader;

    KM_EXECLIST_RING_CONTEXT_REGISTER    ContextControl;
    KM_EXECLIST_RING_CONTEXT_REGISTER    RingHead;
    KM_EXECLIST_RING_CONTEXT_REGISTER    RingTail;
    KM_EXECLIST_RING_CONTEXT_REGISTER    RingBufferStart;
    KM_EXECLIST_RING_CONTEXT_REGISTER    RingBufferControl;
    KM_EXECLIST_RING_CONTEXT_REGISTER    BatchBufferCurrentHead_Udw;
    KM_EXECLIST_RING_CONTEXT_REGISTER    BatchBufferCurrentHead;
    KM_EXECLIST_RING_CONTEXT_REGISTER    BatchBufferState;

    KM_EXECLIST_RING_CONTEXT_REGISTER    SecondBatchBufferAddr_Udw;
    KM_EXECLIST_RING_CONTEXT_REGISTER    SecondBatchBufferAddr;
    KM_EXECLIST_RING_CONTEXT_REGISTER    SecondBatchBufferState;

    KM_EXECLIST_RING_CONTEXT_REGISTER    PostRestoreBb;
    KM_EXECLIST_RING_CONTEXT_REGISTER    IndirectContext;
    KM_EXECLIST_RING_CONTEXT_REGISTER    IndirectContextOffset;

    union
    {
        KM_EXECLIST_RING_CONTEXT_REGISTER    RingModeCCID;          //Only KBL-H
        ULONG   Padding1[2];    //2 Noops
    };
    
    ULONG   Padding2; // 1 Noop

    ULONG   PdpInfoLriHeader;

    KM_EXECLIST_RING_CONTEXT_REGISTER    ContextTimestamp;

    KM_EXECLIST_RING_CONTEXT_REGISTER    Pdp3_UDW;
    KM_EXECLIST_RING_CONTEXT_REGISTER    Pdp3_LDW;

    KM_EXECLIST_RING_CONTEXT_REGISTER    Pdp2_UDW;
    KM_EXECLIST_RING_CONTEXT_REGISTER    Pdp2_LDW;

    KM_EXECLIST_RING_CONTEXT_REGISTER    Pdp1_UDW;
    KM_EXECLIST_RING_CONTEXT_REGISTER    Pdp1_LDW;

    KM_EXECLIST_RING_CONTEXT_REGISTER    Pdp0_UDW;
    KM_EXECLIST_RING_CONTEXT_REGISTER    Pdp0_LDW;

    ULONG   Padding3[13];

    ULONG                               PcRegisterLriHeader;
    KM_EXECLIST_RING_CONTEXT_REGISTER   RcsPwrClkState;

    ULONG                               GpGpuCsrBaseAddress[3];

    ULONG   Padding4[9];
} KM_EXECLIST_HW_RING_CONTEXT;


//*****************************************************************************
// Enum:  KM_RING_STATUS
// PURPOSE: To describe status of current ring
//*****************************************************************************

typedef enum KM_RING_STATUS_REC
{
    RING_NOT_PRESENT,
    RING_NOT_ALLOCATED,
    RING_NOT_INITALIZED,
    RING_AVAILABLE,
    RING_CURRENTLY_USED,
    RING_STOPPED,
    RING_STATUS_UNKOWN,
} KM_RING_STATUS;

#endif     // end: #ifndef KM_MAX_ELEMENTS_PER_EXEC_LIST -- above is for non-KMD environments.

//*****************************************************************************
// Struct:  UK_EXECLIST_RING_BUFFER
// PURPOSE: To describe status and access information of current ring buffer for a given EL context
//*****************************************************************************
typedef struct
{
    KM_RING_STATUS              RingStatus;                // Status
    ADDRESS32                   pExeclistRingContext;      // uKernel Pointer to pExeclistRingContext

    ADDRESS32                   pRingBegin;                // uKernel address for RingBegin
    ADDRESS32                   pRingEnd;                  // uKernel final byte address that is valid for this ring
    ADDRESS32                   pNextFreeLocation;         // uKernel address for next location in ring
                                                           //
    ULONG                       CurrentTailPointerValue;   // Last value written by software for tracking (just in case HW corrupts the tail in its context)

} UK_EXECLIST_RING_BUFFER;

typedef struct KM_PP_HWSP_REC
{
    union {
        struct {
            DWORD       Reserved0[4];   // 4 Reserved DWORDS at the beginning
            DWORD       RingHeadPointer;
            DWORD       Reserved1[11];
            DWORD       CumulativeContextRunTime;
            DWORD       SubmitInfo;
            ULONG64     PreemptRequestTimestamp;
            ULONG64     ContextRestoreCompleteTimestamp;
            ULONG64     ContextSaveFinishedTimestamp;
        };

        DWORD       PpHwSp[KM_KBYTES_TO_DWORD_COUNT(4)];
    };
} KM_PP_HWSP;

#define KM_EXECLIST_CONTEXT_PPHWSP_SIZE         PAGE_SIZE
#define KM_EXECLIST_SHARED_DATA_SIZE            PAGE_SIZE

// Macros to get the offset of elements in the execution list context layout
#define KM_EXECLIST_CONTEXT_GET_HHWSP_OFFSET                    ( KM_EXECLIST_SHARED_DATA_SIZE )
#define KM_EXECLIST_CONTEXT_GET_RING_CONTEXT_OFFSET             ( KM_EXECLIST_SHARED_DATA_SIZE + KM_EXECLIST_CONTEXT_PPHWSP_SIZE )
#define KM_EXECLIST_CONTEXT_GET_ENGINE_STATE_OFFSET             ( KM_EXECLIST_CONTEXT_GET_RING_CONTEXT_OFFSET + sizeof(KM_EXECLIST_HW_RING_CONTEXT) )

// Offsets in the BSPEC are from the beginning of the LRCA so they don't include the PPHWSP
// Engine state doesnt' include the Ring Contxt though, so we will take a context DWORD offset
// and remove the Ring Context from it via macro

#define KM_CONTEXT_DWORD_OFFSET_TO_ENGINE_STATE_DWORD_OFFSET(Offset)                \
    (Offset - (sizeof(KM_EXECLIST_HW_RING_CONTEXT) / sizeof(DWORD) ))

// Offsets in the BSPEC are from the beginning of the ring context so they don't include the PPHWSP
// Engine state doesnt' include the Ring Contxt though, so we will take a context DWORD offset
// and remove the Ring Context from it via macro
#define KM_CONTEXT_DWORD_OFFSET_TO_ENGINE_STATE_DWORD_OFFSET(Offset)                \
    (Offset - (sizeof(KM_EXECLIST_HW_RING_CONTEXT) / sizeof(DWORD) ))

//*****************************************************************************
// Struct:  UK_EXECLIST_CONTEXT
// PURPOSE: The entire execlist context including software and HW information
//*****************************************************************************
typedef struct UK_EXECLIST_CONTEXT_REC
{
   UK_ELEMENT_DESC            ExecElement;
   UK_EXECLIST_RING_BUFFER    RingBufferObj;
   UK_ENGINE_CONTEXT_STATE    State;          // State holds same info as SwitchReason (removed)
   SHORT                      PageFaultCount; // Number of pagefaults outstanding (possible negative numbers)
   SHORT                      EngineSubmitQueueCount;
} UK_EXECLIST_CONTEXT;


//*****************************************************************************
// Struct:  UK_KM_COMMON_CONTEXT_AREA_DESCRIPTOR
// PURPOSE: A common area for communication from uKernel OS to Scheduler.
//*****************************************************************************
typedef struct UK_KM_COMMON_CONTEXT_AREA_DESCRIPTOR_REC
{

    ULONG a;

}UK_KM_COMMON_CONTEXT_AREA_DESCRIPTOR;

//*****************************************************************************
// Struct:  UK_KM_CONTEXT_DESCRIPTOR
// PURPOSE: Context descriptor for communicating between uKernel and KM Driver
//*****************************************************************************
typedef struct UK_KM_CONTEXT_DESCRIPTOR_REC
{
   UK_KM_COMMON_CONTEXT_AREA_DESCRIPTOR UkSchedCommonArea;
   ULONG                ContextID;
   ULONG                PASID;
   IGFX_ENGINES_USED    EnginesUsed;
   UK_KM_ADDRESS        DoorbellTriggerAddress;   // The doorbell page's trigger cacheline (Ptr to UK_KM_APP_DOORBELL_INFO)
   ADDRESS64            DoorbellTriggerAddressGPA;
   USHORT               DoorbellID;               // Do not modify manually once allocated

   UK_EXECLIST_CONTEXT  ExecListContext[IGFX_ABSOLUTE_MAX_ENGINES];

   union
   {
    struct
    {
     UCHAR      IsContextActive         : KM_BIT      (    0); // Is this context actively assigned to an app
     UCHAR      IsPendingDoorbell       : KM_BIT      (    1);
     UCHAR      IsKMDCreatedContext     : KM_BIT      (    2); // KMD Special WorkItems can be processed.
     UCHAR      IsKMDPreemptContext     : KM_BIT      (    3); // KMD Context used for preemption. This flag is used for tracking if preemption workload is complete.
     UCHAR      IsContextEngReset       : KM_BIT      (    4); // Context was part of engine reset. KMD must take appropriate action (this context will not be resubmitted until this bit is cleared)
     UCHAR      WqProcessingLocked      : KM_BIT      (    5); // Set it = 1 to prevent other code paths to do work queue processing as we use sampled values for WQ processing. Allowing multiple code paths to do WQ processing will cause same workload to execute multiple times.
     UCHAR      IsDoorbellForPCHUse     : KM_BIT      (    6); // If set to 1 at acquire doorbell time, this doorbell address will be programmed in appropriate XTM register so that PCH can ring the doorbell
     UCHAR      IsContextTerminated     : KM_BIT      (    7); // If set 1, the context is terminated by GuC, All the pending work is dropped, its doorbell is evicted and eventually this context will be removed.
    };
    UCHAR      BoolValues;
   };

   UK_CONTEXT_PRIORITY  Priority;

   ULONG                WQSampledTailOffset;       // Sampled and set during doorbell ISR handler
   ULONG                TotalSubmitQueueEnqueues;  // Global (across all submit queues) pending enqueues.

   ADDRESS32            pProcessDescriptor;        // pProcessDescriptor is ptr to (UK_SCHED_PROCESS_DESCRIPTOR *)
   ADDRESS32            pWorkQueueAddress;
   ULONG                WorkQueueSizeBytes;        // WQ address & size is here because we do not trust
                                                   // addresses in UK_SCHED_PROCESS_DESCRIPTOR

   //With the new Submit Queue Implementation also we do not do duplicate entries in the submit queue
   //for a context if it is already present in the submit queue.
   //The flag below are set if a context is present in the submit queue of the engine
   SCHED_CONTEXT_ENGINE_PRESENCE EnginePresence;   // Note that a duplicate copy is in UK_SCHED_PROCESS_DESCRIPTOR is used for letting app know the status.
                                                   // It is duplicated since app is not trusted that it will not write to that location and
                                                   // Enginepresence is used in scheduling decisions.
   IGFX_ENGINES_USED             EngineSchedSuspended;      // EngineSchedSuspended is used in scheduling decisions. If the bit set, its schedule is suspended for corresponding engine.

   UCHAR                         Reserved0[3];

   ULONG64              Reserved1[1];              // For GuC Internal use. MBZ at init time.

}UK_KM_CONTEXT_DESCRIPTOR, ContextDescriptor;      //* ContextDescriptor this is for Fulsim */

//*****************************************************************************
// Struct:  KM_GUC_CONTEXT_INFO
// PURPOSE: Information about the actual contexts stored in the pool
//*****************************************************************************
typedef struct KM_GUC_POOLED_CONTEXT_INFO_REC
{
   UK_KM_CONTEXT_DESCRIPTOR  Context;               // UK_KM_CONTEXT_DESCRIPTORs
   ULONG64                   AssignedGuCGPUDesc;    // CPU back pointer to the GPU descriptor (KM_GUC_GPU_DESC) to which this context is assigned to.
}KM_GUC_POOLED_CONTEXT_INFO;


//*****************************************************************************
// Struct:  KM_GUC_CONTEXT_POOL
// PURPOSE: Descriptor record for the pool of UK_KM_CONTEXT_DESCRIPTOR s
//*****************************************************************************
typedef struct KM_GUC_CONTEXT_POOL_DESC_REC
{

   ULONG64  GMMContextPoolHandle;    //Memory Manager's handle to the pool of KM_GUC_POOLED_CONTEXT_INFO
   ULONG    PoolGFXAddressBegin;     //GFX Address of the pool of KM_GUC_POOLED_CONTEXT_INFO
   ULONG64  PoolCPUAddressBegin;     //CPU address of the pool of KM_GUC_POOLED_CONTEXT_INFO
   ULONG    AllocatedContextCount;   //Total number of Contexts in pool
   ULONG    AssignedContextCount;    //Total number of context assigned to some app (contexts in use count)
   ULONG    NextFreeContextIndex;    //Next free index in the pool

}KM_GUC_CONTEXT_POOL_DESC;


//*****************************************************************************
// Struct:  KM_GUC_LOG_INIT_PARAMS
// PURPOSE: Loging Parameters sent via sched_control_data.
//  Maintained as separate structure to allow debug tools to access logs without
//  contacting guc (for when Guc is stuck in ISR)
//*****************************************************************************
typedef struct KM_GUC_LOG_INIT_PARAMS_REC
{

    union
    {
        struct
        {
            ULONG    IsLogBufferValid             : KM_BIT_RANGE(  0,   0); //Is logbuffer valid
            ULONG    NotifyOnLogHalfFull          : KM_BIT_RANGE(  1,   1); //Raises a GuC to Host interrupt when log buffer is half full.
            ULONG                                 : KM_BIT_RANGE(  2,   2);
            ULONG    AllocatedCountUnits          : KM_BIT_RANGE(  3,   3); // 0 = Log buffer allocation in Pages, 1 = Log buffer allocation in Megabytes
            ULONG    CrashDumpLogAllocatedCount   : KM_BIT_RANGE(  5,   4); //No. of units allocated -1 for Crash Dump Log Buffer(MAX 4 Units)
            ULONG    DpcLogAllocatedCount         : KM_BIT_RANGE(  8,   6); //No. of units allocated -1 for DPC Log Buffer(MAX 8 Units)
            ULONG    IsrLogAllocatedCount         : KM_BIT_RANGE( 11,   9); //No. of units allocated -1 for ISR Log Buffer(MAX 8 Units)
            ULONG    LogBufferGFXAddress          : KM_BIT_RANGE( 31,  12); //Page aligned address for log buffer
        };
        ULONG LogDwordValue;
    };

}KM_GUC_LOG_INIT_PARAMS; //Size must not exceed 1 DWORD


//*****************************************************************************
// Struct:  SCHED_CONTROL_DATA_REC
// PURPOSE: Holds the init values of various parameters used by the uKernel
//*****************************************************************************
typedef struct SCHED_CONTROL_DATA_REC
{
    //Dword 0
    union
    {
        struct
        {
            ULONG    NumContextsInPool16Blocks     : KM_BIT_RANGE( 11,   0);  // Num of Contexts In Pool in blocks of 16, NumContextsInPool16Block = 1 if 16 contexts. 64 if 1024 contexts allocated.
            ULONG    ContextPoolGFXAddressBegin    : KM_BIT_RANGE( 31,  12);  //Aligned bits [31:12] of the GFX address where the pool begins
        };
    };

    //Dword 1
    union
    {
            ULONG   ARATHighRegValue     : KM_BIT_RANGE( 31,   0); // The value to be progammed into ARAT (timer) High register, upon uKernel load
    };
    //Dword 2
    union
    {
            ULONG   ARATLowRegValue      : KM_BIT_RANGE( 31,   0); // The value to be programmed into ARAT Low register,  upon uKernel load. 0-> selects a default value by ukernel
    };

    //Dword 3
    //Device details on which the uKernel is loaded.
    //Specified by the driver to reduce code in uKernel.
    union
    {
        struct
        {
            ULONG  GfxGtType             : KM_BIT_RANGE( 6,  0);  //Enum: GTTYPE
            ULONG  GfxCoreFamily         : KM_BIT_RANGE(12,  7);  //Enum: GFXCORE_FAMILY
            ULONG  usRevId               : KM_BIT_RANGE(28, 13);  //GFX rev ID. Set 0 unless there is a stepping specific WA to be done in uKernel
            ULONG                        : KM_BIT_RANGE(31, 29);
        };
        ULONG DeviceDetailsDword;
    };

    //Dword 4
    // Log buffer setup
    KM_GUC_LOG_INIT_PARAMS  LogInitParams;

    //Dword 5
    //Page fault control
    union
    {
        struct
        {
            ULONG MinPageFaultsBeforeSwitch       : KM_BIT_RANGE (10, 0);  //Value should be (num faults - 1.) 0 -> 1 fault, 4 -> 5 faults
            ULONG                                 : KM_BIT_RANGE (12,11);
            ULONG MinFaultsServicedBeforeRetry    : KM_BIT_RANGE (23,13);  //Value should be (num faults - 1.) 0 -> 1 fault, 4 -> 5 faults
            ULONG                                 : KM_BIT_RANGE (25,24);
            ULONG                                 : KM_BIT_RANGE (31,29);
        };
        ULONG PageFaultControlDword;
    };

    //Dword 6
    //GuC uKernel Specific workarounds that needs to be applied. WA must have a HSD/traceable reference!
    union
    {

        struct
        {
            ULONG     WaPreSiDummyGuC2HostOnCSInterrupt     : KM_BIT      (    0);
            ULONG     WaWorkaround1                         : KM_BIT      (    1);
            ULONG     WaDisableDefaultSchedulerPolicy       : KM_BIT      (    2);
            ULONG     WauKernelLoadedByDriver               : KM_BIT      (    3);
            ULONG     WaDisableDummyAllEngineFaultFix       : KM_BIT      (    4);
            ULONG     WaDisableLiteRestoreOptimization      : KM_BIT      (    5);
            ULONG     WaEnableMultipleAffectCountWrites     : KM_BIT      (    6);
            ULONG     WaReadBackAffectedCountAfterWrite     : KM_BIT      (    7);
            ULONG     WaUseGuc2HostFencingForSQFlush        : KM_BIT      (    8);
            ULONG     WaReadBackAffectedInfoAfterWrite      : KM_BIT      (    9);
            ULONG     WaEnableGoMsgToGAMDuringCPD           : KM_BIT      (    10);
            ULONG     WaDisable2ElemSubmission              : KM_BIT      (    11);
            ULONG     WaDisableDOPRenderClkGatingAtSubmit   : KM_BIT      (    12);
            ULONG     WaDummyWriteBeforeFenceCycle          : KM_BIT      (    13);
            ULONG     WaDisableSRAMRestoreDisable           : KM_BIT      (    14);
            ULONG     WaEnableGoMsgAckDuringCPD             : KM_BIT      (    15);
            ULONG                                           : KM_BIT_RANGE(31, 16);
        };
        ULONG WorkaroundDW;
    };

    //Dword 7
    //GuC uKernel Specific features
    union
    {
        struct
        {
            ULONG     FtrGuCEnableVCS2Engine         : KM_BIT      (    0);  // For GT3 configs.
            ULONG     FtrKmdGuCSubmissions           : KM_BIT      (    1);
            ULONG     FtrFeature2                    : KM_BIT      (    2);
            ULONG     FtrGucPowerGating              : KM_BIT      (    3);  // For power gating
            ULONG     FtrDisableGuCScheduler         : KM_BIT      (    4);  // Prevent GuC Scheduler from initializing
            ULONG     FtrEnablePreemptionDataLogging : KM_BIT      (    5);  // Enable tracking and logging preemption data
            ULONG     FtrEnableGuCPAVPControl        : KM_BIT      (    6);  // Enable GuC PAVP Control
            ULONG     FtrEnableGuCSlpm               : KM_BIT      (    7);  // Enable SLPM in GuC
            ULONG     FtrEnableEngineResetOnPreemptFailure      : KM_BIT      (    8);  // Enable GuC Internal Reset feature.
            ULONG     FtrNotApplicable                          : KM_BIT      (    9);
            ULONG     FtrEnableAsyncFWInEngSchedule             : KM_BIT      (    10); // For disabling tight poll on engine wake during schedule
            ULONG                                               : KM_BIT_RANGE(31, 11);
        };
        ULONG FeatureDword;
    };

    //Dword 8
    // Logging Verbosity Select and other tracking data control
    
    union
        {
            struct
            {
                ULONG     LoggingVerbosity               : KM_BIT_RANGE(3,    0);  // defines the level of logging in uKernel. 0 -> logging only important events 3 -> logging at every step of execution
                ULONG     LogOutputSelection             : KM_BIT_RANGE(5,    4);  //  For log output to NPK/LogBuffer or both
                ULONG     LoggingDisabled                : KM_BIT_RANGE(6,    6);  // Flag to indicate logging is enabled or not. Keeping the bit clear as logging enabled for backward comaptibility with Ukernel.
                ULONG     ProfileEnabled                 : KM_BIT_RANGE(7,    7);  // Flag to indicate profile logs are enabled.
                ULONG     EnableWorkQueueItemTracking    : KM_BIT_RANGE(8,    8);  // This flag enables counting work items seen by each context. This mainly for debug.
                ULONG     AdditionalDataStructsEnabled   : KM_BIT_RANGE(9,    9);  // Note: Additional data structs is *not* optional for most POR use cases of GuC.
                ULONG     DefaultLoggingDisabled         : KM_BIT_RANGE(10, 10); //Enable Logging Critical Messages always 
                ULONG     GfxAddressAdditionalDataStructs: KM_BIT_RANGE(31, 11);  // Gfx Ptr to KM_GUC_ADDITIONAL_DATA_STRUCTS
     
            };
        };
    
    //Dword 9
    union 
    {
        struct
        {
            ULONG    GfxAddressKmSharedData;
        };
    };

}SCHED_CONTROL_DATA;

//Enum to determine what mode the scheduler is in.
typedef enum UK_SCHEDULER_MODE_REC
{
    UK_SCHEDULER_MODE_NORMAL, //Standard scheduling mode no stalling
    UK_SCHEDULER_MODE_STALL_PER_PRESENT, //Stalls scheduling on all engines WI's whose header has IsPresentWorkload is to be scheduled
    UK_SCHEDULER_MODE_STALL_IMMEDIATE, //Stalls scheduling on all engines
    UK_SCHEDULER_MODE_STALL_IMMEDIATE_PREEMPT_TO_IDLE //Stalls scheduling on all engines and preempts any executing workloads
}UK_SCHEDULER_MODE;

typedef struct SCHED_SCHEDULING_POLICY_FLAGS_REC
{
    union
    {
        struct
        {
            ULONG    ResetEngineUponPreemptFailure : KM_BIT_RANGE(0, 0);    // Should we reset engine when preemption failed within its time quantum
            ULONG    PreemptToIdleOnQuantumExpiry  : KM_BIT_RANGE(1, 1);    // Should we preempt to idle unconditionaly for the execution quantum expiry. 
            ULONG                                  : KM_BIT_RANGE(31, 2);
        };
        ULONG PolicyDword;
    };
 
}SCHED_SCHEDULING_POLICY_FLAGS;


typedef struct SCHED_SCHEDULING_POLICY_REC
{
    ULONG                         ExecutionQuantum;                  // Time for one workload to execute. (micro seconds)
    ULONG                         RSVD1;                              // MaxQuantumCredits Usage TBD: No. of schedule quantums before this queue has to give up even if it has work.
    ULONG                         WaitForPreemptionCompletionTime;    // Time to wait for a preemption request to completed before issuing a reset. (micro seconds).
    ULONG                         QuantumUponFirstFaultTime;          // How much time to allow to run after the first fault is observed. Then preempt afterwards. (micro seconds)
    SCHED_SCHEDULING_POLICY_FLAGS PolicyFlags;
    ULONG Rsvd;
    ULONG                         Rsvd2;
}SCHED_SCHEDULING_POLICY;
 

typedef struct SCHED_SCHEDULING_POLICIES_REC
{
    SCHED_SCHEDULING_POLICY PerSubmitQueuePolicy[UK_CONTEXT_PRIORITY_ABSOLUTE_MAX_COUNT][IGFX_ABSOLUTE_MAX_ENGINES];
    ULONG                   DPCPromoteTime; //In MicroSec. How much time to allow before DPC processing is called back via interrupt (to prevent DPC queue drain starving). Typically 1000s of micro seconds (example only, not granularity).
    ULONG                   IsValid;        //Must be set to take these new values.
    ULONG                   MaxNumWorkItemsPerDpcCall; // Number of WIs to process per call to process single. Process Single could have a large Max Tail value which may keep CS idle. Process MaxNumWorkItemsPerDpcCall WIs and try fast schedule.
    ULONG                   Rsvd[19];             //Other global policies that may be used in future
}SCHED_SCHEDULING_POLICIES;





// Datastructures to keep the status of Logging Buffer.

typedef enum UK_LOG_BUFFER_TYPE_ENUM
{
    UK_ISR_LOG_BUFFER,
    UK_DPC_LOG_BUFFER,
    UK_CRASH_DUMP_LOG_BUFFER,
    UK_MAX_LOG_BUFFER,
}UK_LOG_BUFFER_TYPE;

typedef enum UK_LOG_VERBOSITY_ENUM
{
    UK_LOG_VERBOSITY_LOW     = 0x00,
    UK_LOG_VERBOSITY_MED     = 0x01,
    UK_LOG_VERBOSITY_HIGH    = 0x02,
    UK_LOG_VERBOSITY_ULTRA   = 0x03,
    UK_LOG_VERBOSITY_MAX
}UK_LOG_VERBOSITY;

//This enum controls the type of logging output. Can be changed dynamically using Host2GuC interface.
typedef enum LOGOUTPUT_SELECTION_REC
{
    LOGOUTPUT_LOGBUFFER_ONLY    = 0x0,
    LOGOUTPUT_NPK_ONLY          = 0x1,
    LOGOUTPUT_LOGBUFFER_AND_NPK = 0x2,
    LOGOUTPUT_MAX
}LOGOUTPUT_SELECTION;

#define UK_KM_LOG_BUFFER_KMD_VERSION 1

// Filled by KMD except Version and Marker are initialized by uKernel
typedef struct UK_KM_SCHED_STATISTICS_REC
{
    ULONG               Marker[2];                  // Marks the beginning of statistics buffer
    ULONG               Version;
    ULONG               Reserved[5];

    ULONG               GlobalDoorbellRingCount;
    ULONG               GlobalPreemptRequestCount;

}UK_KM_SCHED_STATISTICS;

// Filled by KMD except Version and Marker are initialized by uKernel
typedef struct UK_KM_LOG_BUFFER_STATE_REC
{
    ULONG               Marker[2];                  // Marks the beginning of Buffer Flush(set by uKernel at Log Buffer Init)
    ULONG               LogBufRdPtr;                // This is the Last Byte Offset Location that was read by KMD. KMD will write to this and uKernel will read this.
    ULONG               LogBufWrPtr;                // This is the Byte Offset Location that will be written by uKernel.
    ULONG               LogBufSize;                 // Log Buffer size (set by KMD)
    ULONG               SampledLogBufWrptr;         // This is written by ukernel when it sees the log buffer becoming half full and KMD writes this value in the Log file to avoid stale data.
    union
    {
        struct
        {
            ULONG    LogBufFlushToFile : KM_BIT_RANGE  (0,0);   //  uKernel sets this when log buffer is half full or when a forced flush has been requested through host2guc. uKernel will send GUC2HOST only if this bit is cleared. This is to avoid unnecessary interrupts from GuC.
            ULONG    BufferFullCount   : KM_BIT_RANGE  (4,1);   //  uKernel increments this when log buffer overflows
            ULONG                      : KM_BIT_RANGE  (31,5);
        };
        ULONG    LogBufFlags;
    };

    ULONG               Version;
}UK_KM_LOG_BUFFER_STATE;

//*****************************************************************************
// Struct:  SCHED_PREEMPT_OPTIONS
// PURPOSE: Options for Engine Preempt Host 2 GuC Actions
//*****************************************************************************
typedef struct SCHED_PREEMPT_OPTIONS_REC
{
    //Dword 0
    union
    {
        struct
        {
            ULONG    AttemptScheduleBeforeReturn   : KM_BIT      (       0);  // After adding the Preempt Context ID to submit queue, attempt to schedule it to Runlist submit port before returning from the call.
            ULONG                                  : KM_BIT      (       1);  // MBZ
            ULONG    PreemptTargetWorkQueueItems   : KM_BIT      (       2);  // For the target context ID, drop the work items in WQ that are targeted to this engine.
            ULONG    DropSubmitQueueItemsOnPreempt : KM_BIT      (       3);  // For the target priority, if flag is set, this flag drops the submit queue. Otherwise, reenqueues them back into submit queue
            ULONG    ReportAffectedContexts        : KM_BIT      (       4);  // Applicable only of following KMD submissions. Report back the ptr to Execlist contexts in an array
            ULONG                                  : KM_BIT_RANGE(31    ,5);
        };
        ULONG   OptionsDW;
    };
}SCHED_PREEMPT_OPTIONS;

typedef struct SCHED_ENG_RESET_OPTIONS_REC
{
    //Dword 0  
    union 
    {
        struct
        {
            ULONG    Reserved                      : KM_BIT      (       0);  // After adding the Preempt Context ID to submit queue, attempt to schedule it to Runlist submit port before returning from the call.
            ULONG                                  : KM_BIT      (       1);  // MBZ
            ULONG    Reserved1                     : KM_BIT      (       2);  // For the target context ID, drop the work items in WQ that are targeted to this engine. 
            ULONG    reserved2                     : KM_BIT      (       3);  // For the target priority, if flag is set, this flag drops the submit queue. Otherwise, reenqueues them back into submit queue
            ULONG    ReportAffectedContexts        : KM_BIT      (       4);  // Applicable only of following KMD submissions. Report back the ptr to Execlist contexts in an array 
            ULONG                                  : KM_BIT_RANGE(31    ,5);
        };
        ULONG   OptionsDW;
    };
}SCHED_ENG_RESET_OPTIONS;

/* This Status will be programmed in C1BC - SOFT_SCRATCH_15_REG */
typedef struct UK_GUC_TO_HOST_MESSAGE_RECORD
{
   union
    {
        struct
        {
            ULONG UkInitDone                        : KM_BIT_RANGE(0,  0 );
            ULONG CrashDumpPosted                   : KM_BIT_RANGE(1,  1 );
            ULONG IommuPageFaulted                  : KM_BIT_RANGE(2,  2 );
            ULONG FlushLogBufferToFile              : KM_BIT_RANGE(3,  3 );
            ULONG PreemptRequestOldPreemptPending   : KM_BIT_RANGE(4,  4 );  // Preempt request was unable to start because an old preempt was already pending. Wait for some time.
            ULONG PreemptRequestTargetContextBad    : KM_BIT_RANGE(5,  5 );  // Input Target context ID was incorrect / null.
            ULONG PreemptRequestInfoTargetHasWork   : KM_BIT_RANGE(6,  6 );  // Information flag that indicates either submit queue has pending work. This is to help debug.
            ULONG SleepEntryInProgress              : KM_BIT_RANGE(7,  7 );  // s3/s4 entry in progress.
            ULONG GuCInDebugHalt                    : KM_BIT_RANGE(8,  8 );  // Debug infinite loop is hit inserted in ukernel and is hit. This will halt kmd to carry on debug.
            ULONG GuCReportEngineResetContextId     : KM_BIT_RANGE(9,  9 );
            ULONG HuCAuthenticationFailed           : KM_BIT_RANGE(10, 10);
            ULONG Reserved1                         : KM_BIT_RANGE(15, 11);
            ULONG GpaToHpaXlationError              : KM_BIT_RANGE(16, 16);
            ULONG DoorbellIDAllocationError         : KM_BIT_RANGE(17, 17);
            ULONG DoorbellIDAllocationInvalidCtxID  : KM_BIT_RANGE(18, 18);
            ULONG SetBackLightDutyCycle             : KM_BIT_RANGE(19, 19);  // Revisit later and remove if not needed by dpst/turbo.
            ULONG ForceWakeTimedOut                 : KM_BIT_RANGE(20, 20);
            ULONG ForceWakeTimeOutCounter           : KM_BIT_RANGE(22, 21);  // Max 4, just as an indication that time out happened multiple times
            ULONG PreemptRequestProcessDpcError     : KM_BIT_RANGE(23, 23);
            ULONG IommuCatPageFaulted               : KM_BIT_RANGE(24, 24);
            ULONG Reserved3                         : KM_BIT_RANGE(28, 25);
            ULONG DoorbellIDReleaseError            : KM_BIT_RANGE(29, 29);
            ULONG UkException                       : KM_BIT_RANGE(30, 30);
            ULONG BootromHalt                       : KM_BIT_RANGE(31, 31);
        };
        ULONG Dw;
    };

}UK_GUC_TO_HOST_MESSAGE;

// Note trigger is a write only register - it has no backing storage.
#define KM_GEN8_REG_GUC_HOST2GUC_INTERRUPT (0xC4C8)
#define KM_GEN8_RING_HOST2GUC_INTERRUPT (0x1)
#define KM_GEN8_REG_GUC_HOST2GUC_IIR  (0xC590)

#define KM_GUC_SLEEP_STATE_ENTER_STATUS (0xc1b8)

/* This Action will be programmed in C180 - SOFT_SCRATCH_O_REG */
typedef enum
{
    HOST2GUC_ACTION_DEFAULT                             = 0x0,
    HOST2GUC_ACTION_REQUEST_INIT_DONE_INTERRUPT         = 0x1,
    HOST2GUC_ACTION_REQUEST_PREEMPTION                  = 0x2,
    HOST2GUC_ACTION_REQUEST_ENGINE_RESET                = 0x3,
    HOST2GUC_ACTION_PAUSE_SCHEDULING                    = 0x4,  //Only for Dom0 type KMD
    HOST2GUC_ACTION_RESUME_SCHEDULING                   = 0x5,
    HOST2GUC_ACTION_SAMPLE_FORCEWAKE_FEATURE_REGISTER   = 0x6,  //SKL+ in case OS changes this register to enable/disable it after GuC init, GuC should resample it
    HOST2GUC_ACTION_ALLOCATE_DOORBELL                   = 0x10,
    HOST2GUC_ACTION_DEALLOCATE_DOORBELL                 = 0x20,
    HOST2GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE      = 0x30,
    HOST2GUC_ACTION_CACHE_CRASH_DUMP                    = 0x200,       // Cache address from host to send crash dump
    HOST2GUC_ACTION_DEBUG_RING_DB                       = 0x300,       // For debugging, ring a doorbell via host 2 guc interrupt
    HOST2GUC_ACTION_PERFORM_GLOBAL_DEBUG_ACTIONS        = 0x301,
    HOST2GUC_ACTION_FORCE_LOGBUFFERFLUSH                = 0x302,       // Force a flush of the log buffer in its current state by sending guc2host
    HOST2GUC_ACTION_UK_LOG_VERBOSITY_LOGOUTPUT_SELECT   = 0x400,       // Select Logging Verbosity (may be raised by kmdebugtools) OR logging output selection
    HOST2GUC_ACTION_RESET_ENGINE                        = 0x500,       // Host OS calling for reset of a specific command streamer engine 
    HOST2GUC_ACTION_ENTER_S_STATE                       = 0x501,       // S3/S4 state
    HOST2GUC_ACTION_EXIT_S_STATE                        = 0x502,       // S3/S4 state
    HOST2GUC_ACTION_PREPARE_FOR_TDR                     = 0x503,       // State before. This is to ensure GuC does not touch TDR registers.
    HOST2GUC_ACTION_SET_SCHEDULING_MODE                 = 0x504,       // Set scheduling mode. Currently used by DCC/DFPS
    HOST2GUC_ACTION_PM_TEST_BASE                        = 0x1000,
    HOST2GUC_ACTION_PM_TEST_END                         = 0x2000,
    // Action for PC: 0x3000-0x3FFF
    HOST2GUC_ACTION_PC_TURBO_REQUEST                    = 0x3001,
    HOST2GUC_ACTION_PC_DPST_REQUEST                     = 0x3002,
    HOST2GUC_ACTION_PC_SLPM_REQUEST                     = 0x3003,
    // End action for PC
    HOST2GUC_ACTION_AUTHENTICATE_HUC                    = 0x4000,
    HOST2GUC_ACTION_MAX                                 = 0xF0000000
}HOST2GUC_ACTION;

#define __MAKE_HOST2GUC_STATUS(a) (HOST2GUC_ACTION_MAX+a)
typedef enum
{
    HOST2GUC_STATUS_SUCCESS                     = __MAKE_HOST2GUC_STATUS(0x0),
    HOST2GUC_STATUS_ALLOCATE_DOORBELL_FAIL      = __MAKE_HOST2GUC_STATUS(0x10),
    HOST2GUC_STATUS_DEALLOCATE_DOORBELL_FAIL    = __MAKE_HOST2GUC_STATUS(0x20),
    HOST2GUC_STATUS_FULSIM_TEST_FAIL            = __MAKE_HOST2GUC_STATUS(0x80),
    HOST2GUC_STATUS_LOG_ALLOCATION_TOO_SMALL    = __MAKE_HOST2GUC_STATUS(0x80),     // Not enough space allocated in host for entire log
    HOST2GUC_STATUS_LOG_HOST_ADDRESS_NOT_VALID  = __MAKE_HOST2GUC_STATUS(0x80),     // Location not in 48 bits, SRAM specified as type etc
    HOST2GUC_STATUS_LOG_DMA_FAILED              = __MAKE_HOST2GUC_STATUS(0x80),     // DMA transfer failed. Upper word will have error code from HW
    HOST2GUC_STATUS_UNKNOWN_ACTION              = __MAKE_HOST2GUC_STATUS(0x100),
    HOST2GUC_STATUS_GENERIC_FAIL                = __MAKE_HOST2GUC_STATUS(0x0000F000)
}HOST2GUC_STATUS;

#define KM_MAX_NUM_INPUT_DWORDS (14)
#define KM_MAX_NUM_OUTPUT_DWORDS (16)
//*****************************************************************************
// Struct:  KM_GUC_HOST_TO_GUC_REQUEST
// PURPOSE: Used to pass info for doing a Host 2 Guc call within Driver
//*****************************************************************************
typedef struct KM_GUC_HOST_TO_GUC_REQUEST_REC
{
    ULONG           Rsvd;
    ULONG64         HwDeviceHandle;        //In: HW_DEVICE_EXTENSION as ULONG64
    ULONG          *pInput;                //In: Ptr to array of dwords for input
    ULONG           NumOfInputDwords;      //In: No. of Dwords in array
    ULONG           WriteDisableMask;      //In: Bitwise mask to disable write to registers for each Input dword. when BIT(x) is set, Input[x] won't be written.
    ULONG          *pOutput;               //In/Out: Out of read registers after successful host2guc.  Also space must be allocated by caller for this array for the number of Dwords.
    ULONG           NumOfOutputDwords;     //In: No. of Dwords to read
    LONG            ReturnStatus;          //Out: NTSTATUS of H2G request TODO: Remove this windows specific status.
} KM_GUC_HOST_TO_GUC_REQUEST;


//*****************************************************************************
//
//                  Power Managment Module: SLPC
//
//*****************************************************************************

#ifndef _SLPC_KMD_INTERFACE_H_
#define _SLPC_KMD_INTERFACE_H_

/****************************************************************
OVERVIEW
========
This is the glue between the SLPM core layer and the HAL layer
that is provided by the OS under which the core is running (GuC,
KMD).

It defines the functions that need to be provided by the HAL
layer to the SLPM core layer and visa versa.

It also defines all structures that are shared between the
SLPM core layer and the layer above the HAL (the Host).
****************************************************************/

#ifdef __cplusplus
extern "C" {
#endif
    //A way to force compile check in GCC/ICC.
    // It creates an unique typedef. 
#ifndef CASSERT
#define _impl_PASTE(a,b) a##b
#define _impl_CASSERT_LINE(predicate, line, file)  typedef char _impl_PASTE(assertion_failed_##file##_,line)[2*!!(predicate)-1]; 
#define CASSERT(predicate, file) _impl_CASSERT_LINE(predicate,__LINE__, file)
#endif

#define SLPM_BIT_RANGE(endbit, startbit)     ((endbit)-(startbit)+1)
#define SLPM_BIT(bit)                        (1)

    //---------------------------------------------------------------
    //STATUS CODES
    //---------------------------------------------------------------
    typedef enum _SLPM_STATUS
    {
        SLPM_STATUS_OK                              = 0,
        SLPM_STATUS_ERROR                           = 1,
        SLPM_STATUS_ILLEGAL_COMMAND                 = 2,
        SLPM_STATUS_INVALID_ARGS                    = 3,
        SLPM_STATUS_INVALID_PARAMS                  = 4,
        SLPM_STATUS_INVALID_DATA                    = 5,
        SLPM_STATUS_OUT_OF_RANGE                    = 6,
        SLPM_STATUS_NOT_SUPPORTED                   = 7,
        SLPM_STATUS_NOT_IMPLEMENTED                 = 8,
        SLPM_STATUS_NO_DATA                         = 9,
        SLPM_STATUS_EVENT_NOT_REGISTERED            = 10,
        SLPM_STATUS_REGISTER_LOCKED                 = 11,
        SLPM_STATUS_TEMPORARILY_UNAVAILABLE         = 12,
        SLPM_STATUS_VALUE_ALREADY_SET               = 13,
        SLPM_STATUS_VALUE_ALREADY_UNSET             = 14,
        SLPM_STATUS_VALUE_NOT_CHANGED               = 15,
        SLPM_STATUS_MEMIO_ERROR                     = 16,
        SLPM_STATUS_EVENT_QUEUED_REQ_DPC            = 17,
        SLPM_STATUS_EVENT_QUEUED_NOREQ_DPC          = 18,
        SLPM_STATUS_NO_EVENT_QUEUED                 = 19,
        SLPM_STATUS_OUT_OF_SPACE                    = 20,
        SLPM_STATUS_TIMEOUT                         = 21,
        SLPM_STATUS_NO_LOCK                         = 22
    } SLPM_STATUS;
    //---------------------------------------------------------------
    //END OF STATUS CODES
    //---------------------------------------------------------------

    //---------------------------------------------------------------
    //ALL EVENTS THAT THE HAL WILL SEND TO SLPM CORE.
    //WHEN PASSING EVENTS TO THE ISR HANDLING INTERFACE (SLPM_PFN_EVENT_ISR)
    //15 DWORD PAYLOAD CAN BE PASSED IN. FOR EACH EVENT BELOW, ARGUMENTS ARE
    //DEFINED IN COMMENTS.
    //---------------------------------------------------------------
    typedef enum _SLPM_EVENT_ID
    {
        SLPM_KMD_EVENT_RESET                        = 0,        // Args[0] = lsb of SLPM_KMD_SHARED_DATA, Args[1] = msb of SLPM_KMD_SHARED_DATA, [OPTIONAL] Args[2] = Bitfield of SLPM_PROFILE_RESET_FLAGS
        SLPM_KMD_EVENT_SHUTDOWN                     = 1,        // Args[0] = lsb of SLPM_KMD_SHARED_DATA, Args[1] = msb of SLPM_KMD_SHARED_DATA, [OPTIONAL] Args[2] = Bitfield of SLPM_PROFILE_RESET_FLAGS
        SLPM_KMD_EVENT_PLATFORM_INFO_CHANGE         = 2,        // Args[0] = lsb of SLPM_KMD_SHARED_DATA, Args[1] = msb of SLPM_KMD_SHARED_DATA
        SLPM_KMD_EVENT_DISPLAY_MODE_CHANGE          = 3,        // Args[0] = SLPM_KMD_DISPLAY_MODE_EVENT_PARAM.GlobalData, Args[1..5] = SLPM_KMD_DISPLAY_MODE_EVENT_PARAM.PerPipeData[1..5].Data, 
        SLPM_KMD_EVENT_FLIP_COMPLETE                = 4,        // Args[0] = KM_FPS_TRACKING_FLIP_INFO 
        SLPM_KMD_EVENT_QUERY_TASK_STATE             = 5,
        SLPM_KMD_EVENT_PARAMETER_SET                = 6,        // Args[0] = SLPM_KMD_PARAM_ID, Args[1] = Value
        SLPM_KMD_EVENT_PARAMETER_UNSET              = 7,        // Args[0] = SLPM_KMD_PARAM_ID
        SLPM_END_KMD_EVENTS
    } SLPM_EVENT_ID;
    //---------------------------------------------------------------
    //END OF EVENTS
    //---------------------------------------------------------------

    //---------------------------------------------------------------
    //ALL PARAMS - this is used to start parameter values in an array
    //             and to use a bitfield at the start of the array to
    //             flag the parameters that are set.
    //---------------------------------------------------------------
    typedef enum _SLPM_KMD_PARAM_ID
    {
        // Please explicitly define values to reduce chance of mismatch
        SLPM_KMD_PARAM_TASK_ENABLE_GTPERF                           = 0,
        SLPM_KMD_PARAM_TASK_DISABLE_GTPERF                          = 1,
        SLPM_KMD_PARAM_TASK_ENABLE_BALANCER                         = 2,
        SLPM_KMD_PARAM_TASK_DISABLE_BALANCER                        = 3,
        SLPM_KMD_PARAM_TASK_ENABLE_DCC                              = 4,
        SLPM_KMD_PARAM_TASK_DISABLE_DCC                             = 5,
        SLPM_KMD_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ               = 6,    // Special values defined in enum SLPM_GT_FREQ_MHZ
        SLPM_KMD_PARAM_GLOBAL_MAX_GT_UNSLICE_FREQ_MHZ               = 7,    // Special values defined in enum SLPM_GT_FREQ_MHZ
        SLPM_KMD_PARAM_GLOBAL_MIN_GT_SLICE_FREQ_MHZ                 = 8,    // Special values defined in enum SLPM_GT_FREQ_MHZ
        SLPM_KMD_PARAM_GLOBAL_MAX_GT_SLICE_FREQ_MHZ                 = 9,    // Special values defined in enum SLPM_GT_FREQ_MHZ
        SLPM_KMD_PARAM_GTPERF_THRESHOLD_MAX_FPS                     = 10,
        SLPM_KMD_PARAM_GLOBAL_DISABLE_GT_FREQ_MANAGEMENT            = 11,   // This does not need force enable. Freq range will take care of it when this is FALSE
        SLPM_KMD_PARAM_GTPERF_ENABLE_FRAMERATE_STALLING             = 12,
        SLPM_KMD_PARAM_GLOBAL_DISABLE_RC6_MODE_CHANGE               = 13,
        SLPM_KMD_PARAM_GLOBAL_OC_UNSLICE_FREQ_MHZ                   = 14,
        SLPM_KMD_PARAM_GLOBAL_OC_SLICE_FREQ_MHZ                     = 15,
        SLPM_KMD_PARAM_GLOBAL_ENABLE_IA_GT_BALANCING                = 16,
        SLPM_KMD_PARAM_GLOBAL_ENABLE_ADAPTIVE_BURST_TURBO           = 17,
        SLPM_KMD_PARAM_GLOBAL_ENABLE_EVAL_MODE                      = 18,
        SLPM_KMD_PARAM_GLOBAL_ENABLE_BALANCER_IN_NON_GAMING_MODE    = 19,  // Gaming mode refers to when display flip is exclusively controlled by game context using command streamer flips

        // Also add new ones at the end. 32 KMD parameters are reserved.
        SLPM_END_KMD_PARAMS,
        SLPM_KMD_PARAMS_MAX = 32,
    } SLPM_KMD_PARAM_ID;
    CASSERT(SLPM_END_KMD_PARAMS <= SLPM_KMD_PARAMS_MAX, UkGucKmdInterface_h);

    //---------------------------------------------------------------
    //STRUCTURE THAT WILL BE PASSED TO SLPM CORE BOOTSTRAP. IT
    //CONTAINS THE HAL FUNCTION POINTERS THAT SLPM CORE CAN USE,
    //CONTEXT DATA THAT NEEDS TO BE PASSED TO THESE FUNCTIONS AND
    //SHARED DATA STRUCTURES.
    //---------------------------------------------------------------

    typedef enum _SLPM_PLATFORM_SKU
    {
        SLPM_PLATFORM_SKU_UNDEFINED     = 0,
        SLPM_PLATFORM_SKU_ULX           = 1,
        SLPM_PLATFORM_SKU_ULT           = 2,
        SLPM_PLATFORM_SKU_T             = 3,
        SLPM_PLATFORM_SKU_MOBL          = 4,
        SLPM_PLATFORM_SKU_DT            = 5,

        SLPM_PLATFORM_SKU_UNKNOWN,
        SLPM_PLATFORM_SKU_ALL = 7
    } SLPM_PLATFORM_SKU;
    CASSERT(SLPM_PLATFORM_SKU_UNKNOWN <= SLPM_PLATFORM_SKU_ALL, UkGucKmdInterface_h);

    typedef enum _SLPM_HW_POWERSRC
    {
        SLPM_POWERSRC_UNDEFINED         = 0,
        SLPM_POWERSRC_AC                = 1,
        SLPM_POWERSRC_DC                = 2,

        SLPM_POWERSRC_UNKNOWN,
        SLPM_POWERSRC_ALL = 3
    } SLPM_HW_POWERSRC;
    CASSERT(SLPM_POWERSRC_UNKNOWN <= SLPM_POWERSRC_ALL, UkGucKmdInterface_h);

    typedef enum _SLPM_HW_POWERPLAN
    {
        SLPM_POWERPLAN_UNDEFINED        = 0,
        SLPM_POWERPLAN_BATTERY_SAVER    = 1,
        SLPM_POWERPLAN_BALANCED         = 2,
        SLPM_POWERPLAN_PERFORMANCE      = 3,

        SLPM_POWERPLAN_UNKNOWN,
        SLPM_POWERPLAN_ALL = 7
    } SLPM_HW_POWERPLAN;
    CASSERT(SLPM_POWERPLAN_UNKNOWN <= SLPM_POWERPLAN_ALL, UkGucKmdInterface_h);

    //---------------------------------------------------------------
    //END OF SHARED HOST-SLPM STRUCTURES
    //---------------------------------------------------------------

    //---------------------------------------------------------------
    //STRUCTURES THAT ARE SHARED BETWEEN THE HOST AND SLPM CORE.
    //THESE STRUCTURES ENABLE THE HOST TO COMMUNICATE DATA
    //EFFICIENTLY TO THE SLPM.
    //---------------------------------------------------------------
    typedef struct _SLPM_KMD_PLATFORM_INFO
    {
        union
        {
            ULONG                  Bitfield1;       // SKU info
            struct
            {
                ULONG              PlatformSku      : SLPM_BIT_RANGE(7, 0);
                ULONG              FusedSliceCnt    : SLPM_BIT_RANGE(15, 8);
                ULONG              Reserved         : SLPM_BIT_RANGE(23, 16);
                ULONG              PowerPlan        : SLPM_BIT_RANGE(29, 24);
                ULONG              PowerSrc         : SLPM_BIT_RANGE(31, 30);
            };
        };
        union
        {
            ULONG                  Bitfield2;       // IA capability info
            struct
            {
                ULONG              MaxP0FreqBins    : SLPM_BIT_RANGE(7, 0);
                ULONG              P1FreqBins       : SLPM_BIT_RANGE(15, 8);
                ULONG              PeFreqBins       : SLPM_BIT_RANGE(23, 16);
                ULONG              PnFreqBins       : SLPM_BIT_RANGE(31, 24);
            };
        };
        ULONG                      Reserved1;
        ULONG                      Reserved2;
    } SLPM_KMD_PLATFORM_INFO;

    typedef enum _SLPM_GLOBAL_STATE
    {
        SLPM_GLOBAL_STATE_NOT_RUNNING       = 0,
        SLPM_GLOBAL_STATE_INITIALIZING      = 1,
        SLPM_GLOBAL_STATE_RESETING          = 2,
        SLPM_GLOBAL_STATE_RUNNING           = 3,
        SLPM_GLOBAL_STATE_SHUTTING_DOWN     = 4,
        SLPM_GLOBAL_STATE_ERROR             = 5
    } SLPM_GLOBAL_STATE;

    typedef struct _SLPM_TASK_STATE_DATA
    {
        union
        {
            ULONG Bitfield1;
            struct
            {
                // GT Perf data
                ULONG GtPerfTaskActive              : SLPM_BIT(0);
                ULONG GtPerfIsStallPossible         : SLPM_BIT(1);
                ULONG GtPerfInGamingMode            : SLPM_BIT(2);
                ULONG GtPerfTargetFps               : SLPM_BIT_RANGE(10, 3);    //8bits to support upto 255FPS

                // DCC data
                ULONG DccTaskActive                 : SLPM_BIT(11);
                ULONG DccInDccMode                  : SLPM_BIT(12);
                ULONG DccInDctMode                  : SLPM_BIT(13);

                // Freq Switch data
                ULONG FreqSwitchActive              : SLPM_BIT(14);

                // IBC/PG1 data
                ULONG IbcEnabled                    : SLPM_BIT(15);
                ULONG IbcActive                     : SLPM_BIT(16);
                ULONG PG1Enabled                    : SLPM_BIT(17);
                ULONG PG1Active                     : SLPM_BIT(18);
            };
        };
        union
        {
            ULONG Bitfield2;
            struct
            {
                ULONG FreqRangeUnsliceMax           : SLPM_BIT_RANGE(7, 0);
                ULONG FreqRangeUnsliceMin           : SLPM_BIT_RANGE(15, 8);
                ULONG FreqRangeSliceMax             : SLPM_BIT_RANGE(23, 16);
                ULONG FreqRangeSliceMin             : SLPM_BIT_RANGE(31, 24);
            };
        };
    }SLPM_TASK_STATE_DATA;

#define SLPM_KMD_MAX_OVERRIDE_PARAMETERS 192
#define SLPM_UNSET_PARAM_SETARRAY(setarray, id)      {setarray[(id >> 5)] &= (~(1 << (id % 32)));}
#define SLPM_SET_PARAM_SETARRAY(setarray, id)        {setarray[(id >> 5)] |= (1 << (id % 32));}
#define SLPM_UNSET_PARAM(setarray, valarray, id)     {setarray[(id >> 5)] &= (~(1 << (id % 32)));  valarray[id] = 0;}
#define SLPM_SET_PARAM(setarray, valarray, id, val)  {setarray[(id >> 5)] |= (1 << (id % 32));     valarray[id] = val;}
#define SLPM_GET_PARAM(setarray, valarray, id)       valarray[id]
#define SLPM_ISSET_PARAM(setarray, valarray, id)     (setarray[(id >> 5)] & (1 << (id % 32)))
    CASSERT((SLPM_KMD_MAX_OVERRIDE_PARAMETERS & 0x1F) == 0, UkGucKmdInterface_h);

    typedef struct _SLPM_KMD_SHARED_DATA
    {
        ULONG                              Reserved;
        ULONG                              KmdSharedDataSize;             // KMD must fill this in with the total size in bytes of this buffer.
        SLPM_GLOBAL_STATE                  KmdGlobalState;
        SLPM_KMD_PLATFORM_INFO             KmdPlatformInfo;
        SLPM_TASK_STATE_DATA               KmdTaskStateData;

        // KMD can override some of the internal parameters that are defined above in enum SLPM_KMD_PARAM_ID.
        // There is an array for storing the override value and a bitfield array for specifying which
        // elements of the array have been set. Use the above macros SLPM_UNSET_PARAM and SLPM_SET_PARAM to
        // update these arrays.
        ULONG                              KmdOverrideParametersSetBits[(SLPM_KMD_MAX_OVERRIDE_PARAMETERS + 31) / 32];
        ULONG                              KmdOverrideParametersValues[SLPM_KMD_MAX_OVERRIDE_PARAMETERS];
    } SLPM_KMD_SHARED_DATA;
    //---------------------------------------------------------------
    //END OF SHARED HOST-SLPM STRUCTURES
    //---------------------------------------------------------------

    //---------------------------------------------------------------
    //STRUCTURES FOR DISPLAY MODE EVENT
    //---------------------------------------------------------------
#ifndef MAX_INTEL_PIPES
#define MAX_INTEL_PIPES 3
#endif
#ifndef MAX_PLANE_PER_PIPE
#define MAX_PLANE_PER_PIPE  4
#endif
#ifndef MAX_NUM_OF_PIPE
#define MAX_NUM_OF_PIPE     (MAX_INTEL_PIPES + 1)
#endif

    typedef enum SLPM_PLANE_ENUM
    {
        SLPM_PLANE_1 = 0,
        SLPM_PLANE_2 = 1,
        SLPM_PLANE_3 = 2,
        SLPM_PLANE_4 = 3
    }SLPM_PLANE;

    // Keep this structure in sync with KM_FPS_TRACKING_FLIP_INFO.
    typedef struct SLPM_KMD_FPS_TRACKING_FLIP_INFO_REC
    {
        union
        {
            ULONG Data;
            struct
            {
                ULONG BitwiseTargetPipe     : MAX_NUM_OF_PIPE;
                ULONG PipeAPlane            : MAX_PLANE_PER_PIPE;
                ULONG PipeBPlane            : MAX_PLANE_PER_PIPE;
                ULONG PipeCPlane            : MAX_PLANE_PER_PIPE;
                ULONG PipeTPVPlane          : MAX_PLANE_PER_PIPE;    //20bits
                ULONG VbiVsyncOn            : 1;
                ULONG MpoEnabled            : 1;
                ULONG FlipType              : 2; //MMIO or DMA
                //reserved, let complier pack
            };
        };
    } SLPM_KMD_FPS_TRACKING_FLIP_INFO;

    typedef struct KMD_DISPLAY_PIPE_BASIC_INFO_REC
    {
        union
        {
            ULONG   Data;
            struct
            {
                ULONG IsWiDi                : 1;
                ULONG RefreshRate           : 7;
                ULONG VSyncFTUsec           : 24;
            };
        };
    }KMD_DISPLAY_PIPE_BASIC_INFO;

    typedef struct SLPM_KMD_DISPLAY_MODE_EVENT_PARAM_REC
    {
        struct
        {
            KMD_DISPLAY_PIPE_BASIC_INFO PerPipeInfo[MAX_NUM_OF_PIPE];

            union
            {
                ULONG GlobalData;
                struct
                {
                    ULONG BitwiseActivePipes    : MAX_NUM_OF_PIPE;  // Bitwise
                    ULONG FullscreenPipes       : MAX_NUM_OF_PIPE;  // Bitwise - Fullscreen is defined as a pipe whose
                    // display surfaces are not owned by the OS composer.
                    ULONG VbiVsyncOnPipes       : MAX_NUM_OF_PIPE;  // Bitwise - Pipes that have VBI enabled.
                    ULONG NumOfActivePipes      : 2;
                };
            };
        };
    } SLPM_KMD_DISPLAY_MODE_EVENT_PARAM;
    //---------------------------------------------------------------
    //END OF STRUCTURES FOR DISPLAY MODE EVENT
    //---------------------------------------------------------------

    //---------------------------------------------------------------
    //RESET/SHUTDOWN EVENT FLAGS
    //---------------------------------------------------------------
    typedef enum _SLPM_KMD_RESET_FLAGS
    {
        SLPM_KMD_RESET_FLAG_TDR_OCCURRED = (1 << 0)
    } SLPM_KMD_RESET_FLAGS;
    //---------------------------------------------------------------
    //END OF RESET/SHUTDOWN EVENT FLAGS
    //---------------------------------------------------------------

    //---------------------------------------------------------------
    //STRUCTURE USED TO PASS IN EVENT INPUT DATA
    //---------------------------------------------------------------
#define SLPM_MAX_EVENT_INPUT_ARGS  7
#define SLPM_MAX_EVENT_OUTPUT_ARGS 1


    CASSERT(SLPM_MAX_EVENT_INPUT_ARGS <= 14, UkGucKmdInterface_h); // Host2GuC gives us 15 scratch registers (the first we will use for the event ID).
    CASSERT(SLPM_MAX_EVENT_INPUT_ARGS >= (MAX_NUM_OF_PIPE + 1), UkGucKmdInterface_h); // SLPM_KMD_EVENT_DISPLAY_MODE_CHANGE requires the most number of arguments
    CASSERT(SLPM_MAX_EVENT_OUTPUT_ARGS >= 1, UkGucKmdInterface_h);  // Host2GuC number of Output Args should be at least 1
    CASSERT(SLPM_MAX_EVENT_OUTPUT_ARGS <= 14, UkGucKmdInterface_h); // Host2GuC gives us 15 scratch registers (the first we will use for the event ID).

    typedef union _SLPM_EVENT_INPUT_HEADER
    {
        ULONG                       HeaderData;
        struct
        {
            ULONG                   NumArgs         : SLPM_BIT_RANGE(7, 0);
            ULONG                   EventId         : SLPM_BIT_RANGE(15, 8);
        };
    } SLPM_EVENT_INPUT_HEADER;

    typedef struct _SLPM_EVENT_INPUT
    {
        ULONG                       MessageId; // This is reserved for use when sending requests to GuC.
        SLPM_EVENT_INPUT_HEADER     Header;
        ULONG                       Args[SLPM_MAX_EVENT_INPUT_ARGS];
    } SLPM_EVENT_INPUT;

    typedef union _SLPM_EVENT_OUTPUT_HEADER
    {
        ULONG                      HeaderData;
        struct
        {
            ULONG                  NumArgs          : SLPM_BIT_RANGE(7, 0);
            ULONG                  EventId          : SLPM_BIT_RANGE(15, 8);
            ULONG                  Status           : SLPM_BIT_RANGE(31, 16);
        };
    } SLPM_EVENT_OUTPUT_HEADER;

    typedef struct _SLPM_EVENT_OUTPUT
    {
        ULONG                       Error;  // This contains the result of the ISR function.
        SLPM_EVENT_OUTPUT_HEADER    Header;
        ULONG                       Args[SLPM_MAX_EVENT_OUTPUT_ARGS];
    } SLPM_EVENT_OUTPUT;
    //---------------------------------------------------------------
    //EVENT INPUT DATA
    //---------------------------------------------------------------

#ifdef __cplusplus
}
#endif

#endif  //End of '#define _SLPC_KMD_INTERFACE_H_'

#if defined (_MSC_VER)
    #pragma pack(pop)
#else
    #pragma pack()
#endif

#endif /*_UK_GUCKMDINTEFACE_H_*/