//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
/*++ BUILD Version: 0016    Increment this if a change has global effects


Module Name:

    nkarm.h

Abstract:

    User-mode visible ARM specific structures and constants

--*/

#ifndef _NKARM_
#define _NKARM_

// begin_ntddk begin_nthal

#if defined(ARM)

#define _cdecl



#include "mem_arm.h"

/* Kernel data area
 *
 * This area is always mapped into two well known locations of
 * the virtual memory space. One in user space which is read-only
 * and one in the kernel space which is read-write.
 *
 *BUGBUG: currently must be in sync with kapi.h for sharing with apis.c
 */

typedef struct _PROCESS *PPROCESS;
typedef struct _THREAD *PTHREAD;
typedef struct _SECTION *PSECTION;
typedef struct _EVENT *LPEVENT;

struct KDataStruct {
    LPDWORD lpvTls;         /* 0x000 Current thread local storage pointer */
    HANDLE  ahSys[NUM_SYS_HANDLES]; /* 0x004 If this moves, change kapi.h */
    char    bResched;       /* 0x084 reschedule flag */
    char    cNest;          /* 0x085 kernel exception nesting */
    char    bPowerOff;      /* 0x086 TRUE during "power off" processing */
    char    bProfileOn;     /* 0x087 TRUE if profiling enabled */
    ulong   dwArchitectureId;/* 0x088 architecture id */
    ulong   rsvd2;          /* 0x08c was DiffMSec */
    PPROCESS pCurPrc;       /* 0x090 ptr to current PROCESS struct */
    PTHREAD pCurThd;        /* 0x094 ptr to current THREAD struct */
    DWORD   dwKCRes;        /* 0x098  */
    ulong   handleBase;     /* 0x09c handle table base address */
    PSECTION aSections[64]; /* 0x0a0 section table for virutal memory */
    LPEVENT alpeIntrEvents[SYSINTR_MAX_DEVICES];/* 0x1a0 */
    ulong   pAPIReturn;     /* 0x2a0 direct API return address for kernel mode */
    uchar   *pMap;          /* 0x2a4 ptr to MemoryMap array */
    DWORD   dwInDebugger;   /* 0x2a8 !0 when in debugger */
    PTHREAD pCurFPUOwner;   /* 0x2ac current FPU owner */
    PPROCESS pCpuASIDPrc;   /* 0x2b0 current ASID proc */
    long    nMemForPT;      /* 0x2b4 - Memory used for PageTables */

    DWORD   aPend1;         /* 0x2b8 - low (int 0-31) dword of interrupts pending (must be 8-byte aligned) */
    DWORD   aPend2;         /* 0x2bc - high (int 32-63) dword of interrupts pending */

    DWORD   dwProtMask;     // 0x2c0 - mask for all the permission bits
    DWORD   dwRead;         // 0x2c4 - R/O, both kernel and user
    DWORD   dwWrite;        // 0x2c8 - R/W, both kernel and user
    DWORD   dwKrwUno;       // 0x2cc - Kernel R/W, user no access
    DWORD   dwKrwUro;       // 0x2d0 Kernel R/W, user no access

    long    alPad[11];      /* 0x2d4 - padding */
    DWORD   aInfo[32];      /* 0x300 - misc. kernel info */
                            /* 0x380 - interlocked api code */
                            /* 0x400 - end */
};  /* KDataStruct */

/* High memory layout
 *
 * This structure is mapped in at the end of the 4GB virtual
 * address space.
 *
 *  0xFFFD0000 - first level page table (uncached) (2nd half is r/o)
 *  0xFFFD4000 - disabled for protection
 *  0xFFFE0000 - second level page tables (uncached)
 *  0xFFFE4000 - disabled for protection
 *  0xFFFF0000 - exception vectors
 *  0xFFFF0400 - not used (r/o)
 *  0xFFFF1000 - disabled for protection
 *  0xFFFF2000 - r/o (physical overlaps with vectors)
 *  0xFFFF2400 - Interrupt stack (1k)
 *  0xFFFF2800 - r/o (physical overlaps with Abort stack & FIQ stack)
 *  0xFFFF3000 - disabled for protection
 *  0xFFFF4000 - r/o (physical memory overlaps with vectors & intr. stack & FIQ stack)
 *  0xFFFF4900 - Abort stack (2k - 256 bytes)
 *  0xFFFF5000 - disabled for protection
 *  0xFFFF6000 - r/o (physical memory overlaps with vectors & intr. stack)
 *  0xFFFF6800 - FIQ stack (256 bytes)
 *  0xFFFF6900 - r/o (physical memory overlaps with Abort stack)
 *  0xFFFF7000 - disabled
 *  0xFFFFC000 - kernel stack
 *  0xFFFFC800 - KDataStruct
 *  0xFFFFCC00 - disabled for protection (2nd level page table for 0xFFF00000)
 */

typedef struct _PAGETBL {
    ulong   PTEs[256];
} PAGETBL;

typedef struct ARM_HIGH {
    ulong   firstPT[4096];      // 0xFFFD0000: 1st level page table
    char    reserved2[0x20000-0x4000];

    char    exVectors[0x400];   // 0xFFFF0000: exception vectors
    char    reserved3[0x2400-0x400];

    char    intrStack[0x400];   // 0xFFFF2400: interrupt stack
    char    reserved4[0x4900-0x2800];

    char    abortStack[0x700];  // 0xFFFF4900: abort stack
    char    reserved5[0x6800-0x5000];

    char    fiqStack[0x100];    // 0xFFFF6800: FIQ stack
    char    reserved6[0xC000-0x6900];

    char    kStack[0x800];      // 0xFFFFC000: kernel stack
    struct KDataStruct kdata;   // 0xFFFFC800: kernel data page
} ARM_HIGH;

// KData is already a define on ARM.  Ignore anyone's attempt to
// predefine it.
#ifdef KData
#undef KData
#endif

#define ArmHigh ((ARM_HIGH *)0xFFFD0000)
#define FirstPT (ArmHigh->firstPT)
#define KData   (ArmHigh->kdata)
#define VKData  (*(volatile struct KDataStruct *)&KData)

#define hCurThread  (KData.ahSys[SH_CURTHREAD])
#define hCurProc    (KData.ahSys[SH_CURPROC])
#define pCurThread  (KData.pCurThd)
#define pCurProc    (KData.pCurPrc)
#define ReschedFlag (KData.bResched)
#define PowerOffFlag (KData.bPowerOff)
#define ProfileFlag (KData.bProfileOn)
#define CurAKey     (pCurThread->aky)
#define SectionTable (KData.aSections)
#define MustReschedule()    (*(ushort*)&KData.bResched == 1)
#define IntrEvents  (KData.alpeIntrEvents)
#define IntrData    (KData.alpvIntrData)
#define KPlpvTls    (KData.lpvTls)
#define KInfoTable  (KData.aInfo)
#define DIRECT_RETURN (KData.pAPIReturn)
#define MemoryMap   (KData.pMap)
#define InDebugger  (KData.dwInDebugger)
#define KCResched   (KData.dwKCRes)
#define g_CurFPUOwner (KData.pCurFPUOwner)
#define PROCESSOR_ARCHITECTURE PROCESSOR_ARCHITECTURE_ARM
extern DWORD CEProcessorType;
extern WORD ProcessorLevel;
extern WORD ProcessorRevision;
extern DWORD CEInstructionSet;

#endif // defined(ARM)
// end_ntddk end_nthal

#endif // _NKARM_
