/******************************Module*Header***********************************\
*
*                           *******************
*                           * GDI SAMPLE CODE *
*                           *******************
*
* Module Name: hw.h
*
* All the hardware defines and typedefs.
*
* Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
* Copyright (c) 1995-1999 Microsoft Corporation.  All rights reserved.
*
\******************************************************************************/
#ifndef _HW_H_
#define _HW_H_

#include "p2def.h"

//
// Texture memory allocation macros and structures are in 3DPrivTx.h
//
//
// Definition of handle to a memory region
//
typedef  LONG HMEMREGION;
typedef  LONG HMEMCACHE;
typedef enum
{
    RESIDENCY_NOTLOADED,
    RESIDENCY_PERMANENT,
    RESIDENCY_TRANSIENT,
    RESIDENCY_HOST
} MEM_MGR_RESIDENCY;

//
// Extern declarations
//
extern DWORD    LogicopReadDest[];      // Indicates which logic ops need dest
                                        // read turned on
extern DWORD    ConfigReadDest[];
extern UCHAR    LBWidthBits[];

//
// Definition of counter data area for performance counters (PERFCTR)
//
extern PVOID    pCounterBlock;

//
// Values for flags in HwDataRec
//
typedef enum
{
    GLICAP_NT_CONFORMANT_LINES    = 0x00000001, // draw NT conformant lines
    GLICAP_HW_WRITE_MASK          = 0x00000002, // hardware planemasking
};

typedef int PERMEDIA2_CAPS;

//
// SCISSOR stuff
//
#define SCREEN_SCISSOR_DEFAULT  (0 << 1)
#define SCISSOR_MAX 2047            // Maximum scissor size in P2

//
// PCI device information. Used in an IOCTL return. Ensure this is the same
// as in the miniport drivers permedia.h
//
typedef struct _Hw_Device_Info
{
    ULONG SubsystemId;
    ULONG SubsystemVendorId;
    ULONG VendorId;
    ULONG DeviceId;
    ULONG RevisionId;
    ULONG DeltaRevId;
    ULONG GammaRevId;
    ULONG BoardId;
    ULONG LocalbufferLength;
    LONG  LocalbufferWidth;
    ULONG ActualDacId;
} Hw_Device_Info;


typedef struct tagP2CtxtRec *P2CtxtPtr;

typedef struct _hw_data
{
    DWORD       renderBits;         // Saved render bits set by setup routines
    DWORD       FBWriteMode;        // Software copy of FBWriteMode register
    DWORD       RasterizerMode;     // Software copy of the rasterizer mode
    DWORD       FBPacking;          // Software copy of FBModeSel
    DWORD       FBBlockColor;       // Software copy of FBBlockColor (P1 only)
    DWORD       TextureAddressMode; // Software copy of TextureAddressMode
                                    // (P2 only)
    DWORD       TextureReadMode;    // Software copy of TextureReadMode
                                    // (P2 only)

    ULONG       currentCSbuffer;    // Color space buffer being displayed
    PERMEDIA2_CAPS  flags;          // Various flags

    P2CtxtPtr   pGDICtxt;           // id of the display driver's context for
                                    // this board
    LONG        PixelOffset;        // Last DFB pixel offset

    ULONG       PerfScaleShift;

    PVOID       ContextTable;       // Array of extant contexts
    P2CtxtPtr   pCurrentCtxt;       // id of this board's current context

    union
    {
        UCHAR       _clutBuffer[MAX_CLUT_SIZE];
        VIDEO_CLUT  gammaLUT;       // Saved gamma LUT contents
    };

    //
    // PCI configuration id information
    //
    Hw_Device_Info deviceInfo;
} HwDataRec, *HwDataPtr;


#define TRANSLATE_ADDR_ULONG(a) (a)     //TODO: should be removed in pointer.c

//
// If we have a sparsely mapped framebuffer then we use the xx_REGISTER_ULONG()
// macros, otherwise we just access the framebuffer.
//
#define READ_SCREEN_ULONG(a)\
    ((ppdev->flCaps & CAPS_SPARSE_SPACE) ?\
      (READ_REGISTER_ULONG(a)) : *((volatile PULONG)(a)))

#define WRITE_SCREEN_ULONG(a,d)\
    ((ppdev->flCaps & CAPS_SPARSE_SPACE) ?\
      (WRITE_REGISTER_ULONG(a,d)) : (*(volatile PULONG)(a) = (d)))

//
// Generic macros to access Permedia 2 FIFO and non-FIFO control registers.
// We do nothing sophisticated for the Alpha. We just MEMORY_BARRIER
// everything.
//

#define LD_PERMEDIA_REG(x,y) \
{   \
    WRITE_REGISTER_ULONG(&(ppdev->pCtrlBase[x/sizeof(ULONG)]),y); \
    MEMORY_BARRIER();\
}
    
#define READ_PERMEDIA_REG(x) \
    READ_REGISTER_ULONG(&(ppdev->pCtrlBase[x/sizeof(ULONG)]))

#define READ_PERMEDIA_FIFO_REG(uiTag, d) \
    ((d) = READ_REGISTER_ULONG(&(ppdev->pCoreBase[uiTag*2])))

#define READ_FIFO_REG(uiTag)\
    READ_REGISTER_ULONG(&ppdev->pCoreBase[uiTag*2])

//
// Local variables for all functions that access PERMEDIA 2. Generally we
// use PERMEDIA_DECL. Sometimes we have to split it up if ppdev isn't
// passed into the routine.
//
#define PERMEDIA_DECL_VARS \
    HwDataPtr permediaInfo;

#define PERMEDIA_DECL_INIT \
    permediaInfo = (HwDataPtr)(ppdev->permediaInfo);

#define PERMEDIA_DECL \
    PERMEDIA_DECL_VARS; \
    PERMEDIA_DECL_INIT

// TODO: move to debug???
#if DBG
    VOID vCheckDefaultState(P2DMA * pP2dma);

    #define P2_CHECK_STATE vCheckDefaultState(ppdev->pP2dma)
#else
    #define P2_CHECK_STATE
#endif

//
// Pointer interrupts not enabled so just provide stub definitions
//
#define SYNCHRONOUS_WRITE_ULONG(var, value)
#define SYNCHRONOUS_WRITE_INDIRECT_ULONG(pvar, value)
#define GET_INTR_CMD_BLOCK_MUTEX
#define RELEASE_INTR_CMD_BLOCK_MUTEX

//
// FIFO functions
//
#define MAX_P2_FIFO_ENTRIES         256


#define P2_DEFAULT_FB_DEPTH  P2_SET_FB_DEPTH(ppdev->cPelSize)
#define P2DEPTH8             0
#define P2DEPTH16            1
#define P2DEPTH32            2

//
// External interface to the context switching code. The caller can allocate and
// free a context or ask for a switch to a new context. vSwitchContext
// should not be called except through the given macro. The macro assumes
// that ppdev has been defined.
//
typedef enum
{
    P2CtxtReadWrite,
    P2CtxtWriteOnly,
    P2CtxtUserFunc
} P2CtxtType;

P2CtxtPtr P2AllocateNewContext(PPDev ppdev, 
                          DWORD *pReglist, 
                          LONG lEntries, 
                          P2CtxtType dwCtxtType=P2CtxtReadWrite
                          );

VOID P2FreeContext  (PPDev, P2CtxtPtr);
VOID P2SwitchContext(PPDev, P2CtxtPtr);

//
// Macro used by display driver to validate its context
//
#define VALIDATE_GDI_CONTEXT                                                 \
    P2_VALIDATE_CONTEXT(permediaInfo->pGDICtxt)

//
// Useful macros not defined in standard Permedia 2 header files. Generally, for
// speed we don't want to use the bitfield structures so we define the bit
// shifts to get at the various fields.
//
#define INTtoFIXED(i)   ((i) << 16)         // int to 16.16 fixed format
#define FIXEDtoINT(i)   ((i) >> 16)         // 16.16 fixed format to int
#define INTofFIXED(i)   ((i) & 0xffff0000)  // int part of 16.16
#define FRACTofFIXED(i) ((i) & 0xffff)      // fractional part of 16.16

#define FIXtoFIXED(i)   ((i) << 12)         // 12.4 to 16.16
#define FIXtoINT(i)     ((i) >> 4)          // 28.4 to 28

#define __PERMEDIA_CONSTANT_FB_WRITE   (1 << (4+1))
#define __COLOR_DDA_FLAT_SHADE      (__PERMEDIA_ENABLE | \
                                        (__PERMEDIA_FLAT_SHADE_MODE << 1))
#define __COLOR_DDA_GOURAUD_SHADE   (__PERMEDIA_ENABLE | \
                                        (__PERMEDIA_GOURAUD_SHADE_MODE << 1))

#define INVERT_BITMASK_BITS         (1 << 1)
#define BYTESWAP_BITMASK            (3 << 7)
#define FORCE_BACKGROUND_COLOR      (1 << 6)    // Permedia only

//
// Bits in the Render command
//
#define __RENDER_INCREASE_Y             (1 << 22)
#define __RENDER_INCREASE_X             (1 << 21)
#define __RENDER_VARIABLE_SPANS         (1 << 18)
#define __RENDER_REUSE_BIT_MASK         (1 << 17)
#define __RENDER_TEXTURE_ENABLE         (1 << 13)
#define __RENDER_SYNC_ON_HOST_DATA      (1 << 12)
#define __RENDER_SYNC_ON_BIT_MASK       (1 << 11)
#define __RENDER_RECTANGLE_PRIMITIVE    (__PERMEDIA_RECTANGLE_PRIMITIVE << 6)
#define __RENDER_TRAPEZOID_PRIMITIVE    (__PERMEDIA_TRAPEZOID_PRIMITIVE << 6)
#define __RENDER_LINE_PRIMITIVE         (__PERMEDIA_LINE_PRIMITIVE << 6)
#define __RENDER_POINT_PRIMITIVE        (__PERMEDIA_POINT_PRIMITIVE << 6)
#define __RENDER_FAST_FILL_INC(n)       (((n) >> 4) << 4) // n = 8, 16 or 32
#define __RENDER_FAST_FILL_ENABLE       (1 << 3)
#define __RENDER_RESET_LINE_STIPPLE     (1 << 2)
#define __RENDER_LINE_STIPPLE_ENABLE    (1 << 1)
#define __RENDER_AREA_STIPPLE_ENABLE    (1 << 0)

//
// Bits in the ScissorMode register
//
#define USER_SCISSOR_ENABLE             (1 << 0)
#define SCREEN_SCISSOR_ENABLE           (1 << 1)
#define SCISSOR_XOFFSET                 0
#define SCISSOR_YOFFSET                 16

//
// Bits in the FBReadMode register
//
#define __FB_READ_SOURCE                (1 << 9)
#define __FB_READ_DESTINATION           (1 << 10)
#define __FB_COLOR                      (1 << 15)
#define __FB_WINDOW_ORIGIN              (1 << 16)
#define __FB_PACKED_DATA                (1 << 19)

//
// Extra bits in PERMEDIA FBReadMode
//
#define __FB_RELATIVE_OFFSET            20

//
// P2 also provides a version of Relative Offset in the PackedDataLimits
// register
//
#define __PDL_RELATIVE_OFFSET           29

//
// Bits in the LBReadMode register
//
#define __LB_READ_SOURCE                (1 << 9)
#define __LB_READ_DESTINATION           (1 << 10)
#define __LB_STENCIL                    (1 << 16)
#define __LB_DEPTH                      (1 << 17)
#define __LB_WINDOW_ORIGIN              (1 << 18)
#define __LB_READMODE_PATCH             (1 << 19)
#define __LB_SCAN_INTERVAL_2            (1 << 20)

//
// Bits in the DepthMode register
//
#define __DEPTH_ENABLE                  1
#define __DEPTH_WRITE_ENABLE            (1<<1)
#define __DEPTH_REGISTER_SOURCE         (2<<2)
#define __DEPTH_MSG_SOURCE              (3<<2)
#define __DEPTH_ALWAYS                  (7<<4)

//
// Bits in the LBReadFormat/LBWriteFormat registers
//
#define __LB_FORMAT_DEPTH32             2

//
// Macros to load indexed tags more efficiently than using __HwDMATag struct
//
#define P2_TAG_MAJOR(x)              ((x) & 0xff0)
#define P2_TAG_MINOR(x)              ((x) & 0x00f)

#define P2_TAG_MAJOR_INDEXED(x)                                          \
    ((__PERMEDIA_TAG_MODE_INDEXED << (5+4+1+4)) | P2_TAG_MAJOR(x))
#define P2_TAG_MINOR_INDEX(x)                                            \
    (1 << (P2_TAG_MINOR(x) + 16))

//
// Macro to take a permedia2 logical op and return the enabled LogcialOpMode bits
//
#define P2_ENABLED_LOGICALOP(op)     (((op) << 1) | __PERMEDIA_ENABLE)

#define RECTORIGIN_YX(y,x)              (((y) << 16) | ((x) & 0xFFFF))

//
// Area stipple shifts and bit defines
//
#define AREA_STIPPLE_XSEL(x)            ((x) << 1)
#define AREA_STIPPLE_YSEL(y)            ((y) << 4)
#define AREA_STIPPLE_XOFF(x)            ((x) << 7)
#define AREA_STIPPLE_YOFF(y)            ((y) << 12)
#define AREA_STIPPLE_INVERT_PAT         (1 << 17)
#define AREA_STIPPLE_MIRROR_X           (1 << 18)
#define AREA_STIPPLE_MIRROR_Y           (1 << 19)

//
// We always use 8x8 monochrome brushes.
//
#define AREA_STIPPLE_8x8_ENABLE                                             \
    (__PERMEDIA_ENABLE |                                                    \
    AREA_STIPPLE_XSEL(__PERMEDIA_AREA_STIPPLE_8_PIXEL_PATTERN) |            \
    AREA_STIPPLE_YSEL(__PERMEDIA_AREA_STIPPLE_8_PIXEL_PATTERN))

//
// RasteriserMode values
//
#define BIAS_NONE                  (__PERMEDIA_START_BIAS_ZERO << 4)
#define BIAS_HALF                  (__PERMEDIA_START_BIAS_HALF << 4)
#define BIAS_NEARLY_HALF           (__PERMEDIA_START_BIAS_ALMOST_HALF << 4)

#define FRADJ_NONE                 (__PERMEDIA_FRACTION_ADJUST_NONE << 2)
#define FRADJ_ZERO                 (__PERMEDIA_FRACTION_ADJUST_TRUNC << 2)
#define FRADJ_HALF                 (__PERMEDIA_FRACTION_ADJUST_HALF << 2)
#define FRADJ_NEARLY_HALF          (__PERMEDIA_FRACTION_ADJUST_ALMOST_HALF << 2)


//
// Some constants
//
#define ONE                         0x00010000
#define MINUS_ONE                   0xFFFF0000
#define PLUS_ONE                    ONE
#define NEARLY_ONE                  0x0000FFFF
#define HALF                        0x00008000
#define NEARLY_HALF                 0x00007FFF

//
// Max length of GIQ conformant lines that Permedia2 can draw
// Permedia has only 15 bits of fraction so reduce the lengths.
//
#define MAX_LENGTH_CONFORMANT_NONINTEGER_LINES  (16/2)
#define MAX_LENGTH_CONFORMANT_INTEGER_LINES     (194/2)

//
// We need to byte swap monochrome bitmaps. On 486 we can do this with
// fast assembler.
//
#if defined(_X86_)
//
// This only works on a 486 so the driver won't run on a 386.
//
#define LSWAP_BYTES(dst, pSrc)                                              \
{                                                                           \
    __asm mov eax, pSrc                                                     \
    __asm mov eax, [eax]                                                    \
    __asm bswap eax                                                         \
    __asm mov dst, eax                                                      \
}
#else
#define LSWAP_BYTES(dst, pSrc)                                              \
{                                                                           \
    ULONG   _src = *(ULONG *)pSrc;                                           \
    dst = ((_src) >> 24) |                                                   \
          ((_src) << 24) |                                                   \
          (((_src) >> 8) & 0x0000ff00) |                                     \
          (((_src) << 8) & 0x00ff0000);                                      \
}

#endif

// macro to swap the Red and Blue component of a 32 bit dword
//

#define SWAP_BR(a) ((a & 0xff00ff00l) | \
                   ((a&0xff0000l)>> 16) | \
                   ((a & 0xff) << 16))

//
// min. and max. values for Permedia PP register
#define MAX_PARTIAL_PRODUCT_P2          10
#define MIN_PARTIAL_PRODUCT_P2          5

//
// Permedia2 DMA definitions
//
#include "mini.h"
// structure definitions passed in by the application for mapping and
// unmapping DMA buffers.
//

//
// Registry variable names
//
#define REG_USE_SOFTWARE_WRITEMASK      L"UseSoftwareWriteMask"

//
// Function declarations
//
VOID  vDoMonoBitsDownload(PPDev, BYTE*, LONG, LONG, LONG, LONG);
BOOL bInitializeHW(PPDev);
VOID vDisableHW(PPDev);
VOID vAssertModeHW(PPDev, BOOL);
VOID vP2ChangeFBDepth(PPDev, ULONG);

//
// Calculate the packed partial products
//
VOID    vCalcPackedPP(LONG width, LONG * outPitch, ULONG * outPackedPP);

VOID        vSetNewGammaValue(PPDev ppdev, ULONG ulgvFIX16_16);
BOOL        bInstallGammaLUT(PPDev ppdev, PVIDEO_CLUT pScreenClut);

//
// The following structures and macros define the memory map for the Permedia2
// control registers. We don't use this memory map to access Permedia2 registers
// since on Alpha machines we want to precompute the addresses. So we do
// a TRANSLATE_ADDR_ULONG on all the addresses here and save them into a
// P2RegAddrRec. We use that to obtain the addresses for the different
// registers.
//
typedef struct
{
    ULONG   reg;
    ULONG   pad;
} RAMDAC_REG;

//
// Macros to add padding words to the structures. For the core registers we use
// the tag ids when specifying the pad. So we must multiply by 8 to get a byte
// pad. We need to add an id to make each pad field in the struct unique. The
// id is irrelevant as long as it's different from every other id used in the
// same struct. It's a pity pad##__LINE__ doesn't work.
//
//#define PAD(id, n)              UCHAR   pad##id[n]


//
// Interrupt status bits
//
typedef enum
{
    DMA_INTERRUPT_AVAILABLE     = 0x01, // can use DMA interrupts
    VBLANK_INTERRUPT_AVAILABLE  = 0x02, // can use VBLANK interrupts
} INTERRUPT_CONTROL;

extern DWORD    LogicopReadDest[];  // Indicates which logic ops need dest read
                                    // turned on

#define INTtoFIXED(i)               ((i) << 16)    // int to 16.16 fixed format
#define FIXEDtoINT(i)               ((i) >> 16)    // 16.16 fixed format to int

#define __PERMEDIA_CONSTANT_FB_WRITE                                        \
    (1 << (4+1))
#define __COLOR_DDA_FLAT_SHADE                                              \
    (__PERMEDIA_ENABLE | (__PERMEDIA_FLAT_SHADE_MODE << 1))
#define __COLOR_DDA_GOURAUD_SHADE                                           \
    (__PERMEDIA_ENABLE | (__PERMEDIA_GOURAUD_SHADE_MODE << 1))

#define INVERT_BITMASK_BITS    (1 << 1)

//
// Bits in the Render command
//
#define __RENDER_VARIABLE_SPANS         (1 << 18)
#define __RENDER_SYNC_ON_HOST_DATA      (1 << 12)
#define __RENDER_SYNC_ON_BIT_MASK       (1 << 11)
#define __RENDER_TRAPEZOID_PRIMITIVE    (__PERMEDIA_TRAPEZOID_PRIMITIVE << 6)
#define __RENDER_LINE_PRIMITIVE         (__PERMEDIA_LINE_PRIMITIVE << 6)
#define __RENDER_POINT_PRIMITIVE        (__PERMEDIA_POINT_PRIMITIVE << 6)
#define __RENDER_FAST_FILL_INC(n)       (((n) >> 4) << 4) // n = 8, 16 or 32
#define __RENDER_FAST_FILL_ENABLE       (1 << 3)
#define __RENDER_RESET_LINE_STIPPLE     (1 << 2)
#define __RENDER_LINE_STIPPLE_ENABLE    (1 << 1)
#define __RENDER_AREA_STIPPLE_ENABLE    (1 << 0)
#define __RENDER_TEXTURED_PRIMITIVE     (1 << 13)

//
// Bits in the ScissorMode register
//
#define USER_SCISSOR_ENABLE             (1 << 0)
#define SCREEN_SCISSOR_ENABLE           (1 << 1)
#define SCISSOR_XOFFSET                 0
#define SCISSOR_YOFFSET                 16

//
// Bits in the FBReadMode register
//
#define __FB_READ_SOURCE                (1 << 9)
#define __FB_READ_DESTINATION           (1 << 10)
#define __FB_COLOR                      (1 << 15)
#define __FB_WINDOW_ORIGIN              (1 << 16)
#define __FB_USE_PACKED                 (1 << 19)

//
// Bits in the LBReadMode register
//
#define __LB_READ_SOURCE                (1 << 9)
#define __LB_READ_DESTINATION           (1 << 10)
#define __LB_STENCIL                    (1 << 16)
#define __LB_DEPTH                      (1 << 17)
#define __LB_WINDOW_ORIGIN              (1 << 18)

//
// Area stipple shifts and bit defines
//
#define AREA_STIPPLE_XSEL(x)            ((x) << 1)
#define AREA_STIPPLE_YSEL(y)            ((y) << 4)
#define AREA_STIPPLE_XOFF(x)            ((x) << 7)
#define AREA_STIPPLE_YOFF(y)            ((y) << 12)
#define AREA_STIPPLE_INVERT_PAT         (1 << 17)
#define AREA_STIPPLE_MIRROR_X           (1 << 18)
#define AREA_STIPPLE_MIRROR_Y           (1 << 19)

// we always use 8x8 monochrome brushes.
#define AREA_STIPPLE_8x8_ENABLE \
        (__PERMEDIA_ENABLE | \
         AREA_STIPPLE_XSEL(__PERMEDIA_AREA_STIPPLE_8_PIXEL_PATTERN) | \
         AREA_STIPPLE_YSEL(__PERMEDIA_AREA_STIPPLE_8_PIXEL_PATTERN))

#define DEFAULTWRITEMASK 0xffffffffl


// *******************************************************************
// Permedia Bit Field Macros

// FBReadMode 
#define PM_FBREADMODE_PARTIAL(a)           (a << 0)
#define PM_FBREADMODE_READSOURCE(a)        (a << 9)
#define PM_FBREADMODE_READDEST(a)          (a << 10)
#define PM_FBREADMODE_PATCHENABLE(a)       (a << 18)
#define PM_FBREADMODE_PACKEDDATA(a)        (a << 19)
#define PM_FBREADMODE_RELATIVEOFFSET(a)    (a << 20)
#define PM_FBREADMODE_PATCHMODE(a)         (a << 25)

// Texture read mode
#define PM_TEXREADMODE_ENABLE(a)         (a << 0)
#define PM_TEXREADMODE_WIDTH(a)          (a << 9)
#define PM_TEXREADMODE_HEIGHT(a)         (a << 13)
#define PM_TEXREADMODE_FILTER(a)         (a << 17)

// PackedDataLimits
#define PM_PACKEDDATALIMITS_OFFSET(a)    (a << 29)
#define PM_PACKEDDATALIMITS_XSTART(a)    (a << 16)
#define PM_PACKEDDATALIMITS_XEND(a)      (a << 0)

// Window Register
#define PM_WINDOW_LBUPDATESOURCE(a)      (a << 4)
#define PM_WINDOW_DISABLELBUPDATE(a)     (a << 18)

// Colors
#define PM_BYTE_COLOR(a) (a << 15)

// Config register
#define PM_CHIPCONFIG_AGPCAPABLE (1 << 9)


static __inline int log2(int s)
{
    int d = 1, iter = -1;
    do {
         d *= 2;
         iter++;
    } while (d <= s);
    return iter;
}

VOID
P2DisableAllUnits(PPDev ppdev);

#if DBG && TRACKMEMALLOC
#define ENGALLOCMEM( opt, size, tag)\
    MEMTRACKERALLOCATEMEM( EngAllocMem( opt, size, tag), size, __FILE__, __LINE__, FALSE)
#define ENGFREEMEM( obj)\
    { MEMTRACKERFREEMEM(obj); EngFreeMem( obj);}
#else
#define ENGALLOCMEM( opt, size, tag)\
    EngAllocMem( opt, size, tag)
#define ENGFREEMEM( obj)\
    EngFreeMem( obj)
#endif
    

#endif  // _HW_H_


