3841 lines
144 KiB
C
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
|