windows-nt/Source/XPSP1/NT/drivers/video/matrox/mga/mini/mga.c
2020-09-26 16:20:57 +08:00

3841 lines
144 KiB
C

/**************************************************************************\
$Header: o:\src/RCS/MGA.C 1.10 94/03/02 04:46:47 jyharbec Exp $
$Log: MGA.C $
* Revision 1.10 94/03/02 04:46:47 jyharbec
* Modification for PCI to default to board 0.
*
* Revision 1.9 94/02/28 04:04:36 jyharbec
* Code for 5-6-5 driver;
* Setting cursor colors for ViewPoint.
*
* Revision 1.8 94/01/05 12:03:32 jyharbec
* New service IOCTL_VIDEO_MTX_QUERY_HW_DATA.
*
* Revision 1.7 93/12/20 11:42:36 jyharbec
* Modified S3 to MGA in debug message text.
*
* Revision 1.6 93/11/04 04:50:04 dlee
* Modified for Alpha.
*
* Revision 1.5 93/10/15 11:30:00 jyharbec
* Added service IOCTL_VIDEO_MTX_QUERY_BOARD_ID.
*
* Revision 1.4 93/10/06 05:39:59 jyharbec
* Modifications required to update MGA.INF file to current version.
*
* Revision 1.3 93/09/23 11:42:49 jyharbec
* Modification to IOCTL_VIDEO_MTX_QUERY_RAMDAC_INFO to include Overscan.
*
* Revision 1.2 93/09/01 13:29:07 jyharbec
* Take into account DISPTYPE_UNUSABLE from HwModeData structures.
*
* Revision 1.1 93/08/27 12:37:09 jyharbec
* Initial revision
*
\**************************************************************************/
/****************************************************************************\
* MODULE: MGA.C
*
* DESCRIPTION: This module contains the code that implements the MGA miniport
* driver. [Based on S3.C (Mar 1,1993) from Windows-NT DDK]
*
* Copyright (c) 1990-1992 Microsoft Corporation
* Copyright (c) 1993 Matrox Electronic Systems Ltd.
*
* History:
* 23AUG93 - Added check for micro-channel adapter in FindAdapter
*
\****************************************************************************/
#include "switches.h"
#include <string.h>
#include "bind.h"
#include "sxci.h"
#include "mga.h"
#include "defbind.h"
#include "mga_nt.h"
//
// New entry points added for NT 5.0.
//
#if (_WIN32_WINNT >= 500)
//
// Routine to set a desired DPMS power management state.
//
VP_STATUS
MgaSetPower50(
PMGA_DEVICE_EXTENSION phwDeviceExtension,
ULONG HwDeviceId,
PVIDEO_POWER_MANAGEMENT pVideoPowerMgmt
);
//
// Routine to retrieve possible DPMS power management states.
//
VP_STATUS
MgaGetPower50(
PMGA_DEVICE_EXTENSION phwDeviceExtension,
ULONG HwDeviceId,
PVIDEO_POWER_MANAGEMENT pVideoPowerMgmt
);
//
// Routine to retrieve the Enhanced Display ID structure via DDC
//
ULONG
MgaGetVideoChildDescriptor(
PVOID HwDeviceExtension,
PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
PVIDEO_CHILD_TYPE pChildType,
PVOID pvChildDescriptor,
PULONG pHwId,
PULONG pUnused
);
#endif // _WIN32_WINNT >= 500
// From MTXINIT.C; it should be in some header file.
#define BOARD_MGA_RESERVED 0x07
VIDEO_MODE_INFORMATION CommonVideoModeInformation =
{
sizeof(VIDEO_MODE_INFORMATION), // Size of the mode informtion structure
0, // *Mode index used in setting the mode
1280, // *X Resolution, in pixels
1024, // *Y Resolution, in pixels
1024, // *Screen stride
1, // Number of video memory planes
8, // *Number of bits per plane
1, // Screen Frequency, in Hertz
330, // Horizontal size of screen in millimeters
240, // Vertical size of screen in millimeters
8, // Number Red pixels in DAC
8, // Number Green pixels in DAC
8, // Number Blue pixels in DAC
0x00000000, // *Mask for Red Pixels in non-palette modes
0x00000000, // *Mask for Green Pixels in non-palette modes
0x00000000, // *Mask for Blue Pixels in non-palette modes
0, // *Mode description flags.
1280, // *Video Memory Bitmap Width
1024 // *Video Memory Bitmap Height
};
#if NB_BOARD_MAX > 7
#error Error! Modify MultiModes array!
#endif
UCHAR MgaBusType[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
// Nb of modes supported by 1, 2, 3, 4, 5, 6, 7 boards.
USHORT MultiModes[] = { 0, 1, 2, 2, 3, 2, 4, 2 };
USHORT SingleWidths[] = { 640, 768, 800, 1024, 1152, 1280, 1600, 0xffff};
USHORT SingleHeights[]= { 480, 576, 600, 768, 882, 1024, 1200, 0xffff};
// MGA communication access ranges.
VIDEO_ACCESS_RANGE MgaDriverCommonAccessRange[] =
{
// {0x00000400, 0x00000000, 0x000000AB, 0, 0, 1}, // BIOS Communication Area
{0x000003B4, 0x00000000, 0x00000002, 1, 0, 1}, // 0 Titan VGA & CRTC
{0x000003BA, 0x00000000, 0x00000001, 1, 0, 1}, // 1
{0x000003C0, 0x00000000, 0x00000010, 1, 0, 1}, // 2
{0x000003D4, 0x00000000, 0x00000008, 1, 0, 1}, // 3
{0x000003DE, 0x00000000, 0x00000002, 1, 0, 1}, // 4
#if USE_SETUP_VGA
{0x000046E8, 0x00000000, 0x00000002, 1, 0, 1}, // 5
{0x00000410, 0x00000000, 0x00000001, 0, 0, 1}, // 6
{0x00000449, 0x00000000, 0x0000001e, 0, 0, 1}, // 7
{0x00000484, 0x00000000, 0x00000007, 0, 0, 1}, // 8
{0x000004A8, 0x00000000, 0x00000004, 0, 0, 1}, // 9
{0x000A0000, 0x00000000, 0x00010000, 0, 0, 1} // 10
//{0x000B8000, 0x00000000, 0x00008000, 0, 0, 1} // 11
#else
{0x000046E8, 0x00000000, 0x00000002, 1, 0, 1} // 5
#endif
};
// MGA windows access ranges.
VIDEO_ACCESS_RANGE MgaDriverAccessRange[] =
{
{0x000C8000, 0x00000000, 0x00004000, 0, 0, 0}, // Command window 0
{0x0000C000, 0x00000000, 0x00000100, 1, 0, 0}, // Config space 0
{0x00000000, 0x00000000, 0x00004000, 0, 0, 0}, // Command window 1
{0x0000C000, 0x00000000, 0x00000100, 1, 0, 0}, // Config space 1
{0x00000000, 0x00000000, 0x00004000, 0, 0, 0}, // Command window 2
{0x0000C000, 0x00000000, 0x00000100, 1, 0, 0}, // Config space 2
{0x00000000, 0x00000000, 0x00004000, 0, 0, 0}, // Command window 3
{0x0000C000, 0x00000000, 0x00000100, 1, 0, 0}, // Config space 3
{0x00000000, 0x00000000, 0x00004000, 0, 0, 0}, // Command window 4
{0x0000C000, 0x00000000, 0x00000100, 1, 0, 0}, // Config space 4
{0x00000000, 0x00000000, 0x00004000, 0, 0, 0}, // Command window 5
{0x0000C000, 0x00000000, 0x00000100, 1, 0, 0}, // Config space 5
{0x00000000, 0x00000000, 0x00004000, 0, 0, 0}, // Command window 6
{0x0000C000, 0x00000000, 0x00000100, 1, 0, 0} // Config space 6
};
#if (!USE_VP_GET_ACCESS_RANGES)
VIDEO_ACCESS_RANGE MgaDriverSupplAccessRange[] =
{
{0x00000CF8, 0x00000000, 0x00000008, 1, 0, 1}
//{0x000E0000, 0x00000000, 0x00020000, 1, 0, 1}
};
#endif
#define NUM_MGA_COMMON_ACCESS_RANGES \
(sizeof(MgaDriverCommonAccessRange) / sizeof(VIDEO_ACCESS_RANGE))
#define NUM_MGA_ACCESS_RANGES \
(sizeof(MgaDriverAccessRange) / sizeof(VIDEO_ACCESS_RANGE))
#if (!USE_VP_GET_ACCESS_RANGES)
#define NUM_MGA_SUPPL_ACCESS_RANGES \
(sizeof(MgaDriverSupplAccessRange) / sizeof(VIDEO_ACCESS_RANGE))
#else
#define NUM_MGA_SUPPL_ACCESS_RANGES 0
#endif
#define NUM_ALL_ACCESS_RANGES \
(NUM_MGA_COMMON_ACCESS_RANGES + NUM_MGA_ACCESS_RANGES + NUM_MGA_SUPPL_ACCESS_RANGES)
INTERFACE_TYPE NtInterfaceType;
HwData *pMgaBoardData;
ULONG ulNewInfoSize;
PUCHAR pucNewInfo;
PUCHAR pMgaBiosVl;
extern PVOID pMgaDeviceExtension;
extern word mtxVideoMode;
extern byte NbBoard;
extern dword MgaSel;
extern PVOID pMgaBaseAddr;
extern HwData Hw[NB_BOARD_MAX+1];
extern byte iBoard;
extern char *mgainf;
extern char DefaultVidset[];
extern dword ProductMGA[NB_BOARD_MAX];
// Board number conversion macro.
// In the user-mode drivers, boards are numbered sequentially starting from 0
// at the upper left corner and going from left to right and then top to
// bottom. In the miniport driver, we might want to start from the lower
// left corner.
#if 1
// Same numbering convention as the user-mode driver.
#define CONVERT_BOARD_NUMBER(n) n = n
#else
// Starting from lower left instead of upper left corner.
#define CONVERT_BOARD_NUMBER(n) n = ((pCurMulti->MulArrayHeight - 1) * \
pCurMulti->MulArrayWidth) - n + \
2*(n % pCurMulti->MulArrayWidth)
#endif
// Function Prototypes
//
// Functions that start with 'Mga' are entry points for the OS port driver.
#ifdef MGA_WINNT35
BOOLEAN
MgaResetHw(
PVOID HwDeviceExtension,
ULONG Columns,
ULONG Rows
);
#endif
VP_STATUS
MgaFindAdapter(
PVOID HwDeviceExtension,
PVOID HwContext,
PWSTR ArgumentString,
PVIDEO_PORT_CONFIG_INFO ConfigInfo,
PUCHAR Again
);
BOOLEAN
MgaInitialize(
PVOID HwDeviceExtension
);
BOOLEAN
MgaStartIO(
PVOID HwDeviceExtension,
PVIDEO_REQUEST_PACKET RequestPacket
);
VP_STATUS
MgaInitModeList(
PMGA_DEVICE_EXTENSION MgaDeviceExtension);
VP_STATUS
MgaSetColorLookup(
PMGA_DEVICE_EXTENSION MgaDeviceExtension,
PVIDEO_CLUT ClutBuffer,
ULONG ClutBufferSize
);
VOID MgaSetCursorColour(
PMGA_DEVICE_EXTENSION MgaDeviceExtension,
ULONG ulFgColour,
ULONG ulBgColour);
// For WinNT 3.5
// Code NOT to be made pageable:
// SetVgaEn();
// setVgaMode();
// restoreVga();
// checkCursorEn();
// mtxCheckVgaEn();
// mtxMapVLBSpace();
// mtxUnMapVLBSpace();
// mtxIsVLB();
// isPciBus();
// wideToIsa();
// blankEcran();
// delay_us();
// _inp(); (macro)
// _outp(); (macro)
// rdDubicDReg();
// rdDubicIReg();
// rdDacReg();
// rdTitanReg();
// mgaReadDWORD(); (macro)
// mgaReadBYTE(); (macro)
// wrDubicDReg();
// wrDubicIReg();
// wrDacReg();
// wrTitanReg();
// mgaWriteBYTE(); (macro)
// mgaWriteDWORD(); (macro)
// Data NOT to be made pageable:
// Hw (in mtxinit.c)
// pMgaBaseAddr (in mtxinit.c)
// iBoard (in mtxinit.c)
// mtxVideoMode (in mtxinit.c)
// pMgaDeviceExtension (in mtxinit.c)
// isVLBFlag (in mtxvideo.c)
// cursorStat (in mtxvideo.c)
// saveBitOperation (in mtxvideo.c)
#if defined(ALLOC_PRAGMA)
#pragma alloc_text(PAGE,DriverEntry)
#pragma alloc_text(PAGE,MgaFindAdapter)
#pragma alloc_text(PAGE,MgaInitialize)
#pragma alloc_text(PAGE,MgaStartIO)
#pragma alloc_text(PAGE,MgaInitModeList)
//#pragma alloc_text(PAGE,MgaSetColorLookup)
#pragma alloc_text(PAGE,MgaSetCursorColour)
#if (_WIN32_WINNT >= 500)
#pragma alloc_text(PAGE_COM, MgaSetPower50)
#pragma alloc_text(PAGE_COM, MgaGetPower50)
#pragma alloc_text(PAGE_COM, MgaGetVideoChildDescriptor)
#endif // _WIN32_WINNT >= 500
#endif
//#if defined(ALLOC_PRAGMA)
// #pragma data_seg("PAGE")
//#endif
// External function prototypes
extern volatile byte _Far *setmgasel(dword MgaSel, dword phyadr, dword limit);
bool MapBoard(void);
char *adjustDefaultVidset();
PVOID AllocateSystemMemory(ULONG NumberOfBytes);
char *mtxConvertMgaInf( char * );
void SetVgaEn();
char *selectMgaInfoBoard();
#if USE_SETUP_VGA
void setupVga(void);
void restoreVga();
#endif
/****************************************************************************\
* ULONG
* DriverEntry (
* PVOID Context1,
* PVOID Context2)
*
* DESCRIPTION:
* Installable driver initialization entry point.
* This entry point is called directly by the I/O system.
*
* ARGUMENTS:
* Context1 - First context value passed by the operating system. This is
* the value with which the miniport driver calls VideoPortInitialize().
*
* Context2 - Second context value passed by the operating system. This is
* the value with which the miniport driver calls VideoPortInitialize().
*
* RETURNS:
* Status from VideoPortInitialize()
*
\****************************************************************************/
ULONG
DriverEntry (
PVOID Context1,
PVOID Context2
)
{
VIDEO_HW_INITIALIZATION_DATA hwInitData;
ULONG isaStatus, eisaStatus, microChannelStatus, pciStatus, minStatus;
ULONG i, j;
HwData TempHw;
VideoDebugPrint((1, "MGA.SYS!DriverEntry\n"));
//DbgBreakPoint();
// Zero out structure.
VideoPortZeroMemory(&hwInitData, sizeof(VIDEO_HW_INITIALIZATION_DATA)) ;
// Specify sizes of structure and extension.
hwInitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
// Set entry points.
hwInitData.HwFindAdapter = MgaFindAdapter;
hwInitData.HwInitialize = MgaInitialize;
//hwInitData.HwInterrupt = NULL;
hwInitData.HwStartIO = MgaStartIO;
#ifdef MGA_WINNT35
hwInitData.HwResetHw = MgaResetHw;
//hwInitData.HwTimer = NULL;
#endif
#if (_WIN32_WINNT >= 500)
//
// Set new entry points added for NT 5.0.
//
hwInitData.HwSetPowerState = MgaSetPower50;
hwInitData.HwGetPowerState = MgaGetPower50;
hwInitData.HwGetVideoChildDescriptor = MgaGetVideoChildDescriptor;
#endif // _WIN32_WINNT >= 500
//
// Determine the size we require for the device extension.
//
hwInitData.HwDeviceExtensionSize = sizeof(MGA_DEVICE_EXTENSION);
// Always start with parameters for device0 in this case.
//hwInitData.StartingDeviceNumber = 0;
// This device only supports the internal bus type. So return the status
// value directly to the operating system.
// I think that each VPInitialize call will itself call MgaFindAdapter,
// provided that the specified AdapterInterfaceType makes sense for the
// hardware. MgaFindAdapter will call MapBoard. We can't be sure that
// the last call to MapBoard will find all the boards, so we'll have to
// accumulate the boards found, making sure that we don't record the
// same board twice.
//#if (defined(MGA_WINNT35) && defined(MGA_ALPHA))
NbBoard = 0;
//#endif
hwInitData.AdapterInterfaceType = PCIBus;
pciStatus = VideoPortInitialize(Context1,
Context2,
&hwInitData,
NULL);
hwInitData.AdapterInterfaceType = Isa;
isaStatus = VideoPortInitialize(Context1,
Context2,
&hwInitData,
NULL);
hwInitData.AdapterInterfaceType = Eisa;
eisaStatus = VideoPortInitialize(Context1,
Context2,
&hwInitData,
NULL);
hwInitData.AdapterInterfaceType = MicroChannel;
microChannelStatus = VideoPortInitialize(Context1,
Context2,
&hwInitData,
NULL);
// We should have found all our boards at this point. We want to
// reorder the Hw array so that the PCI boards are the first ones.
// The MgaBusType array was initialized to MGA_BUS_INVALID.
for (i = 0; i < NbBoard; i++)
{
// The only possibilities are MGA_BUS_PCI and MGA_BUS_ISA.
if (MgaBusType[i] == MGA_BUS_ISA)
{
// We found an ISA board. Look for a PCI board.
for (j = i+1; j < NbBoard; j++)
{
if (MgaBusType[j] == MGA_BUS_PCI)
{
// We found a PCI board, exchange them.
TempHw = Hw[j];
Hw[j] = Hw[i];
Hw[i] = TempHw;
MgaBusType[i] = MGA_BUS_PCI;
MgaBusType[j] = MGA_BUS_ISA;
MgaDriverAccessRange[i*2].RangeStart.LowPart = Hw[i].MapAddress;
MgaDriverAccessRange[i*2+1].RangeStart.LowPart = Hw[i].ConfigSpace;
MgaDriverAccessRange[j*2].RangeStart.LowPart = Hw[j].MapAddress;
MgaDriverAccessRange[j*2+1].RangeStart.LowPart = Hw[j].ConfigSpace;
break;
}
}
}
}
// Return the smallest of isaStatus, eisaStatus, pciStatus, and
// microChannelStatus.
minStatus = (isaStatus < eisaStatus) ? isaStatus : eisaStatus;
if (microChannelStatus < minStatus)
minStatus = microChannelStatus;
if (pciStatus < minStatus)
minStatus = pciStatus;
return(minStatus);
} // end DriverEntry()
#ifdef MGA_WINNT35
/****************************************************************************\
* VOID
* MgaResetHw(VOID)
*
* DESCRIPTION:
*
* This function is called when the machine needs to bugchecks (go back
* to the blue screen).
*
* This function should reset the video adapter to a character mode,
* or at least to a state from which an int 10 can reset the card to
* a character mode.
*
* This routine CAN NOT call int10.
* It can only call Read\Write Port\Register functions from the port driver.
*
* The function must also be completely in non-paged pool since the IO\MM
* subsystems may have crashed.
*
* ARGUMENTS:
*
* HwDeviceExtension - Supplies the miniport driver's adapter storage.
*
* Columns - Number of columns in the requested mode.
*
* Rows - Number of rows in the requested mode.
*
* RETURN VALUE:
*
* The return value determines if the mode was completely programmed (TRUE)
* or if an int10 should be done by the HAL to complete the modeset (FALSE).
*
\****************************************************************************/
BOOLEAN MgaResetHw(
PVOID HwDeviceExtension,
ULONG Columns,
ULONG Rows
)
{
PMGA_DEVICE_EXTENSION MgaDeviceExtension;
VideoDebugPrint((1, "MGA.SYS!MgaResetHw\n"));
// There is nothing to be done to reset the board if the one that
// went into hi-res was not VGA-enabled to start with. However it
// will look nicer if we clear the screen. If the board was VGA-
// enabled, we put it back into text mode, or as near as we can get.
pMgaDeviceExtension =
MgaDeviceExtension = (PMGA_DEVICE_EXTENSION)HwDeviceExtension;
pMgaBaseAddr = MgaDeviceExtension->KernelModeMappedBaseAddress[0];
// Make the cursor disappear.
mtxCursorEnable(0);
if (Hw[0].VGAEnable)
{
SetVgaEn();
#if USE_SETUP_VGA
setupVga();
restoreVga();
#endif
mtxVideoMode = mtxPASSTHRU;
}
// Let the caller execute the Int10.
return(FALSE);
}
#endif
/****************************************************************************\
* FIND_ADAPTER_STATUS
* MgaFindAdapter(
* PVOID HwDeviceExtension,
* PVOID HwContext,
* PWSTR ArgumentString,
* PVIDEO_PORT_CONFIG_INFO ConfigInfo,
* PUCHAR Again
* )
*
* DESCRIPTION:
*
* This routine is called to determine if the adapter for this driver
* is present in the system.
* If it is present, the function fills out some information describing
* the adapter.
*
* ARGUMENTS:
*
* HwDeviceExtension - Supplies the miniport driver's adapter storage. This
* storage is initialized to zero before this call.
*
* HwContext - Supplies the context value which was passed to
* VideoPortInitialize(). Must be NULL for PnP drivers.
*
* ArgumentString - Suuplies a NULL terminated ASCII string. This string
* originates from the user.
*
* ConfigInfo - Returns the configuration information structure which is
* filled by the miniport driver. This structure is initialized with
* any knwon configuration information (such as SystemIoBusNumber) by
* the port driver. Where possible, drivers should have one set of
* defaults which do not require any supplied configuration information.
*
* Again - Indicates if the miniport driver wants the port driver to call
* its VIDEO_HW_FIND_ADAPTER function again with a new device extension
* and the same config info. This is used by the miniport drivers which
* can search for several adapters on a bus.
*
* RETURN VALUE:
*
* This routine must return:
*
* VP_RETURN_FOUND - Indicates a host adapter was found and the
* configuration information was successfully determined.
*
* VP_RETURN_ERROR - Indicates a host adapter was found but there was an
* error obtaining the configuration information. If possible an error
* should be logged.
*
* VP_RETURN_BAD_CONFIG - Indicates the supplied configuration was invalid.
*
* VP_RETURN_NOT_FOUND - Indicates no host adapter was found for the
* supplied configuration information.
*
\****************************************************************************/
VP_STATUS
MgaFindAdapter(
PVOID HwDeviceExtension,
PVOID HwContext,
PWSTR ArgumentString,
PVIDEO_PORT_CONFIG_INFO ConfigInfo,
PUCHAR Again
)
{
PMGA_DEVICE_EXTENSION MgaDeviceExtension;
VIDEO_ACCESS_RANGE AllAccessRanges[NUM_ALL_ACCESS_RANGES+1];
VP_STATUS status;
ULONG i, j, SetBiosVl;
//ULONG PreNbBoards;
VideoDebugPrint((1, "MGA.SYS!MgaFindAdapter\n"));
// Make sure the size of the structure is at least as large as what we
// are expecting (check version of the config info structure).
if (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO))
{
return ERROR_INVALID_PARAMETER;
}
pMgaDeviceExtension =
MgaDeviceExtension = HwDeviceExtension;
// Set some global variable saying which bus we'll be exploring.
NtInterfaceType = ConfigInfo->AdapterInterfaceType;
// Get access ranges for our I/O.
// Check to see if there is a hardware resource conflict.
// Register all we'll need for now, unless we already did it.
for (i = 0; i < NUM_MGA_COMMON_ACCESS_RANGES; i++)
{
AllAccessRanges[i] = MgaDriverCommonAccessRange[i];
}
#if (!USE_VP_GET_ACCESS_RANGES)
for (i = 0; i < NUM_MGA_SUPPL_ACCESS_RANGES; i++)
{
AllAccessRanges[i + NUM_MGA_COMMON_ACCESS_RANGES] =
MgaDriverSupplAccessRange[i];
}
#endif
status = VideoPortVerifyAccessRanges(MgaDeviceExtension,
(ULONG)(NUM_MGA_COMMON_ACCESS_RANGES +
NUM_MGA_SUPPL_ACCESS_RANGES),
AllAccessRanges);
if (status != NO_ERROR)
{
VideoDebugPrint((1, "MGA.SYS!MgaFindAdapter: Access Range conflict\n"));
return status;
}
for (i=0; i < NUM_MGA_COMMON_ACCESS_RANGES; i++)
{
if ((MgaDeviceExtension->MappedAddress[i] =
VideoPortGetDeviceBase(
MgaDeviceExtension,
MgaDriverCommonAccessRange[i].RangeStart,
MgaDriverCommonAccessRange[i].RangeLength,
MgaDriverCommonAccessRange[i].RangeInIoSpace)) == NULL)
{
VideoDebugPrint((1, "MGA.SYS!MgaFindAdapter failed to map port addresses\n"));
return(ERROR_INVALID_PARAMETER);
}
}
// Search for MGA boards installed in the system.
// On x86, the first call to MapBoard should have found all the boards.
if (NbBoard != 0)
{
return(ERROR_DEV_NOT_EXIST);
}
if (!MapBoard())
{
VideoDebugPrint((1, "MGA.SYS!MgaFindAdapter failed MapBoard\n"));
return(ERROR_DEV_NOT_EXIST);
}
//PreNbBoards = (ULONG)NbBoard;
////if (!MapBoard())
//if (!MapBoard() || (PreNbBoards == (ULONG)NbBoard))
//{
// VideoDebugPrint((1, "MGA.SYS!MgaFindAdapter failed MapBoard\n"));
// return(ERROR_DEV_NOT_EXIST);
//}
SetBiosVl = 0;
// Fill out RangeStart portion of VIDEO_ACCESS_RANGE structure
// with the mapping of the MGA boards found.
for (i = 0; i < (ULONG)NbBoard; i++)
{
MgaDriverAccessRange[i*2].RangeStart.LowPart = Hw[i].MapAddress;
if (Hw[i].MapAddress == 0xAC000)
{
// Make sure that this is shareable.
MgaDriverAccessRange[i*2].RangeShareable = 1;
// We'll also need access to 4 pages for BIOS_VL.
SetBiosVl = 1;
}
MgaDriverAccessRange[i*2+1].RangeStart.LowPart = Hw[i].ConfigSpace;
if (Hw[i].ConfigSpace == 0)
{
// This board doesn't require access to config space.
MgaDriverAccessRange[i*2+1].RangeLength = 0;
MgaDriverAccessRange[i*2+1].RangeInIoSpace = 0;
}
// Also make sure that the pHwMode field is set to 0.
Hw[i].pHwMode = NULL;
}
// Register all we'll need.
j = NUM_MGA_SUPPL_ACCESS_RANGES + NUM_MGA_COMMON_ACCESS_RANGES;
for (i = 0; i < (ULONG)NbBoard*2; i++)
{
if (MgaDriverAccessRange[i].RangeStart.LowPart != 0)
{
AllAccessRanges[j] = MgaDriverAccessRange[i];
j++;
}
}
if (SetBiosVl == 1)
{
// Add one more range.
AllAccessRanges[j] = MgaDriverAccessRange[0];
AllAccessRanges[j].RangeStart.LowPart = 0xc0000;
AllAccessRanges[j].RangeShareable = 1;
j++;
pMgaBiosVl = (PUCHAR)setmgasel(MgaSel, 0xc0000, 4);
}
//status = VideoPortVerifyAccessRanges(MgaDeviceExtension,
// (ULONG) (NbBoard +
// NUM_MGA_SUPPL_ACCESS_RANGES +
// NUM_MGA_COMMON_ACCESS_RANGES),
// AllAccessRanges);
//if (status != NO_ERROR)
//{
// VideoDebugPrint((1, "MGA.SYS!MgaFindAdapter: Access Range conflict\n"));
// return status;
//}
VideoPortVerifyAccessRanges(MgaDeviceExtension,
j,
AllAccessRanges);
// Special limitation:
// The user-mode driver used by Microsoft doesn't allow for multiple
// boards, so we'll make certain that only one board is considered here:
NbBoard = 1;
// Intel and Alpha both support VideoPortInt10.
MgaDeviceExtension->bUsingInt10 = TRUE;
// Clear out the Emulator entries and the state size since this driver
// is not VGA compatible and does not support them.
ConfigInfo->NumEmulatorAccessEntries = 0;
ConfigInfo->EmulatorAccessEntries = NULL;
ConfigInfo->EmulatorAccessEntriesContext = 0;
// BUGBUG: Andrea, why do I have to do this. Faking out a VGA.
if (!(MgaDeviceExtension->bUsingInt10))
{
ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart = 0x00000000;
ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0x00000000;
ConfigInfo->VdmPhysicalVideoMemoryLength = 0x00000000;
}
else
{
// !!! This should be removed or looked into some more.
// These values are set to the same values as a VGA to try and
// work around some memory mapping issues in the port driver.
ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart = 0x000A0000;
ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0x00000000;
ConfigInfo->VdmPhysicalVideoMemoryLength = 0x00020000;
}
ConfigInfo->HardwareStateSize = 0;
// Let's try to build a list of modes right here. We'll use the
// default vidset for now, but we may change our mind later and
// build a different list.
iBoard = 0;
mgainf = adjustDefaultVidset();
// Call the service.
MgaInitModeList(MgaDeviceExtension);
// If an error occurred, pMgaDeviceExtension->NumberOfSuperModes will
// be zero; otherwise, it will be the appropriate number of modes.
// Indicate we do not wish to be called over
*Again = 0;
// Indicate a successful completion status.
return NO_ERROR;
} // end MgaFindAdapter()
/****************************************************************************\
* BOOLEAN
* MgaInitialize(
* PVOID HwDeviceExtension
* )
*
*
* DESCRIPTION:
*
* This routine does one time initialization of the device.
*
* ARGUMENTS:
*
* HwDeviceExtension - Supplies a pointer to the miniport's device extension.
*
* RETURN VALUE:
*
* Always returns TRUE since this routine can never fail.
*
\****************************************************************************/
BOOLEAN
MgaInitialize(
PVOID HwDeviceExtension
)
{
UNREFERENCED_PARAMETER(HwDeviceExtension);
VideoDebugPrint((1, "MGA.SYS!MgaInitialize\n"));
// We would like to do some work here, but we have to wait until we get
// the contents of the MGA.INF file. Since MGA.INF has to be opened by
// the user-mode driver, this work will be done by a special
// INITIALIZE_MGA service of MgaStartIO.
// Some day, we might want to write an application that will update the
// registry instead of a file. We would then be able to do our work here.
return (TRUE);
} // end MgaInitialize()
/****************************************************************************\
* BOOLEAN
* MgaStartIO(
* PVOID HwDeviceExtension,
* PVIDEO_REQUEST_PACKET RequestPacket
* )
*
* Routine Description:
*
* This routine is the main execution routine for the miniport driver. It
* acceptss a Video Request Packet, performs the request, and then returns
* with the appropriate status.
*
* Arguments:
*
* HwDeviceExtension - Supplies a pointer to the miniport's device
* extension.
*
* RequestPacket - Pointer to the video request packet. This structure
* contains all the parameters passed to the VideoIoControl function.
*
* Return Value:
*
\****************************************************************************/
BOOLEAN
MgaStartIO(
PVOID HwDeviceExtension,
PVIDEO_REQUEST_PACKET RequestPacket
)
{
PMGA_DEVICE_EXTENSION MgaDeviceExtension = HwDeviceExtension;
PVIDEO_MODE_INFORMATION modeInformation;
PVIDEO_MEMORY_INFORMATION memoryInformation;
PVIDEO_CLUT pclutBuffer;
PVIDEO_PUBLIC_ACCESS_RANGES publicAccessRanges;
PRAMDAC_INFO pVideoPointerAttributes;
HwModeData *pMgaDispMode;
OffScrData *pMgaOffScreenData;
MULTI_MODE *pCurMulti;
PWSTR pwszChip, pwszDAC, pwszAdapterString;
PUCHAR pucInBuffer, pucOutBuffer;
PVOID pCurBaseAddr;
VIDEO_CLUT clutBufferOne;
VP_STATUS status;
ULONG ZoomFactor;
ULONG i, n;
ULONG ulWindowLength, ulSizeOfBuffer;
ULONG CurrentResNbBoards, ModeInit;
ULONG cbChip, cbDAC, cbAdapterString, AdapterMemorySize;
USHORT j;
USHORT MaxWidth, MaxHeight, usTemp;
UCHAR iCurBoard;
UCHAR ucTemp;
//DbgBreakPoint();
VideoDebugPrint((1, "MGA.SYS!MgaStartIO\n"));
pMgaDeviceExtension = MgaDeviceExtension;
// Switch on the IoContolCode in the RequestPacket. It indicates which
// function must be performed by the driver.
switch (RequestPacket->IoControlCode)
{
/*------------------------------------------------------------------*\
| Special service: IOCTL_VIDEO_MTX_INITIALIZE_MGA
|
| This will normally be the first call made to MgaStartIO. We do
| here what we should have done in MgaInitialize, but couldn't.
| We first determine if we'll be using the default vidset or the
| contents of some MGA.INF file. If the file is an older version,
| we will send back a non-zero FileInfoSize, so that the user-mode
| driver can call us with MTX_GET_UPDATED_INF to get an updated
| version.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_MTX_INITIALIZE_MGA:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - MTX_INITIALIZE_MGA\n"));
//DbgBreakPoint();
#if 1
status = NO_ERROR;
pucInBuffer = (PUCHAR)(RequestPacket->InputBuffer);
ulSizeOfBuffer = RequestPacket->InputBufferLength;
ulNewInfoSize = 0;
iBoard = 0;
mgainf = adjustDefaultVidset();
pucNewInfo = mgainf;
*(PULONG)(RequestPacket->OutputBuffer) = ulNewInfoSize;
RequestPacket->StatusBlock->Information = sizeof(ULONG);
break;
#else
status = NO_ERROR;
pucInBuffer = (PUCHAR)(RequestPacket->InputBuffer);
ulSizeOfBuffer = RequestPacket->InputBufferLength;
// We may have to update the current MGA.INF file later.
// For now, assume that we won't. If the call to mtxConvertMgaInf
// is required and successful, this will be changed.
ulNewInfoSize = 0;
iBoard = 0;
// Check to see if we are to use the default vidset.
if ((pucInBuffer == NULL) ||
(ulSizeOfBuffer == 0))
{
// The user-mode driver tells us to use the default.
mgainf = adjustDefaultVidset();
}
else
{
// The user-mode driver sends us the actual file contents.
if ( ((header *)pucInBuffer)->Revision != (short)VERSION_NUMBER)
{
// The file is an older version, convert it to current format.
// The returned value can be DefaultVidset, NULL, or a pointer
// to a character buffer allocated by the conversion routine.
if ( !(mgainf = mtxConvertMgaInf(pucInBuffer)) ||
(mgainf == DefaultVidset) )
{
// The returned value was NULL or DefaultVidset.
mgainf = adjustDefaultVidset();
}
}
else
{
// The file is in the current format.
// Allocate memory for the input buffer.
mgainf = (PUCHAR)AllocateSystemMemory(ulSizeOfBuffer);
if (mgainf == NULL)
{
// The memory allocation failed, use the default set.
mgainf = adjustDefaultVidset();
}
else
{
// The memory allocation was successful, copy the buffer.
VideoPortMoveMemory(mgainf, pucInBuffer, ulSizeOfBuffer);
}
}
// At this point, mgainf points to DefaultVidset or to the
// MGA.INF information, in the current version format.
if (mgainf != DefaultVidset)
{
// We are not looking at the default vidset.
if ((selectMgaInfoBoard() == NULL) ||
(strncmp(mgainf, "Matrox MGA Setup file", 21) != 0))
{
// The MGA.INF file is incomplete or corrupted.
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - Incomplete MGA.INF file, using default\n"));
// Either memory was allocated for the input buffer, or
// memory was allocated by mtxConvertMgaInf. Free it.
VideoPortReleaseBuffer(pMgaDeviceExtension, mgainf);
// Make sure that we won't try to update MGA.INF.
ulNewInfoSize = 0;
// And use the default set.
mgainf = adjustDefaultVidset();
}
}
}
// At this point, mgainf points to DefaultVidset or to the
// validated MGA.INF information, in the current version format.
// Record the mgainf value, in case we need it later.
pucNewInfo = mgainf;
// Set the length of the file to be updated.
*(PULONG)(RequestPacket->OutputBuffer) = ulNewInfoSize;
// And don't forget to set this to the appropriate length!
RequestPacket->StatusBlock->Information = sizeof(ULONG);
break; // end MTX_INITIALIZE_MGA
#endif // #if 0
/*------------------------------------------------------------------*\
| Special service: IOCTL_VIDEO_MTX_INIT_MODE_LIST
|
| This will normally be the second or third call made to MgaStartIO.
| We call mtxCheckHwAll() and we fill in our MgaDeviceExtension
| structure with mode information for each board we found. From
| this, we build a series of MULTI_MODE structures describing each
| 'super-mode', starting at MgaDeviceExtension->pSuperModes, and
| we set the total number of supported modes in
| MgaDeviceExtension->NumberOfSuperModes.
|
| The miniport driver builds a default list of modes (using the
| default vidset) at HwFindAdapter time. The default list will
| be discarded when the user-mode driver calls INIT_MODE_LIST
| explicitly. When the BASEVIDEO driver calls QUERY_NUM_AVAIL_MODES
| without first calling INIT_MODE_LIST, the default list will be
| used.
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_MTX_INIT_MODE_LIST:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - MTX_INIT_MODE_LIST\n"));
//DbgBreakPoint();
status = MgaInitModeList(MgaDeviceExtension);
break; // end MTX_INIT_MODE_LIST
/*------------------------------------------------------------------*\
| Special service: MTX_GET_UPDATED_INF
|
| This service will be called if a non-zero file size was returned
| by MTX_INITIALIZE_MGA. It will return the updated MGA.INF
| contents to the user-mode driver.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_MTX_GET_UPDATED_INF:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - MTX_GET_UPDATED_INF\n"));
//DbgBreakPoint();
if (ulNewInfoSize == 0)
{
status = NO_ERROR;
break;
}
pucOutBuffer = (PUCHAR)(RequestPacket->OutputBuffer);
ulSizeOfBuffer = RequestPacket->OutputBufferLength;
if (ulSizeOfBuffer < ulNewInfoSize)
{
// Not enough room reserved for the file contents.
status = ERROR_INSUFFICIENT_BUFFER;
}
else
{
// We should be able to copy our data.
VideoPortMoveMemory(pucOutBuffer, pucNewInfo, ulNewInfoSize);
// And don't forget to set this to the appropriate length!
RequestPacket->StatusBlock->Information = ulNewInfoSize;
status = NO_ERROR;
}
break; // end MTX_GET_UPDATED_INF
/*------------------------------------------------------------------*\
| Required service: IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
|
| The MGA user-mode drivers will call this very early in their
| initialization sequence, probably right after MTX_INITIALIZE_MGA.
| This will return the number of video modes supported by the
| adapter by filling out a VIDEO_NUM_MODES structure.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - QUERY_NUM_AVAIL_MODES\n"));
//DbgBreakPoint();
// Find out the size of the data to be put in the the buffer and
// return that in the status information (whether or not the
// information is there).
// If the buffer passed in is not large enough return an appropriate
// error code.
if (RequestPacket->OutputBufferLength <
(RequestPacket->StatusBlock->Information =
sizeof(VIDEO_NUM_MODES)))
{
status = ERROR_INSUFFICIENT_BUFFER;
}
else
{
if (MgaDeviceExtension->NumberOfSuperModes == 0)
{
// No modes are listed so far, try to make up the list.
iBoard = 0;
if (mgainf == NULL)
{
// No vidset yet, use the default one.
mgainf = adjustDefaultVidset();
}
// Call the service.
MgaInitModeList(MgaDeviceExtension);
// If an error occurred, NumberOfSuperModes will be zero;
// otherwise, it will be the appropriate number of modes.
}
((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->NumModes =
MgaDeviceExtension->NumberOfSuperModes;
((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->
ModeInformationLength = sizeof(VIDEO_MODE_INFORMATION);
status = NO_ERROR;
}
break; // end QUERY_NUM_AVAIL_MODES
/*------------------------------------------------------------------*\
| Required service: IOCTL_VIDEO_QUERY_AVAIL_MODES
|
| The MGA user-mode drivers will call this very early in their
| initialization sequence, just after QUERY_NUM_AVAIL_MODES.
| This will return return information about each video mode
| supported by the adapter (including modes that require more than
| one board if more than one are present) by filling out an array
| of VIDEO_MODE_INFORMATION structures.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_QUERY_AVAIL_MODES:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - QUERY_AVAIL_MODES\n"));
//DbgBreakPoint();
if (RequestPacket->OutputBufferLength <
(RequestPacket->StatusBlock->Information =
MgaDeviceExtension->NumberOfSuperModes *
sizeof(VIDEO_MODE_INFORMATION)) )
{
status = ERROR_INSUFFICIENT_BUFFER;
}
else
{
modeInformation = RequestPacket->OutputBuffer;
// Fill in a VIDEO_MODE_INFORMATION struc for each available mode.
pCurMulti = MgaDeviceExtension->pSuperModes;
if (pCurMulti == NULL)
{
status = ERROR_DEV_NOT_EXIST;
break;
}
for (i = 0; i < MgaDeviceExtension->NumberOfSuperModes; i++)
{
// Fill in common values that apply to all modes
modeInformation[i] = CommonVideoModeInformation;
// Fill in mode specific informations
modeInformation[i].ModeIndex = pCurMulti->MulModeNumber;
modeInformation[i].VisScreenWidth = pCurMulti->MulWidth;
modeInformation[i].VisScreenHeight= pCurMulti->MulHeight;
modeInformation[i].ScreenStride =
pCurMulti->MulWidth * pCurMulti->MulPixWidth / 8;
modeInformation[i].BitsPerPlane = pCurMulti->MulPixWidth;
modeInformation[i].Frequency = pCurMulti->MulRefreshRate;
// XMillimeter and YMillimeter will be modified by the user-
// mode driver.
// If we're in TrueColor mode, then set RGB masks
if ((modeInformation[i].BitsPerPlane == 32) ||
(modeInformation[i].BitsPerPlane == 24))
{
// This makes 32 bpp look like 24 to the display driver
modeInformation[i].BitsPerPlane = 24;
modeInformation[i].RedMask = 0x00FF0000;
modeInformation[i].GreenMask = 0x0000FF00;
modeInformation[i].BlueMask = 0x000000FF;
modeInformation[i].AttributeFlags =
VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS;
}
else if (modeInformation[i].BitsPerPlane == 16)
{
modeInformation[i].AttributeFlags =
VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS;
if (pCurMulti->MulHwModes[0]->DispType & DISPTYPE_M565)
{
modeInformation[i].RedMask = 0x0000F800;
modeInformation[i].GreenMask = 0x000007E0;
modeInformation[i].BlueMask = 0x0000001F;
}
else
{
modeInformation[i].RedMask = 0x00007C00;
modeInformation[i].GreenMask = 0x000003E0;
modeInformation[i].BlueMask = 0x0000001F;
modeInformation[i].AttributeFlags |= VIDEO_MODE_555;
modeInformation[i].BitsPerPlane = 15;
}
}
else
{
modeInformation[i].AttributeFlags =
VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS |
VIDEO_MODE_PALETTE_DRIVEN |
VIDEO_MODE_MANAGED_PALETTE;
}
if (pCurMulti->MulHwModes[0]->ZBuffer)
{
// This is a 3D mode.
modeInformation[i].AttributeFlags |= VIDEO_MODE_3D;
}
// Number of boards involved in the current super-mode.
CurrentResNbBoards = pCurMulti->MulArrayWidth *
pCurMulti->MulArrayHeight;
// For each of them...
for (n = 0; n < CurrentResNbBoards; n++)
{
// Point to the mode information structure.
pMgaDispMode = pCurMulti->MulHwModes[n];
// For now, don't disclose whether we're interlaced.
//if (pMgaDispMode->DispType & TYPE_INTERLACED)
//{
// modeInformation[i].AttributeFlags |=
// VIDEO_MODE_INTERLACED;
//}
// Figure out the width and height of the video memory bitmap
MaxWidth = pMgaDispMode->DispWidth;
MaxHeight = pMgaDispMode->DispHeight;
pMgaOffScreenData = pMgaDispMode->pOffScr;
for (j = 0; j < pMgaDispMode->NumOffScr; j++)
{
if ((usTemp=(pMgaOffScreenData[j].XStart +
pMgaOffScreenData[j].Width)) > MaxWidth)
MaxWidth=usTemp;
if ((usTemp=(pMgaOffScreenData[j].YStart +
pMgaOffScreenData[j].Height)) > MaxHeight)
MaxHeight=usTemp;
}
modeInformation[i].VideoMemoryBitmapWidth = MaxWidth;
modeInformation[i].VideoMemoryBitmapHeight= MaxHeight;
}
pCurMulti++;
}
status = NO_ERROR;
}
break; // end QUERY_AVAIL_MODES
/*------------------------------------------------------------------*\
| Required service: IOCTL_VIDEO_SET_CURRENT_MODE
|
| The MGA user-mode drivers will probably call this service right
| after QUERY_AVAIL_MODES. This will set the adapter to the mode
| specified by VIDEO_MODE. If more than one board are involved
| in the mode, each one will be set to the appropriate mode. We
| want to take care not to re-program the mode already current.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_SET_CURRENT_MODE:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - SET_CURRENT_MODE\n"));
//DbgBreakPoint();
ModeInit = *(ULONG *)(RequestPacket->InputBuffer);
if (MgaDeviceExtension->SuperModeNumber == ModeInit)
{
// The requested mode is already the current mode
status = NO_ERROR;
break;
}
// Save the current board, because this service will modify it.
iCurBoard = iBoard;
pCurBaseAddr = pMgaBaseAddr;
// Check to see if we have a valid ModeNumber.
if (ModeInit >= MgaDeviceExtension->NumberOfSuperModes)
{
// If the mode number is invalid, choose the first one.
ModeInit = 0;
}
MgaDeviceExtension->SuperModeNumber = ModeInit;
// Point to the appropriate MULTI_MODE structure.
pCurMulti = &MgaDeviceExtension->pSuperModes[ModeInit];
if (pCurMulti == NULL)
{
status = ERROR_DEV_NOT_EXIST;
break;
}
#if DBG
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - Requested mode: %u\n", ModeInit));
VideoDebugPrint((1, "ModeNumber Width Height PW X Y n mo pHwMode\n"));
VideoDebugPrint((1, "0x%08x % 6d % 6d % 3d % 3d % 3d\n",
pCurMulti->MulModeNumber,
pCurMulti->MulWidth,
pCurMulti->MulHeight,
pCurMulti->MulPixWidth,
pCurMulti->MulArrayWidth,
pCurMulti->MulArrayHeight));
j = pCurMulti->MulArrayWidth * pCurMulti->MulArrayHeight;
for (n = 0; n < j; n++)
{
VideoDebugPrint((1, " %d %02x 0x%08x\n",
pCurMulti->MulBoardNb[n],
pCurMulti->MulBoardMode[n],
pCurMulti->MulHwModes[n]));
}
//DbgBreakPoint();
#endif
// Use info for the first board to set a few Registry values.
iBoard = pCurMulti->MulBoardNb[0];
switch((Hw[iBoard].ProductRev >> 4) & 0x0000000f)
{
case TITAN_CHIP: pwszChip = L"MGA (A2681700)";
cbChip = sizeof(L"MGA (A2681700)");
break;
case ATLAS_CHIP: pwszChip = L"MGA (A2681701)";
cbChip = sizeof(L"MGA (A2681701)");
break;
case ATHENA_CHIP: pwszChip = L"MGA (A2681702)";
cbChip = sizeof(L"MGA (A2681702)");
break;
default: pwszChip = L"MGA (Unspecified)";
cbChip = sizeof(L"MGA (Unspecified)");
break;
}
switch(Hw[iBoard].DacType)
{
case BT482: pwszDAC = L"Brooktree Bt482";
cbDAC = sizeof(L"Brooktree Bt482");
break;
case BT485: pwszDAC = L"Brooktree Bt485";
cbDAC = sizeof(L"Brooktree Bt485");
break;
case PX2085: pwszDAC = L"Cirrus Logic PX2085";
cbDAC = sizeof(L"Cirrus Logic PX2085");
break;
case VIEWPOINT: pwszDAC = L"TI TVP3020";
cbDAC = sizeof(L"TI TVP3020");
break;
case TVP3026: pwszDAC = L"TI TVP3026";
cbDAC = sizeof(L"TI TVP3026");
break;
default: pwszDAC = L"Unknown";
cbDAC = sizeof(L"Unknown");
break;
}
AdapterMemorySize = Hw[iBoard].VramAvail + Hw[iBoard].DramAvail;
if ((Hw[iBoard].ProductType & 0x0f) == BOARD_MGA_RESERVED)
{
MgaDeviceExtension->BoardId = TYPE_QVISION_PCI;
// This is a Compaq board.
if (Hw[iBoard].DacType == PX2085)
{
pwszAdapterString = L"QVision 2000";
cbAdapterString = sizeof(L"QVision 2000");
}
else if (Hw[iBoard].DacType == TVP3026)
{
pwszAdapterString = L"QVision 2000+";
cbAdapterString = sizeof(L"QVision 2000+");
}
else
{
MgaDeviceExtension->BoardId = TYPE_QVISION_ISA;
pwszAdapterString = L"Compaq Unknown";
cbAdapterString = sizeof(L"Compaq Unknown");
}
}
else
{
MgaDeviceExtension->BoardId = TYPE_MATROX;
switch(Hw[iBoard].ProductType >> 16)
{
case MGA_ULTIMA: pwszAdapterString = L"Ultima";
cbAdapterString = sizeof(L"Ultima");
break;
case MGA_ULTIMA_VAFC:
pwszAdapterString = L"Ultima VAFC";
cbAdapterString = sizeof(L"Ultima VAFC");
break;
case MGA_ULTIMA_PLUS:
pwszAdapterString = L"Ultima Plus";
cbAdapterString = sizeof(L"Ultima Plus");
break;
case MGA_ULTIMA_PLUS_200:
pwszAdapterString = L"Ultima Plus 200";
cbAdapterString = sizeof(L"Ultima Plus 200");
break;
case MGA_IMPRESSION_PLUS:
pwszAdapterString = L"Impression Plus";
cbAdapterString = sizeof(L"Impression Plus");
break;
case MGA_IMPRESSION_PLUS_200:
pwszAdapterString = L"Impression Plus 200";
cbAdapterString = sizeof(L"Impression Plus 200");
break;
case MGA_IMPRESSION:
pwszAdapterString = L"Impression";
cbAdapterString = sizeof(L"Impression");
break;
case MGA_IMPRESSION_PRO:
pwszAdapterString = L"Impression PRO";
cbAdapterString = sizeof(L"Impression PRO");
break;
case MGA_IMPRESSION_LTE:
pwszAdapterString = L"Impression Lite";
cbAdapterString = sizeof(L"Impression Lite");
break;
default: pwszAdapterString = L"Unknown";
cbAdapterString = sizeof(L"Unknown");
break;
}
}
VideoPortSetRegistryParameters(MgaDeviceExtension,
L"HardwareInformation.ChipType",
pwszChip,
cbChip);
VideoPortSetRegistryParameters(MgaDeviceExtension,
L"HardwareInformation.DacType",
pwszDAC,
cbDAC);
VideoPortSetRegistryParameters(MgaDeviceExtension,
L"HardwareInformation.MemorySize",
&AdapterMemorySize,
sizeof(ULONG));
VideoPortSetRegistryParameters(MgaDeviceExtension,
L"HardwareInformation.AdapterString",
pwszAdapterString,
cbAdapterString);
// Number of boards involved in the current super-mode.
CurrentResNbBoards = pCurMulti->MulArrayWidth *
pCurMulti->MulArrayHeight;
// For each of them...
for (n = 0; n < CurrentResNbBoards; n++)
{
// Point to the mode information structure.
pMgaDispMode = pCurMulti->MulHwModes[n];
// Make the board current.
iBoard = pCurMulti->MulBoardNb[n];
pMgaBaseAddr = MgaDeviceExtension->KernelModeMappedBaseAddress[iBoard];
// If the board is mapped at 0x000AC000, we must set the
// MAP SEL 1 bit of the VGA MISC register to have the TITAN
// mapped.
if (Hw[iBoard].MapAddress == 0x000AC000)
{
// Select VGA MISC register (Index 6)
VideoPortWritePortUchar(TITAN_GCTL_ADDR_PORT, (UCHAR) 6);
ucTemp = VideoPortReadPortUchar(TITAN_GCTL_DATA_PORT) | 0x08;
VideoPortWritePortUchar(TITAN_GCTL_DATA_PORT, ucTemp);
}
// Reset all Titan host registers
VideoPortWriteRegisterUlong((PULONG)((PUCHAR)pMgaBaseAddr +
TITAN_OFFSET + TITAN_RST), 1);
VideoPortStallExecution(2000);
VideoPortWriteRegisterUlong((PULONG)((PUCHAR)pMgaBaseAddr +
TITAN_OFFSET + TITAN_RST), 0);
// Set the graphics mode from the available hardware modes.
mtxSelectHwMode(pMgaDispMode);
// Select the display mode.
// Pass the frequency in the last byte of the ZOOM factor
ZoomFactor = (pCurMulti->MulRefreshRate << 24) | ZOOM_X1;
mtxSetDisplayMode(pMgaDispMode, ZoomFactor);
// Set the cursor colors to white and black.
MgaSetCursorColour(MgaDeviceExtension, 0xFFFFFF, 0x000000);
// Set the MCtlWtSt register.
VideoPortWriteRegisterUlong((PULONG)((PUCHAR)pMgaBaseAddr +
TITAN_OFFSET + TITAN_MCTLWTST), (ULONG)MCTLWTST_STD);
}
// Restore the current board to what it used to be.
iBoard = iCurBoard;
pMgaBaseAddr = pCurBaseAddr;
// At this point, the RAMDAC should be okay, but it looks
// like it's not quite ready to accept data, particularly
// on VL boards. Adding a delay seems to fix things.
VideoPortStallExecution(100); // Microseconds
status = NO_ERROR;
break; // end SET_CURRENT_MODE
/*------------------------------------------------------------------*\
| Special service: IOCTL_VIDEO_MTX_QUERY_BOARD_ARRAY
|
| The MGA user-mode drivers will probably call this service after
| the mode has been set by SET_CURRENT_MODE. The user-mode drivers
| have to know how the boards are arrayed to make up the display
| surface, so that they know which board to address when writing
| to a specific (x, y) position. The miniport driver knows this,
| since it has just set the mode.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_MTX_QUERY_BOARD_ARRAY:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - MTX_QUERY_BOARD_ARRAY\n"));
//DbgBreakPoint();
// If the buffer passed in is not large enough return an appropriate
// error code.
if (RequestPacket->OutputBufferLength <
(RequestPacket->StatusBlock->Information = sizeof(SIZEL)))
{
status = ERROR_INSUFFICIENT_BUFFER;
}
else
{
if(MgaDeviceExtension->SuperModeNumber == 0xFFFFFFFF)
{
// No mode has been selected yet, so we don't know...
status = ERROR_DEV_NOT_EXIST;
}
else
{
ModeInit = MgaDeviceExtension->SuperModeNumber;
// Point to the appropriate MULTI_MODE structure.
pCurMulti = &MgaDeviceExtension->pSuperModes[ModeInit];
if (pCurMulti == NULL)
{
status = ERROR_DEV_NOT_EXIST;
break;
}
((SIZEL*)RequestPacket->OutputBuffer)->cx =
pCurMulti->MulArrayWidth;
((SIZEL*)RequestPacket->OutputBuffer)->cy =
pCurMulti->MulArrayHeight;
status = NO_ERROR;
}
}
break; // end MTX_QUERY_BOARD_ARRAY
/*------------------------------------------------------------------*\
| Special service: IOCTL_VIDEO_MTX_MAKE_BOARD_CURRENT
|
| The MGA user-mode drivers will call this service whenever a
| miniport operation need be executed on a particular board, as
| opposed to every single board involved in the current mode.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_MTX_MAKE_BOARD_CURRENT:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - MTX_MAKE_BOARD_CURRENT\n"));
//DbgBreakPoint();
n = *(ULONG *)(RequestPacket->InputBuffer);
// Check to see if we have a valid board number.
i = MgaDeviceExtension->SuperModeNumber;
if (i == 0xFFFFFFFF)
{
status = ERROR_DEV_NOT_EXIST;
break;
}
pCurMulti = &MgaDeviceExtension->pSuperModes[i];
if (pCurMulti == NULL)
{
status = ERROR_DEV_NOT_EXIST;
break;
}
if (n >= (ULONG)(pCurMulti->MulArrayWidth * pCurMulti->MulArrayHeight))
{
status = ERROR_DEV_NOT_EXIST;
}
else
{
// Make the board current.
CONVERT_BOARD_NUMBER(n);
iBoard = pCurMulti->MulBoardNb[n];
pMgaBaseAddr = MgaDeviceExtension->KernelModeMappedBaseAddress[iBoard];
status = NO_ERROR;
}
break; // end MTX_MAKE_BOARD_CURRENT
/*------------------------------------------------------------------*\
| Special service: IOCTL_VIDEO_MTX_QUERY_BOARD_ID
|
| This service returns the board type information to the user-mode
| driver. A call to MTX_MAKE_BOARD_CURRENT must have been made
| previously to set which board is to be queried.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_MTX_QUERY_BOARD_ID:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - MTX_QUERY_BOARD_ID\n"));
//DbgBreakPoint();
if (RequestPacket->OutputBufferLength < sizeof(ULONG))
{
// Not enough room reserved for the board ID.
status = ERROR_INSUFFICIENT_BUFFER;
}
else
{
*((PULONG)(RequestPacket->OutputBuffer)) = ProductMGA[iBoard];
// And don't forget to set this to the appropriate length!
RequestPacket->StatusBlock->Information = sizeof(ULONG);
status = NO_ERROR;
}
break; // end MTX_QUERY_BOARD_ID
/*------------------------------------------------------------------*\
| Special service: IOCTL_VIDEO_MTX_QUERY_HW_DATA
|
| This service returns hardware information about the current
| board by filling out a HW_DATA structure. A call to
| MTX_MAKE_BOARD_CURRENT must have been made previously to set
| which board is to be queried.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_MTX_QUERY_HW_DATA:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - MTX_QUERY_HW_DATA\n"));
//DbgBreakPoint();
// Check if we have a sufficient output buffer
if (RequestPacket->OutputBufferLength <
(RequestPacket->StatusBlock->Information = sizeof(HW_DATA)))
{
status = ERROR_INSUFFICIENT_BUFFER;
}
else
{
register PHW_DATA pUserModeHwData;
register HwData *pMiniportHwData;
pUserModeHwData = RequestPacket->OutputBuffer;
pMiniportHwData = &Hw[iBoard];
pUserModeHwData->MapAddress = pMiniportHwData->MapAddress;
pUserModeHwData->ProductType = pMiniportHwData->ProductType;
pUserModeHwData->ProductRev = pMiniportHwData->ProductRev;
pUserModeHwData->ShellRev = pMiniportHwData->ShellRev;
pUserModeHwData->BindingRev = pMiniportHwData->BindingRev;
pUserModeHwData->VGAEnable = pMiniportHwData->VGAEnable;
pUserModeHwData->Sync = pMiniportHwData->Sync;
pUserModeHwData->Device8_16 = pMiniportHwData->Device8_16;
pUserModeHwData->PortCfg = pMiniportHwData->PortCfg;
pUserModeHwData->PortIRQ = pMiniportHwData->PortIRQ;
pUserModeHwData->MouseMap = pMiniportHwData->MouseMap;
pUserModeHwData->MouseIRate = pMiniportHwData->MouseIRate;
pUserModeHwData->DacType = pMiniportHwData->DacType;
pUserModeHwData->cursorInfo.MaxWidth =
pMiniportHwData->cursorInfo.MaxWidth;
pUserModeHwData->cursorInfo.MaxHeight =
pMiniportHwData->cursorInfo.MaxHeight;
pUserModeHwData->cursorInfo.MaxDepth =
pMiniportHwData->cursorInfo.MaxDepth;
pUserModeHwData->cursorInfo.MaxColors =
pMiniportHwData->cursorInfo.MaxColors;
pUserModeHwData->cursorInfo.CurWidth =
pMiniportHwData->cursorInfo.CurWidth;
pUserModeHwData->cursorInfo.CurHeight =
pMiniportHwData->cursorInfo.CurHeight;
pUserModeHwData->cursorInfo.cHotSX =
pMiniportHwData->cursorInfo.cHotSX;
pUserModeHwData->cursorInfo.cHotSY =
pMiniportHwData->cursorInfo.cHotSY;
pUserModeHwData->cursorInfo.HotSX =
pMiniportHwData->cursorInfo.HotSX;
pUserModeHwData->cursorInfo.HotSY =
pMiniportHwData->cursorInfo.HotSY;
pUserModeHwData->VramAvail = pMiniportHwData->VramAvail;
pUserModeHwData->DramAvail = pMiniportHwData->DramAvail;
pUserModeHwData->CurrentOverScanX = pMiniportHwData->CurrentOverScanX;
pUserModeHwData->CurrentOverScanY = pMiniportHwData->CurrentOverScanY;
pUserModeHwData->YDstOrg = pMiniportHwData->YDstOrg;
status = NO_ERROR;
}
break; // end MTX_QUERY_HW_DATA
/*------------------------------------------------------------------*\
| Special service: IOCTL_VIDEO_MTX_QUERY_NUM_OFFSCREEN_BLOCKS
|
| This service returns the number of offscreen memory areas
| available for the requested super-mode. A call to
| MTX_MAKE_BOARD_CURRENT must have been made previously to set
| which board is to be queried.
|
| Input: A pointer to a VIDEO_MODE_INFORMATION structure, as
| returned by a QUERY_AVAIL_MODES request.
|
| Output: A pointer to a VIDEO_NUM_OFFSCREEN_BLOCKS structure, as
| defined below.
|
| The calling routine will have allocated the memory for the
| VIDEO_NUM_OFFSCREEN_BLOCKS structure.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_MTX_QUERY_NUM_OFFSCREEN_BLOCKS:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - MTX_QUERY_NUM_OFFSCREEN_BLOCKS\n"));
//DbgBreakPoint();
// Verify that input & output buffers are the correct sizes
if ( (RequestPacket->OutputBufferLength <
(RequestPacket->StatusBlock->Information =
sizeof(VIDEO_NUM_OFFSCREEN_BLOCKS))) ||
(RequestPacket->InputBufferLength <
sizeof(VIDEO_MODE_INFORMATION)) )
{
status = ERROR_INSUFFICIENT_BUFFER;
}
else
{
PVIDEO_NUM_OFFSCREEN_BLOCKS pVideoNumOffscreenBlocks =
RequestPacket->OutputBuffer;
// Get the super-mode number the user-mode driver is asking about.
modeInformation = RequestPacket->InputBuffer;
ModeInit = modeInformation->ModeIndex;
// Point to the appropriate MULTI_MODE structure.
pCurMulti = &MgaDeviceExtension->pSuperModes[ModeInit];
if (pCurMulti == NULL)
{
status = ERROR_DEV_NOT_EXIST;
break;
}
// Look for the current board.
i = 0;
while ((i < NB_BOARD_MAX) && (pCurMulti->MulBoardNb[i] != iBoard))
i++;
// Point to the appropriate hw mode.
pMgaDispMode = pCurMulti->MulHwModes[i];
// Fill out NumBlocks.
pVideoNumOffscreenBlocks->NumBlocks = pMgaDispMode->NumOffScr;
// Fill out OffScreenBlockLength.
pVideoNumOffscreenBlocks->OffscreenBlockLength =
sizeof(OFFSCREEN_BLOCK);
status = NO_ERROR;
}
break; // end MTX_QUERY_NUM_OFFSCREEN_BLOCKS
/*------------------------------------------------------------------*\
| Special service: IOCTL_VIDEO_MTX_QUERY_OFFSCREEN_BLOCKS
|
| This service returns a description of each offscreen memory area
| available for the requested super-mode. A call to
| MTX_MAKE_BOARD_CURRENT must have been made previously to set
| which board is to be queried.
|
| Input: A pointer to a VIDEO_MODE_INFORMATION structure, as
| returned by a QUERY_AVAIL_MODES request.
|
| Output: A pointer to the first of a series of OFFSCREEN_BLOCK
| structures, as defined below.
|
| The calling routine will have allocated the memory for the
| OFFSCREEN_BLOCK structures.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_MTX_QUERY_OFFSCREEN_BLOCKS:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - MTX_QUERY_OFFSCREEN_BLOCKS\n"));
//DbgBreakPoint();
// Verify that the input buffer is the correct size.
if (RequestPacket->InputBufferLength < sizeof(VIDEO_MODE_INFORMATION))
{
status = ERROR_INSUFFICIENT_BUFFER;
}
else
{
UCHAR NumOffScrBlocks;
OffScrData *pOffScrDataArray;
POFFSCREEN_BLOCK pOffscreenBlockArray =
RequestPacket->OutputBuffer;
// Get the super-mode number the user-mode driver is asking about.
modeInformation = RequestPacket->InputBuffer;
ModeInit = modeInformation->ModeIndex;
// Point to the appropriate MULTI_MODE structure.
pCurMulti = &MgaDeviceExtension->pSuperModes[ModeInit];
if (pCurMulti == NULL)
{
status = ERROR_DEV_NOT_EXIST;
break;
}
// Look for the current board.
i = 0;
while ((i < NB_BOARD_MAX) && (pCurMulti->MulBoardNb[i] != iBoard))
i++;
// Point to the appropriate hw mode.
pMgaDispMode = pCurMulti->MulHwModes[i];
NumOffScrBlocks = pMgaDispMode->NumOffScr;
// Verify that the output buffer is the correct size.
if (RequestPacket->OutputBufferLength <
(RequestPacket->StatusBlock->Information =
NumOffScrBlocks * sizeof(OFFSCREEN_BLOCK)))
{
status = ERROR_INSUFFICIENT_BUFFER;
}
else
{
// Fill the OFFSCREEN_BLOCK structures
pOffScrDataArray = pMgaDispMode->pOffScr;
for (i = 0; i < NumOffScrBlocks; i++)
{
pOffscreenBlockArray[i].Type =pOffScrDataArray[i].Type;
pOffscreenBlockArray[i].XStart=pOffScrDataArray[i].XStart;
pOffscreenBlockArray[i].YStart=pOffScrDataArray[i].YStart;
pOffscreenBlockArray[i].Width =pOffScrDataArray[i].Width;
pOffscreenBlockArray[i].Height=pOffScrDataArray[i].Height;
pOffscreenBlockArray[i].SafePlanes =
pOffScrDataArray[i].SafePlanes;
pOffscreenBlockArray[i].ZOffset =
pOffScrDataArray[i].ZXStart;
}
status = NO_ERROR;
}
}
break; // end MTX_QUERY_OFFSCREEN_BLOCKS
/*------------------------------------------------------------------*\
| Special service: IOCTL_VIDEO_MTX_QUERY_RAMDAC_INFO
|
| This service returns information about the type and capabilities
| of the installed ramdac by filling out a RAMDAC_INFO structure.
| A call to MTX_MAKE_BOARD_CURRENT must have been made previously
| to set which board is to be queried.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_MTX_QUERY_RAMDAC_INFO:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - MTX_QUERY_RAMDAC_INFO\n"));
//DbgBreakPoint();
// Check if we have a sufficient output buffer
if (RequestPacket->OutputBufferLength <
(RequestPacket->StatusBlock->Information =
sizeof(RAMDAC_INFO)))
{
status = ERROR_INSUFFICIENT_BUFFER;
}
else
{
pVideoPointerAttributes=RequestPacket->OutputBuffer;
pVideoPointerAttributes->Flags = RAMDAC_NONE;
pVideoPointerAttributes->OverScanX =
Hw[iBoard].CurrentOverScanX;
pVideoPointerAttributes->OverScanY =
Hw[iBoard].CurrentOverScanY;
if (Hw[iBoard].DacType == DacTypeBT482)
{
pVideoPointerAttributes->Flags = VIDEO_MODE_MONO_POINTER | RAMDAC_BT482;
pVideoPointerAttributes->Width = 32;
pVideoPointerAttributes->Height = 32;
}
if (Hw[iBoard].DacType == DacTypeBT485)
{
pVideoPointerAttributes->Flags = VIDEO_MODE_MONO_POINTER | RAMDAC_BT485;
pVideoPointerAttributes->Width = 64;
pVideoPointerAttributes->Height = 64;
}
if (Hw[iBoard].DacType == DacTypePX2085)
{
pVideoPointerAttributes->Flags = VIDEO_MODE_MONO_POINTER | RAMDAC_PX2085;
pVideoPointerAttributes->Width = 64;
pVideoPointerAttributes->Height = 64;
}
if (Hw[iBoard].DacType == DacTypeVIEWPOINT)
{
pVideoPointerAttributes->Flags = VIDEO_MODE_MONO_POINTER | RAMDAC_VIEWPOINT;
pVideoPointerAttributes->Width = 64;
pVideoPointerAttributes->Height = 64;
}
if (Hw[iBoard].DacType == DacTypeTVP3026)
{
pVideoPointerAttributes->Flags = VIDEO_MODE_MONO_POINTER | RAMDAC_TVP3026;
pVideoPointerAttributes->Width = 64;
pVideoPointerAttributes->Height = 64;
}
status = NO_ERROR;
}
break; // end MTX_QUERY_RAMDAC_INFO
/*------------------------------------------------------------------*\
| Required service: IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES
|
| This service will return the address ranges used by the user-mode
| drivers to program the video hardware directly, by filling out
| a VIDEO_PUBLIC_ACCESS_RANGES structure. A call to
| MTX_MAKE_BOARD_CURRENT must have been made previously to set
| which board is to be accessed.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - QUERY_PUBLIC_ACCESS_RANGES\n"));
//DbgBreakPoint();
// Make sure the output buffer is big enough.
if (RequestPacket->OutputBufferLength <
(RequestPacket->StatusBlock->Information =
sizeof(VIDEO_PUBLIC_ACCESS_RANGES)))
{
status = ERROR_INSUFFICIENT_BUFFER;
}
else
{
// Fill out the VIDEO_PUBLIC_ACCESS_RANGES buffer.
publicAccessRanges = RequestPacket->OutputBuffer;
ulWindowLength = MgaDriverAccessRange[iBoard*2].RangeLength;
publicAccessRanges->InIoSpace =
MgaDriverAccessRange[iBoard*2].RangeInIoSpace;
publicAccessRanges->MappedInIoSpace =
MgaDriverAccessRange[iBoard*2].RangeInIoSpace;
publicAccessRanges->VirtualAddress =
(PVOID) NULL; // Any virtual address
status = VideoPortMapMemory(
MgaDeviceExtension,
MgaDriverAccessRange[iBoard*2].RangeStart,
&ulWindowLength,
&(publicAccessRanges->InIoSpace),
&(publicAccessRanges->VirtualAddress)
);
MgaDeviceExtension->UserModeMappedBaseAddress[iBoard] =
publicAccessRanges->VirtualAddress;
}
break; // end QUERY_PUBLIC_ACCESS_RANGES
/*------------------------------------------------------------------*\
| Required service: IOCTL_VIDEO_SET_COLOR_REGISTERS
|
| This service sets the adapter's color registers to the specified
| RGB values.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_SET_COLOR_REGISTERS:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - SET_COLOR_REGISTERS\n"));
//DbgBreakPoint();
if ((ModeInit = MgaDeviceExtension->SuperModeNumber) == 0xFFFFFFFF)
{
status = ERROR_DEV_NOT_EXIST;
break;
}
pclutBuffer = RequestPacket->InputBuffer;
// Save the current board, because this service will modify it.
iCurBoard = iBoard;
pCurBaseAddr = pMgaBaseAddr;
status = NO_ERROR;
// Point to the appropriate MULTI_MODE structure.
pCurMulti = &MgaDeviceExtension->pSuperModes[ModeInit];
if (pCurMulti == NULL)
{
status = ERROR_DEV_NOT_EXIST;
break;
}
// Number of boards involved in the current super-mode.
CurrentResNbBoards = pCurMulti->MulArrayWidth *
pCurMulti->MulArrayHeight;
// For each of them...
for (n = 0; n < CurrentResNbBoards; n++)
{
// Point to the mode information structure.
pMgaDispMode = pCurMulti->MulHwModes[n];
// Make the board current.
iBoard = pCurMulti->MulBoardNb[n];
pMgaBaseAddr = MgaDeviceExtension->KernelModeMappedBaseAddress[iBoard];
status |= MgaSetColorLookup(MgaDeviceExtension,
(PVIDEO_CLUT) RequestPacket->InputBuffer,
RequestPacket->InputBufferLength);
}
// Restore the current board to what it used to be.
iBoard = iCurBoard;
pMgaBaseAddr = pCurBaseAddr;
break; // end SET_COLOR_REGISTERS
/*------------------------------------------------------------------*\
| Required service: IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES
|
| This service will release the address ranges used by the user-mode
| drivers to program the video hardware. In the S3 code, and in
| the DDK reference, it is said that the input buffer should
| contain an array of VIDEO_PUBLIC_ACCESS_RANGES to be released.
| However, I did not get anything in the input buffer when I traced
| through the code. Instead, I have observed that SET_CURRENT_MODE
| had been called, so that there is a current valid mode. We will
| simply free the access ranges not required by the current mode.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - FREE_PUBLIC_ACCESS_RANGES\n"));
//DbgBreakPoint();
// Make sure the input buffer is big enough.
if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
{
// The input buffer is not large enough.
// Assume all will be right.
status = NO_ERROR;
ModeInit = MgaDeviceExtension->SuperModeNumber;
if(ModeInit == 0xFFFFFFFF)
{
// No mode has been selected yet, so we'll free everything.
// For every board...
for (i = 0; i< NbBoard; i++)
{
if (MgaDeviceExtension->UserModeMappedBaseAddress[i])
{
// This board has a non-null user-mode base address.
// Fill out the VIDEO_PUBLIC_ACCESS_RANGES buffer.
publicAccessRanges=RequestPacket->OutputBuffer;
publicAccessRanges->InIoSpace = 0; // Not in I/O space
publicAccessRanges->MappedInIoSpace = 0; // Not in I/O space
publicAccessRanges->VirtualAddress =
MgaDeviceExtension->UserModeMappedBaseAddress[i];
status |= VideoPortUnmapMemory(
MgaDeviceExtension,
publicAccessRanges->VirtualAddress,
0);
// Reset the user-mode base address.
MgaDeviceExtension->UserModeMappedBaseAddress[i] = 0;
}
}
}
else
{
// We know our current mode.
// Point to the appropriate MULTI_MODE structure.
pCurMulti = &MgaDeviceExtension->pSuperModes[ModeInit];
if (pCurMulti == NULL)
{
status = ERROR_DEV_NOT_EXIST;
break;
}
// Number of boards involved in the current super-mode.
CurrentResNbBoards = pCurMulti->MulArrayWidth *
pCurMulti->MulArrayHeight;
// For every board...
for (i = 0; i< NbBoard; i++)
{
// Check whether it's used by the current mode.
n = 0;
while ((n < CurrentResNbBoards) &&
(pCurMulti->MulBoardNb[n] != i))
n++;
if ((n == CurrentResNbBoards) &&
(MgaDeviceExtension->UserModeMappedBaseAddress[i]))
{
// We went through the list, the board is not in use,
// and the board has a non-null user-mode base address.
// Fill out the VIDEO_PUBLIC_ACCESS_RANGES buffer.
publicAccessRanges=RequestPacket->OutputBuffer;
publicAccessRanges->InIoSpace = 0; // Not in I/O space
publicAccessRanges->MappedInIoSpace = 0; // Not in I/O space
publicAccessRanges->VirtualAddress =
MgaDeviceExtension->UserModeMappedBaseAddress[i];
status |= VideoPortUnmapMemory(
MgaDeviceExtension,
publicAccessRanges->VirtualAddress,
0);
// Reset the user-mode base address.
MgaDeviceExtension->UserModeMappedBaseAddress[i] = 0;
}
}
}
}
else
{
// The input buffer is large enough, use it.
status = VideoPortUnmapMemory(MgaDeviceExtension,
((PVIDEO_MEMORY)
(RequestPacket->InputBuffer))->
RequestedVirtualAddress,
0);
}
break; // end FREE_PUBLIC_ACCESS_RANGES
/*------------------------------------------------------------------*\
| Required service: IOCTL_VIDEO_MAP_VIDEO_MEMORY
|
| This service maps the frame buffer and VRAM into the virtual
| address space of the requestor. For now, we'll just return NULL
| addresses and lengths.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - MAP_VIDEO_MEMORY\n"));
//DbgBreakPoint();
if ( (RequestPacket->OutputBufferLength <
(RequestPacket->StatusBlock->Information =
sizeof(VIDEO_MEMORY_INFORMATION))) ||
(RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) )
{
status = ERROR_INSUFFICIENT_BUFFER;
}
else
{
memoryInformation = RequestPacket->OutputBuffer;
memoryInformation->VideoRamBase = 0;
memoryInformation->VideoRamLength = 0;
memoryInformation->FrameBufferBase = 0;
memoryInformation->FrameBufferLength = 0;
status = NO_ERROR;
}
break; // end MAP_VIDEO_MEMORY
/*------------------------------------------------------------------*\
| Required service: IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
|
| This service releases mapping of the frame buffer and VRAM from
| the virtual address space of the requestor. For now, we'll just
| do nothing.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - UNMAP_VIDEO_MEMORY\n"));
//DbgBreakPoint();
if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
{
status = ERROR_INSUFFICIENT_BUFFER;
}
else
{
status = NO_ERROR;
}
break;
/*------------------------------------------------------------------*\
| Required service: IOCTL_VIDEO_QUERY_CURRENT_MODE
|
| This service returns information about the current video mode
| by filling out a VIDEO_MODE_INFORMATION structure.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_QUERY_CURRENT_MODE:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - QUERY_CURRENT_MODE\n"));
//DbgBreakPoint();
if (RequestPacket->OutputBufferLength <
(RequestPacket->StatusBlock->Information =
sizeof(VIDEO_MODE_INFORMATION)) )
{
status = ERROR_INSUFFICIENT_BUFFER;
}
else
{
modeInformation = RequestPacket->OutputBuffer;
// Fill in a VIDEO_MODE_INFORMATION struc for the mode indicated
// by MgaDeviceExtension->SuperModeNumber
i = MgaDeviceExtension->SuperModeNumber;
if (i == 0xFFFFFFFF)
{
status = ERROR_DEV_NOT_EXIST;
break;
}
pCurMulti = &MgaDeviceExtension->pSuperModes[i];
if (pCurMulti == NULL)
{
status = ERROR_DEV_NOT_EXIST;
break;
}
// Fill in common values that apply to all modes.
*modeInformation=CommonVideoModeInformation;
// Fill in mode specific informations.
modeInformation->ModeIndex = pCurMulti->MulModeNumber;
modeInformation->VisScreenWidth = pCurMulti->MulWidth;
modeInformation->VisScreenHeight= pCurMulti->MulHeight;
modeInformation->ScreenStride =
pCurMulti->MulWidth * pCurMulti->MulPixWidth / 8;
modeInformation->BitsPerPlane = pCurMulti->MulPixWidth;
modeInformation->Frequency = pCurMulti->MulRefreshRate;
// If we're in TrueColor mode, then set RGB masks
if ((modeInformation[i].BitsPerPlane == 32) ||
(modeInformation[i].BitsPerPlane == 24))
{
modeInformation[i].RedMask = 0x00FF0000;
modeInformation[i].GreenMask = 0x0000FF00;
modeInformation[i].BlueMask = 0x000000FF;
modeInformation[i].AttributeFlags =
VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS;
}
else if (modeInformation[i].BitsPerPlane == 16)
{
modeInformation[i].AttributeFlags =
VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS;
if (pCurMulti->MulHwModes[0]->DispType & DISPTYPE_M565)
{
modeInformation[i].RedMask = 0x0000F800;
modeInformation[i].GreenMask = 0x000007E0;
modeInformation[i].BlueMask = 0x0000001F;
}
else
{
modeInformation[i].RedMask = 0x00007C00;
modeInformation[i].GreenMask = 0x000003E0;
modeInformation[i].BlueMask = 0x0000001F;
modeInformation[i].AttributeFlags |= VIDEO_MODE_555;
modeInformation[i].BitsPerPlane = 15;
}
}
else
{
modeInformation[i].AttributeFlags =
VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS |
VIDEO_MODE_PALETTE_DRIVEN |
VIDEO_MODE_MANAGED_PALETTE;
}
if (pCurMulti->MulHwModes[0]->ZBuffer)
{
// This is a 3D mode.
modeInformation[i].AttributeFlags |= VIDEO_MODE_3D;
}
// Number of boards involved in the current super-mode.
CurrentResNbBoards = pCurMulti->MulArrayWidth *
pCurMulti->MulArrayHeight;
// For each of them...
for (n = 0; n < CurrentResNbBoards; n++)
{
// Point to the mode information structure.
pMgaDispMode = pCurMulti->MulHwModes[n];
// For now, don't disclose whether we're interlaced.
//if (pMgaDispMode->DispType & TYPE_INTERLACED)
//{
// modeInformation[i].AttributeFlags |=
// VIDEO_MODE_INTERLACED;
//}
// Figure out the width and height of the video memory bitmap
MaxWidth = pMgaDispMode->DispWidth;
MaxHeight = pMgaDispMode->DispHeight;
pMgaOffScreenData = pMgaDispMode->pOffScr;
for (j = 0; j < pMgaDispMode->NumOffScr; j++)
{
if ((usTemp=(pMgaOffScreenData[j].XStart +
pMgaOffScreenData[j].Width)) > MaxWidth)
MaxWidth=usTemp;
if ((usTemp=(pMgaOffScreenData[j].YStart +
pMgaOffScreenData[j].Height)) > MaxHeight)
MaxHeight=usTemp;
}
modeInformation[i].VideoMemoryBitmapWidth = MaxWidth;
modeInformation[i].VideoMemoryBitmapHeight= MaxHeight;
}
status = NO_ERROR;
}
break; // end QUERY_CURRENT_MODE
/*------------------------------------------------------------------*\
| Required service: IOCTL_VIDEO_RESET_DEVICE
|
| This service resets the video hardware to the default mode, to
| which it was initialized at system boot.
|
\*------------------------------------------------------------------*/
case IOCTL_VIDEO_RESET_DEVICE:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - RESET_DEVICE\n"));
//DbgBreakPoint();
if ((ModeInit = MgaDeviceExtension->SuperModeNumber) == 0xFFFFFFFF)
{
// RESET has been done already.
status = NO_ERROR;
break;
}
// Save the current board, because this service will modify it.
iCurBoard = iBoard;
pCurBaseAddr = pMgaBaseAddr;
// Point to the appropriate MULTI_MODE structure.
pCurMulti = &MgaDeviceExtension->pSuperModes[ModeInit];
if (pCurMulti == NULL)
{
status = ERROR_DEV_NOT_EXIST;
break;
}
// Number of boards involved in the current super-mode.
CurrentResNbBoards = pCurMulti->MulArrayWidth *
pCurMulti->MulArrayHeight;
// For each of them...
for (n = 0; n < CurrentResNbBoards; n++)
{
// Point to the mode information structure.
pMgaDispMode = pCurMulti->MulHwModes[n];
// Make the board current.
iBoard = pCurMulti->MulBoardNb[n];
pMgaBaseAddr = MgaDeviceExtension->KernelModeMappedBaseAddress[iBoard];
// Disable the hardware cursor.
mtxCursorEnable(0);
if(Hw[iBoard].VGAEnable)
{
// This board is VGA-enabled, reset it to VGA.
mtxSetVideoMode(mtxPASSTHRU);
}
else
{
// This board is not VGA-enabled.
// Just clear the screen, it will look nicer.
clutBufferOne.NumEntries = 1;
clutBufferOne.LookupTable[0].RgbLong = 0;
for (j = 0; j <= VIDEO_MAX_COLOR_REGISTER; j++)
{
clutBufferOne.FirstEntry = j;
MgaSetColorLookup(MgaDeviceExtension,
&clutBufferOne,
sizeof(VIDEO_CLUT));
}
// Make the cursor disappear.
// MgaSetCursorColour(MgaDeviceExtension, 0, 0);
}
}
// Signal that no mode is currently selected.
MgaDeviceExtension->SuperModeNumber = 0xFFFFFFFF;
if (MgaDeviceExtension->pSuperModes != (PMULTI_MODE) NULL)
{
// Free our allocated memory.
VideoPortReleaseBuffer(pMgaDeviceExtension, MgaDeviceExtension->pSuperModes);
MgaDeviceExtension->pSuperModes = (PMULTI_MODE) NULL;
}
MgaDeviceExtension->NumberOfSuperModes = 0;
// Memory might have been allocated for mgainf.
if (mgainf != DefaultVidset)
{
VideoPortReleaseBuffer(pMgaDeviceExtension, mgainf);
// And use the default set.
mgainf = adjustDefaultVidset();
}
// Restore the current board to what it used to be.
iBoard = iCurBoard;
pMgaBaseAddr = pCurBaseAddr;
status = NO_ERROR;
break; // end IOCTL_VIDEO_RESET_DEVICE
#if 0
case IOCTL_VIDEO_SAVE_HARDWARE_STATE:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - SAVE_HARDWARE_STATE\n"));
status = ERROR_INVALID_FUNCTION;
break;
case IOCTL_VIDEO_RESTORE_HARDWARE_STATE:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - RESTORE_HARDWARE_STATE\n"));
status = ERROR_INVALID_FUNCTION;
break;
case IOCTL_VIDEO_ENABLE_VDM:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - ENABLE_VDM\n"));
status = ERROR_INVALID_FUNCTION;
break;
#endif
/*------------------------------------------------------------------*\
| If we get here, an invalid IoControlCode was specified.
\*------------------------------------------------------------------*/
default:
VideoDebugPrint((1, "MGA.SYS!MgaStartIO - Invalid service\n"));
status = ERROR_INVALID_FUNCTION;
break;
}
RequestPacket->StatusBlock->Status = status;
return TRUE;
} // end MgaStartIO()
/*--------------------------------------------------------------------------*\
| VP_STATUS
| MgaInitModeList(
| PMGA_DEVICE_EXTENSION MgaDeviceExtension)
|
| Routine Description:
|
| This routine builds the list of modes available for the detected boards.
|
| Arguments:
|
| HwDeviceExtension - Pointer to the miniport driver's device extension.
|
| Return Value:
|
| NO_ERROR, ERROR_DEV_NOT_EXIST, or ERROR_NOT_ENOUGH_MEMORY.
|
\*--------------------------------------------------------------------------*/
VP_STATUS
MgaInitModeList(
PMGA_DEVICE_EXTENSION MgaDeviceExtension)
{
HwModeData *pMgaDispMode, *pMgaModeData, *pCurrentMgaModeData;
HwModeData *Mga2dMode[16], *Mga3dMode[16];
MULTI_MODE *pCurMulti;
PULONG pulModeFlags;
ULONG ulNb2DRefreshRates, ulNb3DRefreshRates, ulNbRefreshRates;
ULONG VGABoard, VGABoardBit, ModePixDepth, ulModeListOffset,
NbSuperModes, ResTag, ModeInit;
ULONG CurrentResFlags, CurrentFlag,
CurrentResWidth, CurrentResHeight, CurrentRefreshRate,
CurrentResNbBoards, CurrentResNbBoards3D, CurrentPixWidth;
ULONG i, k, m, n, ir, ja, i2d, i3d;
VP_STATUS status;
USHORT j;
USHORT us2DRefreshRates, us3DRefreshRates, usRefreshRates;
UCHAR ValidBoard[NB_BOARD_MAX];
UCHAR ucTestFlags, ucRefreshBit;
UCHAR ucMask;
BOOLEAN bSupported2dMode, bSupported3dMode;
// Assume we won't have any problem.
status = NO_ERROR;
// Check whether we've already built a mode list. MgaDeviceExtension
// is assumed to have been zeroed out when it was first given us.
if (MgaDeviceExtension->NumberOfSuperModes != 0)
{
if (MgaDeviceExtension->pSuperModes != (PMULTI_MODE) NULL)
{
// Free our allocated memory.
VideoPortReleaseBuffer(pMgaDeviceExtension,
MgaDeviceExtension->pSuperModes);
MgaDeviceExtension->pSuperModes = (PMULTI_MODE) NULL;
}
// Memory might have been allocated for mgainf. It's all right,
// we'll want to use the current mgainf.
}
// Just in case we leave early...
MgaDeviceExtension->NumberOfSuperModes = 0;
// Get information on all the MGA boards currently installed in the
// system.
if ((pMgaBoardData = mtxCheckHwAll()) == NULL)
{
// mtxCheckHwAll should always return success, since MapBoard has
// already been executed.
// BUGBUG - if it never occurs, then this code isn't needed.
// a better answer would be to code an ASSERT() and
// write code that would handle the failure anyways
VideoDebugPrint((1, "MGA.SYS!MGAStartIO failed mtxCheckHwAll\n"));
status = ERROR_DEV_NOT_EXIST;
return(status);
}
else
{
// There may be several MGA boards installed. Look at all of
// them, and map their physical addresses into kernel space.
// While we're at it, find out if any of our boards is VGA enabled.
VGABoard = (ULONG)-1;
VGABoardBit = 0;
// No mode has been selected yet, so make this invalid.
MgaDeviceExtension->SuperModeNumber = 0xFFFFFFFF;
MgaDeviceExtension->pSuperModes = (PMULTI_MODE) NULL;
// We don't care whether the mode is interlaced or not, because
// the only modes that we'll get will be selected according to
// the monitor capabilities through the mga.inf file.
ucMask = (UCHAR)(~DISPTYPE_INTERLACED);
// pMgaBoardData is really the address of Hw[0].
for (i = 0; i < NbBoard; i++)
{
MgaDeviceExtension->NumberOfModes[i] = 0;
MgaDeviceExtension->NumberOfValidModes[i] = 0;
MgaDeviceExtension->ModeFlags2D[i] = 0;
MgaDeviceExtension->ModeFlags3D[i] = 0;
// Make it clean: initialize the ModeList to an invalid mode.
for (j = 0; j < 64; j++)
{
MgaDeviceExtension->ModeList[i][j] = 0xFF;
}
if (mtxSelectHw(&Hw[i]) == mtxFAIL)
{
// mtxSelectHw should always return success, since
// MapBoard has already been executed.
// BUGBUG - if it never occurs, then this code isn't needed.
// a better answer would be to code an ASSERT() and
// write code that would handle the failure anyways
VideoDebugPrint((1, "MGA.SYS!MGAStartIO failed mtxSelectHw for board %d\n", i));
MgaDeviceExtension->KernelModeMappedBaseAddress[i] =
(PVOID)0xffffffff;
continue;
}
// MGA board i has been selected.
//VideoDebugPrint((1, "MGA.SYS!MGAStartIO mapped board %d at 0x%x\n", i, pMgaBaseAddr));
//DbgPrint("MGA.SYS!MGAStartIO mapped board %d at 0x%x\n", i, pMgaBaseAddr);
MgaDeviceExtension->KernelModeMappedBaseAddress[i] =
pMgaBaseAddr;
if (Hw[i].VGAEnable)
{
VGABoard = i;
VGABoardBit = 1 << i;
}
// Set up the test flags. TITAN always supports
// double-buffering, while Atlas and Athena use different
// modes.
if ((Hw[i].ProductRev & 0x000000F0) == 0)
{
// This is TITAN.
ucTestFlags = DISPTYPE_DB;
}
else
{
// This is not TITAN.
ucTestFlags = 0;
}
// Get information on all the hardware modes available for
// the current MGA board.
if ((pMgaModeData = mtxGetHwModes()) == NULL)
{
// This case never occurs.
// BUGBUG - if it never occurs, then this code isn't needed.
// a better answer would be to code an ASSERT() and
// write code that would handle the failure anyways
VideoDebugPrint((1, "MGA.SYS!MGAStartIO failed mtxGetHwModes for board %d\n", i));
continue;
}
// Store it in the DeviceExtension structure.
MgaDeviceExtension->pMgaHwModes[i] = pMgaModeData;
// Modes we may want to support:
//
// 2D modes -------------------------------------------------
// 8bpp, LUT
// DispType = 14, ZBuffer = 0, PixWidth = 8 (Titan)
// DispType = 4, ZBuffer = 0, PixWidth = 8 (others)
// 16bpp, 565
// DispType = 8, ZBuffer = 0, PixWidth = 16
// 24bpp
// DispType = 0, ZBuffer = 0, PixWidth = 24 (Storm only)
// 32bpp
// DispType = 10, ZBuffer = 0, PixWidth = 32 (Titan)
// DispType = 0, ZBuffer = 0, PixWidth = 32 (others)
//
// 3D modes -------------------------------------------------
// 8bpp, no LUT
// DispType = 10, ZBuffer = 1, PixWidth = 8
// 16bpp, 555
// DispType = 10, ZBuffer = 1, PixWidth = 16 (Mga or Storm)
// OR
// 16bpp, 565
// DispType = 18, ZBuffer = 1, PixWidth = 16 (Storm only)
// 24bpp
// DispType = 10, ZBuffer = 1, PixWidth = 24 (Storm only)
// 32bpp
// DispType = 10, ZBuffer = 1, PixWidth = 32
// Calculate the number of available modes for this board.
// *IMPORTANT* We assume the last entry in the HwMode
// array has DispWidth equal to -1.
// NEW!
// We do not want to support 16bpp modes here. We'll
// support 5-5-5 modes, but the trick is that some of
// them will be 3D modes, and the other ones will be 2D.
// We have to examine the list for these.
i2d = 0;
i3d = 0;
for (pCurrentMgaModeData = pMgaModeData;
pCurrentMgaModeData->DispWidth != (word)-1;
pCurrentMgaModeData++)
{
if (pCurrentMgaModeData->PixWidth == 16)
{
if (pCurrentMgaModeData->ZBuffer)
{
// 16bpp, Z buffer.
if ((pCurrentMgaModeData->DispType & ucMask) ==
DISPTYPE_DB)
{
Mga3dMode[i3d] = pCurrentMgaModeData;
i3d++;
}
}
else
{
// 16bpp, no Z buffer.
if ((pCurrentMgaModeData->DispType & ucMask) ==
ucTestFlags)
{
Mga2dMode[i2d] = pCurrentMgaModeData;
i2d++;
}
}
}
}
for (m = 0; m < i2d; m++)
{
// Examine one of the 2D modes.
bSupported2dMode = TRUE;
pCurrentMgaModeData = Mga2dMode[m];
CurrentResWidth = pCurrentMgaModeData->DispWidth;
CurrentResHeight = pCurrentMgaModeData->DispHeight;
// Look for a similar 3D mode.
for (k = 0; k < i3d; k++)
{
pCurrentMgaModeData = Mga3dMode[k];
if ((pCurrentMgaModeData->DispWidth == CurrentResWidth ) &&
(pCurrentMgaModeData->DispHeight== CurrentResHeight))
{
// The current 2D mode is simlar to a 3D mode,
// we want to reject this 2D mode.
bSupported2dMode = FALSE;
break;
}
}
if (bSupported2dMode == TRUE)
{
// We want to keep this one, so remove it from the
// checklist.
Mga2dMode[m] = 0;
}
}
for (pCurrentMgaModeData = pMgaModeData;
pCurrentMgaModeData->DispWidth != (word)-1;
pCurrentMgaModeData++)
{
// Update the total number of modes supported.
MgaDeviceExtension->NumberOfModes[i]++;
for (m = 0; m < i2d; m++)
{
if (pCurrentMgaModeData == Mga2dMode[m])
{
// This one is on our black list, reject it.
goto IML_END_OF_LOOP;
}
}
// Assume this mode won't be supported.
bSupported2dMode = FALSE;
bSupported3dMode = FALSE;
// Update the number of valid modes supported.
ModePixDepth = pCurrentMgaModeData->PixWidth;
switch (ModePixDepth)
{
case 8: if (pCurrentMgaModeData->ZBuffer)
{
// 8bpp, Z buffer.
// We don't support any of these.
}
else
{
// 8bpp, no Z buffer.
if ((pCurrentMgaModeData->DispType & ucMask) ==
(ucTestFlags | DISPTYPE_LUT))
{
bSupported2dMode = TRUE;
}
}
break;
case 16:if (pCurrentMgaModeData->ZBuffer)
{
// 16bpp, Z buffer.
if ((pCurrentMgaModeData->DispType & ucMask) ==
DISPTYPE_DB)
{
bSupported3dMode = TRUE;
}
}
else
{
// 16bpp, no Z buffer.
//if ((pCurrentMgaModeData->DispType & ucMask) ==
// DISPTYPE_M565)
if ((pCurrentMgaModeData->DispType & ucMask) ==
ucTestFlags)
{
bSupported2dMode = TRUE;
}
}
break;
case 24:if (pCurrentMgaModeData->ZBuffer)
{
// 24bpp, Z buffer.
// We don't support any of these.
}
else
{
// 24bpp, no Z buffer.
// We don't support any of these.
}
break;
case 32:if (pCurrentMgaModeData->ZBuffer)
{
// 32bpp, Z buffer.
// We don't support any of these.
}
else
{
// 32bpp, no Z buffer.
if ((pCurrentMgaModeData->DispType & ucMask) ==
ucTestFlags)
{
bSupported2dMode = TRUE;
}
}
break;
default:
break;
}
if ((bSupported2dMode == FALSE) &&
(bSupported3dMode == FALSE))
{
// We don't support this mode, get out.
continue;
}
if (bSupported2dMode)
ulModeListOffset = 0;
else
ulModeListOffset = 32;
// We can do something with the current mode.
switch(pCurrentMgaModeData->DispWidth)
{
case 640: ResTag = BIT_640;
break;
case 768: ResTag = BIT_768;
break;
case 800: ResTag = BIT_800;
break;
case 1024: ResTag = BIT_1024;
break;
case 1152: ResTag = BIT_1152;
break;
case 1280: ResTag = BIT_1280;
break;
case 1600: ResTag = BIT_1600;
break;
default: ResTag = BIT_INVALID;
}
// Record the HW mode to be used for this mode.
// ModePixDepth is either 8, 16, 24, or 32.
if (ResTag != BIT_INVALID)
{
// We know this hardware mode is correct. Now find
// out how many refresh rates this mode supports.
usRefreshRates = mtxGetRefreshRates(pCurrentMgaModeData);
for (j = 0; j < 16; j++)
{
if (usRefreshRates & (1 << j))
{
MgaDeviceExtension->NumberOfValidModes[i]++;
}
}
MgaDeviceExtension->
ModeList[i][ResTag+ModePixDepth+ulModeListOffset-8]
= (UCHAR)(MgaDeviceExtension->NumberOfModes[i] - 1);
MgaDeviceExtension->
ModeFreqs[i][ResTag+ModePixDepth+ulModeListOffset-8]
= usRefreshRates;
}
// Make up the resolution tag from the bit field.
ResTag = 1 << ResTag;
// Shift the resolution tag into its pixel-depth field.
ResTag <<= (ModePixDepth - 8);
// Record the resolution/pixel-depth flag.
if (bSupported2dMode)
MgaDeviceExtension->ModeFlags2D[i] |= ResTag;
else
MgaDeviceExtension->ModeFlags3D[i] |= ResTag;
IML_END_OF_LOOP:
;
}
}
// We have recorded information for each of our boards in the
// MgaDeviceExtension structure. For each board, we have set:
//
// NumberOfModes[n] The number of available modes
// NumberOfValidModes[n] The number of modes supported by the
// user-mode drivers
// ModeFlags2D[n] The bit flags describing the supported
// 2D modes
// ModeFlags3D[n] The bit flags describing the supported
// 3D modes
// KernelModeMappedBaseAddress[n]
// The board's registers window mapping,
// returned when VideoPortGetDeviceBase
// is called with Hw[n].MapAddress
// pMgaHwModes[n] The pointer to an array of HwModeData
// structures describing available modes
// ModeList[n][64] A list of hardware modes corresponding
// to the ModeFlags bits
//
//DbgBreakPoint();
#if DBG
// Display it so that we can see if it makes sense...
VideoDebugPrint((1, "# NbModes NbValid ModeFlg2D ModeFlg3D BaseAddr pHwModes ModeList\n"));
for (i = 0; i < NbBoard; i++)
{
VideoDebugPrint((1, "%d % 7d % 7d 0x%08x 0x%08x 0x%08x\n",i,
MgaDeviceExtension->NumberOfModes[i],
MgaDeviceExtension->NumberOfValidModes[i],
MgaDeviceExtension->ModeFlags2D[i],
MgaDeviceExtension->ModeFlags3D[i],
MgaDeviceExtension->KernelModeMappedBaseAddress[i],
MgaDeviceExtension->pMgaHwModes[i]));
for (j = 0; j < 64; j+=8)
{
VideoDebugPrint((1, " %02x %02x %02x %02x %02x %02x %02x %02x\n",
MgaDeviceExtension->ModeList[i][j],
MgaDeviceExtension->ModeList[i][j+1],
MgaDeviceExtension->ModeList[i][j+2],
MgaDeviceExtension->ModeList[i][j+3],
MgaDeviceExtension->ModeList[i][j+4],
MgaDeviceExtension->ModeList[i][j+5],
MgaDeviceExtension->ModeList[i][j+6],
MgaDeviceExtension->ModeList[i][j+7]));
}
}
#endif // #if DBG
// Now for the fun part: find out the resolutions and
// combinations of resolutions that we can support.
// First, run through the ModeFlags to determine how many modes
// we can make up from the single-board modes.
// For each bit in our ModeFlags...
NbSuperModes = 0;
for (i = 0; i < 32; i++)
{
// Find out which boards, if any, support this mode.
CurrentResNbBoards = 0;
CurrentResNbBoards3D = 0;
for (n = 0; n < (ULONG)NbBoard; n++)
{
ulNb2DRefreshRates = 0;
ulNb3DRefreshRates = 0;
us2DRefreshRates = MgaDeviceExtension->ModeFreqs[n][i];
us3DRefreshRates = MgaDeviceExtension->ModeFreqs[n][i+32];
for (j = 0; j < 16; j++)
{
if (us2DRefreshRates & (1 << j))
{
ulNb2DRefreshRates++;
}
if (us3DRefreshRates & (1 << j))
{
ulNb3DRefreshRates++;
}
}
if ((MgaDeviceExtension->ModeFlags2D[n] >> i) & 1)
{
// The mode is supported by the current board.
CurrentResNbBoards++;
NbSuperModes += (ulNb2DRefreshRates *
MultiModes[CurrentResNbBoards]);
}
if ((MgaDeviceExtension->ModeFlags3D[n] >> i) & 1)
{
// The mode is supported by the current board.
CurrentResNbBoards3D++;
NbSuperModes += (ulNb3DRefreshRates *
MultiModes[CurrentResNbBoards3D]);
}
}
}
if (NbSuperModes == 0)
{
// We did not find any mode!
status = ERROR_DEV_NOT_EXIST;
return(status);
}
// Now, allocate some memory to hold the new structures.
MgaDeviceExtension->pSuperModes =
pCurMulti = (MULTI_MODE*)
AllocateSystemMemory(NbSuperModes*sizeof(MULTI_MODE));
if (pCurMulti == NULL)
{
// The memory allocation failed. We won't be able to use
// our supermode list, so we'll fall back on the single-
// board code.
NbSuperModes = 0;
status = ERROR_NOT_ENOUGH_MEMORY;
return(status);
}
// And we're ready to go!
ModeInit = 0x00000000;
pulModeFlags = &MgaDeviceExtension->ModeFlags2D[0];
ulModeListOffset = 0;
MTX_INIT_MODE_LIST_LOOP:
// For each bit in our ModeFlags...
for (i = 0; i < 32; i++)
{
// Find out which boards, if any, support this
// resolution/pixel-depth.
CurrentResNbBoards = 0;
CurrentResFlags = 0;
k = 0;
for (n = 0; n < (ULONG)NbBoard; n++)
{
CurrentFlag = (pulModeFlags[n] >> i) & 1;
CurrentResNbBoards += CurrentFlag;
if (CurrentFlag)
{
// This one is valid.
usRefreshRates = MgaDeviceExtension->
ModeFreqs[n][i+ulModeListOffset];
CurrentResFlags |= (1 << n);
ValidBoard[k++] = (UCHAR)n;
}
}
// Nothing to do if no boards support this combination.
if (CurrentResNbBoards == 0)
continue;
// At least one board supports this resolution/pixel-depth.
CurrentResWidth = (ULONG)SingleWidths[i%8];
CurrentResHeight = (ULONG)SingleHeights[i%8];
CurrentPixWidth = (i/8 + 1)*8;
ulNbRefreshRates = 0;
for (j = 0; j < 16; j++)
{
if (usRefreshRates & (1 << j))
{
ulNbRefreshRates++;
}
}
ucRefreshBit = 0;
for (ir = 0; ir < ulNbRefreshRates; ir++)
{
while ((usRefreshRates & 1) == 0)
{
usRefreshRates >>= 1;
ucRefreshBit++;
}
CurrentRefreshRate = (ULONG)ConvBitToFreq(ucRefreshBit);
usRefreshRates >>= 1;
ucRefreshBit++;
// Set the 1x1 display.
pCurMulti->MulArrayWidth = 1;
pCurMulti->MulArrayHeight = 1;
pCurMulti->MulWidth = CurrentResWidth;
pCurMulti->MulHeight = CurrentResHeight;
pCurMulti->MulPixWidth = CurrentPixWidth;
pCurMulti->MulRefreshRate = CurrentRefreshRate;
// For 1x1, select the VGA-enabled board, if possible.
if (CurrentResFlags & VGABoardBit)
{
// The VGA-enabled board supports this resolution.
pCurMulti->MulBoardNb[0] = (UCHAR)VGABoard;
}
else
{
// Otherwise, pick board 0.
pCurMulti->MulBoardNb[0] = ValidBoard[0];
}
n = pCurMulti->MulBoardNb[0];
pCurMulti->MulBoardMode[0] =
MgaDeviceExtension->ModeList[n]
[i+ulModeListOffset];
// Record a pointer to the HwModeData structure.
pMgaDispMode = MgaDeviceExtension->pMgaHwModes[n];
pCurMulti->MulHwModes[0] =
&pMgaDispMode[pCurMulti->MulBoardMode[0]];
pCurMulti->MulModeNumber = ModeInit++;
pCurMulti++;
if (CurrentResNbBoards == 1)
continue;
// At least two boards support this resolution/pixel-depth.
// For each number of boards up to the maximum...
for (k = 2; k <= CurrentResNbBoards; k++)
{
// For each integer up to the maximum...
for (m = 1; m <= CurrentResNbBoards; m++)
{
if ((k % m) == 0)
{
// We can get a (k/m, m) desktop.
pCurMulti->MulArrayHeight = (USHORT)m;
pCurMulti->MulHeight = m*CurrentResHeight;
pCurMulti->MulArrayWidth = (USHORT)(k/m);
pCurMulti->MulWidth = pCurMulti->MulArrayWidth *
CurrentResWidth;
pCurMulti->MulPixWidth = CurrentPixWidth;
pCurMulti->MulRefreshRate = CurrentRefreshRate;
// Select the boards we'll be using.
// Select the VGA-enabled board as the first
// board, if possible. Except for that, we
// won't try to place the boards in any
// consistent way for now.
if (CurrentResFlags & VGABoardBit)
{
// The VGA-enabled board supports this mode.
pCurMulti->MulBoardNb[0] = (UCHAR)VGABoard;
ja = 0;
for (j = 1; j < k; j++)
{
if (ValidBoard[ja] == VGABoard)
ja++;
pCurMulti->MulBoardNb[j] =
ValidBoard[ja];
ja++;
}
}
else
{
// The VGA-enabled board won't be involved.
for (j = 0; j < k; j++)
{
pCurMulti->MulBoardNb[j] =
ValidBoard[j];
}
}
// For each board...
for (j = 0; j < k; j++)
{
// Record the hardware mode the board
// would use.
n = pCurMulti->MulBoardNb[j];
pCurMulti->MulBoardMode[j] =
MgaDeviceExtension->ModeList[n]
[i+ulModeListOffset];
// Record a ptr to the HwModeData structure.
pMgaDispMode =
MgaDeviceExtension->pMgaHwModes[n];
pCurMulti->MulHwModes[j] =
&pMgaDispMode[pCurMulti->MulBoardMode[j]];
}
pCurMulti->MulModeNumber = ModeInit++;
pCurMulti++;
} // If it's a valid desktop...
} // For each integer up to the maximum...
} // For each number of boards up to the maximum...
} // For the number of Refresh...
} // For each bit in our ModeFlags...
if (pulModeFlags == &MgaDeviceExtension->ModeFlags2D[0])
{
// We just looked at the 2D modes, now look at the 3D modes.
pulModeFlags = &MgaDeviceExtension->ModeFlags3D[0];
ulModeListOffset = 32;
goto MTX_INIT_MODE_LIST_LOOP;
}
MgaDeviceExtension->NumberOfSuperModes = NbSuperModes;
// At this point, we have a table of 'super-modes' (which includes
// all the regular modes also). All the modes in this table are
// supported, and each of them is unique. MgaDeviceExtension->
// pSuperModes points to the start of the mode list. Each entry
// in the list holds:
//
// MulModeNumber A unique mode Id
// MulWidth The total width for this mode
// MulHeight The total height for this mode
// MulPixWidth The pixel depth for this mode
// MulArrayWidth The number of boards arrayed along X
// MulArrayHeight The number of boards arrayed along Y
// MulBoardNb[n] The board numbers of the required boards
// MulBoardMode[n] The mode required from each board
// *MulHwModes[n] The pointers to the required HwModeData
//
// Moreover, MgaDeviceExtension->NumberOfSuperModes holds the
// number of entries in the list.
//DbgBreakPoint();
#if DBG
// Now display our results...
VideoDebugPrint((1, "ModeNumber Width Height PW X Y n mo pHwMode\n"));
pCurMulti = MgaDeviceExtension->pSuperModes;
for (i = 0; i < NbSuperModes; i++)
{
VideoDebugPrint((1, "0x%08x % 6d % 6d % 3d % 3d % 3d\n",
pCurMulti->MulModeNumber,
pCurMulti->MulWidth,
pCurMulti->MulHeight,
pCurMulti->MulPixWidth,
pCurMulti->MulArrayWidth,
pCurMulti->MulArrayHeight));
j = pCurMulti->MulArrayWidth * pCurMulti->MulArrayHeight;
for (n = 0; n < j; n++)
{
VideoDebugPrint((1, " %d %02x 0x%08x\n",
pCurMulti->MulBoardNb[n],
pCurMulti->MulBoardMode[n],
pCurMulti->MulHwModes[n]));
}
pCurMulti++;
}
#endif // #if DBG
}
return(status);
}
/*--------------------------------------------------------------------------*\
| VP_STATUS
| MgaSetColorLookup(
| PMGA_DEVICE_EXTENSION MgaDeviceExtension,
| PVIDEO_CLUT ClutBuffer,
| ULONG ClutBufferSize
| )
|
| Routine Description:
|
| This routine sets a specified portion of the color lookup table settings.
|
| Arguments:
|
| HwDeviceExtension - Pointer to the miniport driver's device extension.
|
| ClutBufferSize - Length of the input buffer supplied by the user.
|
| ClutBuffer - Pointer to the structure containing the color lookup table.
|
| Return Value:
|
| None.
|
\*--------------------------------------------------------------------------*/
VP_STATUS
MgaSetColorLookup(
PMGA_DEVICE_EXTENSION MgaDeviceExtension,
PVIDEO_CLUT ClutBuffer,
ULONG ClutBufferSize
)
{
ULONG ulVal;
PUCHAR pucPaletteDataReg, pucPaletteWriteReg;
LONG i, m, n, lNumEntries;
// DbgBreakPoint();
// Check if the size of the data in the input buffer is large enough.
if ( (ClutBufferSize < sizeof(VIDEO_CLUT) - sizeof(ULONG)) ||
(ClutBufferSize < sizeof(VIDEO_CLUT) +
(sizeof(ULONG) * (ClutBuffer->NumEntries - 1)) ) )
{
return ERROR_INSUFFICIENT_BUFFER;
}
// Check to see if the parameters are valid.
if ( (ClutBuffer->NumEntries == 0) ||
(ClutBuffer->FirstEntry > VIDEO_MAX_COLOR_REGISTER) ||
(ClutBuffer->FirstEntry + ClutBuffer->NumEntries >
VIDEO_MAX_COLOR_REGISTER + 1) )
{
return ERROR_INVALID_PARAMETER;
}
pucPaletteDataReg =
(PUCHAR)MgaDeviceExtension->KernelModeMappedBaseAddress[iBoard] +
PALETTE_DATA;
pucPaletteWriteReg=
(PUCHAR)MgaDeviceExtension->KernelModeMappedBaseAddress[iBoard] +
PALETTE_RAM_WRITE;
// Set CLUT registers directly on the hardware.
VideoPortWriteRegisterUchar(pucPaletteWriteReg,
(UCHAR)ClutBuffer->FirstEntry);
n = 0;
m = (LONG)ClutBuffer->NumEntries;
if (pMgaBoardData[iBoard].DacType == DacTypeTVP3026)
{
// TVP3026 cursor is very touchy.
#define TVP3026_PAL_BATCH_SIZE 64
m = TVP3026_PAL_BATCH_SIZE;
lNumEntries = (LONG)ClutBuffer->NumEntries;
while ((lNumEntries -= 64) > 0)
{
// Wait for VSYNC.
do
{
ulVal = VideoPortReadRegisterUlong((PULONG)
((PUCHAR)pMgaBaseAddr + TITAN_OFFSET + TITAN_STATUS));
} while (!(ulVal & TITAN_VSYNCSTS_M));
for (i = n; i < m; i++)
{
VideoPortWriteRegisterUchar(pucPaletteDataReg,
(UCHAR) ClutBuffer->LookupTable[i].RgbArray.Red);
VideoPortWriteRegisterUchar(pucPaletteDataReg,
(UCHAR) ClutBuffer->LookupTable[i].RgbArray.Green);
VideoPortWriteRegisterUchar(pucPaletteDataReg,
(UCHAR) ClutBuffer->LookupTable[i].RgbArray.Blue);
}
n += TVP3026_PAL_BATCH_SIZE;
m += TVP3026_PAL_BATCH_SIZE;
}
m += lNumEntries;
// Wait for VSYNC.
do
{
ulVal = VideoPortReadRegisterUlong((PULONG)
((PUCHAR)pMgaBaseAddr + TITAN_OFFSET + TITAN_STATUS));
} while (!(ulVal & TITAN_VSYNCSTS_M));
}
for (i = n; i < m; i++)
{
VideoPortWriteRegisterUchar(pucPaletteDataReg,
((UCHAR) ClutBuffer->LookupTable[i].RgbArray.Red));
VideoPortWriteRegisterUchar(pucPaletteDataReg,
((UCHAR) ClutBuffer->LookupTable[i].RgbArray.Green));
VideoPortWriteRegisterUchar(pucPaletteDataReg,
((UCHAR) ClutBuffer->LookupTable[i].RgbArray.Blue));
}
return NO_ERROR;
} // end MgaSetColorLookup()
VOID MgaSetCursorColour(
PMGA_DEVICE_EXTENSION MgaDeviceExtension,
ULONG ulFgColour,
ULONG ulBgColour)
{
PUCHAR pucCursorDataReg, pucCursorWriteReg;
PUCHAR pucCmdRegA, pucPixRdMaskReg;
UCHAR ucOldCmdRegA, ucOldRdMask;
VideoDebugPrint((1, "MGA.SYS!MgaSetCursorColour\n"));
// DbgBreakPoint();
switch(pMgaBoardData[iBoard].DacType)
{
case DacTypeBT485:
case DacTypePX2085:
// Set cursor colour for Bt485.
pucCursorDataReg = (PUCHAR)MgaDeviceExtension->
KernelModeMappedBaseAddress[iBoard] +
RAMDAC_OFFSET + BT485_COL_OVL;
pucCursorWriteReg= (PUCHAR)MgaDeviceExtension->
KernelModeMappedBaseAddress[iBoard] +
RAMDAC_OFFSET + BT485_WADR_OVL;
VideoPortWriteRegisterUchar(pucCursorWriteReg, 1);
// Set Background Colour
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulBgColour & 0xFF));
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulBgColour>>8 & 0xFF));
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulBgColour>>16 & 0xFF));
// Set Foreground Colour
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulFgColour & 0xFF));
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulFgColour>>8 & 0xFF));
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulFgColour>>16 & 0xFF));
break;
case DacTypeBT482:
// Set cursor colour for Bt482.
pucCursorDataReg = (PUCHAR)MgaDeviceExtension->
KernelModeMappedBaseAddress[iBoard] +
RAMDAC_OFFSET + BT482_COL_OVL;
pucCmdRegA = (PUCHAR)MgaDeviceExtension->
KernelModeMappedBaseAddress[iBoard] +
RAMDAC_OFFSET + BT482_CMD_REGA;
pucPixRdMaskReg = (PUCHAR)MgaDeviceExtension->
KernelModeMappedBaseAddress[iBoard] +
RAMDAC_OFFSET + BT482_PIX_RD_MSK;
ucOldCmdRegA = VideoPortReadRegisterUchar(pucCmdRegA);
VideoPortWriteRegisterUchar(pucCmdRegA,
(UCHAR) (ucOldCmdRegA | BT482_EXT_REG_EN));
VideoPortWriteRegisterUchar((PUCHAR)MgaDeviceExtension->
KernelModeMappedBaseAddress[iBoard] +
RAMDAC_OFFSET + BT482_WADR_PAL,
BT482_CUR_REG);
ucOldRdMask = VideoPortReadRegisterUchar(pucPixRdMaskReg);
VideoPortWriteRegisterUchar(pucPixRdMaskReg, 0);
VideoPortWriteRegisterUchar((PUCHAR)MgaDeviceExtension->
KernelModeMappedBaseAddress[iBoard] +
RAMDAC_OFFSET + BT482_WADR_OVL,
0x11);
// Set Colour 1
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulBgColour & 0xFF));
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulBgColour>>8 & 0xFF));
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulBgColour>>16 & 0xFF));
// Set Colour 2
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulFgColour & 0xFF));
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulFgColour>>8 & 0xFF));
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulFgColour>>16 & 0xFF));
// Restore old read mask and command register values
VideoPortWriteRegisterUchar((PUCHAR)MgaDeviceExtension->
KernelModeMappedBaseAddress[iBoard] +
RAMDAC_OFFSET + BT482_WADR_PAL,
BT482_CUR_REG);
VideoPortWriteRegisterUchar(pucPixRdMaskReg, ucOldRdMask);
VideoPortWriteRegisterUchar(pucCmdRegA, ucOldCmdRegA);
break;
case DacTypeVIEWPOINT:
// Set cursor colour for ViewPoint
pucCursorDataReg = (PUCHAR)MgaDeviceExtension->
KernelModeMappedBaseAddress[iBoard] +
RAMDAC_OFFSET + VPOINT_DATA;
pucCursorWriteReg= (PUCHAR)MgaDeviceExtension->
KernelModeMappedBaseAddress[iBoard] +
RAMDAC_OFFSET + VPOINT_INDEX;
// Set Background Colour
VideoPortWriteRegisterUchar(pucCursorWriteReg,VPOINT_CUR_COL0_RED);
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulBgColour & 0xFF));
VideoPortWriteRegisterUchar(pucCursorWriteReg,VPOINT_CUR_COL0_GREEN);
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulBgColour>>8 & 0xFF));
VideoPortWriteRegisterUchar(pucCursorWriteReg,VPOINT_CUR_COL0_BLUE);
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulBgColour>>16 & 0xFF));
// Set Foreground Colour
VideoPortWriteRegisterUchar(pucCursorWriteReg,VPOINT_CUR_COL1_RED);
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulFgColour & 0xFF));
VideoPortWriteRegisterUchar(pucCursorWriteReg,VPOINT_CUR_COL1_GREEN);
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulFgColour>>8 & 0xFF));
VideoPortWriteRegisterUchar(pucCursorWriteReg,VPOINT_CUR_COL1_BLUE);
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulFgColour>>16 & 0xFF));
break;
case DacTypeTVP3026:
// Set cursor colour for TVP3026
pucCursorDataReg = (PUCHAR)MgaDeviceExtension->
KernelModeMappedBaseAddress[iBoard] +
RAMDAC_OFFSET + TVP3026_CUR_COL_DATA;
pucCursorWriteReg= (PUCHAR)MgaDeviceExtension->
KernelModeMappedBaseAddress[iBoard] +
RAMDAC_OFFSET + TVP3026_CUR_COL_ADDR;
// Set Background Colour
VideoPortWriteRegisterUchar(pucCursorWriteReg,1);
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulBgColour & 0xFF));
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulBgColour>>8 & 0xFF));
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulBgColour>>16 & 0xFF));
// Set Foreground Colour
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulFgColour & 0xFF));
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulFgColour>>8 & 0xFF));
VideoPortWriteRegisterUchar(pucCursorDataReg,
(UCHAR)(ulFgColour>>16 & 0xFF));
break;
default:
break;
}
}
#if (_WIN32_WINNT >= 500)
//
// Routine to set a desired DPMS power management state.
//
VP_STATUS
MgaSetPower50(
PMGA_DEVICE_EXTENSION phwDeviceExtension,
ULONG HwDeviceId,
PVIDEO_POWER_MANAGEMENT pVideoPowerMgmt
)
{
if ((pVideoPowerMgmt->PowerState == VideoPowerOn) ||
(pVideoPowerMgmt->PowerState == VideoPowerHibernate)) {
return NO_ERROR;
} else {
return ERROR_INVALID_FUNCTION;
}
}
//
// Routine to retrieve possible DPMS power management states.
//
VP_STATUS
MgaGetPower50(
PMGA_DEVICE_EXTENSION phwDeviceExtension,
ULONG HwDeviceId,
PVIDEO_POWER_MANAGEMENT pVideoPowerMgmt
)
{
if ((pVideoPowerMgmt->PowerState == VideoPowerOn) ||
(pVideoPowerMgmt->PowerState == VideoPowerHibernate)) {
return NO_ERROR;
} else {
return ERROR_INVALID_FUNCTION;
}
}
//
// Routine to retrieve the Enhanced Display ID structure via DDC
//
ULONG
MgaGetVideoChildDescriptor(
PVOID HwDeviceExtension,
PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
PVIDEO_CHILD_TYPE pChildType,
PVOID pvChildDescriptor,
PULONG pHwId,
PULONG pUnused
)
{
PMGA_DEVICE_EXTENSION pHwDeviceExtension = HwDeviceExtension;
ULONG Status;
ASSERT(pHwDeviceExtension != NULL && pMoreChildren != NULL);
VideoDebugPrint((2, "mga.SYS mgaGetVideoChildDescriptor: *** Entry point ***\n"));
//
// Determine if the graphics adapter in the system supports
// DDC2 (our miniport only supports DDC2, not DDC1). This has
// the side effect (assuming both monitor and card support
// DDC2) of switching the monitor from DDC1 mode (repeated
// "blind" broadcast of EDID clocked by the vertical sync
// signal) to DDC2 mode (query/response not using any of the
// normal video lines - can transfer information rapidly
// without first disrupting the screen by switching into
// a pseudo-mode with a high vertical sync frequency).
//
// Since we must support hot-plugging of monitors, and our
// routine to obtain the EDID structure via DDC2 assumes that
// the monitor is in DDC2 mode, we must make this test each
// time this entry point is called.
//
switch (ChildEnumInfo->ChildIndex) {
case 0:
//
// Case 0 is used to enumerate devices found by the ACPI firmware.
//
// Since we do not support ACPI devices yet, we must return failure.
//
Status = ERROR_NO_MORE_DEVICES;
break;
case 1:
//
// We do not support monitor enumeration
//
Status = ERROR_NO_MORE_DEVICES;
break;
case DISPLAY_ADAPTER_HW_ID:
{
PUSHORT pPnpDeviceDescription = NULL;
ULONG stringSize = sizeof(L"*PNPXXXX");
//
// Special ID to handle return legacy PnP IDs for root enumerated
// devices.
//
*pChildType = VideoChip;
*pHwId = DISPLAY_ADAPTER_HW_ID;
//
// Figure out which card type and set pPnpDeviceDescription at
// associated string.
//
if (pHwDeviceExtension->BoardId == TYPE_QVISION_PCI)
pPnpDeviceDescription = L"*PNP0919";
else
pPnpDeviceDescription = L"*PNP0918";
//
// Now just copy the string into memory provided.
//
if (pPnpDeviceDescription)
memcpy(pvChildDescriptor, pPnpDeviceDescription, stringSize);
Status = ERROR_MORE_DATA;
break;
}
default:
Status = ERROR_NO_MORE_DEVICES;
break;
}
return Status;
}
#endif // _WIN32_WINNT >= 500