Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

819 lines
26 KiB

/******************************************************************************
*
* Module: SETMODE.C Set Video Mode Function Module
*
* Revision: 1.00
*
* Date: April 8, 1994
*
* Author: Randy Spurlock
*
*******************************************************************************
*
* Module Description:
*
* This module contains code for the SetMode function. This
* function can be used to set a video mode that was obtained via the
* GetModeTable function.
*
*******************************************************************************
*
* Changes:
*
* DATE REVISION DESCRIPTION AUTHOR
* -------- -------- -------------------------------------------------------
* 04/08/94 1.00 Original Randy Spurlock
*
*******************************************************************************
* Include Files
******************************************************************************/
#include <stdlib.h> /* Include standard library header */
#include <stdio.h> /* Include standard I/O header file */
#include <conio.h> /* Include console I/O header file */
#include <dos.h> /* Include dos header file */
#include <string.h> /* Include string header file */
#include <malloc.h> /* Include malloc header file */
//
// Is this Windows NT or something else?
//
#ifndef WIN_NT
#if NT_MINIPORT
#define WIN_NT 1
#else
#define WIN_NT 0
#endif
#endif
#include "type.h" /* Include type header file */
#include "modemon.h" /* Include mode/monitor header file */
#include "structs.h" /* Include the struct header file */
#if WIN_NT && NT_MINIPORT // If NT and Miniport
#include "cirrus.h"
#endif
/******************************************************************************
* Local Defintions
******************************************************************************/
#define STACK_SIZE 32 /* Maximum stack size value */
#define VIDEO_BIOS 0x10 /* Video BIOS function value */
#define VIDEO_SETMODE 0x00 /* Video set mode funtion value */
#define DMA_PAGE 0x84 /* Unused DMA page register port */
#if WIN_NT // If NT and Miniport
#if NT_MINIPORT
//
// NT Miniport has it's own set of I/O functions.
//
#define outp(port,val) VideoPortWritePortUchar ((unsigned char *)port, (unsigned char)val)
#define outpw(port,val) VideoPortWritePortUshort((unsigned short *)port, (unsigned short)val)
#define outpd(port,val) VideoPortWritePortUlong ((unsigned long *)port, (unsigned long)val)
#define inp(port) VideoPortReadPortUchar ((unsigned char *)port)
#define inpw(port) VideoPortReadPortUshort ((unsigned short *)port)
#define inpd(port) VideoPortReadPortUlong ((unsigned long *)port)
#else
#define outp(port,val) _outp ((unsigned short)(port), (BYTE) (val))
#define outpw(port,val) _outpw ((unsigned short)(port), (WORD) (val))
#define outpd(port,val) _outpd ((unsigned short)(port), (DWORD)(val))
#define inp(port) _inp ((unsigned short)(port))
#define inpw(port) _inpw ((unsigned short)(port))
#define inpd(port) _inpd ((unsigned short)(port))
#endif
#if 0 // Stress test
#if defined(ALLOC_PRAGMA)
#pragma alloc_text(PAGE,SetMode)
#endif
#endif
#endif
#if WIN_NT
#ifndef NT_MINIPORT
#define VideoDebugPrint(x)
#endif
#endif
#if !(WIN_NT)
int WriteI2CRegister(BYTE * pMem, int nPort, int nAddr, int nReg, int nData);
#endif
void WaitNVsyncs (BYTE * pMemory, WORD wNumVsyncs );
/******************************************************************************
*
* void SetMode(BYTE *pModeTable, BYTE *pMemory)
*
* Where:
*
* pModeTable - Pointer to mode table to set
* pMemory - Pointer to memory mapped I/O space
*
* Notes:
*
* This function will set the video mode using the mode table.
*
******************************************************************************/
void SetMode(BYTE *pModeTable, BYTE *pMemory, BYTE * pBinaryData, ULONG SkipIO)
{
DWORD nHold; /* Holding register value */
int nPort; /* Register port address value */
int nOffset; /* Memory address offset value */
int nIndex; /* Register port index value */
int nCount; /* Multiple output count value */
int nLoop; /* Generic loop counter */
int nPointer = 0; /* Stack pointer value */
int anStack[STACK_SIZE]; /* Stack array */
BYTE *pPointer; /* Mode table pointer */
#if !(WIN_NT)
union REGS Regs; /* Register union structure */
#endif
int i; /* Temporary Register for Counting */
PI2C pI2C; /* Some data pointers */
PI2CDATA pI2CData;
#if 0 // Stress test
#if NT_MINIPORT
PAGED_CODE();
#endif
#endif
/*
Init nHold to 0 to make PREfast happy. This is a bit risky though
in case write happens before read, but it was working fine so far.
This is an example of the bad programming though and the only reason
we don't really validate it is that this is the legacy part with
the support to be removed soon.
*/
nHold = 0;
/* Loop processing the commands in the mode table */
pPointer = pModeTable; /* Initialize the mode table pointer */
while (TRUE == TRUE)
{
/* Switch on the mode command opcode */
#if 0
if (*(DWORD *)(pMemory + 0x3F8) & 0x0100 == 0x0000)
{
fprintf(stdout,"VGA Shadow %x\n", (DWORD *)(pMemory + 0x3F8));
exit(0);
}
fprintf(stdout,"Type %x %x %x Shadow=%x\n", ((Mode *) pPointer)->Mode_Opcode, pPointer, pBinaryData, *(DWORD *)(pMemory + 0x3F8));
#endif
//VideoDebugPrint((2, " Setmode: Processing opcode 0x%X.\n",
// ((Mode *) pPointer)->Mode_Opcode));
switch(((Mode *) pPointer)->Mode_Opcode)
{
case END_TABLE: /* End of table command */
/* Check for end of top level */
if (nPointer == 0)
return; /* End of mode set, return to caller */
else
pPointer = pModeTable + anStack[--nPointer];
break;
case SET_BIOS_MODE: /* Set BIOS mode command */
/* Setup the required registers and do the BIOS mode set */
#if WIN_NT
VideoDebugPrint((2,
"\n* * * * CL546X.SYS * Unsupported BIOS call in SetMode() * * * *\n\n"));
#else
Regs.h.ah = VIDEO_SETMODE;
Regs.h.al = ((SBM *) pPointer)->SBM_Mode;
#ifdef __WATCOMC__
int386(VIDEO_BIOS, &Regs, &Regs);
#else
int86(VIDEO_BIOS, &Regs, &Regs);
#endif
#endif
/* Update the mode table pointer */
pPointer += sizeof(SBM);
break;
case SINGLE_INDEXED_OUTPUT: /* Single indexed output command */
if (!SkipIO) // are VGA regs ours?
{
/* Setup the register index value */
outp(((SIO *) pPointer)->SIO_Port,
((SIO *) pPointer)->SIO_Index);
/* Output a single byte to the desired port */
outp(((SIO *) pPointer)->SIO_Port + 1,
((SIO *) pPointer)->SIO_Value);
}
/* Update the mode table pointer */
pPointer += sizeof(SIO);
break;
#if 0
case SINGLE_BYTE_INPUT: /* Single byte input command */
/* Input a single byte into the holding buffer */
nHold = inp(((SBI *) pPointer)->SBI_Port);
/* Update the mode table pointer */
pPointer += sizeof(SBI);
break;
case SINGLE_WORD_INPUT: /* Single word input command */
/* Input a single word into the holding buffer */
nHold = inpw(((SWI *) pPointer)->SWI_Port);
/* Update the mode table pointer */
pPointer += sizeof(SWI);
break;
case SINGLE_DWORD_INPUT: /* Single dword input command */
/* Input a single dword into the holding buffer */
nHold = inpd(((SDI *) pPointer)->SDI_Port);
/* Update the mode table pointer */
pPointer += sizeof(SDI);
break;
case SINGLE_INDEXED_INPUT: /* Single indexed input command */
/* Setup the register index value */
outp(((SII *) pPointer)->SII_Port,
((SII *) pPointer)->SII_Index);
/* Input a single byte into the holding buffer */
nHold = inp(((SII *) pPointer)->SII_Port + 1);
/* Update the mode table pointer */
pPointer += sizeof(SII);
break;
case SINGLE_BYTE_OUTPUT: /* Single byte output command */
/* Output a single byte to the desired port */
outp(((SBO *) pPointer)->SBO_Port,
((SBO *) pPointer)->SBO_Value);
/* Update the mode table pointer */
pPointer += sizeof(SBO);
break;
case SINGLE_WORD_OUTPUT: /* Single word output command */
/* Output a single word to the desired port */
outpw(((SWO *) pPointer)->SWO_Port,
((SWO *) pPointer)->SWO_Value);
/* Update the mode table pointer */
pPointer += sizeof(SWO);
break;
case SINGLE_DWORD_OUTPUT: /* Single dword output command */
/* Output a single dword to the desired port */
outpd(((SDO *) pPointer)->SDO_Port,
((SDO *) pPointer)->SDO_Value);
/* Update the mode table pointer */
pPointer += sizeof(SDO);
break;
case HOLDING_BYTE_OUTPUT: /* Holding byte output command */
/* Output holding byte to the desired port */
outp(((HBO *) pPointer)->HBO_Port, nHold);
/* Update the mode table pointer */
pPointer += sizeof(HBO);
break;
case HOLDING_WORD_OUTPUT: /* Holding word output command */
/* Output holding word to the desired port */
outpw(((HWO *) pPointer)->HWO_Port, nHold);
/* Update the mode table pointer */
pPointer += sizeof(HWO);
break;
case HOLDING_DWORD_OUTPUT: /* Holding dword output command */
/* Output holding dword to the desired port */
outpd(((HDO *) pPointer)->HDO_Port, nHold);
/* Update the mode table pointer */
pPointer += sizeof(HDO);
break;
case HOLDING_INDEXED_OUTPUT:/* Holding indexed output command */
/* Setup the register index value */
outp(((HIO *) pPointer)->HIO_Port,
((HIO *) pPointer)->HIO_Index);
/* Output holding byte to the desired port */
outp(((HIO *) pPointer)->HIO_Port + 1, nHold);
/* Update the mode table pointer */
pPointer += sizeof(HIO);
break;
case MULTIPLE_BYTE_OUTPUT: /* Multiple byte output command */
/* Setup the port address and count values */
nPort = ((MBO *) pPointer)->MBO_Port;
nCount = ((MBO *) pPointer)->MBO_Count;
/* Update the mode table pointer */
pPointer += sizeof(MBO);
/* Loop outputting bytes to the desired port */
for (nLoop = 0; nLoop < nCount; nLoop++)
outp(nPort, *((BYTE *) pPointer++));
break;
case MULTIPLE_WORD_OUTPUT: /* Multiple word output command */
/* Setup the port address and count values */
nPort = ((MWO *) pPointer)->MWO_Port;
nCount = ((MWO *) pPointer)->MWO_Count;
/* Update the mode table pointer */
pPointer += sizeof(MWO);
/* Loop outputting words to the desired port */
for (nLoop = 0; nLoop < nCount; nLoop++)
outpw(nPort, *((WORD *) pPointer++));
break;
case MULTIPLE_DWORD_OUTPUT: /* Multiple dword output command */
/* Setup the port address and count values */
nPort = ((MDO *) pPointer)->MDO_Port;
nCount = ((MDO *) pPointer)->MDO_Count;
/* Update the mode table pointer */
pPointer += sizeof(MDO);
/* Loop outputting dwords to the desired port */
for (nLoop = 0; nLoop < nCount; nLoop++)
outpd(nPort, *((DWORD *) pPointer++));
break;
case MULTIPLE_INDEXED_OUTPUT:/* Multiple indexed output command */
/* Setup the port address and count values */
nPort = ((MIO *) pPointer)->MIO_Port;
nIndex = ((MIO *) pPointer)->MIO_Index;
nCount = ((MIO *) pPointer)->MIO_Count;
/* Update the mode table pointer */
pPointer += sizeof(MIO);
/* Loop outputting bytes to the desired port */
for (nLoop = 0; nLoop < nCount; nLoop++)
{
/* Setup the register index value */
outp(nPort, nIndex++);
/* Output the actual data value */
outp(nPort + 1, *((BYTE *) pPointer++));
}
break;
#endif
case SINGLE_BYTE_READ: /* Single byte read command */
/* Read a single byte into the holding buffer */
nHold = *((BYTE *) (pMemory + (((SBR *) pPointer)->SBR_Address)));
/* Update the mode table pointer */
pPointer += sizeof(SBR);
break;
case SINGLE_WORD_READ: /* Single word read command */
/* Read a single word into the holding buffer */
nHold = *((WORD *) (pMemory + (((SWR *) pPointer)->SWR_Address)));
/* Update the mode table pointer */
pPointer += sizeof(SWR);
break;
case SINGLE_DWORD_READ: /* Single dword read command */
/* Read a single dword into the holding buffer */
nHold = *((DWORD *) (pMemory + (((SDR *) pPointer)->SDR_Address)));
/* Update the mode table pointer */
pPointer += sizeof(SDR);
break;
case SINGLE_BYTE_WRITE: /* Single byte write command */
/* Write a single byte to the desired adress */
*((BYTE *) (pMemory + (((SBW *) pPointer)->SBW_Address))) =
(BYTE) ((SBW *) pPointer)->SBW_Value;
#if 0
fprintf(stdout,"SBW %x %x\n",
((SBW *) pPointer)->SBW_Address,
((SBW *) pPointer)->SBW_Value);
#endif
/* Update the mode table pointer */
pPointer += sizeof(SBW);
break;
case SINGLE_WORD_WRITE: /* Single word write command */
/* Write a single word to the desired address */
*((WORD *) (pMemory + (((SWW *) pPointer)->SWW_Address))) =
((SWW *) pPointer)->SWW_Value;
/* Update the mode table pointer */
#if 0
fprintf(stdout,"SWW %x %x\n",
((SWW *) pPointer)->SWW_Address,
((SWW *) pPointer)->SWW_Value);
#endif
pPointer += sizeof(SWW);
break;
case SINGLE_DWORD_WRITE: /* Single dword write command */
/* Write a single dword to the desired address */
*((DWORD *) (pMemory + (((SDW *) pPointer)->SDW_Address))) =
((SDW *) pPointer)->SDW_Value;
/* Update the mode table pointer */
#if 0
fprintf(stdout,"SDW %x %x\n",
((SDW *) pPointer)->SDW_Address,
((SDW *) pPointer)->SDW_Value);
#endif
pPointer += sizeof(SDW);
break;
case HOLDING_BYTE_WRITE: /* Holding byte write command */
/* Write holding byte to the desired address */
*((BYTE *) (pMemory + (((HBW *) pPointer)->HBW_Address))) =(BYTE) nHold;
#if 0
fprintf(stdout,"HBW %x %x\n",
((HBW *) pPointer)->HBW_Address,
nHold);
#endif
/* Update the mode table pointer */
pPointer += sizeof(HBW);
break;
case HOLDING_WORD_WRITE: /* Holding word write command */
/* Write holding word to the desired address */
*((WORD *) (pMemory + (((HWW *) pPointer)->HWW_Address))) = (WORD) nHold;
/* Update the mode table pointer */
#if 0
fprintf(stdout,"HWW %x %x\n",
((HWW *) pPointer)->HWW_Address,
nHold);
#endif
pPointer += sizeof(HWW);
break;
case HOLDING_DWORD_WRITE: /* Holding dword write command */
/* Write holding dword to the desired address */
*((DWORD *) (pMemory + (((HDW *) pPointer)->HDW_Address))) = nHold;
/* Update the mode table pointer */
#if 0
fprintf(stdout,"HDW %x %x\n",
((HDW *) pPointer)->HDW_Address,
nHold);
#endif
pPointer += sizeof(HDW);
break;
case MULTIPLE_BYTE_WRITE: /* Multiple byte write command */
/* Setup the offset and count values */
nOffset = ((MBW *) pPointer)->MBW_Address;
nCount = ((MBW *) pPointer)->MBW_Count;
/* Update the mode table pointer */
pPointer += sizeof(MBW);
/* Loop writing bytes to the desired addresses */
for (nLoop = 0; nLoop < nCount; nLoop++)
{
/* Write the next byte and update memory offset value */
#if 0
fprintf(stdout,"MBW %x %x\n", nOffset, (BYTE *)pPointer);
#endif
*((BYTE *) (pMemory + nOffset)) = *((BYTE *) pPointer++);
nOffset += sizeof(BYTE);
}
break;
case MULTIPLE_WORD_WRITE: /* Multiple word write command */
/* Setup the offset and count values */
nOffset = ((MWW *) pPointer)->MWW_Address;
nCount = ((MWW *) pPointer)->MWW_Count;
/* Update the mode table pointer */
pPointer += sizeof(MWW);
/* Loop writing words to the desired addresses */
for (nLoop = 0; nLoop < nCount; nLoop++)
{
/* Write the next word and update memory offset value */
#if 0
fprintf(stdout,"MWW %x %x\n", nOffset, (WORD *)pPointer);
#endif
*((WORD *) (pMemory + nOffset)) = *((WORD *) pPointer++);
nOffset += sizeof(WORD);
}
break;
case MULTIPLE_DWORD_WRITE: /* Multiple dword write command */
/* Setup the address and count values */
nOffset = ((MDW *) pPointer)->MDW_Address;
nCount = ((MDW *) pPointer)->MDW_Count;
/* Update the mode table pointer */
pPointer += sizeof(MDW);
/* Loop writing dwords to the desired addresses */
#if 0
fprintf(stdout,"nOffset %x nCount %d\n", nOffset, nCount);
#endif
for (nLoop = 0; nLoop < nCount; nLoop++)
{
/* Write the next dword and update memory offset value */
#if 0
fprintf(stdout,"nOffset %x Data %x %x\n", nOffset, *pPointer, pPointer);
#endif
*((DWORD *) (pMemory + nOffset)) = *((DWORD *) pPointer);
pPointer += sizeof(DWORD);
nOffset += sizeof(DWORD);
}
break;
case PERFORM_OPERATION: /* Perform logical operation command */
/* Switch on the logical operation type */
switch(((LO *) pPointer)->LO_Operation)
{
case AND_OPERATION: /* Logical AND operation */
/* Perform logical AND operation on holding value */
nHold &= ((LO *) pPointer)->LO_Value;
break;
case OR_OPERATION: /* Logical OR operation */
/* Perform logical OR operation on holding value */
nHold |= ((LO *) pPointer)->LO_Value;
break;
case XOR_OPERATION: /* Logical XOR operation */
/* Perform logical XOR operation on holding value */
nHold ^= ((LO *) pPointer)->LO_Value;
break;
}
/* Update the mode table pointer */
pPointer += sizeof(LO);
break;
case PERFORM_DELAY: /* Perform delay operation command */
// delay by waiting for the specified number of vsyncs
WaitNVsyncs(pMemory, (WORD)((DO *)pPointer)->DO_Time);
/* Update the mode table pointer */
pPointer += sizeof(DO);
break;
case SUB_TABLE: /* Perform mode sub-table command */
/* Check the current nesting level */
if (nPointer < STACK_SIZE)
{
/* Put current offset into stack and update the pointer */
anStack[nPointer++] = pPointer - pModeTable + sizeof(MST);
if (pBinaryData)
pPointer = pBinaryData + ((MST *) pPointer)->MST_Pointer;
else
pPointer = pModeTable + ((MST *) pPointer)->MST_Pointer;
}
else /* Nesting level too deep, skip table */
{
#if WIN_NT
VideoDebugPrint((2,
"\n* * * * CL546X.SYS * Nesting level too deep in SetMode()\n\n"));
#else
fprintf(stdout,"Nesting to depth %s %d\n", __FILE__, __LINE__);
#endif
pPointer += sizeof(MST);
}
break;
case I2COUT_WRITE:
#if WIN_NT
VideoDebugPrint((2,
"\n* * * * CL546X.SYS * Unsupported I2C call in SetMode() \n\n"));
#endif
pI2C = (PI2C)pPointer;
pI2CData = (PI2CDATA)(pPointer + sizeof(I2C));
for (i=0; i<pI2C->I2C_Count; i++)
{
#if !WIN_NT
WriteI2CRegister(pMemory, pI2C->I2C_Port, pI2C->I2C_Addr, pI2CData->I2C_Reg, pI2CData->I2C_Data);
#endif
pI2CData++;
}
pPointer += sizeof(I2C) + pI2C->I2C_Count * sizeof(I2CDATA);
break;
default: /* Unknown mode command, abort */
#if WIN_NT
VideoDebugPrint((2,
"Miniport - Setmode abort. Unknnown command.\n"));
#else
fprintf(stdout,"Unknown Command [%x] %s %d\n", ((Mode *) pPointer)->Mode_Opcode, __FILE__, __LINE__);
#endif
return; /* Invalid command, return to caller */
break;
}
}
/* Mode set is complete, return control to the caller */
return; /* Return control to the caller */
}
void WaitNVsyncs (BYTE * pMemory, WORD wNumVsyncs )
{
volatile BYTE * pMBE = (BYTE *)(pMemory + 0xEC);
unsigned long uCount = 0x00FFFF;
int nPort;
// VideoDebugPrint((2, " ---- WaitNVsyncs. Enter.\n"));
//
// This code will work on 5462, 5464, 5465
//
#if 0
nPort = inp(0x3cc) & 0x01 ? 0x3da : 0x3ba;
while ( (inp(nPort) & 0x08) && (--uCount) )
;
uCount = 0x00FFFF;
while ( (!(inp(nPort) & 0x08)) && (--uCount) )
;
#else
while ( ((*pMBE & 0x80) == 0x80) && (--uCount) )
;
uCount = 0x00FFFF;
while ( ((*pMBE & 0x80) == 0x00) && (--uCount) )
;
#endif
// VideoDebugPrint((2, " ---- WaitNVsyncs. Exit.\n"));
}