/******************************************************************************/
/*                                 SCRAMNet GT                                 */
/******************************************************************************/
/*                                                                            */
/* Copyright (c) 2021 Curtiss-Wright Controls Electronic System, Inc.         */
/*     dtn_support@curtisswright.com 800-252-5601 (U.S. only) 937-252-5601    */
/*                                                                            */
/* This program is free software; you can redistribute it and/or              */
/* modify it under the terms of the GNU General Public License                */
/* as published by the Free Software Foundation; either version 2             */
/* of the License, or (at your option) any later version.                     */
/*                                                                            */
/* See the GNU General Public License for more details.                       */
/*                                                                            */
/******************************************************************************/

/******************************************************************************/
/*                                                                            */
/*    Module      : scgt.h                                                    */
/*    Description : supporting structures and defines for scgt.c              */
/*    Platform    : Win2K                                                     */
/*                                                                            */
/******************************************************************************/

/**
 * @file scgt.h
 * @brief supporting structures and defines for scgt.c
*/

#ifndef __SCGT_H__
/** Flag to prevent multiple inclusions of scgt.h */
#define __SCGT_H__

#include "gtcoreTypes.h"

/** File revision number updated  11/11/21  */
#define FILE_REV_SCGT_H    "7"

/** Valid Data in DMA buffer */
#define SCGT_DMA_FULL  0
/** DMA buffer empty */
#define SCGT_DMA_EMPTY 1

/** Max number of concurrent PIO user virtual memory mappings to track */
#define MAX_USER_PTRS 128

/** Data buffer to hold Data used in DMA transfers **/
typedef struct _scgtDmaBuffer
{
   uint32 Status;              /**< status of DMA buffer full or empty */
   uint32 Cnt;                 /**< count number of times buffer used for DMA transfers */
   uint32 * pData;             /**< aligned virtialPointer to allocated DMA data buffer */
   PHYSICAL_ADDRESS physAddr;  /**< Physical Address of aligned data Buffer */
}scgtDmaBuffer;

/** DMA tools for control access to DMA buffers **/
typedef struct _scgtDMATools
{
    ksysSemS entrySem_1;   /**< DMA control semaphore 1 */
    ksysSemS entrySem_2;   /**< DMA control semaphore 2 */
    uint32 pending;        /**< DMA operation pending completion */
} scgtDMATools;

WARNING_DISABLE(5045); /*Compiler will insert Spectre mitigation for memory load if / Qspectre switch specified */

#ifdef __cplusplus
WARNING_PUSH
WARNING_DISABLE(4625)  /* copy constructor was implicitly defined as deleted */
WARNING_DISABLE(5027)  /* move assignment operator was implicitly defined as deleted */
WARNING_DISABLE(5026)  /* move constructor was implicitly defined as deleted */
WARNING_DISABLE(4626)  /* assignment operator was implicitly defined as deleted */

#endif


/** Device structure for scgtDevice Object **/
typedef struct _scgtDevice
{
    SCGT_DEVICE_CORE

    void *cRegPtr;                     /**< Pointer to control registers */
    void *nmRegPtr;                    /**< Pointer to network management registers */
    void* memPtr;                      /**< Kernel Pointer to GT on board memory. **/
    PHYSICAL_ADDRESS gtMemPhysAddr;    /**< Pointer to GT physical memory address */
    volatile long MappedMemory;        /**< Number of memory Map calls - number memory unmap calls. */
    
    scgtDMATools writeTools;           /**< GT DMA write tools */
    scgtDMATools readTools;            /**< GT DMA read tools */
        
    UNICODE_STRING unicodeSymLinkName;      /**< Unicode string storing symbolic Link name to our device interface.
                                                 link named used to access the card */
    PDEVICE_OBJECT  FunctionalDeviceObject; /**< Device object pointer */
    PDEVICE_OBJECT  lowerDeviceInStack;     /**< Pointer to lower functional device object
                                                 in stack to pass IRPS to **/
    PDEVICE_OBJECT  physDeviceObject;       /**< Pointer to physical device object **/
    DMA_ADAPTER    *dmaAdapter;             /**< Same value as mapData **/

    /* interrupt control values */
    uint32 interruptLevel;             /**< Interrupt level  DIRQL **/
    uint32 interruptVector;            /**< Interrupt vector  **/
    KAFFINITY interruptAffinity;       /**< KAFFINITY value representing the 
                                       set of processors on which device 
                                       interrupts can occur in this platform **/
    PKINTERRUPT interruptObject;       /**< Pointer to the address of driver-supplied 
                                           storage for a pointer to a set of interrupt objects **/

    ksysSemB threadSem;                /**< Interrupt thread semaphore **/
    uint32 threadTimeToExit;           /**< Flag to indicate when to exit interrupt thread **/
    
    KTIMER getIntrTimer;               /**< Interrupt timer **/
    KDPC getIntrTimerDPC;              /**< Pointer to KDPC structure that represent the DPC
                                        (scgtGetIntrTimerCallback) object for interrupt processing **/
    ksysSemS getIntrSem;               /**< Semaphore for use in interrupt processing **/
    volatile uint32 getIntrWaitCount;  /**< Number of call waiting for interrupts 
                                            Guarded by getIntrWaitCountSpinLock**/
    ksysSpinLock getIntrWaitCountSpinLock;  /**< Protects wait count **/
    ksysSpinLock getIntrTimerSpinLock;      /**< Protects timer use count and timer started **/
                                              
                                              
    volatile uint32 getIntrTmrUseCnt;      /**< number of threads using the timer **/
    volatile uint8 getIntrTimerStarted;    /**< flag indicating if get interrupt timer started **/

    scgtDmaBuffer DmaRead[SCGT_DMA_NUM_BUFFERS];  /**< DMA read buffers **/
    scgtDmaBuffer DmaWrite[SCGT_DMA_NUM_BUFFERS]; /**< DMA Write buffers **/
    uint32 MaxDMABlockSize;                       /**< Maximum size allowed to transfer in one DMA transfer **/
    BOOLEAN Is64BitOS;                            /**< Is 64-bit operating system **/
    
    /* device states for PNP purposes */
    long SystemState;                            /**< System state stopped started query removed*/
    long QueryRemoveState;                       /**< System state when IRP_MN_QUERY_REMOVE_DEVICE called
                                                  used to in IRP_CANCEL_REMOVE to restore to original state */

    
    BOOLEAN HoldNewRequests;                      /**< PNP FLAG  indicating if new Irps can be processed */
    _Interlocked_operand_ volatile LONG holdNewRequests;   /**< Flag indicating if SCGT IOCTL calls can be processed. */
    _Interlocked_operand_ volatile LONG OutstandingIO;     /**< Number of outstanding i/O  operations */
    _Interlocked_operand_ volatile LONG requestCount;      /**< Number of active SCGT ioctl calls */
    
    /* PNP Events */
    KEVENT RemoveEvent;                          /**< Event flag indication if is save to remove the device */
    KEVENT StopEvent;                            /**< Flag indication safe to stop */
#ifdef USE_REMOVE_LOCK
    IO_REMOVE_LOCK RemoveLock;                    /**< remove lock to prevent the use of ioctl calls during IRP_REMOVE_DEVICE */
#endif
    
    //POWER STATES
    DEVICE_POWER_STATE DevicePowerState;        /**< Current device power state. (PowerDeviceD0 PowerDeviceD1, PowerDeviceD2,PowerDeviceD3) */
    DEVICE_POWER_STATE SytemPowerState;         /**< System Power State Value. s0, s1 ,s2 ,s3 s4 s5 */
    DEVICE_POWER_STATE DeviceState[PowerSystemMaximum]; /**< device sate of parent buss acquired in IRP_QUERY_RESOUCES */

    PIRP SystemPowerIrp;  /**< system power IRP temporary storage.*/

    POWER_STATE         PowerState;  /**< Power State */

    _Interlocked_operand_ volatile long numOpenCalls;      /**< Number of open calls. Increments on open and decremented on close. */
    
    uint64 virtualAddress;   /**< Virtual address used to map GT memory or zero if not mapped.*/

    /** Store MDL and user mode pointer addres for each memoy map call */
    PVOID userModePtrMem[MAX_USER_PTRS]; /* user mode pointer to GT on board memory */
    PMDL  userModePtrMdl[MAX_USER_PTRS]; /* MSL used to map GT on board memory. */    
    PEPROCESS userModePtrPrc[MAX_USER_PTRS];  /*current process id of application calling memory mapping IOCTL function */
} scgtDevice;

#ifdef __cplusplus
WARNING_POP
#endif 

/**  @addtogroup PNPCode
@{ */
/** In STATE_REMOVED, we immediately fail any received I/O requests */
#define STATE_REMOVED            0x00000000
/** In STATE_SURPRISE_REMOVED, we immediately fail all incoming requests. */
#define STATE_SURPRISE_REMOVED   0x00010000
/** In STATE_NEVER_STARTED, we also immediately fail all incoming requests. */
#define  STATE_NEVER_STARTED    0x00020000

/** Dummy State  When the state is < this value, no H/W access is allowed. */
#define STATE_ALL_BELOW_NO_HW    0x00030000

/* ALL below fail.*/

/** Dummy state  When an IRP arrives at the driver, if the current device 
    state is below this value, it is immediately failed. */
#define STATE_ALL_BELOW_FAIL    0x00FF0000	

/** In STATE_REMOVE_PENDING, we fail CREATE requests but we must still process all other Irps */
#define STATE_REMOVE_PENDING    0x01100000
/** In STATE_STARTED, requests are processed and removed from the queues normally */
#define STATE_STARTED           0X01000000

/* Queue entries above this. */

/** Dummy state -- When an IRP arrives at the driver, if the current
 device state is above this value, it is queued, not initiated on
 the device (even if the device is free) */
#define STATE_ALL_ABOVE_QUEUE   0x0FFF0000	

/* if IRP < this start Irp to drain queue */

/** Dummy State -- When an IRP is COMPLETED on the device, if
 the device state is below this value, we'll start another
 IRP in an attempt to drain the queue of pending requests. */
#define STATE_ALL_BELOW_DRAIN   STATE_ALL_ABOVE_QUEUE	

/** In STATE_STOP_PENDING, we queue incoming requests */
#define STATE_STOP_PENDING      0x10000000

/** In STATE_STOPPED, we queue incoming requests */
#define STATE_STOPPED           0x10010000

/** end PNPCode 
@} */

/** @addtogroup UtilCode
@{ */

/** write to control register */
#define scgtWriteCReg(pdev, offset, val) \
        ksysWriteReg(pdev->cRegPtr, offset, val)
/** read from  control register  */
#define scgtReadCReg(pdev, offset) \
        ksysReadReg(pdev->cRegPtr, offset)

/** write to network management register */
#define scgtWriteNMReg(pdev, offset, val) \
        ksysWriteReg(pdev->nmRegPtr, offset, val)

/** read from network management register */
#define scgtReadNMReg(pdev, offset) \
        ksysReadReg(pdev->nmRegPtr, offset)

/** Are queues stalled indication no new requests are allowed */
#define scgtAreQueuesStalled(devExt)         \
    (BOOLEAN)InterlockedCompareExchange((PLONG)&devExt->HoldNewRequests, (LONG)TRUE, (LONG)TRUE)
/** end UTILCode @} */ 

/*
#define scgtStallQueues(devExt)             \
    InterlockedExchange((PLONG)&devExt->HoldNewRequests, (LONG)TRUE)
    */

/** unStall queues allowing new request to be preprocessed */
/*
#define scgtUnstallQueues(devExt)             \
    InterlockedExchange((PLONG)&devExt->HoldNewRequests, (LONG)FALSE)
*/

uint32 scgtDrvExchChain(scgtDevice *dev, gtcoreExchMgrData *exchMgrData,
    uint32 exchNum, uint8 direction, uint8 doAlloc);
uint32 scgtDrvTrQueue(scgtDevice *dev, gtcoreExchMgrData *exchMgrData,
    uint8 direction, uint8 doAlloc);

//#define scgtTrQueue(a,b,c,d)     scgtDrvTrQueue(a,b,c,d)
//#define scgtExchChain(a,b,c,d,e) scgtDrvExchChain(a,b,c,d,e)

#endif /* __SCGT_H__ */
