/*************************************************************************************************
// INTEL CONFIDENTIAL Copyright 2011-2024 Intel Corporation All Rights Reserved.
//
// The source code contained or described herein and all documents related to the source code
// ("Material") are owned by Intel Corporation or its suppliers or licensors. Title to the Material
// remains with Intel Corporation or its suppliers and licensors. The Material contains trade secrets
// and proprietary and confidential information of Intel or its suppliers and licensors. The Material is
// protected by worldwide copyright and trade secret laws and treaty provisions. No part of the
// Material may be used, copied, reproduced, modified, published, uploaded, posted, transmitted,
// distributed, or disclosed in any way without Intel's prior express written permission.
//
// No license under any patent, copyright, trade secret or other intellectual property right is
// granted to or conferred upon you by disclosure or delivery of the Materials, either expressly, by
// implication, inducement, estoppel or otherwise. Any license under such intellectual property
// rights must be express and approved by Intel in writing.
//*************************************************************************************************/

#ifndef __SS_COMMON_H_
#define __SS_COMMON_H_

#include <ntifs.h>
#include <Acpiioct.h>
#include <wdf.h>

#define CHECK_POINTER(ctx)  \
    if (!ctx) \
    { \
        status = STATUS_INVALID_PARAMETER; \
        goto done; \
    } \

#define CHECK_POINTER_INVALID(ctx)  \
    if (!ctx) \
    { \
        status = STATUS_INVALID_PARAMETER; \
        goto invalid; \
    } \

#define CHECK_STATUS_SUCCESS(status)  (status == STATUS_SUCCESS ? TRUE : FALSE)
#define CHECK_STATUS(status)        if (!(NT_SUCCESS(status))) { goto done; }
#define CHECK_STATUS_INVALID(status) if (!(NT_SUCCESS(status))) { goto invalid; }


/*! "brief divsave_rounded 
 *    divides a by b using half up rounding and div/0 prevention
 */
#define divsave_rounded(a, b)    (((b) != 0) ? (((a)+((b)>>1))/(b)) : (-1))
#define MIPI_BPS_M_LOWEST     80
#define MIPI_BPS_M_BIGEST     2500
#define MIPI_BPS_M_UNIT       1000000
extern UNICODE_STRING g_RegistryPath;

/*! "brief SleepMSecond 
 *    Delay in milisecond
 *
 * Arg:
 *    LONG msec - miliseconds to delay
 */
void SleepMSecond(
    LONG msec
    );

/*! "brief GetTickCount
 *    Get current system tick count
 *
 * Arg:
 *    LARGE_INTEGER* TickCount - output, tick count get
 */
VOID GetTickCount(
    OUT LARGE_INTEGER* TickCount
    );

/*! "brief QuerySystemTime
 *    Query system time
 *
 * Return:
 *    ULONG - system time
 */
ULONG QuerySystemTime(
    );

/*! "brief ConvertEndian
 *    Convert endian between little endian and big endian
 *
 * Arg:
 *    UINT16* Data - pointer of data buffer
 *    ULONG Length - length of data to convert
 * Return:
 *    UINT8* - pointer of data buffer
 */
UINT8* ConvertEndian(
    UINT16* Data, 
    ULONG Length
    );

/*! "brief ConvertEndianForUSHORT
 *    Convert endian between little endian and big endian for short data type
 *
 * Arg:
 *    UINT16* Data - pointer of data buffer
 *    ULONG Length - length of data to convert
 * Return:
 *    UINT8* - pointer of data buffer
 */
UINT8* ConvertEndianForUSHORT(
    UINT16* Data, 
    ULONG Length
    );

/*! "brief ConvertEndianForULONG
 *    Convert endian between little endian and big endian for long data type
 *
 * Arg:
 *    ULONG* Data - pointer of data buffer
 *    ULONG Length - length of data to convert
 * Return:
 *    UINT8* - pointer of data buffer
 */
UINT8* ConvertEndianForULONG(
    ULONG* Data,
    ULONG Length
    );

/*! "brief OS_ReadRegistry
 *    Read registry from certain path
 *
 * Arg:
 *    PUNICODE_STRING Path - registry path
 *    PUCHAR ValueName - value name
 *    ULONG Type - data type
 *    PUCHAR Buffer - data buffer
 *    PULONG BufferLength - buffer length
 *    ULONG PoolTag - pool tag for memory
 * Return:
 *    NTSTATUS - status
 */
NTSTATUS OS_ReadRegistry(
    IN PUNICODE_STRING Path,
    IN PUCHAR   ValueName,
    IN ULONG    Type,
    IN PUCHAR   Buffer,
    IN PULONG   BufferLength,
    IN ULONG    PoolTag
    );

/*
* Important note:The fourth parameter deviceCtx should be PDEVICE_CONTEXT.
*/
NTSTATUS OS_ReadRegistry_V2(
    IN PUNICODE_STRING Path,
    IN PUCHAR   ValueName,
    IN ULONG    Type,
    IN PUCHAR   Buffer,
    IN PULONG   BufferLength,
    IN ULONG    PoolTag,
    IN void *deviceCtx
    );

/*
* Important note:The fourth parameter deviceCtx should be PDEVICE_CONTEXT.
*/
NTSTATUS OS_ReadSoftwareRegistry(
    IN PUCHAR   ValueName,
    IN PUCHAR   Buffer,
    IN PULONG   BufferLength,
    IN void *deviceCtx
    );

NTSTATUS OS_ReadRegistryValueSize(
    IN PUNICODE_STRING Path,
    IN PUCHAR   ValueName,
    IN ULONG    Type,
    IN PULONG   BufferLength,
    IN ULONG    PoolTag
    );


/*! "brief OS_WriteRegistry
 *    Write registry from certain path
 *
 * Arg:
 *    PUNICODE_STRING Path - registry path
 *    PUCHAR ValueName - value name
 *    ULONG Type - data type
 *    PUCHAR Buffer - data buffer
 *    PULONG BufferLength - buffer length
 * Return:
 *    NTSTATUS - status
 */
NTSTATUS OS_WriteRegistry(
    IN PUNICODE_STRING Path,
    IN PUCHAR   ValueName,
    IN ULONG    Type,
    IN PVOID   Buffer,
    IN ULONG    BufferLength
    );

/*! "brief GetAcpiDsmData
 *    Get ACPI DSM data
 *
 * Arg:
    Arg0: UUID Unique function identifier 
    Arg1: Integer Revision Level
    Arg2: Integer Function Index (0 = Return Supported Functions)
    Arg3: Package Parameters
 * Return:
 *    NTSTATUS - status
*/
NTSTATUS
GetAcpiDsmData(
    IN WDFDEVICE Device,
    IN ULONG PoolTag,
    IN PUCHAR Arg0,
    IN ULONG Arg1,
    IN ULONG Arg2,
    IN ULONG Arg3,
    IN ULONG ValueLength,
    OUT PVOID Value
    );

/*! "brief GetAcpiSsdbData
 *    Get ACPI SSDB data
 *
 * Arg:
    WDFDEVICE Device: device handle 
    ULONG PoolTag: pool tag for memory
    ULONG ValueLength: value length
    PVOID Value: pointer for value to get
 * Return:
 *    NTSTATUS - status
*/
NTSTATUS GetAcpiSsdbData(
    IN WDFDEVICE Device,
    IN ULONG PoolTag,
    IN ULONG ValueLength,
    OUT PVOID Value
    );

/*! "brief GetAcpiSsdbData
 *    Delay that not schedule thread.
 *
 * Arg:
    long long time_delay
    BOOLEAN bSleep
 * Return:
 *  void
*/

// time_delay is in units of 100 nanoseconds.
void safe_delay(long long time_delay, BOOLEAN bSleep);

#endif
