/* _NVRM_COPYRIGHT_BEGIN_
 *
 * Copyright 2014-2015 by NVIDIA Corporation.  All rights reserved.  All
 * information contained herein is proprietary and confidential to NVIDIA
 * Corporation.  Any use, reproduction, or disclosure without the written
 * permission of NVIDIA Corporation is prohibited.
 *
 * _NVRM_COPYRIGHT_END_
 */

//
// This file provides common types for both UVM driver and RM's UVM interface.
//

#ifndef _NV_UVM_TYPES_H_
#define _NV_UVM_TYPES_H_

#include "nvtypes.h"
#include "nvgputypes.h"
#include "nvCpuUuid.h"

//
// Default Page Size if left "0" because in RM BIG page size is default & there
// are multiple BIG page sizes in RM. These defines are used as flags to "0" 
// should be OK when user is not sure which pagesize allocation it wants
//
#define UVM_PAGE_SIZE_DEFAULT    0x0
#define UVM_PAGE_SIZE_4K         0x1000
#define UVM_PAGE_SIZE_64K        0x10000
#define UVM_PAGE_SIZE_128K       0x20000
#define UVM_PAGE_SIZE_2M         0x200000

#define UVM_GPU_PAGE_LEVEL_INFO_MAX_LEVELS    5
#define UVM_GPU_PAGE_LEVEL_INFO_LEVEL_4K      0
#define UVM_GPU_PAGE_LEVEL_INFO_LEVEL_64K     1
#define UVM_GPU_PAGE_LEVEL_INFO_LEVEL_2M      2

#define UVM_UUID_LEN 16

typedef NvProcessorUuid UvmGpuUuid;
typedef unsigned long long UvmGpuPointer;

//
// The following typedefs serve to explain the resources they point to.
// The actual resources remain RM internal and not exposed.
//
typedef struct uvmGpuSession_tag      *uvmGpuSessionHandle;      // gpuSessionHandle
typedef struct uvmGpuAddressSpace_tag *uvmGpuAddressSpaceHandle; // gpuAddressSpaceHandle
typedef struct uvmGpuChannel_tag      *uvmGpuChannelHandle;      // gpuChannelHandle
typedef struct uvmGpuCopyEngine_tag   *uvmGpuCopyEngineHandle;   // gpuObjectHandle

typedef struct UvmGpuChannelPointers_tag
{
    volatile unsigned *GPGet;
    volatile unsigned *GPPut;
    UvmGpuPointer     *gpFifoEntries;
    unsigned           numGpFifoEntries;
    unsigned           channelClassNum;
    NvNotification    *errorNotifier;
    NvBool            *eccErrorNotifier;
} UvmGpuChannelPointers;

typedef struct UvmGpuCaps_tag
{
    unsigned largePageSize;
    unsigned smallPageSize;
    unsigned eccMask;
    unsigned eccOffset;
    void    *eccReadLocation;
    unsigned pcieSpeed;
    unsigned pcieWidth;
    NvBool   bEccEnabled;
} UvmGpuCaps;

typedef struct UvmGpuAllocInfo_tag
{
    NvU64   rangeBegin;             // Allocation will be made between
    NvU64   rangeEnd;               // rangeBegin & rangeEnd both included
    NvU64   gpuPhysOffset;          // Returns gpuPhysOffset if contiguous requested
    NvU32   pageSize;               // default is RM big page size - 64K or 128 K" else use 4K or 2M
    NvBool  bContiguousPhysAlloc;   // Flag to request contiguous physical allocation
    NvBool  bHandleProvided;        // Client provides the handle for phys allocation
    NvBool  bMemGrowsDown;          // Causes RM to reserve physical heap from top of FB
    NvHandle hPhysHandle;           // Handle for phys allocation either provided or retrieved
} UvmGpuAllocInfo;

typedef struct UvmGpuSurfaceMappingInfo_tag
{
    NvU64 mappingOffset;
    NvU64 mappingLength;
    NvU8  *pteTemplate;
    NvU64 pageCount;
    NvU64 *pteArray;
    NvU32 pageSize;    
} UvmGpuSurfaceMappingInfo;

typedef struct UvmGpuInfo_tag
{
    NvU32  gpuArch;      // GPU Architecture number
    NvBool gpuInTcc;     // Set if GPU supports TCC Mode & is in TCC mode.  
}UvmGpuInfo;

typedef struct UvmGpuVaAllocInfo_tag
{
    NvU64    vaStart;                    // Needs to be alinged to pagesize
    NvBool   bFixedAddressAllocate;      // rangeBegin & rangeEnd both included
    NvU32    pageSize;                   // default is 4k or 64k else use pagesize= 2M 
} UvmGpuVaAllocInfo;

typedef struct UvmGpuFbInfo_tag
{
    NvU32 heapSize;         // RAM in KB available for user allocations
    NvU32 reservedHeapSize; // RAM in KB reserved for internal RM allocation
    NvBool bZeroFb;         // Zero FB mode enabled.
}UvmGpuFbInfo;

typedef struct UvmGpuPageLevelInfo_tag
{
    NvU32 pageSize;
    NvU64 vAddr;
    struct
    {
        NvU64 physAddress;
        NvU32 aperture;
    }levels[UVM_GPU_PAGE_LEVEL_INFO_MAX_LEVELS];
}UvmGpuPageLevelInfo;

typedef struct UvmGpuChannelPhysInfo_tag
{
    NvU64 pdb;
    NvBool bPdbLocVidmem;
    NvU64 instPtr;
    NvBool bInstPtrLocVidmem;
    NvP64 memHandle;
}UvmGpuChannelPhysInfo;

typedef struct UvmGpuChannelCtxBufferInfo_tag
{
    NvU64   alignment;      // Buffer aligment
    NvU64   size;           // Buffer allocation size after enforcing alignment
    NvP64   bufferHandle;   // RM memDesc handle for buffer
    NvU64   pageCount;      // Number of pages allocated
    NvU32   aperture;       // Allocation aperture
    NvBool  bIsContigous;   // Set if allocation is physically contigous
    NvBool  bGlobalBuffer;  // Set if global buffer as they are mapped only once
    NvBool  bLocalBuffer;   // Set if local buffer as they are mapped per channel
}UvmGpuChannelCtxBufferInfo;

/*******************************************************************************
    uvmEventStartDevice
    This function will be called by the GPU driver once it has finished its
    initialization to tell the UVM driver that this GPU has come up.
*/
typedef NV_STATUS (*uvmEventStartDevice_t) (UvmGpuUuid *pGpuUuidStruct);

/*******************************************************************************
    uvmEventStopDevice
    This function will be called by the GPU driver to let UVM know that a GPU
    is going down.
*/
typedef NV_STATUS (*uvmEventStopDevice_t) (UvmGpuUuid *pGpuUuidStruct);

#if defined (_WIN32)
/*******************************************************************************
    uvmEventWddmResetDuringTimeout
    This function will be called by KMD in a TDR servicing path to unmap channel
    resources and to destroy channels. This is a Windows specific event.
*/
typedef NV_STATUS (*uvmEventWddmResetDuringTimeout_t) (UvmGpuUuid *pGpuUuidStruct);

/*******************************************************************************
    uvmEventWddmRestartAfterTimeout
    This function will be called by KMD in a TDR servicing path to map channel
    resources and to create channels. This is a Windows specific event.
*/
typedef NV_STATUS (*uvmEventWddmRestartAfterTimeout_t) (UvmGpuUuid *pGpuUuidStruct);

/*******************************************************************************
    uvmEventServiceInterrupt
    This function gets called from RM's intr service routine when an interrupt
    to service a page fault is triggered.
*/
typedef NV_STATUS (*uvmEventServiceInterrupt_t) (void *pDeviceObject,
    NvU32 deviceId, NvU32 subdeviceId);
#endif

/*******************************************************************************
    uvmEventIsrTopHalf_t
    This function will be called by the GPU driver to let UVM know
    that an interrupt has occurred.

    Returns:
        NV_OK if the UVM driver handled the interrupt
        NV_ERR_NO_INTR_PENDING if the interrupt is not for the UVM driver
*/
#if defined (__linux__)
typedef NV_STATUS (*uvmEventIsrTopHalf_t) (UvmGpuUuid *pGpuUuidStruct);
#else
typedef void (*uvmEventIsrTopHalf_t) (void);
#endif

struct UvmOpsUvmEvents
{
    uvmEventStartDevice_t startDevice;
    uvmEventStopDevice_t  stopDevice;
    uvmEventIsrTopHalf_t  isrTopHalf;
#if defined (_WIN32)
    uvmEventWddmResetDuringTimeout_t wddmResetDuringTimeout;
    uvmEventWddmRestartAfterTimeout_t wddmRestartAfterTimeout;
    uvmEventServiceInterrupt_t serviceInterrupt;
#endif
};

typedef struct UvmGpuFaultInfo_tag
{
    // Register mappings obtained from RM
    volatile NvU32* pFaultBufferGet;
    volatile NvU32* pFaultBufferPut;
    volatile NvU32* pPmcIntr;
    volatile NvU32* pPmcIntrEnSet;
    volatile NvU32* pPmcIntrEnClear;
    NvU32 replayableFaultMask;
    // fault buffer cpu mapping and size
    void* bufferAddress;
    NvU32  bufferSize;
} UvmGpuFaultInfo;

typedef struct UvmGpuChannelBufferVa_tag
{
    NvP64 bufferHandle; // RM memDesc handle
    NvP64 bufferVa;     // Virtual address where the RM buffer is mapped
    NvBool bIsGlobalBuffer;
} UvmGpuChannelBufferVa;

#endif // _NV_UVM_TYPES_H_
