/******************************************************************************/
/*                                 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.                       */
/*                                                                            */
/******************************************************************************/

/**
 * @file ksys.h
 * @brief   Win2k ksys
 **/
 
#ifndef __K_SYS_H__
#define __K_SYS_H__  /**< macro to prevent multiple inclusions */


/*********************************/
/********* INCLUDE FILES *********/
/*********************************/

/* If you are building a driver that targets versions of Windows prior to 
   Windows 10, version 2004, You must #define POOL_ZERO_DOWN_LEVEL_SUPPORT 
   and call ExInitializeDriverRuntime during driver initialization, 
   before calling the pool allocation functions. */
#define POOL_ZERO_DOWN_LEVEL_SUPPORT

#include "systypes.h"

#define FILE_REV_KSYS_H    "9"     /**< Ksys.h file revision 11/11/2021 */

#ifndef __cplusplus
#include <Wdm.h>
#else
/* disable warning found in wdm.h files*/
WARNING_PUSH
WARNING_DISABLE( 4514 ) /* unreferenced inline function has been removed */
WARNING_DISABLE( 5220 ) /*  a non-static data member with a volatile qualified type no longer implies
    that compiler generated copy/move constructors and copy/move assignment operators are not trivial */
#include <Wdm.h>
WARNING_POP

WARNING_DISABLE(5220)  /* a non-static data member with a volatile qualified type no longer implies */
     /* that compiler generated copy / move constructors and copy / move assignment operators are not trivial */
WARNING_DISABLE(26493) /* Don't use C-style casts (type.4).  C+ cast using 'reinterpret_cast<int*>' */
WARNING_DISABLE(26429) /* Symbol 'SYM' is never tested for nullness, it can be marked as not_null(f.23).*/
WARNING_DISABLE(26481) /* Don't use pointer arithmetic. Use span instead (bounds.1). */
WARNING_DISABLE(26482) /* Only index into arrays using constant expressions(bounds.2). */
WARNING_DISABLE(26446) /* Prefer to use gsl::at() instead of unchecked subscript operator (bounds.4). */
WARNING_DISABLE(26485) /* Expression '`XXX': No array to pointer decay (bounds.3). */
#endif
WARNING_DISABLE(4820)  /*'foo': '4' bytes padding added after data member 'foo::x') */

/*****************************************/
/************** DEFINITIONS **************/
/******************************************/

/** max semaphore count */
#define MAX_SEM_CNT  128   

/** Align transaction queue address */
#define ksysAlignTQueueAddr(ptr, tqsize)   ((void*)((uintpsize)ptr & ~((uintpsize)(tqsize - 1))))

/** Flush cache buffer */
#define ksysCacheFlush(dmaHandlePtr, ptr, size)

/** Invaliadate cache buffer */
#define ksysCacheInvalidate(dmaHandlePtr, ptr, size)

/* default ksysDmaMallocs are used for Windows */

/****************************************/
/********** TYPES & STRUCTURES **********/
/****************************************/

/** For implementation of semaphores w/ timeouts */
typedef struct _ksysSemB
{
    volatile uint32 waiting;  /**< used for stats only */
    KSEMAPHORE sem;           /**< semaphore */
} ksysSemB;

/** Initialize Semaphore with timeout */
#define ksysSemBCreate(pSemB)  KeInitializeSemaphore(&((pSemB)->sem), 0, MAX_SEM_CNT); (pSemB)->waiting = 0
/** Destroy semaphore with timeout */
#define ksysSemBDestroy(pSemB)

/*******************************************************/
/***** simple semaphore (no timeout functionality) *****/
/*******************************************************/
/** Simple semaphore no timeout type */
typedef KSEMAPHORE ksysSemS;

/** Initialize simple semaphore */
#define ksysSemSCreate(pSemS)     KeInitializeSemaphore((pSemS), 0, MAX_SEM_CNT)
/** Destroy simple semaphore */
#define ksysSemSDestroy(pSemS)
/** Take simple semaphore */
#define ksysSemSTake(pSemS)       KeWaitForSingleObject(((PVOID)(pSemS)), Executive, KernelMode, FALSE, NULLPTR)
/** Give simple semaphore */
#define ksysSemSGive(pSemS)       KeReleaseSemaphore((pSemS), 0, 1, FALSE);

/******************************/
/****** mutex type ************/
/******************************/
/** Mutex type */
typedef FAST_MUTEX ksysMutex;

/** Create mutex */
#define ksysMutexCreate(pMutex)   ExInitializeFastMutex(pMutex)
/** Destroy mutex */
#define ksysMutexDestroy(pMutex)  
/** Take mutex */
#define ksysMutexTake(pMutex)     ExAcquireFastMutex(pMutex)
/** Give  mutex */
#define ksysMutexGive(pMutex)     ExReleaseFastMutex(pMutex)
/** Try mutex */
#define ksysMutexTry(pMutex)      ExTryToAcquireFastMutex(pMutex)

/******************************/
/****** spin lock type ********/
/******************************/
/** Dpin lock type */
typedef KSPIN_LOCK ksysSpinLock;
/** Spin lock KIRQL flag */
typedef KIRQL      ksysSpinLockFlags;

/** Create spin-lock */
#define ksysSpinLockCreate(pSpinLock)   KeInitializeSpinLock((pSpinLock))
/** Destroy spin-lock */
#define ksysSpinLockDestroy(pSpinLock)  
/** lock spin-lock */
#define ksysSpinLockLock(pSpinLock, pSpinLockFlags)     KeAcquireSpinLock((pSpinLock), (pSpinLockFlags))
/** Unlock spin-lock */
#define ksysSpinLockUnlock(pSpinLock, pSpinLockFlags)   KeReleaseSpinLock((pSpinLock), *(pSpinLockFlags))

/****************** prototypes ********************/
#ifdef __cplusplus
void ksysCopyToUser(_Inout_ __drv_aliasesMem void *userPtrDest,
                    _In_reads_bytes_(numBytes) void *src, uint32 numBytes);
void ksysCopyFromUser(_Out_writes_bytes_all_(numBytes) void *dst,
    _In_reads_bytes_(numBytes) void *userPtrSrc, uint32 numBytes);
#else
void ksysCopyToUser(void *userPtrDest, void *src, uint32 numBytes);
void ksysCopyFromUser(void *dst, void *userPtrSrc, uint32 numBytes);
#endif

uint32 ksysMapVirtToBus(void *dmaHandle, void *ptr, uint32 numBytes);
void ksysUnmapVirtToBus(void *dmaHandle, void *ptr);

void ksysWriteReg(void *pRegs, uint32 offset, uint32 val);
uint32 ksysReadReg(void *pRegs, uint32 offset);

void *ksysMalloc(uint32 nbytes);
void ksysFree(void *p, uint32 len);

/* time outing binary semaphore */

uint32 ksysSemBTakeWithTimeout(ksysSemB *p_sem, long to);
uint32 ksysSemBTake(ksysSemB *p_sem);
uint32 ksysSemBGive(ksysSemB *p_sem);

void ksysUSleep(unsigned long usec);


#endif /* __K_SYS_H__ */
