461 lines
12 KiB
C
461 lines
12 KiB
C
|
/******************************Module*Header*******************************\
|
||
|
*
|
||
|
* *******************
|
||
|
* * GDI SAMPLE CODE *
|
||
|
* *******************
|
||
|
*
|
||
|
* Module Name: debug.c
|
||
|
*
|
||
|
* Debug helper routines.
|
||
|
*
|
||
|
* Copyright (c) 1992-1998 Microsoft Corporation
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
|
||
|
#if DBG
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
// DEBUGGING INITIALIZATION CODE
|
||
|
//
|
||
|
// When you're bringing up your display for the first time, you can
|
||
|
// recompile with 'DebugLevel' set to 100. That will cause absolutely
|
||
|
// all DISPDBG messages to be displayed on the kernel debugger (this
|
||
|
// is known as the "PrintF Approach to Debugging" and is about the only
|
||
|
// viable method for debugging driver initialization code).
|
||
|
|
||
|
LONG DebugLevel = 0; // Set to '100' to debug initialization code
|
||
|
// (the default is '0')
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
LONG gcFifo = 0; // Number of currently free FIFO entries
|
||
|
|
||
|
BOOL gbCrtcCriticalSection = FALSE;
|
||
|
// Have we acquired the CRTC register
|
||
|
// critical section?
|
||
|
|
||
|
#define LARGE_LOOP_COUNT 10000000
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
// Miscellaneous Driver Debug Routines
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Routine Description:
|
||
|
*
|
||
|
* This function is variable-argument, level-sensitive debug print
|
||
|
* routine.
|
||
|
* If the specified debug level for the print statement is lower or equal
|
||
|
* to the current debug level, the message will be printed.
|
||
|
*
|
||
|
* Arguments:
|
||
|
*
|
||
|
* DebugPrintLevel - Specifies at which debugging level the string should
|
||
|
* be printed
|
||
|
*
|
||
|
* DebugMessage - Variable argument ascii c string
|
||
|
*
|
||
|
* Return Value:
|
||
|
*
|
||
|
* None.
|
||
|
*
|
||
|
***************************************************************************/
|
||
|
|
||
|
VOID
|
||
|
DebugPrint(
|
||
|
LONG DebugPrintLevel,
|
||
|
PCHAR DebugMessage,
|
||
|
...
|
||
|
)
|
||
|
{
|
||
|
va_list ap;
|
||
|
|
||
|
va_start(ap, DebugMessage);
|
||
|
|
||
|
if (DebugPrintLevel <= DebugLevel)
|
||
|
{
|
||
|
EngDebugPrint(STANDARD_DEBUG_PREFIX, DebugMessage, ap);
|
||
|
EngDebugPrint("", "\n", ap);
|
||
|
}
|
||
|
|
||
|
va_end(ap);
|
||
|
|
||
|
} // DebugPrint()
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* VOID vCheckDataComplete
|
||
|
\**************************************************************************/
|
||
|
|
||
|
VOID vCheckDataReady(
|
||
|
PDEV* ppdev)
|
||
|
{
|
||
|
ASSERTDD((IO_GP_STAT(ppdev) & HARDWARE_BUSY),
|
||
|
"Not ready for data transfer.");
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* VOID vCheckDataComplete
|
||
|
\**************************************************************************/
|
||
|
|
||
|
VOID vCheckDataComplete(
|
||
|
PDEV* ppdev)
|
||
|
{
|
||
|
LONG i;
|
||
|
|
||
|
// We loop because it may take a while for the hardware to finish
|
||
|
// digesting all the data we transferred:
|
||
|
|
||
|
for (i = LARGE_LOOP_COUNT; i > 0; i--)
|
||
|
{
|
||
|
if (!(IO_GP_STAT(ppdev) & HARDWARE_BUSY))
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
RIP("Data transfer not complete.");
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* VOID vOutFifoW
|
||
|
\**************************************************************************/
|
||
|
|
||
|
VOID vOutFifoW(
|
||
|
VOID* p,
|
||
|
ULONG v)
|
||
|
{
|
||
|
gcFifo--;
|
||
|
if (gcFifo < 0)
|
||
|
{
|
||
|
gcFifo = 0;
|
||
|
RIP("Incorrect FIFO wait count");
|
||
|
}
|
||
|
|
||
|
WRITE_PORT_USHORT(p, (USHORT)v);
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* VOID vOutFifoPseudoD
|
||
|
\**************************************************************************/
|
||
|
|
||
|
VOID vOutFifoPseudoD(
|
||
|
PDEV* ppdev,
|
||
|
VOID* p,
|
||
|
ULONG v)
|
||
|
{
|
||
|
ULONG ulMiscState;
|
||
|
|
||
|
ASSERTDD(!(ppdev->flCaps & CAPS_MM_IO),
|
||
|
"No pseudo 32-bit writes when using memory-mapped I/O");
|
||
|
ASSERTDD(ppdev->iBitmapFormat == BMF_32BPP,
|
||
|
"We're trying to do 32bpp output while not in 32bpp mode");
|
||
|
|
||
|
IO_GP_WAIT(ppdev); // Wait so we don't interfere with any
|
||
|
// pending commands waiting on the
|
||
|
// FIFO
|
||
|
IO_READ_SEL(ppdev, 6); // We'll be reading index 0xE
|
||
|
IO_GP_WAIT(ppdev); // Wait until that's processed
|
||
|
IO_RD_REG_DT(ppdev, ulMiscState); // Read ulMiscState
|
||
|
|
||
|
ASSERTDD((ulMiscState & 0x10) == 0,
|
||
|
"Register select flag is out of sync");
|
||
|
|
||
|
gcFifo -= 2;
|
||
|
if (gcFifo < 0)
|
||
|
{
|
||
|
gcFifo = 0;
|
||
|
RIP("Incorrect FIFO wait count");
|
||
|
}
|
||
|
|
||
|
OUT_PSEUDO_DWORD(p, v);
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* VOID vWriteFifoW
|
||
|
\**************************************************************************/
|
||
|
|
||
|
VOID vWriteFifoW(
|
||
|
VOID* p,
|
||
|
ULONG v)
|
||
|
{
|
||
|
gcFifo--;
|
||
|
if (gcFifo < 0)
|
||
|
{
|
||
|
gcFifo = 0;
|
||
|
RIP("Incorrect FIFO wait count");
|
||
|
}
|
||
|
|
||
|
WRITE_REGISTER_USHORT(p, (USHORT) v);
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* VOID vWriteFifoD
|
||
|
\**************************************************************************/
|
||
|
|
||
|
VOID vWriteFifoD(
|
||
|
VOID* p,
|
||
|
ULONG v)
|
||
|
{
|
||
|
gcFifo--;
|
||
|
if (gcFifo < 0)
|
||
|
{
|
||
|
gcFifo = 0;
|
||
|
RIP("Incorrect FIFO wait count");
|
||
|
}
|
||
|
|
||
|
WRITE_REGISTER_ULONG(p, v);
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* VOID vIoFifoWait
|
||
|
\**************************************************************************/
|
||
|
|
||
|
VOID vIoFifoWait(
|
||
|
PDEV* ppdev,
|
||
|
LONG level)
|
||
|
{
|
||
|
LONG i;
|
||
|
|
||
|
ASSERTDD((level > 0) && (level <= 8), "Illegal wait level");
|
||
|
|
||
|
gcFifo = level;
|
||
|
|
||
|
for (i = LARGE_LOOP_COUNT; i != 0; i--)
|
||
|
{
|
||
|
if (!(IO_FIFO_BUSY(ppdev, level)))
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
RIP("vIoFifoWait timeout -- The hardware is in a funky state.");
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* VOID vMmFifoWait
|
||
|
\**************************************************************************/
|
||
|
|
||
|
VOID vMmFifoWait(
|
||
|
PDEV* ppdev,
|
||
|
BYTE* pjMmBase,
|
||
|
LONG level)
|
||
|
{
|
||
|
LONG i;
|
||
|
|
||
|
// We only enabled MM I/O on the 864/964 and newer, so we can wait
|
||
|
// for up to 13 FIFO slots:
|
||
|
|
||
|
ASSERTDD((level > 0) && (level <= 13), "Illegal wait level");
|
||
|
|
||
|
gcFifo = level;
|
||
|
|
||
|
for (i = LARGE_LOOP_COUNT; i != 0; i--)
|
||
|
{
|
||
|
if (!(MM_FIFO_BUSY(ppdev, pjMmBase, level)))
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
RIP("vMmFifoWait timeout -- The hardware is in a funky state.");
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* VOID vNwFifoWait
|
||
|
\**************************************************************************/
|
||
|
|
||
|
VOID vNwFifoWait(
|
||
|
PDEV* ppdev,
|
||
|
BYTE* pjMmBase,
|
||
|
LONG level)
|
||
|
{
|
||
|
LONG i;
|
||
|
|
||
|
ASSERTDD((level > 0) && (level <= 13), "Illegal wait level");
|
||
|
|
||
|
gcFifo = level;
|
||
|
|
||
|
for (i = LARGE_LOOP_COUNT; i != 0; i--)
|
||
|
{
|
||
|
if (!(NW_FIFO_BUSY(ppdev, pjMmBase, level)))
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
RIP("vNwFifoWait timeout -- The hardware is in a funky state.");
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* VOID vDbgFakeWait
|
||
|
\**************************************************************************/
|
||
|
|
||
|
VOID vDbgFakeWait(
|
||
|
PDEV* ppdev,
|
||
|
BYTE* pjMmBase,
|
||
|
LONG level)
|
||
|
{
|
||
|
gcFifo = level;
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* VOID vIoGpWait
|
||
|
\**************************************************************************/
|
||
|
|
||
|
VOID vIoGpWait(
|
||
|
PDEV* ppdev)
|
||
|
{
|
||
|
LONG i;
|
||
|
|
||
|
gcFifo = (ppdev->flCaps & CAPS_16_ENTRY_FIFO) ? 16 : 8;
|
||
|
|
||
|
for (i = LARGE_LOOP_COUNT; i != 0; i--)
|
||
|
{
|
||
|
if (!(IO_GP_STAT(ppdev) & HARDWARE_BUSY))
|
||
|
return; // It isn't busy
|
||
|
}
|
||
|
|
||
|
RIP("vIoGpWait timeout -- The hardware is in a funky state.");
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* VOID vNwGpWait
|
||
|
\**************************************************************************/
|
||
|
|
||
|
VOID vNwGpWait(
|
||
|
PDEV* ppdev,
|
||
|
BYTE* pjMmBase)
|
||
|
{
|
||
|
LONG i;
|
||
|
|
||
|
gcFifo = 16;
|
||
|
|
||
|
for (i = LARGE_LOOP_COUNT; i != 0; i--)
|
||
|
{
|
||
|
if (!NW_GP_BUSY(ppdev, pjMmBase))
|
||
|
return; // It isn't busy
|
||
|
}
|
||
|
|
||
|
RIP("vNwGpWait timeout -- The hardware is in a funky state.");
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* VOID vIoAllEmpty
|
||
|
\**************************************************************************/
|
||
|
|
||
|
VOID vIoAllEmpty(
|
||
|
PDEV* ppdev)
|
||
|
{
|
||
|
LONG i;
|
||
|
|
||
|
ASSERTDD(ppdev->flCaps & CAPS_16_ENTRY_FIFO,
|
||
|
"Can't call ALL_EMPTY on chips with 8-deep FIFOs");
|
||
|
|
||
|
gcFifo = 16;
|
||
|
|
||
|
for (i = LARGE_LOOP_COUNT; i != 0; i--)
|
||
|
{
|
||
|
if (IO_GP_STAT(ppdev) & GP_ALL_EMPTY) // Not implemented on 911/924s
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
RIP("ALL_EMPTY timeout -- The hardware is in a funky state.");
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routines*****************************\
|
||
|
* UCHAR jInp() - INP()
|
||
|
* USHORT wInpW() - INPW()
|
||
|
* VOID vOutp() - OUTP()
|
||
|
* VOID vOutpW() - OUTPW()
|
||
|
*
|
||
|
* Debug thunks for general I/O routines. This is used primarily to verify
|
||
|
* that any code accessing the CRTC register has grabbed the CRTC critical
|
||
|
* section (necessary because with GCAPS_ASYNCMOVE, DrvMovePointer calls
|
||
|
* may happen at any time, and they need to access the CRTC register).
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
UCHAR jInp(BYTE* pjIoBase, ULONG p)
|
||
|
{
|
||
|
if (((p == CRTC_INDEX) || (p == CRTC_DATA)) &&
|
||
|
(!gbCrtcCriticalSection))
|
||
|
{
|
||
|
RIP("Must have acquired CRTC critical section to access CRTC register");
|
||
|
}
|
||
|
|
||
|
CP_EIEIO();
|
||
|
return((UCHAR) READ_PORT_UCHAR(pjIoBase + (p)));
|
||
|
}
|
||
|
|
||
|
USHORT wInpW(BYTE* pjIoBase, ULONG p)
|
||
|
{
|
||
|
if (((p == CRTC_INDEX) || (p == CRTC_DATA)) &&
|
||
|
(!gbCrtcCriticalSection))
|
||
|
{
|
||
|
RIP("Must have acquired CRTC critical section to access CRTC register");
|
||
|
}
|
||
|
|
||
|
CP_EIEIO();
|
||
|
return(READ_PORT_USHORT(pjIoBase + (p)));
|
||
|
}
|
||
|
|
||
|
VOID vOutp(BYTE* pjIoBase, ULONG p, ULONG v)
|
||
|
{
|
||
|
if (((p == CRTC_INDEX) || (p == CRTC_DATA)) &&
|
||
|
(!gbCrtcCriticalSection))
|
||
|
{
|
||
|
RIP("Must have acquired CRTC critical section to access CRTC register");
|
||
|
}
|
||
|
|
||
|
CP_EIEIO();
|
||
|
WRITE_PORT_UCHAR((PUCHAR)((ULONG_PTR)(pjIoBase + p)), (UCHAR)(v));
|
||
|
CP_EIEIO();
|
||
|
}
|
||
|
|
||
|
VOID vOutpW(BYTE* pjIoBase, ULONG p, ULONG v)
|
||
|
{
|
||
|
if (((p == CRTC_INDEX) || (p == CRTC_DATA)) &&
|
||
|
(!gbCrtcCriticalSection))
|
||
|
{
|
||
|
RIP("Must have acquired CRTC critical section to access CRTC register");
|
||
|
}
|
||
|
|
||
|
CP_EIEIO();
|
||
|
WRITE_PORT_USHORT(pjIoBase + (p), (USHORT)(v));
|
||
|
CP_EIEIO();
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* VOID vAcquireCrtc()
|
||
|
* VOID vReleaseCrtc()
|
||
|
*
|
||
|
* Debug thunks for grabbing the CRTC register critical section.
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
VOID vAcquireCrtc(PDEV* ppdev)
|
||
|
{
|
||
|
EngAcquireSemaphore(ppdev->csCrtc);
|
||
|
|
||
|
if (gbCrtcCriticalSection)
|
||
|
RIP("Had already acquired Critical Section");
|
||
|
gbCrtcCriticalSection = TRUE;
|
||
|
}
|
||
|
|
||
|
VOID vReleaseCrtc(PDEV* ppdev)
|
||
|
{
|
||
|
// 80x/805i/928 and 928PCI chips have a bug where if I/O registers
|
||
|
// are left unlocked after accessing them, writes to memory with
|
||
|
// similar addresses can cause writes to I/O registers. The problem
|
||
|
// registers are 0x40, 0x58, 0x59 and 0x5c. We will simply always
|
||
|
// leave the index set to an innocuous register (namely, the text
|
||
|
// mode cursor start scan line):
|
||
|
|
||
|
OUTP(ppdev->pjIoBase, CRTC_INDEX, 0xa);
|
||
|
|
||
|
if (!gbCrtcCriticalSection)
|
||
|
RIP("Hadn't yet acquired Critical Section");
|
||
|
gbCrtcCriticalSection = FALSE;
|
||
|
EngReleaseSemaphore(ppdev->csCrtc);
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#endif // DBG
|