From 5ba4b4bbebd8a4392982d5268e8acaa5f905bef5 Mon Sep 17 00:00:00 2001 From: evb Date: Fri, 5 Mar 2010 17:22:18 +0000 Subject: [PATCH] - Add new unified VGA/VBE miniport driver. Based on NT4 DDK Cirrus Miniport Driver Sample with my modifications (marked with // eVb) to change Cirrus parts to VGA parts if needed. Also add VBE suppor which is not in Cirrus driver, but exists in Windows VGA miniport. - Work-in-progress, can boot to GUI with VMWare, but banked modes not yet supported, no VDM, no Mode-X, etc... - Thanks to sir_richard for help with headers, comments and other English stuff. - Driver is only built, not yet used. - NOTE: Some parts of BootVid seem to use functions copied from this sample (VgaInterpretCmdStream) but under "GPL", and also buggy (Chain4 Mode test will not work on most cards and VgaIsPresent == FALSE). Someone should fix. svn path=/trunk/; revision=45873 --- .../drivers/video/miniport/directory.rbuild | 7 +- .../drivers/video/miniport/vga_new/cmdcnst.h | 92 ++ .../drivers/video/miniport/vga_new/modeset.c | 747 +++++++++ reactos/drivers/video/miniport/vga_new/vbe.c | 196 +++ reactos/drivers/video/miniport/vga_new/vbe.h | 217 +++ .../drivers/video/miniport/vga_new/vbemodes.c | 449 ++++++ reactos/drivers/video/miniport/vga_new/vga.c | 1401 +++++++++++++++++ reactos/drivers/video/miniport/vga_new/vga.h | 446 ++++++ .../drivers/video/miniport/vga_new/vga.rbuild | 18 + reactos/drivers/video/miniport/vga_new/vga.rc | 5 + .../drivers/video/miniport/vga_new/vgadata.c | 490 ++++++ 11 files changed, 4063 insertions(+), 5 deletions(-) create mode 100644 reactos/drivers/video/miniport/vga_new/cmdcnst.h create mode 100644 reactos/drivers/video/miniport/vga_new/modeset.c create mode 100644 reactos/drivers/video/miniport/vga_new/vbe.c create mode 100644 reactos/drivers/video/miniport/vga_new/vbe.h create mode 100644 reactos/drivers/video/miniport/vga_new/vbemodes.c create mode 100644 reactos/drivers/video/miniport/vga_new/vga.c create mode 100644 reactos/drivers/video/miniport/vga_new/vga.h create mode 100644 reactos/drivers/video/miniport/vga_new/vga.rbuild create mode 100644 reactos/drivers/video/miniport/vga_new/vga.rc create mode 100644 reactos/drivers/video/miniport/vga_new/vgadata.c diff --git a/reactos/drivers/video/miniport/directory.rbuild b/reactos/drivers/video/miniport/directory.rbuild index 2575e1a7677..b61f80c1fda 100644 --- a/reactos/drivers/video/miniport/directory.rbuild +++ b/reactos/drivers/video/miniport/directory.rbuild @@ -1,11 +1,8 @@ - - - - - + + diff --git a/reactos/drivers/video/miniport/vga_new/cmdcnst.h b/reactos/drivers/video/miniport/vga_new/cmdcnst.h new file mode 100644 index 00000000000..c818b49d494 --- /dev/null +++ b/reactos/drivers/video/miniport/vga_new/cmdcnst.h @@ -0,0 +1,92 @@ +/* + * PROJECT: ReactOS VGA Miniport Driver + * LICENSE: Microsoft NT4 DDK Sample Code License + * FILE: boot/drivers/video/miniport/vga/cmdcnst.h + * PURPOSE: Command Code Definitions for VGA Command Streams + * PROGRAMMERS: Copyright (c) 1992 Microsoft Corporation + */ + + +//-------------------------------------------------------------------------- +// Definition of the set/clear mode command language. +// +// Each command is composed of a major portion and a minor portion. +// The major portion of a command can be found in the most significant +// nibble of a command byte, while the minor portion is in the least +// significant portion of a command byte. +// +// maj minor Description +// ---- ----- -------------------------------------------- +// 00 End of data +// +// 10 in and out type commands as described by flags +// flags: +// +// xxxx +// |||| +// |||+-------- unused +// ||+--------- 0/1 single/multiple values to output (in's are always +// |+---------- 0/1 8/16 bit operation single) +// +----------- 0/1 out/in instruction +// +// Outs +// ---------------------------------------------- +// 0 reg:W val:B +// 2 reg:W cnt:W val1:B val2:B...valN:B +// 4 reg:W val:W +// 6 reg:W cnt:W val1:W val2:W...valN:W +// +// Ins +// ---------------------------------------------- +// 8 reg:W +// a reg:W cnt:W +// c reg:W +// e reg:W cnt:W +// +// 20 Special purpose outs +// 00 do indexed outs for seq, crtc, and gdc +// indexreg:W cnt:B startindex:B val1:B val2:B...valN:B +// 01 do indexed outs for atc +// index-data_reg:W cnt:B startindex:B val1:B val2:B...valN:B +// 02 do masked outs +// indexreg:W andmask:B xormask:B +// +// F0 Nop +// +//--------------------------------------------------------------------------- + +// some useful equates - major commands + +#define EOD 0x000 // end of data +#define INOUT 0x010 // do ins or outs +#define METAOUT 0x020 // do special types of outs +#define NCMD 0x0f0 // Nop command + + +// flags for INOUT major command + +//#define UNUSED 0x01 // reserved +#define MULTI 0x02 // multiple or single outs +#define BW 0x04 // byte/word size of operation +#define IO 0x08 // out/in instruction + +// minor commands for metout + +#define INDXOUT 0x00 // do indexed outs +#define ATCOUT 0x01 // do indexed outs for atc +#define MASKOUT 0x02 // do masked outs using and-xor masks + + +// composite inout type commands + +#define OB (INOUT) // output 8 bit value +#define OBM (INOUT+MULTI) // output multiple bytes +#define OW (INOUT+BW) // output single word value +#define OWM (INOUT+BW+MULTI) // output multiple words + +#define IB (INOUT+IO) // input byte +#define IBM (INOUT+IO+MULTI) // input multiple bytes +#define IW (INOUT+IO+BW) // input word +#define IWM (INOUT+IO+BW+MULTI) // input multiple words + +/* EOF */ diff --git a/reactos/drivers/video/miniport/vga_new/modeset.c b/reactos/drivers/video/miniport/vga_new/modeset.c new file mode 100644 index 00000000000..83c00011a88 --- /dev/null +++ b/reactos/drivers/video/miniport/vga_new/modeset.c @@ -0,0 +1,747 @@ +/* + * PROJECT: ReactOS VGA Miniport Driver + * LICENSE: Microsoft NT4 DDK Sample Code License + * FILE: boot/drivers/video/miniport/vga/modeset.c + * PURPOSE: Handles switching to Standard VGA Modes for compatible cards + * PROGRAMMERS: Copyright (c) 1992 Microsoft Corporation + * ReactOS Portable Systems Group + */ + +#include "vga.h" + +VP_STATUS +VgaInterpretCmdStream( + PHW_DEVICE_EXTENSION HwDeviceExtension, + PUSHORT pusCmdStream + ); + +VP_STATUS +VgaSetMode( + PHW_DEVICE_EXTENSION HwDeviceExtension, + PVIDEO_MODE Mode, + ULONG ModeSize, +// eVb: 2.1 [SET MODE] - Add new output parameter for framebuffer update functionality + PULONG PhysPtrChange +// eVb: 2.1 [END] + ); + +VP_STATUS +VgaQueryAvailableModes( + PHW_DEVICE_EXTENSION HwDeviceExtension, + PVIDEO_MODE_INFORMATION ModeInformation, + ULONG ModeInformationSize, + PULONG OutputSize + ); + +VP_STATUS +VgaQueryNumberOfAvailableModes( + PHW_DEVICE_EXTENSION HwDeviceExtension, + PVIDEO_NUM_MODES NumModes, + ULONG NumModesSize, + PULONG OutputSize + ); + +VOID +VgaZeroVideoMemory( + PHW_DEVICE_EXTENSION HwDeviceExtension + ); + +#if defined(ALLOC_PRAGMA) +#pragma alloc_text(PAGE,VgaInterpretCmdStream) +#pragma alloc_text(PAGE,VgaSetMode) +#pragma alloc_text(PAGE,VgaQueryAvailableModes) +#pragma alloc_text(PAGE,VgaQueryNumberOfAvailableModes) +#pragma alloc_text(PAGE,VgaZeroVideoMemory) +#endif + +//--------------------------------------------------------------------------- +VP_STATUS +VgaInterpretCmdStream( + PHW_DEVICE_EXTENSION HwDeviceExtension, + PUSHORT pusCmdStream + ) + +/*++ + +Routine Description: + + Interprets the appropriate command array to set up VGA registers for the + requested mode. Typically used to set the VGA into a particular mode by + programming all of the registers + +Arguments: + + HwDeviceExtension - Pointer to the miniport driver's device extension. + + pusCmdStream - array of commands to be interpreted. + +Return Value: + + The status of the operation (can only fail on a bad command); TRUE for + success, FALSE for failure. + +--*/ + +{ + ULONG ulCmd; + ULONG ulPort; + UCHAR jValue; + USHORT usValue; + ULONG culCount; + ULONG ulIndex; + ULONG ulBase; + + if (pusCmdStream == NULL) { + + VideoDebugPrint((1, "VgaInterpretCmdStream - Invalid pusCmdStream\n")); + return TRUE; + } + + ulBase = (ULONG)HwDeviceExtension->IOAddress; + + // + // Now set the adapter to the desired mode. + // + + while ((ulCmd = *pusCmdStream++) != EOD) { + + // + // Determine major command type + // + + switch (ulCmd & 0xF0) { + + // + // Basic input/output command + // + + case INOUT: + + // + // Determine type of inout instruction + // + + if (!(ulCmd & IO)) { + + // + // Out instruction. Single or multiple outs? + // + + if (!(ulCmd & MULTI)) { + + // + // Single out. Byte or word out? + // + + if (!(ulCmd & BW)) { + + // + // Single byte out + // + + ulPort = *pusCmdStream++; + jValue = (UCHAR) *pusCmdStream++; + VideoPortWritePortUchar((PUCHAR)(ulBase+ulPort), + jValue); + + } else { + + // + // Single word out + // + + ulPort = *pusCmdStream++; + usValue = *pusCmdStream++; + VideoPortWritePortUshort((PUSHORT)(ulBase+ulPort), + usValue); + + } + + } else { + + // + // Output a string of values + // Byte or word outs? + // + + if (!(ulCmd & BW)) { + + // + // String byte outs. Do in a loop; can't use + // VideoPortWritePortBufferUchar because the data + // is in USHORT form + // + + ulPort = ulBase + *pusCmdStream++; + culCount = *pusCmdStream++; + + while (culCount--) { + jValue = (UCHAR) *pusCmdStream++; + VideoPortWritePortUchar((PUCHAR)ulPort, + jValue); + + } + + } else { + + // + // String word outs + // + + ulPort = *pusCmdStream++; + culCount = *pusCmdStream++; + VideoPortWritePortBufferUshort((PUSHORT) + (ulBase + ulPort), pusCmdStream, culCount); + pusCmdStream += culCount; + + } + } + + } else { + + // In instruction + // + // Currently, string in instructions aren't supported; all + // in instructions are handled as single-byte ins + // + // Byte or word in? + // + + if (!(ulCmd & BW)) { + // + // Single byte in + // + + ulPort = *pusCmdStream++; + jValue = VideoPortReadPortUchar((PUCHAR)ulBase+ulPort); + + } else { + + // + // Single word in + // + + ulPort = *pusCmdStream++; + usValue = VideoPortReadPortUshort((PUSHORT) + (ulBase+ulPort)); + + } + + } + + break; + + // + // Higher-level input/output commands + // + + case METAOUT: + + // + // Determine type of metaout command, based on minor + // command field + // + switch (ulCmd & 0x0F) { + + // + // Indexed outs + // + + case INDXOUT: + + ulPort = ulBase + *pusCmdStream++; + culCount = *pusCmdStream++; + ulIndex = *pusCmdStream++; + + while (culCount--) { + + usValue = (USHORT) (ulIndex + + (((ULONG)(*pusCmdStream++)) << 8)); + VideoPortWritePortUshort((PUSHORT)ulPort, usValue); + + ulIndex++; + + } + + break; + + // + // Masked out (read, AND, XOR, write) + // + + case MASKOUT: + + ulPort = *pusCmdStream++; + jValue = VideoPortReadPortUchar((PUCHAR)ulBase+ulPort); + jValue &= *pusCmdStream++; + jValue ^= *pusCmdStream++; + VideoPortWritePortUchar((PUCHAR)ulBase + ulPort, + jValue); + break; + + // + // Attribute Controller out + // + + case ATCOUT: + + ulPort = ulBase + *pusCmdStream++; + culCount = *pusCmdStream++; + ulIndex = *pusCmdStream++; + + while (culCount--) { + + // Write Attribute Controller index + VideoPortWritePortUchar((PUCHAR)ulPort, + (UCHAR)ulIndex); + + // Write Attribute Controller data + jValue = (UCHAR) *pusCmdStream++; + VideoPortWritePortUchar((PUCHAR)ulPort, jValue); + + ulIndex++; + + } + + break; + + // + // None of the above; error + // + default: + + return FALSE; + + } + + + break; + + // + // NOP + // + + case NCMD: + + break; + + // + // Unknown command; error + // + + default: + + return FALSE; + + } + + } + + return TRUE; + +} // end VgaInterpretCmdStream() + + +VP_STATUS +VgaSetMode( + PHW_DEVICE_EXTENSION HwDeviceExtension, + PVIDEO_MODE Mode, + ULONG ModeSize, +// eVb: 2.2 [SET MODE] - Add new output parameter for framebuffer update functionality + PULONG PhysPtrChange +// eVb: 2.2 [END] + ) + +/*++ + +Routine Description: + + This routine sets the vga into the requested mode. + +Arguments: + + HwDeviceExtension - Pointer to the miniport driver's device extension. + + Mode - Pointer to the structure containing the information about the + font to be set. + + ModeSize - Length of the input buffer supplied by the user. + +Return Value: + + ERROR_INSUFFICIENT_BUFFER if the input buffer was not large enough + for the input data. + + ERROR_INVALID_PARAMETER if the mode number is invalid. + + NO_ERROR if the operation completed successfully. + +--*/ + +{ + PVIDEOMODE pRequestedMode; + VP_STATUS status; + ULONG RequestedModeNum; +// eVb: 2.3 [SET MODE] - Add new output parameter for framebuffer update functionality + *PhysPtrChange = FALSE; +// eVb: 2.3 [END] + // + // Check if the size of the data in the input buffer is large enough. + // + + if (ModeSize < sizeof(VIDEO_MODE)) + { + return ERROR_INSUFFICIENT_BUFFER; + } + + // + // Extract the clear memory, and map linear bits. + // + + RequestedModeNum = Mode->RequestedMode & + ~(VIDEO_MODE_NO_ZERO_MEMORY | VIDEO_MODE_MAP_MEM_LINEAR); + + + if (!(Mode->RequestedMode & VIDEO_MODE_NO_ZERO_MEMORY)) + { +#if defined(_X86_) + VgaZeroVideoMemory(HwDeviceExtension); +#endif + } + + // + // Check to see if we are requesting a valid mode + // +// eVb: 2.4 [CIRRUS] - Remove Cirrus-specific check for valid mode + if ( (RequestedModeNum >= NumVideoModes) ) +// eVb: 2.4 [END] + { + VideoDebugPrint((0, "Invalide Mode Number = %d!\n", RequestedModeNum)); + + return ERROR_INVALID_PARAMETER; + } + + VideoDebugPrint((2, "Attempting to set mode %d\n", + RequestedModeNum)); +// eVb: 2.5 [VBE] - Use dynamic VBE mode list instead of hard-coded VGA list + pRequestedMode = &VgaModeList[RequestedModeNum]; +// eVb: 2.5 [END] + VideoDebugPrint((2, "Info on Requested Mode:\n" + "\tResolution: %dx%d\n", + pRequestedMode->hres, + pRequestedMode->vres )); + + // + // VESA BIOS mode switch + // +// eVb: 2.6 [VBE] - VBE Mode Switch Support + status = VbeSetMode(HwDeviceExtension, pRequestedMode, PhysPtrChange); + if (status == ERROR_INVALID_FUNCTION) + { + // + // VGA mode switch + // + + if (!pRequestedMode->CmdStream) return ERROR_INVALID_FUNCTION; + if (!VgaInterpretCmdStream(HwDeviceExtension, pRequestedMode->CmdStream)) return ERROR_INVALID_FUNCTION; + goto Cleanup; + } + else if (status != NO_ERROR) return status; +// eVb: 2.6 [END] +// eVb: 2.7 [MODE-X] - Windows VGA Miniport Supports Mode-X, we should too + // + // ModeX check + // + + if (pRequestedMode->hres == 320) + { + VideoPortDebugPrint(0, "ModeX not support!!!\n"); + return ERROR_INVALID_PARAMETER; + } +// eVb: 2.7 [END] + // + // Text mode check + // + + if (!(pRequestedMode->fbType & VIDEO_MODE_GRAPHICS)) + { +// eVb: 2.8 [TODO] - This code path is not implemented yet + VideoPortDebugPrint(0, "Text-mode not support!!!\n"); + return ERROR_INVALID_PARAMETER; +// eVb: 2.8 [END] + } + +Cleanup: + // + // Update the location of the physical frame buffer within video memory. + // +// eVb: 2.9 [VBE] - Linear and banked support is unified in VGA, unlike Cirrus + HwDeviceExtension->PhysicalVideoMemoryBase.LowPart = pRequestedMode->PhysBase; + HwDeviceExtension->PhysicalVideoMemoryLength = pRequestedMode->PhysSize; + + HwDeviceExtension->PhysicalFrameLength = + pRequestedMode->FrameBufferSize; + + HwDeviceExtension->PhysicalFrameOffset.LowPart = + pRequestedMode->FrameBufferBase; +// eVb: 2.9 [END] + + // + // Store the new mode value. + // + + HwDeviceExtension->CurrentMode = pRequestedMode; + HwDeviceExtension->ModeIndex = Mode->RequestedMode; + + return NO_ERROR; + +} //end VgaSetMode() + +VP_STATUS +VgaQueryAvailableModes( + PHW_DEVICE_EXTENSION HwDeviceExtension, + PVIDEO_MODE_INFORMATION ModeInformation, + ULONG ModeInformationSize, + PULONG OutputSize + ) + +/*++ + +Routine Description: + + This routine returns the list of all available available modes on the + card. + +Arguments: + + HwDeviceExtension - Pointer to the miniport driver's device extension. + + ModeInformation - Pointer to the output buffer supplied by the user. + This is where the list of all valid modes is stored. + + ModeInformationSize - Length of the output buffer supplied by the user. + + OutputSize - Pointer to a buffer in which to return the actual size of + the data in the buffer. If the buffer was not large enough, this + contains the minimum required buffer size. + +Return Value: + + ERROR_INSUFFICIENT_BUFFER if the output buffer was not large enough + for the data being returned. + + NO_ERROR if the operation completed successfully. + +--*/ + +{ + PVIDEO_MODE_INFORMATION videoModes = ModeInformation; + ULONG i; + + // + // Find out the size of the data to be put in 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 (ModeInformationSize < (*OutputSize = +// eVb: 2.10 [VBE] - We store VBE/VGA mode count in this global, not in DevExt like Cirrus + NumVideoModes * +// eVb: 2.10 [END] + sizeof(VIDEO_MODE_INFORMATION)) ) { + + return ERROR_INSUFFICIENT_BUFFER; + + } + + // + // For each mode supported by the card, store the mode characteristics + // in the output buffer. + // + + for (i = 0; i < NumVideoModes; i++) + { + videoModes->Length = sizeof(VIDEO_MODE_INFORMATION); + videoModes->ModeIndex = i; +// eVb: 2.11 [VBE] - Use dynamic VBE mode list instead of hard-coded VGA list + videoModes->VisScreenWidth = VgaModeList[i].hres; + videoModes->ScreenStride = VgaModeList[i].wbytes; + videoModes->VisScreenHeight = VgaModeList[i].vres; + videoModes->NumberOfPlanes = VgaModeList[i].numPlanes; + videoModes->BitsPerPlane = VgaModeList[i].bitsPerPlane; + videoModes->Frequency = VgaModeList[i].Frequency; + videoModes->XMillimeter = 320; // temporary hardcoded constant + videoModes->YMillimeter = 240; // temporary hardcoded constant + videoModes->AttributeFlags = VgaModeList[i].fbType; +// eVb: 2.11 [END] + + if ((VgaModeList[i].bitsPerPlane == 32) || + (VgaModeList[i].bitsPerPlane == 24)) + { + + videoModes->NumberRedBits = 8; + videoModes->NumberGreenBits = 8; + videoModes->NumberBlueBits = 8; + videoModes->RedMask = 0xff0000; + videoModes->GreenMask = 0x00ff00; + videoModes->BlueMask = 0x0000ff; + + } + else if (VgaModeList[i].bitsPerPlane == 16) + { + + videoModes->NumberRedBits = 6; + videoModes->NumberGreenBits = 6; + videoModes->NumberBlueBits = 6; + videoModes->RedMask = 0x1F << 11; + videoModes->GreenMask = 0x3F << 5; + videoModes->BlueMask = 0x1F; + + } +// eVb: 2.12 [VGA] - Add support for 15bpp modes, which Cirrus doesn't support + else if (VgaModeList[i].bitsPerPlane == 15) + { + + videoModes->NumberRedBits = 6; + videoModes->NumberGreenBits = 6; + videoModes->NumberBlueBits = 6; + videoModes->RedMask = 0x3E << 9; + videoModes->GreenMask = 0x1F << 5; + videoModes->BlueMask = 0x1F; + } +// eVb: 2.12 [END] + else + { + + videoModes->NumberRedBits = 6; + videoModes->NumberGreenBits = 6; + videoModes->NumberBlueBits = 6; + videoModes->RedMask = 0; + videoModes->GreenMask = 0; + videoModes->BlueMask = 0; + } + +// eVb: 2.13 [VGA] - All modes are palette managed/driven, unlike Cirrus + videoModes->AttributeFlags |= VIDEO_MODE_PALETTE_DRIVEN | + VIDEO_MODE_MANAGED_PALETTE; +// eVb: 2.13 [END] + videoModes++; + + } + + return NO_ERROR; + +} // end VgaGetAvailableModes() + +VP_STATUS +VgaQueryNumberOfAvailableModes( + PHW_DEVICE_EXTENSION HwDeviceExtension, + PVIDEO_NUM_MODES NumModes, + ULONG NumModesSize, + PULONG OutputSize + ) + +/*++ + +Routine Description: + + This routine returns the number of available modes for this particular + video card. + +Arguments: + + HwDeviceExtension - Pointer to the miniport driver's device extension. + + NumModes - Pointer to the output buffer supplied by the user. This is + where the number of modes is stored. + + NumModesSize - Length of the output buffer supplied by the user. + + OutputSize - Pointer to a buffer in which to return the actual size of + the data in the buffer. + +Return Value: + + ERROR_INSUFFICIENT_BUFFER if the output buffer was not large enough + for the data being returned. + + NO_ERROR if the operation completed successfully. + +--*/ + +{ + // + // 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 (NumModesSize < (*OutputSize = sizeof(VIDEO_NUM_MODES)) ) { + + return ERROR_INSUFFICIENT_BUFFER; + + } + + // + // Store the number of modes into the buffer. + // + +// eVb: 2.14 [VBE] - We store VBE/VGA mode count in this global, not in DevExt like Cirrus + NumModes->NumModes = NumVideoModes; +// eVb: 2.14 [END] + NumModes->ModeInformationLength = sizeof(VIDEO_MODE_INFORMATION); + + return NO_ERROR; + +} // end VgaGetNumberOfAvailableModes() + +VOID +VgaZeroVideoMemory( + PHW_DEVICE_EXTENSION HwDeviceExtension + ) + +/*++ + +Routine Description: + + This routine zeros the first 256K on the VGA. + +Arguments: + + HwDeviceExtension - Pointer to the miniport driver's device extension. + + +Return Value: + + None. + +--*/ +{ + UCHAR temp; + + // + // Map font buffer at A0000 + // + + VgaInterpretCmdStream(HwDeviceExtension, EnableA000Data); + + // + // Enable all planes. + // + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT, + IND_MAP_MASK); + + temp = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + + SEQ_DATA_PORT) | (UCHAR)0x0F; + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_DATA_PORT, + temp); + + VideoPortZeroDeviceMemory(HwDeviceExtension->VideoMemoryAddress, 0xFFFF); + + VgaInterpretCmdStream(HwDeviceExtension, DisableA000Color); + +} diff --git a/reactos/drivers/video/miniport/vga_new/vbe.c b/reactos/drivers/video/miniport/vga_new/vbe.c new file mode 100644 index 00000000000..a2c593da460 --- /dev/null +++ b/reactos/drivers/video/miniport/vga_new/vbe.c @@ -0,0 +1,196 @@ +/* + * PROJECT: ReactOS VGA Miniport Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: boot/drivers/video/miniport/vga/vbe.c + * PURPOSE: Main VESA VBE 1.02+ SVGA Miniport Handling Code + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include "vga.h" + +/* GLOBALS ********************************************************************/ + +static const PCHAR Nv11Board = "NV11 (GeForce2) Board"; +static const PCHAR Nv11Chip = "Chip Rev B2"; +static const PCHAR Nv11Vendor = "NVidia Corporation"; +static const PCHAR IntelBrookdale = "Brookdale-G Graphics Controller"; +static const PCHAR BrokenVesaBiosList[] = +{ + "SiS 5597", + "MGA-G100", + "3Dfx Banshee", + "Voodoo3 2000 LC ", + "Voodoo3 3000 LC ", + "Voodoo4 4500 ", + "ArtX I", + "ATI S1-370TL" +}; + +BOOLEAN g_bIntelBrookdaleBIOS; + +/* FUNCTIONS ******************************************************************/ + +BOOLEAN +NTAPI +IsVesaBiosOk(IN PVIDEO_PORT_INT10_INTERFACE Interface, + IN ULONG OemRevision, + IN PCHAR Vendor, + IN PCHAR Product, + IN PCHAR Revision) +{ + ULONG i; + CHAR Version[21]; + + /* If the broken VESA bios found, turn VESA off */ + VideoPortDebugPrint(0, "Vendor: %s Product: %s Revision: %s (%lx)\n", Vendor, Product, Revision, OemRevision); + for (i = 0; i < (sizeof(BrokenVesaBiosList) / sizeof(PCHAR)); i++) + { + if (!strncmp(Product, BrokenVesaBiosList[i], sizeof(BrokenVesaBiosList[i]))) return FALSE; + } + + /* For Brookdale-G (Intel), special hack used */ + g_bIntelBrookdaleBIOS = !strncmp(Product, IntelBrookdale, sizeof(IntelBrookdale)); + + /* For NVIDIA make sure */ + if (!(strncmp(Vendor, Nv11Vendor, sizeof(Nv11Vendor))) && + !(strncmp(Product, Nv11Board, sizeof(Nv11Board))) && + !(strncmp(Revision, Nv11Chip, sizeof(Nv11Chip))) && + (OemRevision == 0x311)) + { + /* Read version */ + if (Interface->Int10ReadMemory(Interface->Context, + 0xC000, + 345, + Version, + sizeof(Version))) return FALSE; + if (!strncmp(Version, "Version 3.11.01.24N16", sizeof(Version))) return FALSE; + } + + /* VESA ok */ + //VideoPortDebugPrint(0, "Vesa ok\n"); + return TRUE; +} + +BOOLEAN +NTAPI +ValidateVbeInfo(IN PHW_DEVICE_EXTENSION VgaExtension, + IN PVBE_INFO VbeInfo) +{ + BOOLEAN VesaBiosOk; + PVOID Context; + CHAR ProductRevision[80]; + CHAR OemString[80]; + CHAR ProductName[80]; + CHAR VendorName[80]; + VP_STATUS Status; + + /* Set default */ + VesaBiosOk = FALSE; + Context = VgaExtension->Int10Interface.Context; + + /* Check magic and version */ + if (strncmp(VbeInfo->Info.Signature, "VESA", 4)) return VesaBiosOk; + if (VbeInfo->Info.Version < 0x102) return VesaBiosOk; + + /* Read strings */ + Status = VgaExtension->Int10Interface.Int10ReadMemory(Context, + HIWORD(VbeInfo->Info.OemStringPtr), + LOWORD(VbeInfo->Info.OemStringPtr), + OemString, + sizeof(OemString)); + if (Status != NO_ERROR) return VesaBiosOk; + Status = VgaExtension->Int10Interface.Int10ReadMemory(Context, + HIWORD(VbeInfo->Info.OemVendorNamePtr), + LOWORD(VbeInfo->Info.OemVendorNamePtr), + VendorName, + sizeof(VendorName)); + if (Status != NO_ERROR) return VesaBiosOk; + Status = VgaExtension->Int10Interface.Int10ReadMemory(Context, + HIWORD(VbeInfo->Info.OemProductNamePtr), + LOWORD(VbeInfo->Info.OemProductNamePtr), + ProductName, + sizeof(ProductName)); + if (Status != NO_ERROR) return VesaBiosOk; + Status = VgaExtension->Int10Interface.Int10ReadMemory(Context, + HIWORD(VbeInfo->Info.OemProductRevPtr), + LOWORD(VbeInfo->Info.OemProductRevPtr), + ProductRevision, + sizeof(ProductRevision)); + if (Status != NO_ERROR) return VesaBiosOk; + + /* Null-terminate strings */ + VendorName[sizeof(OemString) - 1] = ANSI_NULL; + ProductName[sizeof(OemString) - 1] = ANSI_NULL; + ProductRevision[sizeof(OemString) - 1] = ANSI_NULL; + OemString[sizeof(OemString) - 1] = ANSI_NULL; + + /* Check for known bad BIOS */ + VesaBiosOk = IsVesaBiosOk(&VgaExtension->Int10Interface, + VbeInfo->Info.OemSoftwareRevision, + VendorName, + ProductName, + ProductRevision); + VgaExtension->VesaBiosOk = VesaBiosOk; + return VesaBiosOk; +} + +VP_STATUS +NTAPI +VbeSetColorLookup(IN PHW_DEVICE_EXTENSION VgaExtension, + IN PVIDEO_CLUT ClutBuffer) +{ + PVBE_COLOR_REGISTER VesaClut; + INT10_BIOS_ARGUMENTS BiosArguments; + PVOID Context; + ULONG Entries; + ULONG BufferSize = 4 * 1024; + USHORT TrampolineMemorySegment, TrampolineMemoryOffset; + VP_STATUS Status; + USHORT i; + + Entries = ClutBuffer->NumEntries; + + /* Allocate INT10 context/buffer */ + VesaClut = VideoPortAllocatePool(VgaExtension, 1, sizeof(ULONG) * Entries, 0x20616756u); + if (!VesaClut) return ERROR_INVALID_PARAMETER; + if (!VgaExtension->Int10Interface.Size) return ERROR_INVALID_PARAMETER; + Context = VgaExtension->Int10Interface.Context; + Status = VgaExtension->Int10Interface.Int10AllocateBuffer(Context, + &TrampolineMemorySegment, + &TrampolineMemoryOffset, + &BufferSize); + if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER; + + /* VESA has color registers backward! */ + for (i = 0; i < Entries; i++) + { + VesaClut[i].Blue = ClutBuffer->LookupTable[i].RgbArray.Blue; + VesaClut[i].Green = ClutBuffer->LookupTable[i].RgbArray.Green; + VesaClut[i].Red = ClutBuffer->LookupTable[i].RgbArray.Red; + VesaClut[i].Pad = 0; + } + Status = VgaExtension->Int10Interface.Int10WriteMemory(Context, + TrampolineMemorySegment, + TrampolineMemoryOffset, + VesaClut, + Entries * sizeof(ULONG)); + if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER; + + /* Write new palette */ + BiosArguments.Ebx = 0; + BiosArguments.Ecx = Entries; + BiosArguments.Edx = ClutBuffer->FirstEntry; + BiosArguments.Edi = TrampolineMemoryOffset; + BiosArguments.SegEs = TrampolineMemorySegment; + BiosArguments.Eax = VBE_SET_GET_PALETTE_DATA; + Status = VgaExtension->Int10Interface.Int10CallBios(Context, &BiosArguments); + if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER; + VideoPortFreePool(VgaExtension, VesaClut); + VideoPortDebugPrint(Error, "VBE Status: %lx\n", BiosArguments.Eax); + if (BiosArguments.Eax == VBE_SUCCESS) return NO_ERROR; + return ERROR_INVALID_PARAMETER; +} + +/* EOF */ diff --git a/reactos/drivers/video/miniport/vga_new/vbe.h b/reactos/drivers/video/miniport/vga_new/vbe.h new file mode 100644 index 00000000000..8802a5ead16 --- /dev/null +++ b/reactos/drivers/video/miniport/vga_new/vbe.h @@ -0,0 +1,217 @@ +/* + * PROJECT: VGA Miniport Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: boot/drivers/video/miniport/vga/vbe.h + * PURPOSE: VESA VBE Registers and Structures + * PROGRAMMERS: ReactOS Portable Systems Group + */ + + +#define LOWORD(l) ((USHORT)((ULONG_PTR)(l))) +#define HIWORD(l) ((USHORT)(((ULONG_PTR)(l)>>16)&0xFFFF)) + + +/* + * VBE Command Definitions + */ + +#define VBE_GET_CONTROLLER_INFORMATION 0x4F00 +#define VBE_GET_MODE_INFORMATION 0x4F01 +#define VBE_SET_VBE_MODE 0x4F02 +#define VBE_GET_CURRENT_VBE_MODE 0x4F03 +#define VBE_SAVE_RESTORE_STATE 0x4F04 +#define VBE_DISPLAY_WINDOW_CONTROL 0x4F05 +#define VBE_SET_GET_LOGICAL_SCAN_LINE_LENGTH 0x4F06 +#define VBE_SET_GET_DISPLAY_START 0x4F07 +#define VBE_SET_GET_DAC_PALETTE_FORMAT 0x4F08 +#define VBE_SET_GET_PALETTE_DATA 0x4F09 + +/* VBE 2.0+ */ +#define VBE_RETURN_PROTECTED_MODE_INTERFACE 0x4F0A +#define VBE_GET_SET_PIXEL_CLOCK 0x4F0B + +/* Extensions */ +#define VBE_POWER_MANAGEMENT_EXTENSIONS 0x4F10 +#define VBE_FLAT_PANEL_INTERFACE_EXTENSIONS 0x4F11 +#define VBE_AUDIO_INTERFACE_EXTENSIONS 0x4F12 +#define VBE_OEM_EXTENSIONS 0x4F13 +#define VBE_DISPLAY_DATA_CHANNEL 0x4F14 +#define VBE_DDC 0x4F15 + +/* + * VBE DDC Sub-Functions + */ + +#define VBE_DDC_READ_EDID 0x01 +#define VBE_DDC_REPORT_CAPABILITIES 0x10 +#define VBE_DDC_BEGIN_SCL_SDA_CONTROL 0x11 +#define VBE_DDC_END_SCL_SDA_CONTROL 0x12 +#define VBE_DDC_WRITE_SCL_CLOCK_LINE 0x13 +#define VBE_DDC_WRITE_SDA_DATA_LINE 0x14 +#define VBE_DDC_READ_SCL_CLOCK_LINE 0x15 +#define VBE_DDC_READ_SDA_DATA_LINE 0x16 + +/* + * VBE Video Mode Information Definitions + */ +#define VBE_MODEATTR_VALID 0x01 +#define VBE_MODEATTR_COLOR 0x08 +#define VBE_MODEATTR_GRAPHICS 0x10 +#define VBE_MODEATTR_NON_VGA 0x20 +#define VBE_MODEATTR_NO_BANK_SWITCH 0x40 +#define VBE_MODEATTR_LINEAR 0x80 + +#define VBE_MODE_BITS 8 +#define VBE_MODE_RESERVED_1 0x200 +#define VBE_MODE_RESERVED_2 0x400 +#define VBE_MODE_REFRESH_CONTROL 0x800 +#define VBE_MODE_ACCELERATED_1 0x1000 +#define VBE_MODE_ACCELERATED_2 0x2000 +#define VBE_MODE_LINEAR_FRAMEBUFFER 0x4000 +#define VBE_MODE_PRESERVE_DISPLAY 0x8000 +#define VBE_MODE_MASK ((1 << (VBE_MODE_BITS + 1)) - 1) + +#define VBE_MEMORYMODEL_PACKEDPIXEL 0x04 +#define VBE_MEMORYMODEL_DIRECTCOLOR 0x06 + +/* + * VBE Return Codes + */ + +#define VBE_SUCCESS 0x4F +#define VBE_UNSUCCESSFUL 0x14F +#define VBE_NOT_SUPPORTED 0x24F +#define VBE_FUNCTION_INVALID 0x34F + +#define VBE_GETRETURNCODE(x) (x & 0xFFFF) + +#include + +/* + * VBE specification defined structure for general adapter info + * returned by function VBE_GET_CONTROLLER_INFORMATION command. + */ + +typedef struct _VBE_CONTROLLER_INFO +{ + CHAR Signature[4]; + USHORT Version; + ULONG OemStringPtr; + LONG Capabilities; + ULONG VideoModePtr; + USHORT TotalMemory; + USHORT OemSoftwareRevision; + ULONG OemVendorNamePtr; + ULONG OemProductNamePtr; + ULONG OemProductRevPtr; + CHAR Reserved[222]; + CHAR OemData[256]; +} VBE_CONTROLLER_INFO, *PVBE_CONTROLLER_INFO; + +/* + * VBE specification defined structure for specific video mode + * info returned by function VBE_GET_MODE_INFORMATION command. + */ + +typedef struct _VBE_MODE_INFO +{ + /* Mandatory information for all VBE revisions */ + USHORT ModeAttributes; + UCHAR WinAAttributes; + UCHAR WinBAttributes; + USHORT WinGranularity; + USHORT WinSize; + USHORT WinASegment; + USHORT WinBSegment; + ULONG WinFuncPtr; + USHORT BytesPerScanLine; + + /* Mandatory information for VBE 1.2 and above */ + USHORT XResolution; + USHORT YResolution; + UCHAR XCharSize; + UCHAR YCharSize; + UCHAR NumberOfPlanes; + UCHAR BitsPerPixel; + UCHAR NumberOfBanks; + UCHAR MemoryModel; + UCHAR BankSize; + UCHAR NumberOfImagePages; + UCHAR Reserved1; + + /* Direct Color fields (required for Direct/6 and YUV/7 memory models) */ + UCHAR RedMaskSize; + UCHAR RedFieldPosition; + UCHAR GreenMaskSize; + UCHAR GreenFieldPosition; + UCHAR BlueMaskSize; + UCHAR BlueFieldPosition; + UCHAR ReservedMaskSize; + UCHAR ReservedFieldPosition; + UCHAR DirectColorModeInfo; + + /* Mandatory information for VBE 2.0 and above */ + ULONG PhysBasePtr; + ULONG Reserved2; + USHORT Reserved3; + + /* Mandatory information for VBE 3.0 and above */ + USHORT LinBytesPerScanLine; + UCHAR BnkNumberOfImagePages; + UCHAR LinNumberOfImagePages; + UCHAR LinRedMaskSize; + UCHAR LinRedFieldPosition; + UCHAR LinGreenMaskSize; + UCHAR LinGreenFieldPosition; + UCHAR LinBlueMaskSize; + UCHAR LinBlueFieldPosition; + UCHAR LinReservedMaskSize; + UCHAR LinReservedFieldPosition; + ULONG MaxPixelClock; + + CHAR Reserved4[190]; +} VBE_MODE_INFO, *PVBE_MODE_INFO; + +#include + +typedef struct _VBE_INFO +{ + VBE_CONTROLLER_INFO Info; + VBE_MODE_INFO Modes; + USHORT ModeArray[129]; +} VBE_INFO, *PVBE_INFO; + +C_ASSERT(sizeof(VBE_CONTROLLER_INFO) == 0x200); +C_ASSERT(sizeof(VBE_MODE_INFO) == 0x100); + +typedef struct _VBE_COLOR_REGISTER +{ + UCHAR Blue; + UCHAR Green; + UCHAR Red; + UCHAR Pad; +} VBE_COLOR_REGISTER, *PVBE_COLOR_REGISTER; + +VOID +NTAPI +InitializeModeTable(IN PHW_DEVICE_EXTENSION VgaExtension); + +VP_STATUS +NTAPI +VbeSetMode(IN PHW_DEVICE_EXTENSION VgaDeviceExtension, + IN PVIDEOMODE VgaMode, + OUT PULONG PhysPtrChange); + +VP_STATUS +NTAPI +VbeSetColorLookup(IN PHW_DEVICE_EXTENSION VgaExtension, + IN PVIDEO_CLUT ClutBuffer); + +BOOLEAN +NTAPI +ValidateVbeInfo(IN PHW_DEVICE_EXTENSION VgaExtension, + IN PVBE_INFO VbeInfo); + +extern BOOLEAN g_bIntelBrookdaleBIOS; + +/* EOF */ diff --git a/reactos/drivers/video/miniport/vga_new/vbemodes.c b/reactos/drivers/video/miniport/vga_new/vbemodes.c new file mode 100644 index 00000000000..39537c64563 --- /dev/null +++ b/reactos/drivers/video/miniport/vga_new/vbemodes.c @@ -0,0 +1,449 @@ +/* + * PROJECT: ReactOS VGA Miniport Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: boot/drivers/video/miniport/vga/vbemodes.c + * PURPOSE: Mode Initialization and Mode Set for VBE-compatible cards + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include "vga.h" + +/* FUNCTIONS ******************************************************************/ + +ULONG +NTAPI +RaiseToPower2Ulong(IN ULONG Value) +{ + ULONG SquaredResult = Value; + if ((Value - 1) & Value) for (SquaredResult = 1; (SquaredResult < Value) && (SquaredResult); SquaredResult *= 2); + return SquaredResult; +} + +ULONG +NTAPI +RaiseToPower2(IN USHORT Value) +{ + ULONG SquaredResult = Value; + if ((Value - 1) & Value) for (SquaredResult = 1; (SquaredResult < Value) && (SquaredResult); SquaredResult *= 2); + return SquaredResult; +} + +ULONG +NTAPI +VbeGetVideoMemoryBaseAddress(IN PHW_DEVICE_EXTENSION VgaExtension, + IN PVIDEOMODE VgaMode) +{ + ULONG Length = 4 * 1024; + USHORT TrampolineMemorySegment, TrampolineMemoryOffset; + PVOID Context; + INT10_BIOS_ARGUMENTS BiosArguments; + PVBE_MODE_INFO VbeModeInfo; + ULONG BaseAddress; + VP_STATUS Status; + + /* Need linear and INT10 interface */ + if (!(VgaMode->fbType & VIDEO_MODE_BANKED)) return 0; + if (VgaExtension->Int10Interface.Size) return 0; + + /* Allocate scratch area and context */ + VbeModeInfo = VideoPortAllocatePool(VgaExtension, 1, sizeof(VBE_MODE_INFO), ' agV'); + if (!VbeModeInfo) return 0; + Context = VgaExtension->Int10Interface.Context; + Status = VgaExtension->Int10Interface.Int10AllocateBuffer(Context, + &TrampolineMemorySegment, + &TrampolineMemoryOffset, + &Length); + if (Status != NO_ERROR) return 0; + + /* Ask VBE BIOS for mode info */ + BiosArguments.Ecx = HIWORD(VgaMode->Mode); + BiosArguments.Edi = TrampolineMemorySegment; + BiosArguments.SegEs = TrampolineMemoryOffset; + BiosArguments.Eax = VBE_GET_MODE_INFORMATION; + Status = VgaExtension->Int10Interface.Int10CallBios(Context, &BiosArguments); + if (Status != NO_ERROR) return 0; + if (BiosArguments.Eax != VBE_SUCCESS) return 0; + Status = VgaExtension->Int10Interface.Int10ReadMemory(Context, + TrampolineMemorySegment, + TrampolineMemoryOffset, + VbeModeInfo, + sizeof(VBE_MODE_INFO)); + if (Status != NO_ERROR) return 0; + + /* Return phys address and cleanup */ + BaseAddress = VbeModeInfo->PhysBasePtr; + VgaExtension->Int10Interface.Int10FreeBuffer(Context, + TrampolineMemorySegment, + TrampolineMemoryOffset); + VideoPortFreePool(VgaExtension, VbeModeInfo); + return BaseAddress; +} + +VP_STATUS +NTAPI +VbeSetMode(IN PHW_DEVICE_EXTENSION VgaDeviceExtension, + IN PVIDEOMODE VgaMode, + OUT PULONG PhysPtrChange) +{ + VP_STATUS Status; + VIDEO_X86_BIOS_ARGUMENTS BiosArguments; + ULONG ModeIndex; + ULONG BaseAddress; + + VideoPortZeroMemory(&BiosArguments, sizeof(BiosArguments)); + ModeIndex = VgaMode->Mode; + BiosArguments.Eax = ModeIndex & 0x0000FFFF; + BiosArguments.Ebx = ModeIndex >> 16; + VideoPortDebugPrint(0, "Switching to %lx %lx\n", BiosArguments.Eax, BiosArguments.Ebx); + Status = VideoPortInt10(VgaDeviceExtension, &BiosArguments); + if (Status != NO_ERROR) return Status; + + /* Check for VESA mode */ + if (ModeIndex >> 16) + { + /* Mode set fail */ + if (BiosArguments.Eax != VBE_SUCCESS) return ERROR_INVALID_PARAMETER; + + /* Check current mode is desired mode */ + BiosArguments.Eax = VBE_GET_CURRENT_VBE_MODE; + Status = VideoPortInt10(VgaDeviceExtension, &BiosArguments); + if ((Status == NO_ERROR) && + (BiosArguments.Eax == VBE_SUCCESS) && + ((BiosArguments.Ebx ^ (ModeIndex >> 16)) & VBE_MODE_BITS)) + { + return ERROR_INVALID_PARAMETER; + } + + /* Set logical scanline width if different from physical */ + if (VgaMode->LogicalWidth != VgaMode->hres) + { + /* Check setting works after being set */ + BiosArguments.Eax = VBE_SET_GET_LOGICAL_SCAN_LINE_LENGTH; + BiosArguments.Ecx = VgaMode->LogicalWidth; + BiosArguments.Ebx = 0; + Status = VideoPortInt10(VgaDeviceExtension, &BiosArguments); + if ((Status != NO_ERROR) || + (BiosArguments.Eax != VBE_SUCCESS) || + (BiosArguments.Ecx != VgaMode->LogicalWidth)) + { + return ERROR_INVALID_PARAMETER; + } + } + } + + /* Get VRAM address to update changes */ + BaseAddress = VbeGetVideoMemoryBaseAddress(VgaDeviceExtension, VgaMode); + if ((BaseAddress) && (VgaMode->PhysBase != BaseAddress)) + { + *PhysPtrChange = TRUE; + VgaMode->PhysBase = BaseAddress; + } + + return NO_ERROR; +} + +VOID +NTAPI +InitializeModeTable(IN PHW_DEVICE_EXTENSION VgaExtension) +{ + ULONG ModeCount = 0; + ULONG Length = 4 * 1024; + ULONG TotalMemory; + VP_STATUS Status; + INT10_BIOS_ARGUMENTS BiosArguments; + PVBE_INFO VbeInfo; + PVBE_MODE_INFO VbeModeInfo; + PVOID Context; + USHORT TrampolineMemorySegment; + USHORT TrampolineMemoryOffset; + ULONG VbeVersion; + ULONG NewModes = 0; + BOOLEAN FourBppModeFound = FALSE; + USHORT ModeResult; + USHORT Mode; + PUSHORT ThisMode; + BOOLEAN LinearAddressing; + ULONG Size, ScreenSize; + PVIDEOMODE VgaMode; + PVOID BaseAddress; + ULONG ScreenStride = 0; + PHYSICAL_ADDRESS PhysicalAddress; + + /* Enable only default vga modes if no vesa */ + VgaModeList = ModesVGA; + if (VideoPortIsNoVesa()) + { + VgaExtension->Int10Interface.Size = 0; + VgaExtension->Int10Interface.Version = 0; + return; + } + + /* Query INT10 interface */ + VgaExtension->Int10Interface.Version = VIDEO_PORT_INT10_INTERFACE_VERSION_1; + VgaExtension->Int10Interface.Size = sizeof(VIDEO_PORT_INT10_INTERFACE); + if (VideoPortQueryServices(VgaExtension, + VideoPortServicesInt10, + (PINTERFACE)&VgaExtension->Int10Interface)) + { + VgaExtension->Int10Interface.Size = 0; + VgaExtension->Int10Interface.Version = 0; + } + + /* Add ref */ + //VideoPortDebugPrint(0, "have int10 iface\n"); + VgaExtension->Int10Interface.InterfaceReference(VgaExtension->Int10Interface.Context); + Context = VgaExtension->Int10Interface.Context; + + /* Allocate scratch area and context */ + Status = VgaExtension->Int10Interface.Int10AllocateBuffer(Context, + &TrampolineMemorySegment, + &TrampolineMemoryOffset, + &Length); + if (Status != NO_ERROR) return; + VbeInfo = VideoPortAllocatePool(VgaExtension, 1, sizeof(VBE_INFO), ' agV'); + VbeModeInfo = &VbeInfo->Modes; + if (!VbeInfo) return; + + /* Init VBE data and write to card buffer */ + //VideoPortDebugPrint(0, "have int10 data\n"); + VbeInfo->ModeArray[128] = 0xFFFF; + strcpy(VbeInfo->Info.Signature, "VBE2"); + Status = VgaExtension->Int10Interface.Int10WriteMemory(Context, + TrampolineMemorySegment, + TrampolineMemoryOffset, + VbeInfo, + 512); + if (Status != NO_ERROR) return; + + /* Get controller info */ + BiosArguments.Edi = TrampolineMemoryOffset; + BiosArguments.SegEs = TrampolineMemorySegment; + BiosArguments.Eax = VBE_GET_CONTROLLER_INFORMATION; + Status = VgaExtension->Int10Interface.Int10CallBios(Context, &BiosArguments); + if (Status != NO_ERROR) return; + if (BiosArguments.Eax != VBE_SUCCESS) return; + Status = VgaExtension->Int10Interface.Int10ReadMemory(Context, + TrampolineMemorySegment, + TrampolineMemoryOffset, + VbeInfo, + 512); + if (Status != NO_ERROR) return; + + /* Check correct VBE BIOS */ + //VideoPortDebugPrint(0, "have vbe data\n"); + TotalMemory = VbeInfo->Info.TotalMemory << 16; + VbeVersion = VbeInfo->Info.Version; + VideoPortDebugPrint(0, "vbe version %lx memory %lx\n", VbeVersion, TotalMemory); + if (!ValidateVbeInfo(VgaExtension, VbeInfo)) return; + + /* Read modes */ + //VideoPortDebugPrint(0, "read modes from %p\n", VbeInfo->Info.VideoModePtr); + Status = VgaExtension->Int10Interface.Int10ReadMemory(Context, + HIWORD(VbeInfo->Info.VideoModePtr), + LOWORD(VbeInfo->Info.VideoModePtr), + VbeInfo->ModeArray, + 128 * sizeof(USHORT)); + if (Status != NO_ERROR) return; + //VideoPortDebugPrint(0, "Read modes at: %p\n", VbeInfo->ModeArray); + + /* Count modes, check for new 4bpp SVGA modes */ + ThisMode = VbeInfo->ModeArray; + ModeResult = VbeInfo->ModeArray[0]; + while (ModeResult != 0xFFFF) + { + Mode = ModeResult & 0x1FF; + //VideoPortDebugPrint(0, "Mode found: %lx\n", Mode); + if ((Mode == 0x102) || (Mode == 0x6A)) FourBppModeFound = TRUE; + ModeResult = *++ThisMode; + NewModes++; + } + + /* Remove the built-in mode if not supported by card and check max modes */ + if (!FourBppModeFound) --NumVideoModes; + if ((NewModes >= 128) && (NumVideoModes > 8)) goto Cleanup; + + /* Switch to new SVGA mode list, copy VGA modes */ + VgaModeList = VideoPortAllocatePool(VgaExtension, 1, (NewModes + NumVideoModes) * sizeof(VIDEOMODE), ' agV'); + if (!VgaModeList) goto Cleanup; + VideoPortMoveMemory(VgaModeList, ModesVGA, NumVideoModes * sizeof(VIDEOMODE)); + + /* Apply fixup for Intel Brookdale */ + if (g_bIntelBrookdaleBIOS) + { + VideoPortDebugPrint(0, "Intel Brookdale-G Video BIOS Not Support!\n"); + while (TRUE); + } + + /* Scan SVGA modes */ +// VideoPortDebugPrint(0, "Static modes: %d\n", NumVideoModes); + VgaMode = &VgaModeList[NumVideoModes]; + ThisMode = VbeInfo->ModeArray; + //VideoPortDebugPrint(0, "new modes: %d\n", NewModes); + while (NewModes--) + { + /* Get info on mode */ + BiosArguments.Eax = VBE_GET_MODE_INFORMATION; + BiosArguments.Ecx = *ThisMode; + BiosArguments.Edi = TrampolineMemoryOffset; + BiosArguments.SegEs = TrampolineMemorySegment; + Status = VgaExtension->Int10Interface.Int10CallBios(Context, &BiosArguments); + if (Status != NO_ERROR) goto Next; + if (BiosArguments.Eax != VBE_SUCCESS) goto Next; + Status = VgaExtension->Int10Interface.Int10ReadMemory(Context, + TrampolineMemorySegment, + TrampolineMemoryOffset, + VbeModeInfo, + 256); + if (Status != NO_ERROR) goto Next; + + /* Parse graphics modes only if linear framebuffer support */ + //VideoPortDebugPrint(0, "attr: %lx\n", VbeModeInfo->ModeAttributes); + if (!(VbeModeInfo->ModeAttributes & (VBE_MODEATTR_VALID | + VBE_MODEATTR_GRAPHICS))) goto Next; + LinearAddressing = ((VbeVersion >= 0x200) && + (VbeModeInfo->PhysBasePtr) && + (VbeModeInfo->ModeAttributes & VBE_MODEATTR_LINEAR)) ? + TRUE : FALSE; + + /* Check SVGA modes if 8bpp or higher */ + //VideoPortDebugPrint(0, "PhysBase: %lx\n", VbeModeInfo->PhysBasePtr); + if ((VbeModeInfo->XResolution >= 640) && + (VbeModeInfo->YResolution >= 480) && + (VbeModeInfo->NumberOfPlanes >= 1) && + (VbeModeInfo->BitsPerPixel >= 8)) + { + /* Copy VGA mode info */ + VideoPortZeroMemory(VgaMode, sizeof(VIDEOMODE)); + VgaMode->numPlanes = VbeModeInfo->NumberOfPlanes; + VgaMode->hres = VbeModeInfo->XResolution; + VgaMode->vres = VbeModeInfo->YResolution; + VgaMode->Frequency = 1; + VgaMode->Mode = (*ThisMode << 16) | VBE_SET_VBE_MODE; + VgaMode->Granularity = VbeModeInfo->WinGranularity << 10; + //VideoPortDebugPrint(0, "Mode %lx (Granularity %d)\n", VgaMode->Mode, VgaMode->Granularity); + + /* Set flags */ + if (VbeModeInfo->ModeAttributes & VBE_MODEATTR_COLOR) VgaMode->fbType |= VIDEO_MODE_COLOR; + if (VbeModeInfo->ModeAttributes & VBE_MODEATTR_GRAPHICS) VgaMode->fbType |= VIDEO_MODE_GRAPHICS; + if (VbeModeInfo->ModeAttributes & VBE_MODEATTR_NON_VGA) VgaMode->NonVgaMode = TRUE; + + /* If no char data, say 80x25 */ + VgaMode->col = VbeModeInfo->XCharSize ? VbeModeInfo->XResolution / VbeModeInfo->XCharSize : 80; + VgaMode->row = VbeModeInfo->YCharSize ? VbeModeInfo->YResolution / VbeModeInfo->YCharSize : 25; + //VideoPortDebugPrint(0, "%d by %d rows\n", VgaMode->Columns, VgaMode->Rows); + + /* Check RGB555 (15bpp only) */ + VgaMode->bitsPerPlane = VbeModeInfo->BitsPerPixel / VbeModeInfo->NumberOfPlanes; + if ((VgaMode->bitsPerPlane == 16) && (VbeModeInfo->GreenMaskSize == 5)) VgaMode->bitsPerPlane = 15; + //VideoPortDebugPrint(0, "BPP: %d\n", VgaMode->BitsPerPlane); + + /* Do linear or banked frame buffers */ + VgaMode->FrameBufferBase = 0; + if (!LinearAddressing) + { + /* Read the screen stride (scanline size) */ + ScreenStride = RaiseToPower2(VbeModeInfo->BytesPerScanLine); + VgaMode->wbytes = ScreenStride; + //VideoPortDebugPrint(0, "ScanLines: %lx Stride: %lx\n", VbeModeInfo->BytesPerScanLine, VgaMode->Stride); + + /* Size of frame buffer is Height X ScanLine, align to bank/page size */ + ScreenSize = VgaMode->hres * ScreenStride; + //VideoPortDebugPrint(0, "Size: %lx\n", ScreenSize); + Size = (ScreenSize + ((64 * 1024) - 1)) & ((64 * 1024) - 1); + //VideoPortDebugPrint(0, "Size: %lx\n", ScreenSize); + if (Size > TotalMemory) Size = (Size + ((4 * 1024) - 1)) & ((4 * 1024) - 1); + //VideoPortDebugPrint(0, "Size: %lx\n", ScreenSize); + + /* Banked VGA at 0xA0000 (64K) */ + //VideoPortDebugPrint(0, "Final size: %lx\n", Size); + VgaMode->fbType |= VIDEO_MODE_BANKED; + VgaMode->sbytes = Size; + VgaMode->PhysSize = 64 * 1024; + VgaMode->FrameBufferSize = 64 * 1024; + VgaMode->NoBankSwitch = TRUE; + VgaMode->PhysBase = 0xA0000; + VgaMode->LogicalWidth = RaiseToPower2(VgaMode->hres); + } + else + { + /* VBE 3.00+ has specific field, read legacy field if not */ + //VideoPortDebugPrint(0, "LINEAR MODE!!!\n"); + ScreenStride = (VbeVersion >= 0x300) ? VbeModeInfo->LinBytesPerScanLine : 0; + if (!ScreenStride) ScreenStride = VbeModeInfo->BytesPerScanLine; + VgaMode->wbytes = ScreenStride; + //VideoPortDebugPrint(0, "ScanLines: %lx Stride: %lx\n", VbeModeInfo->BytesPerScanLine, VgaMode->Stride); + + /* Size of frame buffer is Height X ScanLine, align to page size */ + ScreenSize = VgaMode->hres * LOWORD(VgaMode->wbytes); + //VideoPortDebugPrint(0, "Size: %lx\n", ScreenSize); + Size = RaiseToPower2Ulong(ScreenSize); + //VideoPortDebugPrint(0, "Size: %lx\n", ScreenSize); + if (Size > TotalMemory) Size = (Size + ((4 * 1024) - 1)) & ((4 * 1024) - 1); + //VideoPortDebugPrint(0, "Size: %lx\n", ScreenSize); + + /* Linear VGA must read settings from VBE */ + VgaMode->fbType |= VIDEO_MODE_LINEAR; + VgaMode->sbytes = Size; + VgaMode->PhysSize = Size; + VgaMode->FrameBufferSize = Size; + VgaMode->NoBankSwitch = FALSE; + VgaMode->PhysBase = VbeModeInfo->PhysBasePtr; + VgaMode->LogicalWidth = VgaMode->hres; + + /* Make VBE_SET_VBE_MODE command use Linear Framebuffer Select */ + VgaMode->Mode |= (VBE_MODE_LINEAR_FRAMEBUFFER << 16); + } + + /* Override bank switch if not support by card */ + if (VbeModeInfo->ModeAttributes & VBE_MODEATTR_NO_BANK_SWITCH) VgaMode->NoBankSwitch = TRUE; + + /* Next */ + if (ScreenSize <= TotalMemory) + { + VgaMode++; + ModeCount++; + } + } +Next: + /* Next */ + ThisMode++; + } + + /* Check if last mode was color to do test */ + VideoPortDebugPrint(0, "mode scan complete. Total modes: %d\n", ModeCount); + if (--VgaMode->fbType & VIDEO_MODE_COLOR) + { + /* Try map physical buffer and free if worked */ + PhysicalAddress.QuadPart = VgaMode->PhysBase; + BaseAddress = VideoPortGetDeviceBase(VgaExtension, PhysicalAddress, 4 * 1024, FALSE); + if (BaseAddress) + { + VideoPortFreeDeviceBase(VgaExtension, BaseAddress); + } + else + { + /* Not work, so throw out VBE data */ + ModeCount = 0; + } + } + + /* Cleanup sucess path */ + VideoPortFreePool(VgaExtension, VbeInfo); + VgaExtension->Int10Interface.Int10FreeBuffer(Context, + TrampolineMemorySegment, + TrampolineMemoryOffset); + NumVideoModes += ModeCount; + return; + +Cleanup: + /* Cleanup failure path, reset standard VGA and free memory */ + VgaModeList = ModesVGA; + VideoPortFreePool(VgaExtension, VbeInfo); + VgaExtension->Int10Interface.Int10FreeBuffer(Context, + TrampolineMemorySegment, + TrampolineMemoryOffset); +} + +/* EOF */ diff --git a/reactos/drivers/video/miniport/vga_new/vga.c b/reactos/drivers/video/miniport/vga_new/vga.c new file mode 100644 index 00000000000..5b59b53624a --- /dev/null +++ b/reactos/drivers/video/miniport/vga_new/vga.c @@ -0,0 +1,1401 @@ +/* + * PROJECT: ReactOS VGA Miniport Driver + * LICENSE: Microsoft NT4 DDK Sample Code License + * FILE: boot/drivers/video/miniport/vga/vga.c + * PURPOSE: Main Standard VGA-compatible Minport Handling Code + * PROGRAMMERS: Copyright (c) 1992 Microsoft Corporation + * ReactOS Portable Systems Group + */ + +//--------------------------------------------------------------------------- + +#include "vga.h" + +//--------------------------------------------------------------------------- +// +// Function declarations +// +// Functions that start with 'VGA' are entry points for the OS port driver. +// + +VP_STATUS +VgaFindAdapter( + PVOID HwDeviceExtension, + PVOID HwContext, + PWSTR ArgumentString, + PVIDEO_PORT_CONFIG_INFO ConfigInfo, + PUCHAR Again + ); + +BOOLEAN +VgaInitialize( + PVOID HwDeviceExtension + ); + +BOOLEAN +VgaStartIO( + PVOID HwDeviceExtension, + PVIDEO_REQUEST_PACKET RequestPacket + ); + +// +// Private function prototypes. +// + +VP_STATUS +VgaQueryAvailableModes( + PHW_DEVICE_EXTENSION HwDeviceExtension, + PVIDEO_MODE_INFORMATION ModeInformation, + ULONG ModeInformationSize, + PULONG OutputSize + ); + +VP_STATUS +VgaQueryNumberOfAvailableModes( + PHW_DEVICE_EXTENSION HwDeviceExtension, + PVIDEO_NUM_MODES NumModes, + ULONG NumModesSize, + PULONG OutputSize + ); + +VP_STATUS +VgaSetMode( + PHW_DEVICE_EXTENSION HwDeviceExtension, + PVIDEO_MODE Mode, + ULONG ModeSize, +// eVb: 1.1 [SET MODE] - Add new output parameter for framebuffer update functionality + PULONG PhysPtrChange +// eVb: 1.1 [END] + ); + +BOOLEAN +VgaIsPresent( + PHW_DEVICE_EXTENSION HwDeviceExtension + ); + +VOID +VgaInterpretCmdStream( + PVOID HwDeviceExtension, + PUSHORT pusCmdStream + ); + +VP_STATUS +VgaSetColorLookup( + PHW_DEVICE_EXTENSION HwDeviceExtension, + PVIDEO_CLUT ClutBuffer, + ULONG ClutBufferSize + ); + +VP_STATUS +GetDeviceDataCallback( + PVOID HwDeviceExtension, + PVOID Context, + VIDEO_DEVICE_DATA_TYPE DeviceDataType, + PVOID Identifier, + ULONG IdentifierLength, + PVOID ConfigurationData, + ULONG ConfigurationDataLength, + PVOID ComponentInformation, + ULONG ComponentInformationLength + ); + +// eVb: 1.2 [RESOURCE] - Add new function for acquiring VGA resources (I/O, memory) +VP_STATUS +VgaAcquireResources( + PHW_DEVICE_EXTENSION DeviceExtension + ); +// eVb: 1.2 [END] + +#if defined(ALLOC_PRAGMA) +#pragma alloc_text(PAGE,DriverEntry) +#pragma alloc_text(PAGE,VgaFindAdapter) +#pragma alloc_text(PAGE,VgaInitialize) +#pragma alloc_text(PAGE,VgaStartIO) +#pragma alloc_text(PAGE,VgaIsPresent) +#pragma alloc_text(PAGE,VgaSetColorLookup) +#endif + + +//--------------------------------------------------------------------------- +ULONG +// eVb: 1.3 [GCC] - Add NTAPI for GCC support +NTAPI +// eVb: 1.3 [END] +DriverEntry( + PVOID Context1, + PVOID Context2 + ) + +/*++ + +Routine 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 3VideoPortInitialize(). + +Return Value: + + Status from VideoPortInitialize() + +--*/ + +{ + + VIDEO_HW_INITIALIZATION_DATA hwInitData; + ULONG status; + ULONG initializationStatus = (ULONG) -1; + + // + // 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 = VgaFindAdapter; + hwInitData.HwInitialize = VgaInitialize; + hwInitData.HwInterrupt = NULL; + hwInitData.HwStartIO = VgaStartIO; + + // + // Determine the size we require for the device extension. + // + + hwInitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION); + + // + // Always start with parameters for device0 in this case. + // We can leave it like this since we know we will only ever find one + // VGA type adapter in a machine. + // + + // hwInitData.StartingDeviceNumber = 0; + + // + // Once all the relevant information has been stored, call the video + // port driver to do the initialization. + // For this device we will repeat this call three times, for ISA, EISA + // and PCI. + // We will return the minimum of all return values. + // + + // + // We will try the PCI bus first so that our ISA detection does'nt claim + // PCI cards (since it is impossible to differentiate between the two + // by looking at the registers). + // + + // + // NOTE: since this driver only supports one adapter, we will return + // as soon as we find a device, without going on to the following buses. + // Normally one would call for each bus type and return the smallest + // value. + // + +#if !defined(_ALPHA_) + + // + // Before we can enable this on ALPHA we need to find a way to map a + // sparse view of a 4MB region successfully. + // + + hwInitData.AdapterInterfaceType = PCIBus; + + initializationStatus = VideoPortInitialize(Context1, + Context2, + &hwInitData, + NULL); + + if (initializationStatus == NO_ERROR) + { + return initializationStatus; + } + +#endif + + hwInitData.AdapterInterfaceType = MicroChannel; + + initializationStatus = VideoPortInitialize(Context1, + Context2, + &hwInitData, + NULL); + + // + // Return immediately instead of checkin for smallest return code. + // + + if (initializationStatus == NO_ERROR) + { + return initializationStatus; + } + + + hwInitData.AdapterInterfaceType = Internal; + + initializationStatus = VideoPortInitialize(Context1, + Context2, + &hwInitData, + NULL); + + if (initializationStatus == NO_ERROR) + { + return initializationStatus; + } + + + hwInitData.AdapterInterfaceType = Isa; + + initializationStatus = VideoPortInitialize(Context1, + Context2, + &hwInitData, + NULL); + + if (initializationStatus == NO_ERROR) + { + return initializationStatus; + } + + + + hwInitData.AdapterInterfaceType = Eisa; + + status = VideoPortInitialize(Context1, + Context2, + &hwInitData, + NULL); + + if (initializationStatus > status) { + initializationStatus = status; + } + + return initializationStatus; + +} // end DriverEntry() + +//--------------------------------------------------------------------------- +VP_STATUS +VgaFindAdapter( + PVOID HwDeviceExtension, + PVOID HwContext, + PWSTR ArgumentString, + PVIDEO_PORT_CONFIG_INFO ConfigInfo, + PUCHAR Again + ) + +/*++ + +Routine 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(). + + ArgumentString - Supplies 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 known 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: + + NO_ERROR - Indicates a host adapter was found and the + configuration information was successfully determined. + + ERROR_INVALID_PARAMETER - Indicates an adapter was found but there was an + error obtaining the configuration information. If possible an error + should be logged. + + ERROR_DEV_NOT_EXIST - Indicates no host adapter was found for the + supplied configuration information. + +--*/ + +{ + + PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension; + + // + // 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; + + } +// eVb: 1.4 [CIRRUS] - Remove CIRRUS-specific support + // + // Check internal VGA (MIPS and ARM systems) + // + + if ((ConfigInfo->AdapterInterfaceType == Internal) && + (VideoPortGetDeviceData(HwDeviceExtension, + VpControllerData, + &GetDeviceDataCallback, + VgaAccessRange) != NO_ERROR)) + { + return ERROR_INVALID_PARAMETER; + } +// eVb: 1.4 [END] + // + // No interrupt information is necessary. + // + + // + // Check to see if there is a hardware resource conflict. + // +// eVb: 1.5 [RESOURCE] - Use new function for acquiring VGA resources (I/O, memory) + if (VgaAcquireResources(hwDeviceExtension) != NO_ERROR) return ERROR_INVALID_PARAMETER; +// eVb: 1.5 [END] + // + // Get logical IO port addresses. + // + + if ((hwDeviceExtension->IOAddress = + VideoPortGetDeviceBase(hwDeviceExtension, + VgaAccessRange->RangeStart, + VGA_MAX_IO_PORT - VGA_BASE_IO_PORT + 1, + VgaAccessRange->RangeInIoSpace)) == NULL) + { + VideoDebugPrint((2, "VgaFindAdapter - Fail to get io address\n")); + + return ERROR_INVALID_PARAMETER; + } + + // + // Determine whether a VGA is present. + // + + if (!VgaIsPresent(hwDeviceExtension)) { + + VideoDebugPrint((0, "VgaFindAdapter - VGA Failed\n")); + return ERROR_DEV_NOT_EXIST; + } + + // + // Minimum size of the buffer required to store the hardware state + // information returned by IOCTL_VIDEO_SAVE_HARDWARE_STATE. + // + + ConfigInfo->HardwareStateSize = VGA_TOTAL_STATE_SIZE; + + // + // Pass a pointer to the emulator range we are using. + // +// eVb: 1.6 [VDM] - Disable VDM for now + ConfigInfo->NumEmulatorAccessEntries = 0; + ConfigInfo->EmulatorAccessEntries = NULL; + ConfigInfo->EmulatorAccessEntriesContext = 0; +// eVb: 1.6 [END] + // + // BUGBUG + // + // There is really no reason to have the frame buffer mapped. On an + // x86 we use if for save/restore (supposedly) but even then we + // would only need to map a 64K window, not all 16 Meg! + // + +#ifdef _X86_ + + // + // Map the video memory into the system virtual address space so we can + // clear it out and use it for save and restore. + // + + if ( (hwDeviceExtension->VideoMemoryAddress = + VideoPortGetDeviceBase(hwDeviceExtension, + VgaAccessRange[2].RangeStart, + VgaAccessRange[2].RangeLength, + FALSE)) == NULL) + { + VideoDebugPrint((1, "VgaFindAdapter - Fail to get memory address\n")); + + return ERROR_INVALID_PARAMETER; + } + + VideoPortDebugPrint(0, "vga mapped at %x\n", hwDeviceExtension->VideoMemoryAddress); +#endif +// eVb: 1.7 [VDM] - Disable VDM for now + ConfigInfo->VdmPhysicalVideoMemoryAddress.QuadPart = 0; + ConfigInfo->VdmPhysicalVideoMemoryLength = 0; +// eVb: 1.7 [END] + // + // Indicate we do not wish to be called again for another initialization. + // + + *Again = 0; + + // + // Indicate a successful completion status. + // + + return NO_ERROR; + + +} // VgaFindAdapter() + +//--------------------------------------------------------------------------- +BOOLEAN +VgaInitialize( + PVOID HwDeviceExtension + ) + +/*++ + +Routine Description: + + This routine does one time initialization of the device. + +Arguments: + + HwDeviceExtension - Pointer to the miniport driver's adapter information. + +Return Value: + + None. + +--*/ + +{ + PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension; + + // + // set up the default cursor position and type. + // + + hwDeviceExtension->CursorPosition.Column = 0; + hwDeviceExtension->CursorPosition.Row = 0; + hwDeviceExtension->CursorTopScanLine = 0; + hwDeviceExtension->CursorBottomScanLine = 31; + hwDeviceExtension->CursorEnable = TRUE; + +// eVb: 1.8 [VBE] - Initialize VBE modes + InitializeModeTable(hwDeviceExtension); +// eVb: 1.8 [END] + return TRUE; + +} // VgaInitialize() + +//--------------------------------------------------------------------------- +BOOLEAN +VgaStartIO( + PVOID HwDeviceExtension, + PVIDEO_REQUEST_PACKET RequestPacket + ) + +/*++ + +Routine Description: + + This routine is the main execution routine for the miniport driver. It + accepts a Video Request Packet, performs the request, and then returns + with the appropriate status. + +Arguments: + + HwDeviceExtension - Pointer to the miniport driver's adapter information. + + RequestPacket - Pointer to the video request packet. This structure + contains all the parameters passed to the VideoIoControl function. + +Return Value: + + This routine will return error codes from the various support routines + and will also return ERROR_INSUFFICIENT_BUFFER for incorrectly sized + buffers and ERROR_INVALID_FUNCTION for unsupported functions. + +--*/ + +{ + PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension; + VP_STATUS status; + VIDEO_MODE videoMode; + PVIDEO_MEMORY_INFORMATION memoryInformation; + ULONG inIoSpace; + ULONG Result; + + // + // Switch on the IoContolCode in the RequestPacket. It indicates which + // function must be performed by the driver. + // +// eVb: 1.9 [IOCTL] - Remove IOCTLs not needed yet + switch (RequestPacket->IoControlCode) + { + case IOCTL_VIDEO_SHARE_VIDEO_MEMORY: + + VideoDebugPrint((2, "VgaStartIO - ShareVideoMemory\n")); + + status = ERROR_INVALID_FUNCTION; + + break; + + case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY: + + VideoDebugPrint((2, "VgaStartIO - UnshareVideoMemory\n")); + + status = ERROR_INVALID_FUNCTION; + + break; + + + case IOCTL_VIDEO_MAP_VIDEO_MEMORY: + + VideoDebugPrint((2, "VgaStartIO - MapVideoMemory\n")); + + if ( (RequestPacket->OutputBufferLength < + (RequestPacket->StatusBlock->Information = + sizeof(VIDEO_MEMORY_INFORMATION))) || + (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) ) + { + status = ERROR_INSUFFICIENT_BUFFER; + } + + memoryInformation = RequestPacket->OutputBuffer; + + memoryInformation->VideoRamBase = ((PVIDEO_MEMORY) + (RequestPacket->InputBuffer))->RequestedVirtualAddress; + + // + // We reserved 16 meg for the frame buffer, however, it makes + // no sense to map more memory than there is on the card. So + // only map the amount of memory we have on the card. + // +// eVb: 1.10 [CIRRUS] - On VGA, we have VRAM size since boot, use it + memoryInformation->VideoRamLength = + hwDeviceExtension->PhysicalVideoMemoryLength; +// eVb: 1.10 [END] + // + // If you change to using a dense space frame buffer, make this + // value a 4 for the ALPHA. + // + + inIoSpace = 0; + + status = VideoPortMapMemory(hwDeviceExtension, + hwDeviceExtension->PhysicalVideoMemoryBase, +// eVb: 1.11 [CIRRUS] - On VGA, we have VRAM size since boot, use it + &memoryInformation->VideoRamLength, +// eVb: 1.11 [END] + &inIoSpace, + &(memoryInformation->VideoRamBase)); + + if (status != NO_ERROR) { + VideoDebugPrint((0, "VgaStartIO - IOCTL_VIDEO_MAP_VIDEO_MEMORY failed VideoPortMapMemory (%x)\n", status)); + } + + memoryInformation->FrameBufferBase = + ((PUCHAR) (memoryInformation->VideoRamBase)) + + hwDeviceExtension->PhysicalFrameOffset.LowPart; + + memoryInformation->FrameBufferLength = + hwDeviceExtension->PhysicalFrameLength ? + hwDeviceExtension->PhysicalFrameLength : + memoryInformation->VideoRamLength; + + + VideoDebugPrint((2, "physical VideoMemoryBase %08lx\n", hwDeviceExtension->PhysicalVideoMemoryBase)); + VideoDebugPrint((2, "physical VideoMemoryLength %08lx\n", hwDeviceExtension->PhysicalVideoMemoryLength)); + VideoDebugPrint((2, "VideoMemoryBase %08lx\n", memoryInformation->VideoRamBase)); + VideoDebugPrint((2, "VideoMemoryLength %08lx\n", memoryInformation->VideoRamLength)); + + VideoDebugPrint((2, "physical framebuf offset %08lx\n", hwDeviceExtension->PhysicalFrameOffset.LowPart)); + VideoDebugPrint((2, "framebuf base %08lx\n", memoryInformation->FrameBufferBase)); + VideoDebugPrint((2, "physical framebuf len %08lx\n", hwDeviceExtension->PhysicalFrameLength)); + VideoDebugPrint((2, "framebuf length %08lx\n", memoryInformation->FrameBufferLength)); + + break; + + case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY: + + VideoDebugPrint((2, "VgaStartIO - UnMapVideoMemory\n")); + + status = ERROR_INVALID_FUNCTION; + + break; + + + case IOCTL_VIDEO_QUERY_AVAIL_MODES: + + VideoDebugPrint((2, "VgaStartIO - QueryAvailableModes\n")); + + status = VgaQueryAvailableModes(HwDeviceExtension, + (PVIDEO_MODE_INFORMATION) + RequestPacket->OutputBuffer, + RequestPacket->OutputBufferLength, + &RequestPacket->StatusBlock->Information); + + break; + + + case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES: + + VideoDebugPrint((2, "VgaStartIO - QueryNumAvailableModes\n")); + + status = VgaQueryNumberOfAvailableModes(HwDeviceExtension, + (PVIDEO_NUM_MODES) + RequestPacket->OutputBuffer, + RequestPacket->OutputBufferLength, + &RequestPacket->StatusBlock->Information); + + break; + + + case IOCTL_VIDEO_QUERY_CURRENT_MODE: + + VideoDebugPrint((2, "VgaStartIO - QueryCurrentMode\n")); + + status = ERROR_INVALID_FUNCTION; + + break; + + + case IOCTL_VIDEO_SET_CURRENT_MODE: + + VideoDebugPrint((2, "VgaStartIO - SetCurrentModes\n")); + + status = VgaSetMode(HwDeviceExtension, + (PVIDEO_MODE) RequestPacket->InputBuffer, + RequestPacket->InputBufferLength, +// eVb: 1.12 [SET MODE] - Use new output parameter for framebuffer update functionality + &Result); +// eVb: 1.12 [END] + + break; + + + case IOCTL_VIDEO_RESET_DEVICE: + + VideoDebugPrint((2, "VgaStartIO - Reset Device\n")); + + videoMode.RequestedMode = 0; + + VgaSetMode(HwDeviceExtension, + (PVIDEO_MODE) &videoMode, + sizeof(videoMode), +// eVb: 1.13 [SET MODE] - Use new output parameter for framebuffer update functionality + &Result); +// eVb: 1.13 [END] + + // + // Always return succcess since settings the text mode will fail on + // non-x86. + // + // Also, failiure to set the text mode is not fatal in any way, since + // this operation must be followed by another set mode operation. + // + + status = NO_ERROR; + + break; + + + case IOCTL_VIDEO_LOAD_AND_SET_FONT: + + VideoDebugPrint((2, "VgaStartIO - LoadAndSetFont\n")); + + status = ERROR_INVALID_FUNCTION; + + break; + + + case IOCTL_VIDEO_QUERY_CURSOR_POSITION: + + VideoDebugPrint((2, "VgaStartIO - QueryCursorPosition\n")); + + status = ERROR_INVALID_FUNCTION; + + break; + + + case IOCTL_VIDEO_SET_CURSOR_POSITION: + + VideoDebugPrint((2, "VgaStartIO - SetCursorPosition\n")); + + status = ERROR_INVALID_FUNCTION; + + break; + + + case IOCTL_VIDEO_QUERY_CURSOR_ATTR: + + VideoDebugPrint((2, "VgaStartIO - QueryCursorAttributes\n")); + + status = ERROR_INVALID_FUNCTION; + + break; + + + case IOCTL_VIDEO_SET_CURSOR_ATTR: + + VideoDebugPrint((2, "VgaStartIO - SetCursorAttributes\n")); + + status = ERROR_INVALID_FUNCTION; + + break; + + + case IOCTL_VIDEO_SET_PALETTE_REGISTERS: + + VideoDebugPrint((2, "VgaStartIO - SetPaletteRegs\n")); + + status = ERROR_INVALID_FUNCTION; + + break; + + + case IOCTL_VIDEO_SET_COLOR_REGISTERS: + + VideoDebugPrint((2, "VgaStartIO - SetColorRegs\n")); + + status = VgaSetColorLookup(HwDeviceExtension, + (PVIDEO_CLUT) RequestPacket->InputBuffer, + RequestPacket->InputBufferLength); + + break; + + + case IOCTL_VIDEO_ENABLE_VDM: + + VideoDebugPrint((2, "VgaStartIO - EnableVDM\n")); + + status = ERROR_INVALID_FUNCTION; + + break; + + + case IOCTL_VIDEO_RESTORE_HARDWARE_STATE: + + VideoDebugPrint((2, "VgaStartIO - RestoreHardwareState\n")); + + status = ERROR_INVALID_FUNCTION; + + break; + + + case IOCTL_VIDEO_SAVE_HARDWARE_STATE: + + VideoDebugPrint((2, "VgaStartIO - SaveHardwareState\n")); + + status = ERROR_INVALID_FUNCTION; + + break; + + case IOCTL_VIDEO_GET_BANK_SELECT_CODE: + + VideoDebugPrint((2, "VgaStartIO - GetBankSelectCode\n")); + + status = ERROR_INVALID_FUNCTION; + break; + + case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES: + case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES: + + // + // if we get here, an invalid IoControlCode was specified. + // + + default: + + VideoDebugPrint((0, "Fell through vga startIO routine - invalid command\n")); + + status = ERROR_INVALID_FUNCTION; + + break; + + } +// eVb: 1.9 [END] + RequestPacket->StatusBlock->Status = status; + + return TRUE; + +} // VgaStartIO() + + +//--------------------------------------------------------------------------- +// +// private routines +// + + +//--------------------------------------------------------------------------- +BOOLEAN +VgaIsPresent( + PHW_DEVICE_EXTENSION HwDeviceExtension + ) + +/*++ + +Routine Description: + + This routine returns TRUE if a VGA is present. Determining whether a VGA + is present is a two-step process. First, this routine walks bits through + the Bit Mask register, to establish that there are readable indexed + registers (EGAs normally don't have readable registers, and other adapters + are unlikely to have indexed registers). This test is done first because + it's a non-destructive EGA rejection test (correctly rejects EGAs, but + doesn't potentially mess up the screen or the accessibility of display + memory). Normally, this would be an adequate test, but some EGAs have + readable registers, so next, we check for the existence of the Chain4 bit + in the Memory Mode register; this bit doesn't exist in EGAs. It's + conceivable that there are EGAs with readable registers and a register bit + where Chain4 is stored, although I don't know of any; if a better test yet + is needed, memory could be written to in Chain4 mode, and then examined + plane by plane in non-Chain4 mode to make sure the Chain4 bit did what it's + supposed to do. However, the current test should be adequate to eliminate + just about all EGAs, and 100% of everything else. + + If this function fails to find a VGA, it attempts to undo any damage it + may have inadvertently done while testing. The underlying assumption for + the damage control is that if there's any non-VGA adapter at the tested + ports, it's an EGA or an enhanced EGA, because: a) I don't know of any + other adapters that use 3C4/5 or 3CE/F, and b), if there are other + adapters, I certainly don't know how to restore their original states. So + all error recovery is oriented toward putting an EGA back in a writable + state, so that error messages are visible. The EGA's state on entry is + assumed to be text mode, so the Memory Mode register is restored to the + default state for text mode. + + If a VGA is found, the VGA is returned to its original state after + testing is finished. + +Arguments: + + None. + +Return Value: + + TRUE if a VGA is present, FALSE if not. + +--*/ + +{ + UCHAR originalGCAddr; + UCHAR originalSCAddr; + UCHAR originalBitMask; + UCHAR originalReadMap; + UCHAR originalMemoryMode; + UCHAR testMask; + BOOLEAN returnStatus; + + // + // Remember the original state of the Graphics Controller Address register. + // + + originalGCAddr = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + + GRAPH_ADDRESS_PORT); + + // + // Write the Read Map register with a known state so we can verify + // that it isn't changed after we fool with the Bit Mask. This ensures + // that we're dealing with indexed registers, since both the Read Map and + // the Bit Mask are addressed at GRAPH_DATA_PORT. + // + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + GRAPH_ADDRESS_PORT, IND_READ_MAP); + + // + // If we can't read back the Graphics Address register setting we just + // performed, it's not readable and this isn't a VGA. + // + + if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress + + GRAPH_ADDRESS_PORT) & GRAPH_ADDR_MASK) != IND_READ_MAP) { + + return FALSE; + } + + // + // Set the Read Map register to a known state. + // + + originalReadMap = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + + GRAPH_DATA_PORT); + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + GRAPH_DATA_PORT, READ_MAP_TEST_SETTING); + + if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress + + GRAPH_DATA_PORT) != READ_MAP_TEST_SETTING) { + + // + // The Read Map setting we just performed can't be read back; not a + // VGA. Restore the default Read Map state. + // + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + GRAPH_DATA_PORT, READ_MAP_DEFAULT); + + return FALSE; + } + + // + // Remember the original setting of the Bit Mask register. + // + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + GRAPH_ADDRESS_PORT, IND_BIT_MASK); + if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress + + GRAPH_ADDRESS_PORT) & GRAPH_ADDR_MASK) != IND_BIT_MASK) { + + // + // The Graphics Address register setting we just made can't be read + // back; not a VGA. Restore the default Read Map state. + // + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + GRAPH_ADDRESS_PORT, IND_READ_MAP); + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + GRAPH_DATA_PORT, READ_MAP_DEFAULT); + + return FALSE; + } + + originalBitMask = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + + GRAPH_DATA_PORT); + + // + // Set up the initial test mask we'll write to and read from the Bit Mask. + // + + testMask = 0xBB; + + do { + + // + // Write the test mask to the Bit Mask. + // + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + GRAPH_DATA_PORT, testMask); + + // + // Make sure the Bit Mask remembered the value. + // + + if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress + + GRAPH_DATA_PORT) != testMask) { + + // + // The Bit Mask is not properly writable and readable; not a VGA. + // Restore the Bit Mask and Read Map to their default states. + // + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + GRAPH_DATA_PORT, BIT_MASK_DEFAULT); + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + GRAPH_ADDRESS_PORT, IND_READ_MAP); + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + GRAPH_DATA_PORT, READ_MAP_DEFAULT); + + return FALSE; + } + + // + // Cycle the mask for next time. + // + + testMask >>= 1; + + } while (testMask != 0); + + // + // There's something readable at GRAPH_DATA_PORT; now switch back and + // make sure that the Read Map register hasn't changed, to verify that + // we're dealing with indexed registers. + // + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + GRAPH_ADDRESS_PORT, IND_READ_MAP); + if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress + + GRAPH_DATA_PORT) != READ_MAP_TEST_SETTING) { + + // + // The Read Map is not properly writable and readable; not a VGA. + // Restore the Bit Mask and Read Map to their default states, in case + // this is an EGA, so subsequent writes to the screen aren't garbled. + // + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + GRAPH_DATA_PORT, READ_MAP_DEFAULT); + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + GRAPH_ADDRESS_PORT, IND_BIT_MASK); + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + GRAPH_DATA_PORT, BIT_MASK_DEFAULT); + + return FALSE; + } + + // + // We've pretty surely verified the existence of the Bit Mask register. + // Put the Graphics Controller back to the original state. + // + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + GRAPH_DATA_PORT, originalReadMap); + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + GRAPH_ADDRESS_PORT, IND_BIT_MASK); + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + GRAPH_DATA_PORT, originalBitMask); + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + GRAPH_ADDRESS_PORT, originalGCAddr); + + // + // Now, check for the existence of the Chain4 bit. + // + + // + // Remember the original states of the Sequencer Address and Memory Mode + // registers. + // + + originalSCAddr = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + + SEQ_ADDRESS_PORT); + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + SEQ_ADDRESS_PORT, IND_MEMORY_MODE); + if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress + + SEQ_ADDRESS_PORT) & SEQ_ADDR_MASK) != IND_MEMORY_MODE) { + + // + // Couldn't read back the Sequencer Address register setting we just + // performed. + // + + return FALSE; + } + originalMemoryMode = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + + SEQ_DATA_PORT); + + // + // Toggle the Chain4 bit and read back the result. This must be done during + // sync reset, since we're changing the chaining state. + // + + // + // Begin sync reset. + // + + VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress + + SEQ_ADDRESS_PORT), + (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8))); + + // + // Toggle the Chain4 bit. + // + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + SEQ_ADDRESS_PORT, IND_MEMORY_MODE); + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + SEQ_DATA_PORT, (UCHAR)(originalMemoryMode ^ CHAIN4_MASK)); + + if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress + + SEQ_DATA_PORT) != (UCHAR) (originalMemoryMode ^ CHAIN4_MASK)) { + + // + // Chain4 bit not there; not a VGA. + // Set text mode default for Memory Mode register. + // + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + SEQ_DATA_PORT, MEMORY_MODE_TEXT_DEFAULT); + // + // End sync reset. + // + + VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress + + SEQ_ADDRESS_PORT), + (IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8))); + + returnStatus = FALSE; + + } else { + + // + // It's a VGA. + // + + // + // Restore the original Memory Mode setting. + // + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + SEQ_DATA_PORT, originalMemoryMode); + + // + // End sync reset. + // + + VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress + + SEQ_ADDRESS_PORT), + (USHORT)(IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8))); + + // + // Restore the original Sequencer Address setting. + // + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + SEQ_ADDRESS_PORT, originalSCAddr); + + returnStatus = TRUE; + } + + return returnStatus; + +} // VgaIsPresent() + + +//--------------------------------------------------------------------------- +VP_STATUS +VgaSetColorLookup( + PHW_DEVICE_EXTENSION HwDeviceExtension, + PVIDEO_CLUT ClutBuffer, + ULONG ClutBufferSize + ) + +/*++ + +Routine Description: + + This routine sets a specified portion of the DAC 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: + + NO_ERROR - information returned successfully + + ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data. + + ERROR_INVALID_PARAMETER - invalid clut size. + +--*/ + +{ + PVIDEOMODE CurrentMode = HwDeviceExtension->CurrentMode; + USHORT i; + + // + // 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; + + } +// eVb: 1.14 [VBE] - Add VBE color support + // + // Check SVGA mode + // + + if (CurrentMode->bitsPerPlane >= 8) return VbeSetColorLookup(HwDeviceExtension, ClutBuffer); +// eVb: 1.14 [END] + // + // Path for VGA mode + // +// eVb: 1.15 [VBE] - Add VBE support for non-VGA-compatible detected modes + if (!CurrentMode->NonVgaMode) + { +// eVb: 1.15 [END] + // + // Set CLUT registers directly on the hardware + // + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + DAC_ADDRESS_WRITE_PORT, (UCHAR) ClutBuffer->FirstEntry); + + for (i = 0; i < ClutBuffer->NumEntries; i++) { + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + DAC_ADDRESS_WRITE_PORT, + (UCHAR)(i + ClutBuffer->FirstEntry)); + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + DAC_DATA_REG_PORT, + ClutBuffer->LookupTable[i].RgbArray.Red); + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + DAC_DATA_REG_PORT, + ClutBuffer->LookupTable[i].RgbArray.Green); + + VideoPortWritePortUchar(HwDeviceExtension->IOAddress + + DAC_DATA_REG_PORT, + ClutBuffer->LookupTable[i].RgbArray.Blue); + } + return NO_ERROR; + } + + return ERROR_INVALID_PARAMETER; + +} // end VgaSetColorLookup() + +VP_STATUS +GetDeviceDataCallback( + PVOID HwDeviceExtension, + PVOID Context, + VIDEO_DEVICE_DATA_TYPE DeviceDataType, + PVOID Identifier, + ULONG IdentifierLength, + PVOID ConfigurationData, + ULONG ConfigurationDataLength, + PVOID ComponentInformation, + ULONG ComponentInformationLength + ) + +/*++ + +Routine Description: + + Callback routine for the VideoPortGetDeviceData function. + +Arguments: + + HwDeviceExtension - Pointer to the miniport drivers device extension. + + Context - Context value passed to the VideoPortGetDeviceData function. + + DeviceDataType - The type of data that was requested in + VideoPortGetDeviceData. + + Identifier - Pointer to a string that contains the name of the device, + as setup by the ROM or ntdetect. + + IdentifierLength - Length of the Identifier string. + + ConfigurationData - Pointer to the configuration data for the device or + BUS. + + ConfigurationDataLength - Length of the data in the configurationData + field. + + ComponentInformation - Undefined. + + ComponentInformationLength - Undefined. + +Return Value: + + Returns NO_ERROR if the function completed properly. + Returns ERROR_DEV_NOT_EXIST if we did not find the device. + Returns ERROR_INVALID_PARAMETER otherwise. + +--*/ + +{ + VideoPortDebugPrint(Error, "Detected internal VGA chip on embedded board, todo\n"); + while (TRUE); + return NO_ERROR; + +} //end GetDeviceDataCallback() + +// eVb: 1.16 [RESOURCE] - Add new function for acquiring VGA resources (I/O, memory) +VP_STATUS +VgaAcquireResources( + PHW_DEVICE_EXTENSION DeviceExtension + ) +{ + VP_STATUS Status = NO_ERROR; + ULONG Ranges, i; + + // + // Try exclusive ranges (vga + ati) + // + + Ranges = NUM_VGA_ACCESS_RANGES; + for (i = 0; i < Ranges; i++) VgaAccessRange[i].RangeShareable = FALSE; + if (VideoPortVerifyAccessRanges(DeviceExtension, Ranges, VgaAccessRange) != NO_ERROR) + { + // + // Not worked, try vga only + // + + Ranges = 3; + if (VideoPortVerifyAccessRanges(DeviceExtension, Ranges, VgaAccessRange) != NO_ERROR) + { + // + // Still not, try shared ranges + // + + for (i = 0; i < Ranges; i++) VgaAccessRange[i].RangeShareable = TRUE; + Status = VideoPortVerifyAccessRanges(DeviceExtension, Ranges, VgaAccessRange); + if (Status == NO_ERROR) + { + // + // It did work + // + + VideoPortVerifyAccessRanges(DeviceExtension, 0, 0); + Status = NO_ERROR; + } + } + } + + if (Status == NO_ERROR) + { + // + // Worked with exclusive, also try shared + // + + for (i = 0; i < Ranges; i++) VgaAccessRange[i].RangeShareable = TRUE; + Status = VideoPortVerifyAccessRanges(DeviceExtension, Ranges, VgaAccessRange); + } + + return Status; +} +// eVb: 1.16 [END] diff --git a/reactos/drivers/video/miniport/vga_new/vga.h b/reactos/drivers/video/miniport/vga_new/vga.h new file mode 100644 index 00000000000..21e411584f8 --- /dev/null +++ b/reactos/drivers/video/miniport/vga_new/vga.h @@ -0,0 +1,446 @@ +/* + * PROJECT: ReactOS VGA Miniport Driver + * LICENSE: Microsoft NT4 DDK Sample Code License + * FILE: boot/drivers/video/miniport/vga/vga.h + * PURPOSE: Main Header File + * PROGRAMMERS: Copyright (c) 1992 Microsoft Corporation + * ReactOS Portable Systems Group + */ + +#include "ntdef.h" +#include "dderror.h" +#include "devioctl.h" +#include "miniport.h" +#include "ntddvdeo.h" +#include "video.h" +#include "cmdcnst.h" + +// +// Base address of VGA memory range. Also used as base address of VGA +// memory when loading a font, which is done with the VGA mapped at A0000. +// + +#define MEM_VGA 0xA0000 +#define MEM_VGA_SIZE 0x20000 + +// +// For memory mapped IO +// + +#define MEMORY_MAPPED_IO_OFFSET (0xB8000 - 0xA0000) + +// +// Port definitions for filling the ACCESS_RANGES structure in the miniport +// information, defines the range of I/O ports the VGA spans. +// There is a break in the IO ports - a few ports are used for the parallel +// port. Those cannot be defined in the ACCESS_RANGE, but are still mapped +// so all VGA ports are in one address range. +// + +#define VGA_BASE_IO_PORT 0x000003B0 +#define VGA_START_BREAK_PORT 0x000003BB +#define VGA_END_BREAK_PORT 0x000003C0 +#define VGA_MAX_IO_PORT 0x000003DF + +// +// VGA register definitions +// +// eVb: 3.1 [VGA] - Use offsets from the VGA Port Address instead of absolute +#define CRTC_ADDRESS_PORT_MONO 0x0004 // CRT Controller Address and +#define CRTC_DATA_PORT_MONO 0x0005 // Data registers in mono mode +#define FEAT_CTRL_WRITE_PORT_MONO 0x000A // Feature Control write port + // in mono mode +#define INPUT_STATUS_1_MONO 0x000A // Input Status 1 register read + // port in mono mode +#define ATT_INITIALIZE_PORT_MONO INPUT_STATUS_1_MONO + // Register to read to reset + // Attribute Controller index/data + +#define ATT_ADDRESS_PORT 0x0010 // Attribute Controller Address and +#define ATT_DATA_WRITE_PORT 0x0010 // Data registers share one port + // for writes, but only Address is + // readable at 0x3C0 +#define ATT_DATA_READ_PORT 0x0011 // Attribute Controller Data reg is + // readable here +#define MISC_OUTPUT_REG_WRITE_PORT 0x0012 // Miscellaneous Output reg write + // port +#define INPUT_STATUS_0_PORT 0x0012 // Input Status 0 register read + // port +#define VIDEO_SUBSYSTEM_ENABLE_PORT 0x0013 // Bit 0 enables/disables the + // entire VGA subsystem +#define SEQ_ADDRESS_PORT 0x0014 // Sequence Controller Address and +#define SEQ_DATA_PORT 0x0015 // Data registers +#define DAC_PIXEL_MASK_PORT 0x0016 // DAC pixel mask reg +#define DAC_ADDRESS_READ_PORT 0x0017 // DAC register read index reg, + // write-only +#define DAC_STATE_PORT 0x0017 // DAC state (read/write), + // read-only +#define DAC_ADDRESS_WRITE_PORT 0x0018 // DAC register write index reg +#define DAC_DATA_REG_PORT 0x0019 // DAC data transfer reg +#define FEAT_CTRL_READ_PORT 0x001A // Feature Control read port +#define MISC_OUTPUT_REG_READ_PORT 0x001C // Miscellaneous Output reg read + // port +#define GRAPH_ADDRESS_PORT 0x001E // Graphics Controller Address +#define GRAPH_DATA_PORT 0x001F // and Data registers + +#define CRTC_ADDRESS_PORT_COLOR 0x0024 // CRT Controller Address and +#define CRTC_DATA_PORT_COLOR 0x0025 // Data registers in color mode +#define FEAT_CTRL_WRITE_PORT_COLOR 0x002A // Feature Control write port +#define INPUT_STATUS_1_COLOR 0x002A // Input Status 1 register read + // port in color mode +// eVb: 3.2 [END] +#define ATT_INITIALIZE_PORT_COLOR INPUT_STATUS_1_COLOR + // Register to read to reset + // Attribute Controller index/data + // toggle in color mode + +// +// Offsets in HardwareStateHeader->PortValue[] of save areas for non-indexed +// VGA registers. +// + +#define CRTC_ADDRESS_MONO_OFFSET 0x04 +#define FEAT_CTRL_WRITE_MONO_OFFSET 0x0A +#define ATT_ADDRESS_OFFSET 0x10 +#define MISC_OUTPUT_REG_WRITE_OFFSET 0x12 +#define VIDEO_SUBSYSTEM_ENABLE_OFFSET 0x13 +#define SEQ_ADDRESS_OFFSET 0x14 +#define DAC_PIXEL_MASK_OFFSET 0x16 +#define DAC_STATE_OFFSET 0x17 +#define DAC_ADDRESS_WRITE_OFFSET 0x18 +#define GRAPH_ADDRESS_OFFSET 0x1E +#define CRTC_ADDRESS_COLOR_OFFSET 0x24 +#define FEAT_CTRL_WRITE_COLOR_OFFSET 0x2A + + // toggle in color mode +// +// VGA indexed register indexes. +// + +// CL-GD542x specific registers: +// +#define IND_CL_EXTS_ENB 0x06 // index in Sequencer to enable exts +#define IND_NORD_SCRATCH_PAD 0x09 // index in Seq of Nordic scratch pad +#define IND_CL_SCRATCH_PAD 0x0A // index in Seq of 542x scratch pad +#define IND_ALP_SCRATCH_PAD 0x15 // index in Seq of Alpine scratch pad +#define IND_CL_REV_REG 0x25 // index in CRTC of ID Register +#define IND_CL_ID_REG 0x27 // index in CRTC of ID Register +// +#define IND_CURSOR_START 0x0A // index in CRTC of the Cursor Start +#define IND_CURSOR_END 0x0B // and End registers +#define IND_CURSOR_HIGH_LOC 0x0E // index in CRTC of the Cursor Location +#define IND_CURSOR_LOW_LOC 0x0F // High and Low Registers +#define IND_VSYNC_END 0x11 // index in CRTC of the Vertical Sync + // End register, which has the bit + // that protects/unprotects CRTC + // index registers 0-7 +#define IND_CR2C 0x2C // Nordic LCD Interface Register +#define IND_CR2D 0x2D // Nordic LCD Display Control +#define IND_SET_RESET_ENABLE 0x01 // index of Set/Reset Enable reg in GC +#define IND_DATA_ROTATE 0x03 // index of Data Rotate reg in GC +#define IND_READ_MAP 0x04 // index of Read Map reg in Graph Ctlr +#define IND_GRAPH_MODE 0x05 // index of Mode reg in Graph Ctlr +#define IND_GRAPH_MISC 0x06 // index of Misc reg in Graph Ctlr +#define IND_BIT_MASK 0x08 // index of Bit Mask reg in Graph Ctlr +#define IND_SYNC_RESET 0x00 // index of Sync Reset reg in Seq +#define IND_MAP_MASK 0x02 // index of Map Mask in Sequencer +#define IND_MEMORY_MODE 0x04 // index of Memory Mode reg in Seq +#define IND_CRTC_PROTECT 0x11 // index of reg containing regs 0-7 in + // CRTC +#define IND_CRTC_COMPAT 0x34 // index of CRTC Compatibility reg + // in CRTC +#define IND_PERF_TUNING 0x16 // index of performance tuning in Seq +#define START_SYNC_RESET_VALUE 0x01 // value for Sync Reset reg to start + // synchronous reset +#define END_SYNC_RESET_VALUE 0x03 // value for Sync Reset reg to end + // synchronous reset + +// +// Value to write to Extensions Control register values extensions. +// + +#define CL64xx_EXTENSION_ENABLE_INDEX 0x0A // GR0A to be exact! +#define CL64xx_EXTENSION_ENABLE_VALUE 0xEC +#define CL64xx_EXTENSION_DISABLE_VALUE 0xCE +#define CL64xx_TRISTATE_CONTROL_REG 0xA1 + +#define CL6340_ENABLE_READBACK_REGISTER 0xE0 +#define CL6340_ENABLE_READBACK_ALLSEL_VALUE 0xF0 +#define CL6340_ENABLE_READBACK_OFF_VALUE 0x00 +#define CL6340_IDENTIFICATION_REGISTER 0xE9 +// +// Values for Attribute Controller Index register to turn video off +// and on, by setting bit 5 to 0 (off) or 1 (on). +// + +#define VIDEO_DISABLE 0 +#define VIDEO_ENABLE 0x20 + +#define INDEX_ENABLE_AUTO_START 0x31 + +// Masks to keep only the significant bits of the Graphics Controller and +// Sequencer Address registers. Masking is necessary because some VGAs, such +// as S3-based ones, don't return unused bits set to 0, and some SVGAs use +// these bits if extensions are enabled. +// + +#define GRAPH_ADDR_MASK 0x0F +#define SEQ_ADDR_MASK 0x07 + +// +// Mask used to toggle Chain4 bit in the Sequencer's Memory Mode register. +// + +#define CHAIN4_MASK 0x08 + +// +// Value written to the Read Map register when identifying the existence of +// a VGA in VgaInitialize. This value must be different from the final test +// value written to the Bit Mask in that routine. +// + +#define READ_MAP_TEST_SETTING 0x03 + +// +// Default text mode setting for various registers, used to restore their +// states if VGA detection fails after they've been modified. +// + +#define MEMORY_MODE_TEXT_DEFAULT 0x02 +#define BIT_MASK_DEFAULT 0xFF +#define READ_MAP_DEFAULT 0x00 + + +// +// Palette-related info. +// + +// +// Highest valid DAC color register index. +// + +#define VIDEO_MAX_COLOR_REGISTER 0xFF + +// +// Highest valid palette register index +// + +#define VIDEO_MAX_PALETTE_REGISTER 0x0F + +// +// Driver Specific Attribute Flags +// + +#define CAPS_NO_HOST_XFER 0x00000002 // Do not use host xfers to + // the blt engine. +#define CAPS_SW_POINTER 0x00000004 // Use software pointer. +#define CAPS_TRUE_COLOR 0x00000008 // Set upper color registers. +#define CAPS_MM_IO 0x00000010 // Use memory mapped IO. +#define CAPS_BLT_SUPPORT 0x00000020 // BLTs are supported +#define CAPS_IS_542x 0x00000040 // This is a 542x +#define CAPS_IS_5436 0x00000080 // This is a 5436 +#define CAPS_CURSOR_VERT_EXP 0x00000100 // Flag set if 8x6 panel, + // but 6x4 resolution + +// +// Structure used to describe each video mode in ModesVGA[]. +// + +typedef struct { + USHORT fbType; // color or monochrome, text or graphics, via + // VIDEO_MODE_COLOR and VIDEO_MODE_GRAPHICS + USHORT numPlanes; // # of video memory planes + USHORT bitsPerPlane; // # of bits of color in each plane + SHORT col; // # of text columns across screen with default font + SHORT row; // # of text rows down screen with default font + USHORT hres; // # of pixels across screen + USHORT vres; // # of scan lines down screen +// eVb: 3.2 [VGA] - Store frequency next to resolution data + ULONG Frequency; // Vertical Frequency +// eVb: 3.2 [END] + USHORT wbytes; // # of bytes from start of one scan line to start of next + ULONG sbytes; // total size of addressable display memory in bytes +// eVb: 3.3 [VBE] - Add VBE mode and bank flag + ULONG NoBankSwitch; + ULONG Mode; +// eVb: 3.3 [VBE] + PUSHORT CmdStream; // pointer to array of register-setting commands to + // set up mode +// eVb: 3.4 [VBE] - Add fields to track linear addresses/sizes and flags + ULONG PhysBase; + ULONG FrameBufferBase; + ULONG FrameBufferSize; + ULONG PhysSize; + ULONG LogicalWidth; + ULONG NonVgaMode; + ULONG Granularity; +// eVb: 3.4 [END] +} VIDEOMODE, *PVIDEOMODE; + +// +// Mode into which to put the VGA before starting a VDM, so it's a plain +// vanilla VGA. (This is the mode's index in ModesVGA[], currently standard +// 80x25 text mode.) +// + +#define DEFAULT_MODE 0 + + +// +// Info used by the Validator functions and save/restore code. +// Structure used to trap register accesses that must be done atomically. +// + +#define VGA_MAX_VALIDATOR_DATA 100 + +#define VGA_VALIDATOR_UCHAR_ACCESS 1 +#define VGA_VALIDATOR_USHORT_ACCESS 2 +#define VGA_VALIDATOR_ULONG_ACCESS 3 + +typedef struct _VGA_VALIDATOR_DATA { + ULONG Port; + UCHAR AccessType; + ULONG Data; +} VGA_VALIDATOR_DATA, *PVGA_VALIDATOR_DATA; + +// +// Number of bytes to save in each plane. +// + +#define VGA_PLANE_SIZE 0x10000 + +// +// Number of each type of indexed register in a standard VGA, used by +// validator and state save/restore functions. +// +// Note: VDMs currently only support basic VGAs only. +// + +#define VGA_NUM_SEQUENCER_PORTS 5 +#define VGA_NUM_CRTC_PORTS 25 +#define VGA_NUM_GRAPH_CONT_PORTS 9 +#define VGA_NUM_ATTRIB_CONT_PORTS 21 +#define VGA_NUM_DAC_ENTRIES 256 + +#define EXT_NUM_GRAPH_CONT_PORTS 0 +#define EXT_NUM_SEQUENCER_PORTS 0 +#define EXT_NUM_CRTC_PORTS 0 +#define EXT_NUM_ATTRIB_CONT_PORTS 0 +#define EXT_NUM_DAC_ENTRIES 0 + +// +// These constants determine the offsets within the +// VIDEO_HARDWARE_STATE_HEADER structure that are used to save and +// restore the VGA's state. +// + +#define VGA_HARDWARE_STATE_SIZE sizeof(VIDEO_HARDWARE_STATE_HEADER) + +#define VGA_BASIC_SEQUENCER_OFFSET (VGA_HARDWARE_STATE_SIZE + 0) +#define VGA_BASIC_CRTC_OFFSET (VGA_BASIC_SEQUENCER_OFFSET + \ + VGA_NUM_SEQUENCER_PORTS) +#define VGA_BASIC_GRAPH_CONT_OFFSET (VGA_BASIC_CRTC_OFFSET + \ + VGA_NUM_CRTC_PORTS) +#define VGA_BASIC_ATTRIB_CONT_OFFSET (VGA_BASIC_GRAPH_CONT_OFFSET + \ + VGA_NUM_GRAPH_CONT_PORTS) +#define VGA_BASIC_DAC_OFFSET (VGA_BASIC_ATTRIB_CONT_OFFSET + \ + VGA_NUM_ATTRIB_CONT_PORTS) +#define VGA_BASIC_LATCHES_OFFSET (VGA_BASIC_DAC_OFFSET + \ + (3 * VGA_NUM_DAC_ENTRIES)) + +#define VGA_EXT_SEQUENCER_OFFSET (VGA_BASIC_LATCHES_OFFSET + 4) +#define VGA_EXT_CRTC_OFFSET (VGA_EXT_SEQUENCER_OFFSET + \ + EXT_NUM_SEQUENCER_PORTS) +#define VGA_EXT_GRAPH_CONT_OFFSET (VGA_EXT_CRTC_OFFSET + \ + EXT_NUM_CRTC_PORTS) +#define VGA_EXT_ATTRIB_CONT_OFFSET (VGA_EXT_GRAPH_CONT_OFFSET +\ + EXT_NUM_GRAPH_CONT_PORTS) +#define VGA_EXT_DAC_OFFSET (VGA_EXT_ATTRIB_CONT_OFFSET + \ + EXT_NUM_ATTRIB_CONT_PORTS) + +#define VGA_VALIDATOR_OFFSET (VGA_EXT_DAC_OFFSET + 4 * EXT_NUM_DAC_ENTRIES) + +#define VGA_VALIDATOR_AREA_SIZE sizeof (ULONG) + (VGA_MAX_VALIDATOR_DATA * \ + sizeof (VGA_VALIDATOR_DATA)) + \ + sizeof (ULONG) + \ + sizeof (ULONG) + \ + sizeof (PVIDEO_ACCESS_RANGE) + +#define VGA_MISC_DATA_AREA_OFFSET VGA_VALIDATOR_OFFSET + VGA_VALIDATOR_AREA_SIZE + +#define VGA_MISC_DATA_AREA_SIZE 0 + +#define VGA_PLANE_0_OFFSET VGA_MISC_DATA_AREA_OFFSET + VGA_MISC_DATA_AREA_SIZE + +#define VGA_PLANE_1_OFFSET VGA_PLANE_0_OFFSET + VGA_PLANE_SIZE +#define VGA_PLANE_2_OFFSET VGA_PLANE_1_OFFSET + VGA_PLANE_SIZE +#define VGA_PLANE_3_OFFSET VGA_PLANE_2_OFFSET + VGA_PLANE_SIZE + +// +// Space needed to store all state data. +// + +#define VGA_TOTAL_STATE_SIZE VGA_PLANE_3_OFFSET + VGA_PLANE_SIZE + + +// +// Device extension for the driver object. This data is only used +// locally, so this structure can be added to as needed. +// + +typedef struct _HW_DEVICE_EXTENSION { + + PHYSICAL_ADDRESS PhysicalVideoMemoryBase; // physical memory address and + PHYSICAL_ADDRESS PhysicalFrameOffset; // physical memory address and + ULONG PhysicalVideoMemoryLength; // length of display memory + ULONG PhysicalFrameLength; // length of display memory for + // the current mode. + + PUCHAR IOAddress; // base I/O address of VGA ports + PUCHAR VideoMemoryAddress; // base virtual memory address of VGA memory + ULONG ModeIndex; // index of current mode in ModesVGA[] + PVIDEOMODE CurrentMode; // pointer to VIDEOMODE structure for + // current mode + + VIDEO_CURSOR_POSITION CursorPosition; // current cursor position + + UCHAR CursorEnable; // whether cursor is enabled or not + UCHAR CursorTopScanLine; // Cursor Start register setting (top scan) + UCHAR CursorBottomScanLine; // Cursor End register setting (bottom scan) +// eVb: 3.5 [VBE] - Add fields for VBE support and XP+ INT10 interface + VIDEO_PORT_INT10_INTERFACE Int10Interface; + BOOLEAN VesaBiosOk; +// eVb: 3.5 [END] +} HW_DEVICE_EXTENSION, *PHW_DEVICE_EXTENSION; + + +// +// Function prototypes. +// + +// +// Entry points for the VGA validator. Used in VgaEmulatorAccessEntries[]. +// + + +// +// Vga init scripts for font loading +// + +extern USHORT EnableA000Data[]; +extern USHORT DisableA000Color[]; + +// +// Mode Information +// + +extern ULONG NumVideoModes; +extern VIDEOMODE ModesVGA[]; +extern PVIDEOMODE VgaModeList; + +// eVb: 3.5 [VGA] - Add ATI/Mach64 Access Range +#define NUM_VGA_ACCESS_RANGES 5 +// eVb: 3.5 [END] +extern VIDEO_ACCESS_RANGE VgaAccessRange[]; + +#include "vbe.h" diff --git a/reactos/drivers/video/miniport/vga_new/vga.rbuild b/reactos/drivers/video/miniport/vga_new/vga.rbuild new file mode 100644 index 00000000000..622440d4423 --- /dev/null +++ b/reactos/drivers/video/miniport/vga_new/vga.rbuild @@ -0,0 +1,18 @@ + + + + . + videoprt + libcntpr + modeset.c + vgadata.c + vga.c + vbemodes.c + vbe.c + vga.rc + vga.h + + -mrtd + -fno-builtin + + diff --git a/reactos/drivers/video/miniport/vga_new/vga.rc b/reactos/drivers/video/miniport/vga_new/vga.rc new file mode 100644 index 00000000000..4aac6fdcae3 --- /dev/null +++ b/reactos/drivers/video/miniport/vga_new/vga.rc @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "VGA Miniport Device Driver\0" +#define REACTOS_STR_INTERNAL_NAME "vga\0" +#define REACTOS_STR_ORIGINAL_FILENAME "vga.sys\0" +#include diff --git a/reactos/drivers/video/miniport/vga_new/vgadata.c b/reactos/drivers/video/miniport/vga_new/vgadata.c new file mode 100644 index 00000000000..6f9ea0f1c61 --- /dev/null +++ b/reactos/drivers/video/miniport/vga_new/vgadata.c @@ -0,0 +1,490 @@ +/* + * PROJECT: ReactOS VGA Miniport Driver + * LICENSE: Microsoft NT4 DDK Sample Code License + * FILE: boot/drivers/video/miniport/vga/vgadata.c + * PURPOSE: Handles switching to VGA Modes and holds VGA Built-in Modes + * PROGRAMMERS: Copyright (c) 1992 Microsoft Corporation + * ReactOS Portable Systems Group + */ + +#include "vga.h" + +// +// This structure describes to which ports access is required. +// + +VIDEO_ACCESS_RANGE VgaAccessRange[] = { +{ + {{VGA_BASE_IO_PORT, 0x00000000}}, // 64-bit linear base address + // of range + VGA_START_BREAK_PORT - VGA_BASE_IO_PORT + 1, // # of ports + 1, // range is in I/O space + 1, // range should be visible + 0 // range should be shareable +}, +{ + {{VGA_END_BREAK_PORT, 0x00000000}}, + VGA_MAX_IO_PORT - VGA_END_BREAK_PORT + 1, + 1, + 1, + 0 +}, + +// +// This next region also includes Memory mapped IO. In MMIO, the ports are +// repeated every 256 bytes from b8000 to bff00. +// + +{ + {{MEM_VGA, 0x00000000}}, + MEM_VGA_SIZE, + 0, + 1, + 0 +}, +// eVb: 4.1 [VGA] - Add ATI/Mach64 VGA registers +// +// ATI Registers +// + +{ + {{0x1CE, 0x00000000}}, + 2, + 1, + 1, + 0 +}, +{ + {{0x2E8, 0x00000000}}, + 8, + 1, + 1, + 0 +} +// eVb: 4.1 [END] +}; + +// +// 640x480 256-color 60Hz mode (BIOS mode 12) set command string for +// VGA. +// +// eVb: 4.2 [VGA] - Add VGA command streams instead of Cirrus +USHORT VGA_640x480[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 5, // count + 0x100, // start sync reset + 0x0101,0x0F02,0x0003,0x0604, // program up sequencer + + OB, // misc. register + MISC_OUTPUT_REG_WRITE_PORT, + 0xE3, + + OW, // text/graphics bit + GRAPH_ADDRESS_PORT, + 0x506, + + OW, // end sync reset + SEQ_ADDRESS_PORT, + IND_SYNC_RESET, + + OB, + SEQ_DATA_PORT, + END_SYNC_RESET_VALUE, + + OW, // unprotect crtc 0-7 + CRTC_ADDRESS_PORT_COLOR, + 0x511, + + METAOUT+INDXOUT, // program gdc registers + GRAPH_ADDRESS_PORT, + VGA_NUM_CRTC_PORTS,0, // count, startindex + 0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E,0x00,0x40,0x0,0x0,0x0,0x0,0x0,0x0, + 0xEA,0x8C,0xDF,0x28,0x0,0xE7,0x4,0xE3,0xFF, + + IB, // prepare atc for writing + INPUT_STATUS_1_COLOR, + + METAOUT+ATCOUT, // program atc registers + ATT_ADDRESS_PORT, + VGA_NUM_ATTRIB_CONT_PORTS,0, // count, startindex + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x17, 0x38, 0x39, 0x3A, 0x3B, 0x3C, + 0x3D, 0x3E, 0x3F, 0x3F, 0x01, 0x00, + 0x0F, 0x00, 0x00, + + METAOUT+INDXOUT, // program gdc registers + GRAPH_ADDRESS_PORT, + VGA_NUM_GRAPH_CONT_PORTS,0, // count, startindex + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x05, 0x0F, 0xFF, + + OB, + DAC_PIXEL_MASK_PORT, + 0xFF, + + IB, // prepare atc for writing + INPUT_STATUS_1_COLOR, + + OB, // turn video on. + ATT_ADDRESS_PORT, + VIDEO_ENABLE, + + EOD +}; + +// +// 720x400 color text mode (BIOS mode 3) set command string for +// VGA. +// + +USHORT VGA_TEXT_0[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 5, // count + 0x100, // start sync reset + 0x0101,0x0302,0x0003,0x0204, // program up sequencer + + OB, // misc. register + MISC_OUTPUT_REG_WRITE_PORT, + 0x67, + + OW, // text/graphics bit + GRAPH_ADDRESS_PORT, + 0x0e06, + + OW, // end sync reset + SEQ_ADDRESS_PORT, + IND_SYNC_RESET, + + OB, + SEQ_DATA_PORT, + END_SYNC_RESET_VALUE, + + OW, // unprotect crtc 0-7 + CRTC_ADDRESS_PORT_COLOR, + 0xE11, + + METAOUT+INDXOUT, // program gdc registers + GRAPH_ADDRESS_PORT, + VGA_NUM_CRTC_PORTS,0, // count, startindex + 0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,0x00,0x4F,0xD,0xE,0x0,0x0,0x0,0x0, + 0x9c,0x8E,0x8F,0x28,0x1F,0x96,0xB9,0xA3,0xFF, + + IB, // prepare atc for writing + INPUT_STATUS_1_COLOR, + + METAOUT+ATCOUT, // program atc registers + ATT_ADDRESS_PORT, + VGA_NUM_ATTRIB_CONT_PORTS,0, // count, startindex + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x17, 0x38, 0x39, 0x3A, 0x3B, 0x3C, + 0x3D, 0x3E, 0x3F, 0x3F, 0x04, 0x00, + 0x0F, 0x08, 0x00, + + METAOUT+INDXOUT, // program gdc registers + GRAPH_ADDRESS_PORT, + VGA_NUM_GRAPH_CONT_PORTS,0, // count, startindex + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x0E, 0x00, 0xFF, + + OB, + DAC_PIXEL_MASK_PORT, + 0xFF, + + IB, // prepare atc for writing + INPUT_STATUS_1_COLOR, + + OB, // turn video on. + ATT_ADDRESS_PORT, + VIDEO_ENABLE, + + EOD +}; + +// +// 640x400 color text mode (BIOS mode 3) set command string for +// VGA. +// + +USHORT VGA_TEXT_1[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 5, // count + 0x100, // start sync reset + 0x0101,0x0302,0x0003,0x0204, // program up sequencer + + OB, // misc. register + MISC_OUTPUT_REG_WRITE_PORT, + 0xA3, + + OW, // text/graphics bit + GRAPH_ADDRESS_PORT, + 0x0e06, + + OW, // end sync reset + SEQ_ADDRESS_PORT, + IND_SYNC_RESET, + + OB, + SEQ_DATA_PORT, + END_SYNC_RESET_VALUE, + + OW, // unprotect crtc 0-7 + CRTC_ADDRESS_PORT_COLOR, + 0x511, + + METAOUT+INDXOUT, // program gdc registers + GRAPH_ADDRESS_PORT, + VGA_NUM_CRTC_PORTS,0, // count, startindex + 0x5F,0x4F,0x50,0x82,0x55,0x81,0xBF,0x1F,0x00,0x4D,0xB,0xC,0x0,0x0,0x0,0x0, + 0x83,0x85,0x5D,0x28,0x1F,0x63,0xBA,0xA3,0xFF, + + IB, // prepare atc for writing + INPUT_STATUS_1_COLOR, + + METAOUT+ATCOUT, // program atc registers + ATT_ADDRESS_PORT, + VGA_NUM_ATTRIB_CONT_PORTS,0, // count, startindex + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x17, 0x38, 0x39, 0x3A, 0x3B, 0x3C, + 0x3D, 0x3E, 0x3F, 0x3F, 0x04, 0x00, + 0x0F, 0x00, 0x00, + + METAOUT+INDXOUT, // program gdc registers + GRAPH_ADDRESS_PORT, + VGA_NUM_GRAPH_CONT_PORTS,0, // count, startindex + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x0E, 0x00, 0xFF, + + OB, + DAC_PIXEL_MASK_PORT, + 0xFF, + + IB, // prepare atc for writing + INPUT_STATUS_1_COLOR, + + OB, // turn video on. + ATT_ADDRESS_PORT, + VIDEO_ENABLE, + + EOD +}; +// eVb: 4.2 [END] +// +// Video mode table - contains information and commands for initializing each +// mode. These entries must correspond with those in VIDEO_MODE_VGA. The first +// entry is commented; the rest follow the same format, but are not so +// heavily commented. +// +// eVb: 4.3 [VGA] - Add VGA, ModeX and SVGA mode instead of Cirrus Modes +VIDEOMODE ModesVGA[] = +{ + // Color text mode 3, 720x400, 9x16 char cell (VGA). + // + { + VIDEO_MODE_BANKED | VIDEO_MODE_COLOR, // flags that this mode is a color mode, but not graphics + 4, // four planes + 1, // one bit of colour per plane + 80, 25, // 80x25 text resolution + 720, 400, // 720x400 pixels on screen + 1, // only support one frequency, non-interlaced + 160, 0x10000, // 160 bytes per scan line, 64K of CPU-addressable bitmap + FALSE, + 0x3, VGA_TEXT_0, // Mode 3, I/O initialization stream + 0xA0000, // Physical address at 0xA0000 + 0x18000, 0x8000, + 0x20000, // 2 banks of 64K, 128KB total memory + 720, // 720 pixels per scan line + FALSE, + 0 + }, + + // + // Color text mode 3, 640x350, 8x14 char cell (EGA). + // + { + VIDEO_MODE_BANKED | VIDEO_MODE_COLOR, + 4, 1, + 80, 25, + 640, 350, + 1, + 160, 0x10000, + FALSE, + 0x3, VGA_TEXT_1, + 0xA0000, + 0x18000, 0x8000, + 0x20000, + 640, + FALSE, + 0 + }, + + // + // + // Standard VGA Color graphics mode 0x12, 640x480 16 colors. + // + { + VIDEO_MODE_BANKED | VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS, + 4, 1, + 80, 30, + 640, 480, + 1, + 80, 0x10000, + FALSE, + 0x12, VGA_640x480, + 0xA0000, + 0, 0x20000, + 0x20000, + 640, + FALSE, + 0 + }, + + { + VIDEO_MODE_BANKED | VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS, + 8, 1, + 0, 0, + 320, 200, + 70, + 80, 0x10000, + FALSE, + 0x3, NULL, + 0xA0000, + 0, 0x20000, + 0x20000, + 320, + FALSE, + 0 + }, + + { + VIDEO_MODE_BANKED | VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS, + 8, 1, + 0, 0, + 320, 240, + 60, + 80, 0x10000, + FALSE, + 0x3, NULL, + 0xA0000, + 0, 0x20000, + 0x20000, + 320, + FALSE, + 0 + }, + + { + VIDEO_MODE_BANKED | VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS, + 8, 1, + 0, 0, + 320, 400, + 70, + 80, 0x10000, + FALSE, + 0x3, NULL, + 0xA0000, + 0, 0x20000, + 0x20000, + 320, + FALSE, + 0 + }, + + { + VIDEO_MODE_BANKED | VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS, + 8, 1, + 0, 0, + 320, 480, + 60, + 80, 0x10000, + FALSE, + 0x3, NULL, + 0xA0000, + 0, 0x20000, + 0x20000, + 320, + FALSE, + 0 + }, + + // + // 800x600 16 colors. + // + { + VIDEO_MODE_BANKED | VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS, + 4, 1, + 100, 37, + 800, 600, + 1, + 100, 0x10000, + FALSE, + (0x102 << 16) | VBE_SET_VBE_MODE, NULL, + 0xA0000, + 0, 0x20000, + 0x20000, + 800, + FALSE, + 0 + }, +}; + +ULONG NumVideoModes = sizeof(ModesVGA) / sizeof(VIDEOMODE); +PVIDEOMODE VgaModeList; +// eVb: 4.3 [END] + +// +// +// Data used to set the Graphics and Sequence Controllers to put the +// VGA into a planar state at A0000 for 64K, with plane 2 enabled for +// reads and writes, so that a font can be loaded, and to disable that mode. +// + +// Settings to enable planar mode with plane 2 enabled. +// + +USHORT EnableA000Data[] = { + OWM, + SEQ_ADDRESS_PORT, + 1, + 0x0100, + + OWM, + GRAPH_ADDRESS_PORT, + 3, + 0x0204, // Read Map = plane 2 + 0x0005, // Graphics Mode = read mode 0, write mode 0 + 0x0406, // Graphics Miscellaneous register = A0000 for 64K, not odd/even, + // graphics mode + OWM, + SEQ_ADDRESS_PORT, + 3, + 0x0402, // Map Mask = write to plane 2 only + 0x0404, // Memory Mode = not odd/even, not full memory, graphics mode + 0x0300, // end sync reset + EOD +}; + +// +// Settings to disable the font-loading planar mode. +// + +USHORT DisableA000Color[] = { + OWM, + SEQ_ADDRESS_PORT, + 1, + 0x0100, + + OWM, + GRAPH_ADDRESS_PORT, + 3, + 0x0004, 0x1005, 0x0E06, + + OWM, + SEQ_ADDRESS_PORT, + 3, + 0x0302, 0x0204, 0x0300, // end sync reset + EOD + +};