|
|
/******************************************************************************\
* * $Workfile: LAGUNA.H $ * * This file to be included by all host programs. * * Copyright (c) 1995,1997 Cirrus Logic, Inc. * * $Log: X:/log/laguna/nt35/displays/cl546x/LAGUNA.H $ * * Rev 1.38 Mar 04 1998 16:13:30 frido * Removed a warning message for the 5462/5464 chips in the REQUIRE * macro. * * Rev 1.37 Mar 04 1998 16:08:50 frido * Removed an invalid break. * * Rev 1.36 Mar 04 1998 14:54:48 frido * Added contional REQUIRE in the new shadow macros. * * Rev 1.35 Mar 04 1998 14:52:54 frido * Added new shadowing macros. * * Rev 1.34 Feb 27 1998 17:02:16 frido * Changed REQUIRE and WRITE_STRING macros for new * shadowQFREE register. * * Rev 1.33 Jan 20 1998 11:42:46 frido * Changed REQUIRE and WRITESTRING macros to support the new * scheme for GBP on. * Added shadowing of BGCOLOR and DRAWBLTDEF registers. * * Rev 1.32 Jan 16 1998 09:50:38 frido * Changed the way the GBP OFF handles WRITE_STRING macros. * * Rev 1.31 Dec 10 1997 13:24:58 frido * Merged from 1.62 branch. * * Rev 1.30.1.0 Nov 18 1997 18:09:00 frido * Changed WRITE_STRING macro so it will work when * DATASTREAMING is turned of. * Changed FUDGE to 0, we are not using DMA inside NT. * * Rev 1.30 Nov 04 1997 19:01:18 frido * Changed HOSTDATA size from 0x800 DWORDs into 0x800 BYTEs. Silly me! * * Rev 1.29 Nov 04 1997 09:17:30 frido * Added Data Streaming macros (REQUIRE and WRITE_STRING). * \******************************************************************************/
#ifndef _LAGUNA_H
#define _LAGUNA_H
#include "optimize.h"
#include "config.h"
#include "lgregs.h"
//
// PCI ID for Laguna chips.
//
#define CL_GD5462 0x00D0 // 5462
#define CL_GD5464 0x00D4 // 5464
#define CL_GD5464_BD 0x00D5 // 5464 BD
#define CL_GD5465 0x00D6 // 5465
//
// These chips don't exist yet, but we're FORWARD COMPATIBLE
// so we'll define them anyway. I've been GUARENTEED that they
// will look and feel just like 5465 chips.
//
#define CL_GD546x_F7 0x00D7
#define CL_GD546x_F8 0x00D8
#define CL_GD546x_F9 0x00D9
#define CL_GD546x_FA 0x00DA
#define CL_GD546x_FB 0x00DB
#define CL_GD546x_FC 0x00DC
#define CL_GD546x_FD 0x00DD
#define CL_GD546x_FE 0x00DE
#define CL_GD546x_FF 0x00DF
//
// CHIP BUG: For certian values in PRESET register cursor enable/disable
// causes scanlines to be duplicated at the cursor hot spot. (Seen
// as screen jump.) There are lots of ways around this. The easiest
// is to turn the cursor on and leave it on. Enable/Disable is handled by
// moving the cursor on/off the visable screen.
//
#define HW_PRESET_BUG 1
// The 5465 (to at least AC) has a problem when PCI configuration space
// is accessible in memory space. On 16-bit writes, a 32-bit write is
// actually performed, so the next register has garbage written to it.
// We get around this problem by clearing bit 0 of the Vendor Specific
// Control register in PCI configuration space. When this bit is set
// to 0, PCI configuration registers are not available through memory
// mapped I/O. Since some functions, such as power management, require
// access to PCI registers, the display driver must post a message to
// the miniport to enable this bit when needed.
//
#define VS_CONTROL_HACK 1
#if ENABLE_LOG_FILE
extern long lg_i; extern char lg_buf[256]; #endif
#if POINTER_SWITCH_ENABLED
extern int pointer_switch; #endif
// The definitions are not portable. 486 / PC only !!!
typedef struct { BYTE b; BYTE g; BYTE r; } pix24;
typedef struct { BYTE u; BYTE y1; BYTE v; BYTE y2; } yuv_422;
typedef struct { unsigned int v : 6; unsigned int u : 6; unsigned int y0: 5; unsigned int y1: 5; unsigned int y2: 5; unsigned int y3: 5; } yuv_411;
typedef struct { unsigned int b : 5; unsigned int g : 5; unsigned int r : 5; } rgb_555;
typedef struct { unsigned int b : 5; unsigned int g : 6; unsigned int r : 5; } rgb_565;
typedef union { DWORD p32; yuv_422 yuv422; yuv_411 yuv411; pix24 p24; rgb_555 rgb555; rgb_565 rgb565; WORD p16[2]; BYTE p8[4]; } pixel;
#define FALSE 0
#ifndef TRUE
#define TRUE (~FALSE)
#endif
/* from struct.h */ #define fldoff(str, fld) ((int)&(((struct str *)0)->fld))
#define fldsiz(str, fld) (sizeof(((struct str *)0)->fld))
#define HPRR(pr_reg) (_AP_direct_read(PADDR(pr_reg),fldsiz(PLUTOREGS,pr_reg), (ul)0))
#define RPR(pr_reg) HPRR(pr_reg)
#define EHIST (*(EXHIST*)excepttion) /* Exception History buffer */
#define STAMP (*(bytearray*)0x0) /* time date stamp */
#define HISTORYBUFFERADDR (ul)&history /* 34020 address of recording */
/* External functions the host program can call */
/*-------------------------------------------------------------------------*/
/* Function prototypes for emulator. Functions defined in host_if.c */ int _cdecl _AP_init(int mode, void * frame_buf); void _cdecl _AP_write(ul addr, int size, ul data); ul _cdecl _AP_read(ul addr,int size); void _cdecl _AP_run(void); boolean _cdecl _AP_busy(); boolean _cdecl _AP_done(); boolean _cdecl _AP_rfifo_empty(); boolean _cdecl _AP_require(int size); ul _cdecl _AP_direct_read(ul addr,int size); void _cdecl _AP_fb_write(ul offset, pixel data, ul size); pixel _cdecl _AP_fb_read(ul offset, ul size);
#if LOG_QFREE
#define START_OF_BLT() \
do{ \ CHECK_QFREE(); \ } while(0)
#define END_OF_BLT() \
do{ \ } while(0) #else
#define START_OF_BLT()
#define END_OF_BLT()
#endif
//
// This waits for the chip to go idle
//
#define WAIT_FOR_IDLE() \
do { \ while (LLDR_SZ (grSTATUS) != 0); \ } while (0)
//
// Macro to require a certian number of free queue entries.
//
#if DATASTREAMING
#define FUDGE 2
#define REQUIRE(n) \
{ \ if (ppdev->dwDataStreaming & 0x80000000) \ { \ if (ppdev->shadowQFREE < ((n) + FUDGE)) \ { \ while (ppdev->shadowQFREE < (n) + FUDGE) \ { \ ppdev->shadowQFREE = LLDR_SZ(grQFREE); \ } \ } \ ppdev->shadowQFREE -= (BYTE) n; \ } \ else if (ppdev->dwDataStreaming) \ { \ if (LLDR_SZ(grQFREE) < ((n) + FUDGE)) \ { \ while (LLDR_SZ(grSTATUS) & 0x8005) ; \ ppdev->dwDataStreaming = 0; \ } \ } \ } #define ENDREQUIRE() \
{ \ ppdev->dwDataStreaming |= 1; \ } #define WRITE_STRING(src, dwords) \
{ \ ULONG nDwords, nTotal = (ULONG) (dwords); \ PULONG data = (PULONG) (src); \ if (ppdev->dwDataStreaming & 0x80000000) \ { \ while (nTotal > 0) \ { \ nDwords = (ULONG) ppdev->shadowQFREE; \ if (nDwords > FUDGE) \ { \ nDwords = min(nDwords - FUDGE, nTotal); \ memcpy((LPVOID) ppdev->pLgREGS->grHOSTDATA, data, nDwords * 4); \ data += nDwords; \ nTotal -= nDwords; \ } \ ppdev->shadowQFREE = LLDR_SZ(grQFREE); \ } \ } \ else \ { \ if ( ppdev->dwDataStreaming && (LLDR_SZ(grQFREE) < nTotal) ) \ { \ while (LLDR_SZ(grSTATUS) & 0x8005) ; \ ppdev->dwDataStreaming = 0; \ } \ while (nTotal > 0) \ { \ nDwords = min(nTotal, 0x200); \ memcpy((LPVOID) ppdev->pLgREGS->grHOSTDATA, data, nDwords * 4); \ data += nDwords; \ nTotal -= nDwords; \ } \ } \ } #else
#define REQUIRE(n)
#define ENDREQUIRE()
#define WRITE_STRING(src, dwords) \
{ \ ULONG nDwords, nTotal = (ULONG) (dwords); \ PULONG data = (PULONG) (src); \ while (nTotal > 0) \ { \ nDwords = min(nTotal, 0x200); \ memcpy((LPVOID) ppdev->pLgREGS->grHOSTDATA, data, nDwords * 4); \ data += nDwords; \ nTotal -= nDwords; \ } \ } #endif
//
// Macros to read Laguna registers.
//
#define LADDR(pr_reg) fldoff(GAR,pr_reg)
// #define LLDR(pr_reg,pr_siz) _AP_direct_read((ul)LADDR(pr_reg),pr_siz)
#define LLDR(pr_reg,pr_siz) (ppdev->pLgREGS_real->pr_reg)
#define LLDR_SZ(pr_reg) LLDR(pr_reg, fldsiz(GAR,pr_reg))
// #define LLR(pr_reg,pr_siz) _AP_read((ul)LADDR(pr_reg),pr_siz)
#define LLR(pr_reg,pr_siz) LLDR(pr_reg,pr_siz)
#define LLR_SZ(pr_reg) LLR(pr_reg, fldsiz(GAR,pr_reg))
#if LOG_WRITES
#define LG_LOG(reg,val) \
do { \ lg_i = sprintf(lg_buf,"LL\t%4X\t%08X\r\n", \ ((DWORD)(&ppdev->pLgREGS->reg) - (DWORD)(&ppdev->pLgREGS->grCR0)), \ (val)); \ WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex); \ } while(0) #else
#define LG_LOG(reg,val)
#endif
//
// Macros to write Laguna registers.
//
// This is an amazingly, incredibly hairy macro that, believe it or not,
// will be greatly reduced by a good compiler. The "if" can be
// pre-determined by the compiler.
// The purpose of this is to ensure that exactly the right number of bytes
// is written to the chip. If the programmer writes, say, a BYTE to a
// DWORD sized register, we need to be sure that the byte is zero extended
// and that a full DWORD gets written.
//
#define LRWRITE(pr_reg,pr_siz,value) \
do { \ LG_LOG(pr_reg,(value)); \ if (sizeof(ppdev->pLgREGS->pr_reg) == sizeof(BYTE)) \ { \ *(volatile BYTE *)(&ppdev->pLgREGS->pr_reg) = (BYTE)(value); \ } \ else if (sizeof(ppdev->pLgREGS->pr_reg) == sizeof(WORD)) \ { \ *(volatile WORD *)(&ppdev->pLgREGS->pr_reg) = (WORD)(value); \ *(volatile WORD *)(&ppdev->pLgREGS->grBOGUS) = (WORD)(value); \ LG_LOG(grBOGUS,(value)); \ } \ else \ { \ *(volatile DWORD *)(&ppdev->pLgREGS->pr_reg) = (DWORD)(value); \ } \ } while(0)
#define LL(pr_reg,value) LRWRITE(pr_reg, fldsiz(GAR,pr_reg), value)
// ----------------------------------------------------------------------------
//
// Certian registers have been giving us problems. We provide special
// write macros for them.
//
//
// Writes any 8 bit register.
//
#define LL8(pr_reg,value) \
do { \ LG_LOG(pr_reg,(value)); \ (*(volatile BYTE *)(&ppdev->pLgREGS->pr_reg) = (BYTE)(value)); \ } while(0)
//
// Writes any 16 bit register.
//
#define LL16(pr_reg,value) \
do { \ LG_LOG(pr_reg,(value)); \ (*(volatile WORD *)(&ppdev->pLgREGS->pr_reg) = (WORD)(value)); \ } while(0)
//
// Double writes any 16 bit register.
//
#define LL16d(pr_reg,value) \
do { \ (*(volatile WORD *)(&ppdev->pLgREGS->pr_reg) = (WORD)(value)); \ LG_LOG(pr_reg,(value)); \ (*(volatile WORD *)(&ppdev->pLgREGS->grBOGUS) = (WORD)(value)); \ LG_LOG(grBOGUS,(value)); \ } while(0)
//
// Writes any 32 bit register.
//
#define LL32(pr_reg,value) \
{ \ *(volatile DWORD *)(&ppdev->pLgREGS->pr_reg) = (DWORD)(value); \ }
//
// MACROS FOR BLTEXT REGISTER.
//
#define LL_BLTEXT(x,y) \
LL32 (grBLTEXT_EX.dw, (((DWORD)(y) << 16) | ((DWORD)(x))))
#if ! DRIVER_5465
#define LL_MBLTEXT(x,y) \
do { \ LL16 (grMBLTEXT_EX.pt.X, x); \ LL16 (grBLTEXT_EX.pt.Y, y); \ } while(0) #else
#define LL_MBLTEXT(x,y) \
LL32 (grMBLTEXT_EX.dw, (((DWORD)(y) << 16) | ((DWORD)(x)))) #endif
#define LL_BLTEXTR(x,y) \
LL32 (grBLTEXTR_EX.dw, (((DWORD)(y) << 16) | ((DWORD)(x))))
#define LL_BLTEXT_EXT(x,y) \
LL32 (grBLTEXT.dw, (((DWORD)(y) << 16) | ((DWORD)(x))))
#define LL_MBLTEXT_EXT(x,y) \
LL32 (grMBLTEXT.dw, (((DWORD)(y) << 16) | ((DWORD)(x))))
// Launch a BLT using the color translation features of the
// resize engine. (1:1 resize)
#define LL_BLTEXT_XLATE(src_bpp, x, y) \
do {\ LL16 (grMIN_X, (~((x)-1)));\ LL16 (grMAJ_X, (x));\ LL16 (grACCUM_X, ((x)-1));\ LL16 (grMIN_Y, (~((y)-1)));\ LL16 (grMAJ_Y, (y));\ LL16 (grACCUM_Y, ((y)-1));\ LL16 (grSRCX, (((x)*(src_bpp)) >> 3) );\ LL_BLTEXTR((x), (y));\ } while(0)
//
// MACROS FOR CLIPULE/CLIPLOR REGISTERS.
//
#define LL_CLIPULE(x,y) \
LL32 (grCLIPULE.dw, (((DWORD)(y) << 16) | ((DWORD)(x))));
#define LL_MCLIPULE(x,y) \
LL32 (grMCLIPULE.dw, (((DWORD)(y) << 16) | ((DWORD)(x))));
#define LL_CLIPLOR(x,y) \
LL32 (grCLIPLOR.dw, (((DWORD)(y) << 16) | ((DWORD)(x))));
#define LL_MCLIPLOR(x,y) \
LL32 (grMCLIPLOR.dw, (((DWORD)(y) << 16) | ((DWORD)(x))));
#define LL_CLIPULE_EX(x,y) \
LL32 (grCLIPULE_EX.dw, (((DWORD)(y) << 16) | ((DWORD)(x))));
#define LL_MCLIPULE_EX(x,y) \
LL32 (grMCLIPULE_EX.dw, (((DWORD)(y) << 16) | ((DWORD)(x))));
#define LL_CLIPLOR_EX(x,y) \
LL32 (grCLIPLOR_EX.dw, (((DWORD)(y) << 16) | ((DWORD)(x))));
#define LL_MCLIPLOR_EX(x,y) \
LL32 (grMCLIPLOR_EX.dw, (((DWORD)(y) << 16) | ((DWORD)(x))));
//
// MACROS FOR OP0_opRDRAM REGISTER.
//
#define LL_OP0(x,y) \
LL32 (grOP0_opRDRAM.dw, (((DWORD)(y) << 16) | ((DWORD)(x))))
#define LL_OP0_MONO(x,y) \
LL32 (grOP0_opMRDRAM.dw, (((DWORD)(y) << 16) | ((DWORD)(x))))
//
// MACROS FOR OP1_opRDRAM REGISTER.
//
#define LL_OP1(x,y) \
LL32 (grOP1_opRDRAM.dw, (((DWORD)(y) << 16) | ((DWORD)(x))))
#define LL_OP1_MONO(x,y) \
LL32 (grOP1_opMRDRAM.dw, (((DWORD)(y) << 16) | ((DWORD)(x))))
//
// MACROS FOR OP2_opRDRAM REGISTER.
//
#define LL_OP2(x,y) \
LL32 (grOP2_opRDRAM.dw, (((DWORD)(y) << 16) | ((DWORD)(x))))
#define LL_OP2_MONO(x,y) \
LL32 (grOP2_opMRDRAM.dw, (((DWORD)(y) << 16) | ((DWORD)(x))))
//
// -- End of special write macros --------------------------------------------
//
/* HPR is the copy of REGISTER_STRUCTURE that the host reads and writes from.
PR is the actual register state after the information has gone through the FIFO. Immediate registers are kept up-to-date in HPR. These structures are allocated in the link file. */
extern GAR PR; /* the emulator working copy */ extern GAR HPR[4]; /* the "host" copy */
#define LAGUNA_SRAM_SIZE 32 /* dwords */
#define IS_SRC 0x03 /* Source mask. */
struct _vid_mode { BYTE Bpp; // Bytes per pixel (8 / 16 / 24 / 32)
WORD Xextent; // Display rsolution in pixels eg 1280
WORD Yextent; // Vertical display resolution
WORD Xpitch; // Offset in bytes from line 0 to line 1
int Vesa_Mode; // Mode number for VESA ( if supported by S3 )
};
typedef struct _vid_mode vid_mode; typedef vid_mode *vid_ptr;
/***************************************************************************
* * MACRO: SYNC_W_3D * * DESCRIPTION: If 3d context(s) active, wait until 3d engine idle * or until 1,000,000 checks have failed * ****************************************************************************/
#if WINNT_VER40 && DRIVER_5465 // WINNT_VER40
#define SYNC_3D_CONDITIONS (ST_POLY_ENG_BUSY|ST_EXEC_ENG_3D_BUSY|ST_XY_ENG_BUSY|/*ST_BLT_ENG_BUSY|*/ST_BLT_WF_EMPTY)
#define ENSURE_3D_IDLE(ppdev) \
{ \ if (ppdev->pLgREGS != NULL) \ { \ int num_syncs=2; \ /* there is a slight chance of a window in which all bits go off while engine fetching */ \ /* next command - double read should catch that */ \ while (num_syncs--) \ { \ int status; \ volatile int wait_count=0; \ do \ { \ status = (*((volatile *)((DWORD *)(ppdev->pLgREGS) + PF_STATUS_3D)) & 0x3FF) ^ SYNC_3D_CONDITIONS; \ /* do something to give bus a breather, and to prevent eternal stall */ \ wait_count++; \ } while(((status & SYNC_3D_CONDITIONS) != SYNC_3D_CONDITIONS) && wait_count<1000000); \ } \ } \ }
#define SYNC_W_3D(ppdev) \
{ \ if (ppdev->NumMCDContexts > 0) \ { \ ENSURE_3D_IDLE(ppdev); \ } \ }
#else // WINNT_VER40 && DRIVER_5465
// no 3D on NT before NT4.0. No 3D on 62 and not used on 64.
#define ENSURE_3D_IDLE(ppdev) {}
#define SYNC_W_3D(ppdev) {}
#endif // WINNT_VER40
//
// New shadowing macros.
//
#define LL_FGCOLOR(color, r) \
{ \ if ((DWORD) (color) != ppdev->shadowFGCOLOR) \ { \ if (r) REQUIRE(r); \ LL32(grOP_opFGCOLOR, ppdev->shadowFGCOLOR = (DWORD) (color)); \ } \ }
#define LL_BGCOLOR(color, r) \
{ \ if ((DWORD) (color) != ppdev->shadowBGCOLOR) \ { \ if (r) REQUIRE(r); \ LL32(grOP_opBGCOLOR, ppdev->shadowBGCOLOR = (DWORD) (color)); \ } \ }
#define LL_DRAWBLTDEF(drawbltdef, r) \
{ \ if ((DWORD) (drawbltdef) != ppdev->shadowDRAWBLTDEF) \ { \ if (r) REQUIRE(r); \ LL32(grDRAWBLTDEF, ppdev->shadowDRAWBLTDEF = (DWORD) (drawbltdef)); \ } \ }
#endif /* ndef _LAGUNA_H */
|