You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2320 lines
83 KiB
2320 lines
83 KiB
/************************************************************************/
|
|
/* */
|
|
/* INIT_CX.C */
|
|
/* */
|
|
/* Nov 15 1993 (c) 1993, ATI Technologies Incorporated. */
|
|
/************************************************************************/
|
|
|
|
/********************** PolyTron RCS Utilities
|
|
|
|
$Revision: 1.42 $
|
|
$Date: 15 May 1996 16:34:38 $
|
|
$Author: RWolff $
|
|
$Log: S:/source/wnt/ms11/miniport/archive/init_cx.c_v $
|
|
*
|
|
* Rev 1.42 15 May 1996 16:34:38 RWolff
|
|
* Now reports failure of mode set, waits for idle after setting
|
|
* accelerator mode.
|
|
*
|
|
* Rev 1.41 01 May 1996 14:09:20 RWolff
|
|
* Calls new routine DenseOnAlpha() to determine dense space support rather
|
|
* than assuming all PCI cards support dense space.
|
|
*
|
|
* Rev 1.40 17 Apr 1996 13:09:04 RWolff
|
|
* Backed out Alpha LFB mapping as dense.
|
|
*
|
|
* Rev 1.39 11 Apr 1996 15:13:20 RWolff
|
|
* Now maps framebuffer as dense on DEC Alpha with PCI graphics card.
|
|
*
|
|
* Rev 1.38 20 Mar 1996 13:42:32 RWolff
|
|
* Removed debug print statements from RestoreMemSize_cx(), which must
|
|
* be nonpageable since it is called from ATIMPResetHw().
|
|
*
|
|
* Rev 1.37 01 Mar 1996 12:11:50 RWolff
|
|
* VGA Graphics Index and Graphics Data are now handled as separate
|
|
* registers rather than as offsets into the block of VGA registers.
|
|
*
|
|
* Rev 1.36 02 Feb 1996 17:16:40 RWolff
|
|
* Now uses VideoPortInt10() rather than our no-BIOS code to set "canned"
|
|
* modes on VGA-disabled cards.
|
|
*
|
|
* Rev 1.35 29 Jan 1996 16:55:02 RWolff
|
|
* Now uses VideoPortInt10() rather than no-BIOS code on PPC.
|
|
*
|
|
* Rev 1.34 23 Jan 1996 11:46:22 RWolff
|
|
* Added debug print statements.
|
|
*
|
|
* Rev 1.33 22 Dec 1995 14:53:30 RWolff
|
|
* Added support for Mach 64 GT internal DAC.
|
|
*
|
|
* Rev 1.32 23 Nov 1995 11:27:46 RWolff
|
|
* Fixes needed for initial run of VT chips (check if they're still needed
|
|
* on the final version), added support for multiple block-relocatable
|
|
* Mach 64 cards.
|
|
*
|
|
* Rev 1.31 28 Jul 1995 14:40:58 RWolff
|
|
* Added support for the Mach 64 VT (CT equivalent with video overlay).
|
|
*
|
|
* Rev 1.30 23 Jun 1995 16:01:46 RWOLFF
|
|
* In 8BPP and lower modes, SetPalette_cx() now uses the VGA palette
|
|
* registers rather than the accelerator palette registers. This is
|
|
* done so that a video capture card attached to the feature connector
|
|
* will know what colours the palette is set to.
|
|
*
|
|
* Rev 1.29 02 Jun 1995 14:26:48 RWOLFF
|
|
* Added debug print statements.
|
|
*
|
|
* Rev 1.28 31 Mar 1995 11:57:12 RWOLFF
|
|
* Changed from all-or-nothing debug print statements to thresholds
|
|
* depending on importance of the message.
|
|
*
|
|
* Rev 1.27 08 Mar 1995 11:33:54 ASHANMUG
|
|
* Fixed a bug if the banked aperture was enabled, the memory mapped register we
|
|
* getting moved if the memory sized was changed to support 4bpp
|
|
*
|
|
* Rev 1.26 27 Feb 1995 17:48:08 RWOLFF
|
|
* Now always reports 1M when mapping video memory for 4BPP, since we
|
|
* force the card to 1M, QueryPublicAccessRanges_cx() now returns
|
|
* the virtual address of the I/O register base rather than the
|
|
* beginning of I/O space.
|
|
*
|
|
* Rev 1.25 20 Feb 1995 18:01:18 RWOLFF
|
|
* Made test and workaround for screen tearing on 2M boundary DAC-independant,
|
|
* 1600x1200 16BPP added to modes that have this tearing.
|
|
*
|
|
* Rev 1.24 14 Feb 1995 15:45:36 RWOLFF
|
|
* Changed conditional compile that uses or fakes failure of
|
|
* VideoPortMapBankedMemory() to look for IOCTL_VIDEO_SHARE_VIDEO_MEMORY
|
|
* instead of the routine itself. Looking for the routine always failed,
|
|
* and since the routine is supplied in order to allow DCI to be used
|
|
* on systems without a linear framebuffer, it should be available on
|
|
* any DDK version that supports the IOCTL. If it isn't, a compile-time
|
|
* error will be generated (unresolved external reference).
|
|
*
|
|
* Rev 1.23 09 Feb 1995 14:57:36 RWOLFF
|
|
* Fix for GX-E IBM DAC screen tearing in 800x600 8BPP.
|
|
*
|
|
* Rev 1.22 07 Feb 1995 18:24:22 RWOLFF
|
|
* Fixed screen trash on return from 4BPP test on CT and 4M Xpression.
|
|
* These were the first cards I was able to obtain that switched aperture
|
|
* size between modes (GX uses 8M aperture only on 4M cards, which used
|
|
* to be made only with DAC that didn't support 4BPP, but CT uses 8M for
|
|
* 2M card and 4M when cut back to 1M).
|
|
*
|
|
* Rev 1.21 03 Feb 1995 15:15:12 RWOLFF
|
|
* Added support for DCI, fixed CT internal DAC 4BPP cursor problem,
|
|
* RestoreMemSize_cx() is no longer pageable, since it is called
|
|
* on a bugcheck.
|
|
*
|
|
* Rev 1.20 30 Jan 1995 11:56:24 RWOLFF
|
|
* Now supports CT internal DAC.
|
|
*
|
|
* Rev 1.19 11 Jan 1995 14:04:04 RWOLFF
|
|
* Added routine RestoreMemSize_cx() which sets the memory size register
|
|
* back to the value read by the BIOS query. This is used when returning
|
|
* from a test of 4BPP (code had been inlined there) or when shutting down
|
|
* from 4BPP (new) because 4BPP modes require that the memory size be
|
|
* set to 1M. On some platforms, the x86 emulation in the firmware does not
|
|
* reset the memory size to the true value, so a warm reboot from 4BPP left
|
|
* the card thinking that it only had 1M.
|
|
*
|
|
* Rev 1.18 23 Dec 1994 10:47:48 ASHANMUG
|
|
* ALPHA/Chrontel-DAC
|
|
*
|
|
* Rev 1.17 18 Nov 1994 11:40:00 RWOLFF
|
|
* Added support for Mach 64 without BIOS.
|
|
*
|
|
* Rev 1.16 14 Sep 1994 15:24:38 RWOLFF
|
|
* Now uses "most desirable supported colour ordering" field in query
|
|
* structure rather than DAC type to determine which colour ordering
|
|
* to use for 24 and 32BPP.
|
|
*
|
|
* Rev 1.15 31 Aug 1994 16:24:02 RWOLFF
|
|
* Added support for TVP3026 DAC, 1152x864, and BGRx colour ordering
|
|
* (used by TVP DAC), uses VideoPort[Read|Write]Register[Uchar|Ushort|Ulong]()
|
|
* instead of direct assignments when accessing structures stored in
|
|
* VGA text screen off-screen memory.
|
|
*
|
|
* Rev 1.14 19 Aug 1994 17:15:32 RWOLFF
|
|
* Added support for non-standard pixel clock generators.
|
|
*
|
|
* Rev 1.13 09 Aug 1994 11:52:30 RWOLFF
|
|
* Shifting of colours when setting up palette is now done in
|
|
* display driver.
|
|
*
|
|
* Rev 1.12 27 Jun 1994 16:27:38 RWOLFF
|
|
* Now reports all hardware default mode tables as noninterlaced to
|
|
* avoid confusing the display applet.
|
|
*
|
|
* Rev 1.11 15 Jun 1994 11:06:24 RWOLFF
|
|
* Now sets the cursor colour every time we enter graphics mode. This is a
|
|
* fix for the black cursor after testing 4BPP from 16BPP.
|
|
*
|
|
* Rev 1.10 12 May 1994 11:22:40 RWOLFF
|
|
* Added routine SetModeFromTable_cx() to allow the use of refresh rates not
|
|
* configured when card was installed, now reports refresh rate from mode table
|
|
* instead of only "use hardware default".
|
|
*
|
|
* Rev 1.9 04 May 1994 10:59:12 RWOLFF
|
|
* Now forces memory size to 1M on all 4BPP-capable DACs when using 4BPP,
|
|
* sets memory size back to true value when not using 4BPP.
|
|
*
|
|
* Rev 1.8 27 Apr 1994 13:59:38 RWOLFF
|
|
* Added support for paged aperture, fixed cursor colour for 4BPP.
|
|
*
|
|
* Rev 1.7 26 Apr 1994 12:38:32 RWOLFF
|
|
* Now uses a frame length of 128k when LFB is disabled.
|
|
*
|
|
* Rev 1.6 31 Mar 1994 15:02:42 RWOLFF
|
|
* Added SetPowerManagement_cx() function to implement DPMS handling,
|
|
* added 4BPP support.
|
|
*
|
|
* Rev 1.5 14 Mar 1994 16:30:58 RWOLFF
|
|
* XMillimeter field of mode information structure now set properly, added
|
|
* fix for 2M boundary tearing.
|
|
*
|
|
* Rev 1.4 03 Mar 1994 12:37:32 ASHANMUG
|
|
* Set palettized mode
|
|
*
|
|
* Rev 1.2 03 Feb 1994 16:44:26 RWOLFF
|
|
* Fixed "ceiling check" on right scissor register (documentation had
|
|
* maximum value wrong). Moved initialization of hardware cursor
|
|
* colours to after the switch into graphics mode. Colour initialization
|
|
* is ignored if it is done before the mode switch (undocumented), but
|
|
* this wasn't noticed earlier because most cards power up with the
|
|
* colours already set to the values we want.
|
|
*
|
|
* Rev 1.1 31 Jan 1994 16:24:38 RWOLFF
|
|
* Fixed setting of cursor colours on cards with 68860 DAC, now fills
|
|
* in Frequency and VideoMemoryBitmap[Width|Height] fields of mode
|
|
* information structure. Sets Number[Red|Green|Blue]Bits fields for
|
|
* palette modes to 6 (assumes VGA-compatible DAC) instead of 0 to allow
|
|
* Windows NT to set the palette colours to the best match for the
|
|
* colours to be displayed.
|
|
*
|
|
* Rev 1.0 31 Jan 1994 11:10:18 RWOLFF
|
|
* Initial revision.
|
|
*
|
|
* Rev 1.3 24 Jan 1994 18:03:52 RWOLFF
|
|
* Changes to accomodate 94/01/19 BIOS document.
|
|
*
|
|
* Rev 1.2 14 Jan 1994 15:20:48 RWOLFF
|
|
* Fixes required by BIOS version 0.13, added 1600x1200 support.
|
|
*
|
|
* Rev 1.1 15 Dec 1993 15:26:30 RWOLFF
|
|
* Clear screen only the first time we set the desired video mode.
|
|
*
|
|
* Rev 1.0 30 Nov 1993 18:32:22 RWOLFF
|
|
* Initial revision.
|
|
|
|
End of PolyTron RCS section *****************/
|
|
|
|
#ifdef DOC
|
|
INIT_CX.C - Highest-level card-dependent routines for miniport.
|
|
|
|
DESCRIPTION
|
|
This file contains initialization and packet handling routines
|
|
for Mach 64-compatible ATI accelerators. Routines in this module
|
|
are called only by routines in ATIMP.C, which is card-independent.
|
|
|
|
OTHER FILES
|
|
|
|
#endif
|
|
|
|
#include "dderror.h"
|
|
|
|
#include "miniport.h"
|
|
#include "ntddvdeo.h"
|
|
#include "video.h"
|
|
|
|
#include "stdtyp.h"
|
|
#include "amachcx.h"
|
|
#include "amach1.h"
|
|
#include "atimp.h"
|
|
#include "atint.h"
|
|
|
|
#define INCLUDE_INIT_CX
|
|
#include "init_cx.h"
|
|
#include "query_cx.h"
|
|
#include "services.h"
|
|
#include "setup_cx.h"
|
|
|
|
|
|
|
|
/*
|
|
* Prototypes for static functions.
|
|
*/
|
|
static void QuerySingleMode_cx(PVIDEO_MODE_INFORMATION ModeInformation, struct query_structure *QueryPtr, ULONG ModeIndex);
|
|
static VP_STATUS SetModeFromTable_cx(struct st_mode_table *ModeTable, VIDEO_X86_BIOS_ARGUMENTS Registers);
|
|
|
|
|
|
/*
|
|
* Allow miniport to be swapped out when not needed.
|
|
*/
|
|
#if defined (ALLOC_PRAGMA)
|
|
#pragma alloc_text(PAGE_CX, Initialize_cx)
|
|
#pragma alloc_text(PAGE_CX, MapVideoMemory_cx)
|
|
#pragma alloc_text(PAGE_CX, QueryPublicAccessRanges_cx)
|
|
#pragma alloc_text(PAGE_CX, QueryCurrentMode_cx)
|
|
#pragma alloc_text(PAGE_CX, QueryAvailModes_cx)
|
|
#pragma alloc_text(PAGE_CX, QuerySingleMode_cx)
|
|
#pragma alloc_text(PAGE_CX, SetCurrentMode_cx)
|
|
#pragma alloc_text(PAGE_CX, SetPalette_cx)
|
|
#pragma alloc_text(PAGE_CX, IdentityMapPalette_cx)
|
|
#pragma alloc_text(PAGE_CX, ResetDevice_cx)
|
|
#pragma alloc_text(PAGE_CX, SetPowerManagement_cx)
|
|
#pragma alloc_text(PAGE_CX, GetPowerManagement_cx)
|
|
#pragma alloc_text(PAGE_CX, SetModeFromTable_cx)
|
|
/* RestoreMemSize_cx() can't be made pageable */
|
|
#pragma alloc_text(PAGE_CX, ShareVideoMemory_cx)
|
|
/* BankMap_cx() can't be made pageable */
|
|
#endif
|
|
|
|
/***************************************************************************
|
|
*
|
|
* void Initialize_cx(void);
|
|
*
|
|
* DESCRIPTION:
|
|
* This routine is the Mach 64-compatible hardware initialization routine
|
|
* for the miniport driver. It is called once an adapter has been found
|
|
* and all the required data structures for it have been created.
|
|
*
|
|
* GLOBALS CHANGED:
|
|
* none
|
|
*
|
|
* CALLED BY:
|
|
* ATIMPInitialize()
|
|
*
|
|
* AUTHOR:
|
|
* Robert Wolff
|
|
*
|
|
* CHANGE HISTORY:
|
|
*
|
|
* TEST HISTORY:
|
|
*
|
|
***************************************************************************/
|
|
|
|
void Initialize_cx(void)
|
|
{
|
|
DWORD Scratch; /* Temporary variable */
|
|
VIDEO_X86_BIOS_ARGUMENTS Registers; /* Used in VideoPortInt10() calls */
|
|
struct query_structure *Query; /* Information about the graphics card */
|
|
|
|
Query = (struct query_structure *) (phwDeviceExtension->CardInfo);
|
|
/*
|
|
* If the linear aperture is not configured, enable the VGA aperture.
|
|
*/
|
|
if (phwDeviceExtension->FrameLength == 0)
|
|
{
|
|
VideoDebugPrint((DEBUG_DETAIL, "Initialize_cx() switching to VGA aperture\n"));
|
|
VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
|
|
Registers.Eax = BIOS_APERTURE;
|
|
Registers.Ecx = BIOS_VGA_APERTURE;
|
|
VideoPortInt10(phwDeviceExtension, &Registers);
|
|
}
|
|
|
|
/*
|
|
* Set the screen to start at the beginning of accelerator memory.
|
|
*/
|
|
Scratch = INPD(CRTC_OFF_PITCH) & ~CRTC_OFF_PITCH_Offset;
|
|
OUTPD(CRTC_OFF_PITCH, Scratch);
|
|
|
|
/*
|
|
* Disable the hardware cursor and set it up with the bitmap
|
|
* starting at the top left corner of the 64x64 block.
|
|
*/
|
|
Scratch = INPD(GEN_TEST_CNTL) & ~GEN_TEST_CNTL_CursorEna;
|
|
OUTPD(GEN_TEST_CNTL, Scratch);
|
|
OUTPD(CUR_HORZ_VERT_OFF, 0x00000000);
|
|
|
|
/*
|
|
* TVP3026 DAC requires special handling to disable
|
|
* the cursor.
|
|
*/
|
|
if (Query->q_DAC_type == DAC_TVP3026)
|
|
{
|
|
/*
|
|
* Access the indirect cursor control register.
|
|
*/
|
|
OUTP(DAC_CNTL, (BYTE)(INP(DAC_CNTL) & 0xFC));
|
|
OUTP(DAC_REGS, 6);
|
|
/*
|
|
* Write the "cursor disabled" value to the
|
|
* indexed data register.
|
|
*/
|
|
OUTP(DAC_CNTL, (BYTE)((INP(DAC_CNTL) & 0xFC) | 2));
|
|
OUTP_HBLW(DAC_REGS, 0);
|
|
/*
|
|
* Go back to using direct registers.
|
|
*/
|
|
OUTP(DAC_CNTL, (BYTE)(INP(DAC_CNTL) & 0xFC));
|
|
}
|
|
|
|
VideoDebugPrint((DEBUG_NORMAL, "Initialize_cx() complete\n"));
|
|
|
|
return;
|
|
|
|
} /* Initialize_cx() */
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* VP_STATUS MapVideoMemory_cx(RequestPacket, QueryPtr);
|
|
*
|
|
* PVIDEO_REQUEST_PACKET RequestPacket; Request packet with input and output buffers
|
|
* struct query_structure *QueryPtr; Query information for the card
|
|
*
|
|
* DESCRIPTION:
|
|
* Map the card's video memory into system memory and store the mapped
|
|
* address and size in OutputBuffer.
|
|
*
|
|
* RETURN VALUE:
|
|
* NO_ERROR if successful
|
|
* error code if failed
|
|
*
|
|
* GLOBALS CHANGED:
|
|
* FrameLength and PhysicalFrameAddress fields of phwDeviceExtension
|
|
* if linear framebuffer is not present.
|
|
*
|
|
* CALLED BY:
|
|
* IOCTL_VIDEO_MAP_VIDEO_MEMORY packet of ATIMPStartIO()
|
|
*
|
|
* AUTHOR:
|
|
* Robert Wolff
|
|
*
|
|
* CHANGE HISTORY:
|
|
*
|
|
* TEST HISTORY:
|
|
*
|
|
***************************************************************************/
|
|
|
|
VP_STATUS MapVideoMemory_cx(PVIDEO_REQUEST_PACKET RequestPacket, struct query_structure *QueryPtr)
|
|
{
|
|
PVIDEO_MEMORY_INFORMATION memoryInformation;
|
|
ULONG inIoSpace; /* Scratch variable used by VideoPortMapMemory() */
|
|
VP_STATUS status; /* Error code obtained from O/S calls */
|
|
UCHAR Scratch; /* Temporary variable */
|
|
ULONG FrameBufferLengthSave;
|
|
|
|
|
|
memoryInformation = RequestPacket->OutputBuffer;
|
|
|
|
memoryInformation->VideoRamBase = ((PVIDEO_MEMORY)
|
|
(RequestPacket->InputBuffer))->RequestedVirtualAddress;
|
|
|
|
/*
|
|
* The VideoRamLength field contains the amount of video memory
|
|
* on the card. The FrameBufferLength field contains the
|
|
* size of the aperture in bytes
|
|
*
|
|
* Initially assume that the linear aperture is available.
|
|
*
|
|
* In 4BPP, we always force the card to think it has 1M of memory.
|
|
*/
|
|
if (QueryPtr->q_pix_depth == 4)
|
|
memoryInformation->VideoRamLength = ONE_MEG;
|
|
else
|
|
memoryInformation->VideoRamLength = phwDeviceExtension->VideoRamSize;
|
|
|
|
Scratch = QueryPtr->q_aperture_cfg & CONFIG_CNTL_LinApMask;
|
|
|
|
if (Scratch == CONFIG_CNTL_LinAp4M)
|
|
{
|
|
memoryInformation->FrameBufferLength = 4 * ONE_MEG;
|
|
}
|
|
else if (Scratch == CONFIG_CNTL_LinAp8M)
|
|
{
|
|
memoryInformation->FrameBufferLength = 8 * ONE_MEG;
|
|
}
|
|
|
|
/*
|
|
* If the linear aperture is not available, map in the VGA aperture
|
|
* instead. Since the Mach 64 needs an aperture in order to use
|
|
* the drawing registers, ATIMPFindAdapter() will have already
|
|
* reported that it couldn't find a usable card if both the linear
|
|
* and VGA apertures are disabled.
|
|
*/
|
|
else if (Scratch == CONFIG_CNTL_LinApDisab)
|
|
{
|
|
phwDeviceExtension->FrameLength = 0x20000;
|
|
phwDeviceExtension->PhysicalFrameAddress.LowPart = 0x0A0000;
|
|
memoryInformation->FrameBufferLength = phwDeviceExtension->FrameLength;
|
|
}
|
|
inIoSpace = 0;
|
|
#if defined(ALPHA)
|
|
/*
|
|
* Use dense space if we can, otherwise use sparse space.
|
|
*/
|
|
if (DenseOnAlpha(QueryPtr) == TRUE)
|
|
{
|
|
VideoDebugPrint((DEBUG_DETAIL, "Using dense space for LFB\n"));
|
|
inIoSpace = 4;
|
|
}
|
|
#endif
|
|
|
|
FrameBufferLengthSave = memoryInformation->FrameBufferLength;
|
|
|
|
status = VideoPortMapMemory(phwDeviceExtension,
|
|
phwDeviceExtension->PhysicalFrameAddress,
|
|
&(memoryInformation->FrameBufferLength),
|
|
&inIoSpace,
|
|
&(memoryInformation->VideoRamBase));
|
|
|
|
#if defined (ALPHA)
|
|
/*
|
|
* VideoPortMapMemory() returns invalid FrameBufferLength
|
|
* on the Alpha.
|
|
*/
|
|
memoryInformation->FrameBufferLength = FrameBufferLengthSave;
|
|
#endif
|
|
|
|
memoryInformation->FrameBufferBase = memoryInformation->VideoRamBase;
|
|
VideoDebugPrint((DEBUG_DETAIL, "Frame buffer mapped base = 0x%X\n", memoryInformation->VideoRamBase));
|
|
|
|
/*
|
|
* On some DAC/memory combinations, some modes which require more
|
|
* than 2M of memory (1152x764 24BPP, 1280x1024 24BPP, and
|
|
* 1600x1200 16BPP) will have screen tearing at the 2M boundary.
|
|
*
|
|
* As a workaround, the display driver must start the framebuffer
|
|
* at an offset which will put the 2M boundary at the start of a
|
|
* scanline.
|
|
*
|
|
* Other DAC/memory combinations are unaffected, but since this
|
|
* fix is nearly harmless (only ill effect is to make DCI unusable
|
|
* in these modes), we can catch all future combinations which
|
|
* suffer from this problem by assuming that all DAC/memory
|
|
* combinations are affected.
|
|
*/
|
|
if ((QueryPtr->q_pix_depth == 24) &&
|
|
(QueryPtr->q_desire_x == 1280))
|
|
(PUCHAR)memoryInformation->FrameBufferBase += (0x40 * 8);
|
|
else if ((QueryPtr->q_pix_depth == 24) &&
|
|
(QueryPtr->q_desire_x == 1152))
|
|
(PUCHAR)memoryInformation->FrameBufferBase += (0x160 * 8);
|
|
else if ((QueryPtr->q_pix_depth == 16) &&
|
|
(QueryPtr->q_desire_x == 1600))
|
|
(PUCHAR)memoryInformation->FrameBufferBase += (0x90 * 8);
|
|
|
|
return status;
|
|
|
|
} /* MapVideoMemory_cx() */
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* VP_STATUS QueryPublicAccessRanges_cx(RequestPacket);
|
|
*
|
|
* PVIDEO_REQUEST_PACKET RequestPacket; Request packet with input and output buffers
|
|
*
|
|
* DESCRIPTION:
|
|
* Map and return information on the video card's public access ranges.
|
|
*
|
|
* RETURN VALUE:
|
|
* NO_ERROR if successful
|
|
* error code if failed
|
|
*
|
|
* GLOBALS CHANGED:
|
|
* none
|
|
*
|
|
* CALLED BY:
|
|
* IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES packet of ATIMPStartIO()
|
|
*
|
|
* AUTHOR:
|
|
* Robert Wolff
|
|
*
|
|
* CHANGE HISTORY:
|
|
*
|
|
* TEST HISTORY:
|
|
*
|
|
***************************************************************************/
|
|
|
|
VP_STATUS QueryPublicAccessRanges_cx(PVIDEO_REQUEST_PACKET RequestPacket)
|
|
{
|
|
PVIDEO_PUBLIC_ACCESS_RANGES portAccess;
|
|
PHYSICAL_ADDRESS physicalPortBase;
|
|
ULONG physicalPortLength;
|
|
|
|
if ( RequestPacket->OutputBufferLength <
|
|
(RequestPacket->StatusBlock->Information =
|
|
sizeof(VIDEO_PUBLIC_ACCESS_RANGES)) )
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "QueryPublicAccessRanges_cx() - buffer too small to handle query\n"));
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
portAccess = RequestPacket->OutputBuffer;
|
|
|
|
portAccess->VirtualAddress = (PVOID) NULL; // Requested VA
|
|
portAccess->InIoSpace = 1; // In IO space
|
|
portAccess->MappedInIoSpace = portAccess->InIoSpace;
|
|
|
|
physicalPortBase.HighPart = 0x00000000;
|
|
physicalPortBase.LowPart = GetIOBase_cx();
|
|
// physicalPortLength = LINEDRAW+2 - physicalPortBase.LowPart;
|
|
/*
|
|
* If we are using packed (relocatable) I/O, all our I/O mapped
|
|
* registers are in a 1k block. If not, they are sparsely distributed
|
|
* in a 32k region.
|
|
*/
|
|
if (IsPackedIO_cx())
|
|
physicalPortLength = 0x400;
|
|
else
|
|
physicalPortLength = 0x8000;
|
|
|
|
// *SANITIZE* Should report MM registers instead
|
|
|
|
return VideoPortMapMemory(phwDeviceExtension,
|
|
physicalPortBase,
|
|
&physicalPortLength,
|
|
&(portAccess->MappedInIoSpace),
|
|
&(portAccess->VirtualAddress));
|
|
|
|
} /* QueryPublicAccessRanges_cx() */
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* VP_STATUS QueryCurrentMode_cx(RequestPacket, QueryPtr);
|
|
*
|
|
* PVIDEO_REQUEST_PACKET RequestPacket; Request packet with input and output buffers
|
|
* struct query_structure *QueryPtr; Query information for the card
|
|
*
|
|
* DESCRIPTION:
|
|
* Get screen information and colour masks for the current video mode.
|
|
*
|
|
* RETURN VALUE:
|
|
* NO_ERROR if successful
|
|
* error code if failed
|
|
*
|
|
* GLOBALS CHANGED:
|
|
* none
|
|
*
|
|
* CALLED BY:
|
|
* IOCTL_VIDEO_QUERY_CURRENT_MODE packet of ATIMPStartIO()
|
|
*
|
|
* AUTHOR:
|
|
* Robert Wolff
|
|
*
|
|
* CHANGE HISTORY:
|
|
*
|
|
* TEST HISTORY:
|
|
*
|
|
***************************************************************************/
|
|
|
|
VP_STATUS QueryCurrentMode_cx(PVIDEO_REQUEST_PACKET RequestPacket, struct query_structure *QueryPtr)
|
|
{
|
|
PVIDEO_MODE_INFORMATION ModeInformation;
|
|
|
|
/*
|
|
* If the output buffer is too small to hold the information we need
|
|
* to put in it, return with the appropriate error code.
|
|
*/
|
|
if (RequestPacket->OutputBufferLength <
|
|
(RequestPacket->StatusBlock->Information =
|
|
sizeof(VIDEO_MODE_INFORMATION)) )
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "QueryCurrentMode_cx() - buffer too small to handle query\n"));
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
/*
|
|
* Fill in the mode information structure.
|
|
*/
|
|
ModeInformation = RequestPacket->OutputBuffer;
|
|
|
|
QuerySingleMode_cx(ModeInformation, QueryPtr, phwDeviceExtension->ModeIndex);
|
|
|
|
return NO_ERROR;
|
|
|
|
} /* QueryCurrentMode_cx() */
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* VP_STATUS QueryAvailModes_cx(RequestPacket, QueryPtr);
|
|
*
|
|
* PVIDEO_REQUEST_PACKET RequestPacket; Request packet with input and output buffers
|
|
* struct query_structure *QueryPtr; Query information for the card
|
|
*
|
|
* DESCRIPTION:
|
|
* Get screen information and colour masks for all available video modes.
|
|
*
|
|
* RETURN VALUE:
|
|
* NO_ERROR if successful
|
|
* error code if failed
|
|
*
|
|
* GLOBALS CHANGED:
|
|
* none
|
|
*
|
|
* CALLED BY:
|
|
* IOCTL_VIDEO_QUERY_AVAIL_MODES packet of ATIMPStartIO()
|
|
*
|
|
* AUTHOR:
|
|
* Robert Wolff
|
|
*
|
|
* CHANGE HISTORY:
|
|
*
|
|
* TEST HISTORY:
|
|
*
|
|
***************************************************************************/
|
|
|
|
VP_STATUS QueryAvailModes_cx(PVIDEO_REQUEST_PACKET RequestPacket, struct query_structure *QueryPtr)
|
|
{
|
|
PVIDEO_MODE_INFORMATION ModeInformation;
|
|
ULONG CurrentMode;
|
|
|
|
/*
|
|
* If the output buffer is too small to hold the information we need
|
|
* to put in it, return with the appropriate error code.
|
|
*/
|
|
if (RequestPacket->OutputBufferLength <
|
|
(RequestPacket->StatusBlock->Information =
|
|
QueryPtr->q_number_modes * sizeof(VIDEO_MODE_INFORMATION)) )
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "QueryAvailModes_cx() - buffer too small to handle query\n"));
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
/*
|
|
* Fill in the mode information structure.
|
|
*/
|
|
ModeInformation = RequestPacket->OutputBuffer;
|
|
|
|
/*
|
|
* For each mode supported by the card, store the mode characteristics
|
|
* in the output buffer.
|
|
*/
|
|
for (CurrentMode = 0; CurrentMode < QueryPtr->q_number_modes; CurrentMode++, ModeInformation++)
|
|
QuerySingleMode_cx(ModeInformation, QueryPtr, CurrentMode);
|
|
|
|
return NO_ERROR;
|
|
|
|
} /* QueryCurrentMode_cx() */
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* static void QuerySingleMode_cx(ModeInformation, QueryPtr, ModeIndex);
|
|
*
|
|
* PVIDEO_MODE_INFORMATION ModeInformation; Table to be filled in
|
|
* struct query_structure *QueryPtr; Query information for the card
|
|
* ULONG ModeIndex; Index of mode table to use
|
|
*
|
|
* DESCRIPTION:
|
|
* Fill in a single Windows NT mode information table using data from
|
|
* one of our CRT parameter tables.
|
|
*
|
|
* GLOBALS CHANGED:
|
|
* none
|
|
*
|
|
* CALLED BY:
|
|
* QueryCurrentMode_cx() and QueryAvailModes_cx()
|
|
*
|
|
* AUTHOR:
|
|
* Robert Wolff
|
|
*
|
|
* CHANGE HISTORY:
|
|
*
|
|
* TEST HISTORY:
|
|
*
|
|
***************************************************************************/
|
|
|
|
static void QuerySingleMode_cx(PVIDEO_MODE_INFORMATION ModeInformation,
|
|
struct query_structure *QueryPtr,
|
|
ULONG ModeIndex)
|
|
{
|
|
struct st_mode_table *CrtTable; /* Pointer to current mode table */
|
|
CrtTable = (struct st_mode_table *)QueryPtr;
|
|
((struct query_structure *)CrtTable)++;
|
|
CrtTable += ModeIndex;
|
|
|
|
|
|
ModeInformation->Length = sizeof(VIDEO_MODE_INFORMATION);
|
|
ModeInformation->ModeIndex = ModeIndex;
|
|
|
|
ModeInformation->VisScreenWidth = CrtTable->m_x_size;
|
|
ModeInformation->VisScreenHeight = CrtTable->m_y_size;
|
|
|
|
// * Bytes per line = ((pixels/line) * (bits/pixel)) / (bits/byte))
|
|
ModeInformation->ScreenStride = (CrtTable->m_screen_pitch * CrtTable->m_pixel_depth) / 8;
|
|
|
|
ModeInformation->NumberOfPlanes = 1;
|
|
ModeInformation->BitsPerPlane = (USHORT) CrtTable->m_pixel_depth;
|
|
|
|
ModeInformation->Frequency = CrtTable->Refresh;
|
|
|
|
/*
|
|
* Driver can't measure the screen size,
|
|
* so take reasonable values (16" diagonal).
|
|
*/
|
|
ModeInformation->XMillimeter = 320;
|
|
ModeInformation->YMillimeter = 240;
|
|
|
|
switch(ModeInformation->BitsPerPlane)
|
|
{
|
|
case 4:
|
|
/*
|
|
* Assume 6 bit DAC, since all VGA-compatible DACs support
|
|
* 6 bit mode. Future expansion (extensive testing needed):
|
|
* check DAC definition to see if 8 bit mode is supported,
|
|
* and use 8 bit mode if available.
|
|
*/
|
|
ModeInformation->RedMask = 0x00000000;
|
|
ModeInformation->GreenMask = 0x00000000;
|
|
ModeInformation->BlueMask = 0x00000000;
|
|
ModeInformation->NumberRedBits = 6;
|
|
ModeInformation->NumberGreenBits = 6;
|
|
ModeInformation->NumberBlueBits = 6;
|
|
CrtTable->ColourDepthInfo = BIOS_DEPTH_4BPP;
|
|
break;
|
|
|
|
case 16:
|
|
/*
|
|
* Assume that all DACs capable of 16BPP support 565.
|
|
*/
|
|
ModeInformation->RedMask = 0x0000f800;
|
|
ModeInformation->GreenMask = 0x000007e0;
|
|
ModeInformation->BlueMask = 0x0000001f;
|
|
ModeInformation->NumberRedBits = 5;
|
|
ModeInformation->NumberGreenBits = 6;
|
|
ModeInformation->NumberBlueBits = 5;
|
|
CrtTable->ColourDepthInfo = BIOS_DEPTH_16BPP_565;
|
|
break;
|
|
|
|
case 24:
|
|
/*
|
|
* Windows NT uses RGB as the standard 24BPP mode,
|
|
* so use this ordering unless this card only
|
|
* supports BGR.
|
|
*/
|
|
if (QueryPtr->q_HiColourSupport & RGB24_RGB)
|
|
{
|
|
ModeInformation->RedMask = 0x00ff0000;
|
|
ModeInformation->GreenMask = 0x0000ff00;
|
|
ModeInformation->BlueMask = 0x000000ff;
|
|
}
|
|
else{
|
|
ModeInformation->RedMask = 0x000000ff;
|
|
ModeInformation->GreenMask = 0x0000ff00;
|
|
ModeInformation->BlueMask = 0x00ff0000;
|
|
}
|
|
CrtTable->ColourDepthInfo = BIOS_DEPTH_24BPP;
|
|
ModeInformation->NumberRedBits = 8;
|
|
ModeInformation->NumberGreenBits = 8;
|
|
ModeInformation->NumberBlueBits = 8;
|
|
break;
|
|
|
|
case 32:
|
|
/*
|
|
* Windows NT uses RGBx as the standard 32BPP mode,
|
|
* so use this ordering if it's available. If it
|
|
* isn't, use the best available colour ordering.
|
|
*/
|
|
if (QueryPtr->q_HiColourSupport & RGB32_RGBx)
|
|
{
|
|
ModeInformation->RedMask = 0xff000000;
|
|
ModeInformation->GreenMask = 0x00ff0000;
|
|
ModeInformation->BlueMask = 0x0000ff00;
|
|
CrtTable->ColourDepthInfo = BIOS_DEPTH_32BPP_RGBx;
|
|
}
|
|
else if (QueryPtr->q_HiColourSupport & RGB32_xRGB)
|
|
{
|
|
ModeInformation->RedMask = 0x00ff0000;
|
|
ModeInformation->GreenMask = 0x0000ff00;
|
|
ModeInformation->BlueMask = 0x000000ff;
|
|
CrtTable->ColourDepthInfo = BIOS_DEPTH_32BPP_xRGB;
|
|
}
|
|
else if (QueryPtr->q_HiColourSupport & RGB32_BGRx)
|
|
{
|
|
ModeInformation->RedMask = 0x0000ff00;
|
|
ModeInformation->GreenMask = 0x00ff0000;
|
|
ModeInformation->BlueMask = 0xff000000;
|
|
CrtTable->ColourDepthInfo = BIOS_DEPTH_32BPP_BGRx;
|
|
}
|
|
else /* if (QueryPtr->q_HiColourSupport & RGB32_xBGR) */
|
|
{
|
|
ModeInformation->RedMask = 0x000000ff;
|
|
ModeInformation->GreenMask = 0x0000ff00;
|
|
ModeInformation->BlueMask = 0x00ff0000;
|
|
CrtTable->ColourDepthInfo = BIOS_DEPTH_32BPP_xBGR;
|
|
}
|
|
ModeInformation->NumberRedBits = 8;
|
|
ModeInformation->NumberGreenBits = 8;
|
|
ModeInformation->NumberBlueBits = 8;
|
|
break;
|
|
|
|
case 8:
|
|
default:
|
|
/*
|
|
* Assume 6 bit DAC, since all VGA-compatible DACs support
|
|
* 6 bit mode. Future expansion (extensive testing needed):
|
|
* check DAC definition to see if 8 bit mode is supported,
|
|
* and use 8 bit mode if available.
|
|
*/
|
|
ModeInformation->RedMask = 0x00000000;
|
|
ModeInformation->GreenMask = 0x00000000;
|
|
ModeInformation->BlueMask = 0x00000000;
|
|
ModeInformation->NumberRedBits = 6;
|
|
ModeInformation->NumberGreenBits = 6;
|
|
ModeInformation->NumberBlueBits = 6;
|
|
CrtTable->ColourDepthInfo = BIOS_DEPTH_8BPP;
|
|
break;
|
|
}
|
|
|
|
ModeInformation->AttributeFlags = VIDEO_MODE_COLOR | VIDEO_MODE_GRAPHICS;
|
|
|
|
if (CrtTable->m_pixel_depth <= 8)
|
|
{
|
|
ModeInformation->AttributeFlags |= VIDEO_MODE_PALETTE_DRIVEN |
|
|
VIDEO_MODE_MANAGED_PALETTE;
|
|
}
|
|
|
|
/*
|
|
* On "canned" mode tables,bit 4 of the m_disp_cntl field is set
|
|
* for interlaced modes and cleared for noninterlaced modes.
|
|
*
|
|
* The display applet gets confused if some of the "Use hardware
|
|
* default" modes are interlaced and some are noninterlaced
|
|
* (two "Use hardware default" entries are shown in the refresh
|
|
* rate list). To avoid this, report all mode tables stored in
|
|
* the EEPROM as noninterlaced, even if they are interlaced.
|
|
* "Canned" mode tables give true reports.
|
|
*
|
|
* If the display applet ever gets fixed, configured mode tables
|
|
* have (CrtTable->control & (CRTC_GEN_CNTL_Interlace << 8)) nonzero
|
|
* for interlaced and zero for noninterlaced.
|
|
*/
|
|
if (CrtTable->Refresh == DEFAULT_REFRESH)
|
|
{
|
|
ModeInformation->AttributeFlags &= ~VIDEO_MODE_INTERLACED;
|
|
}
|
|
else
|
|
{
|
|
if (CrtTable->m_disp_cntl & 0x010)
|
|
{
|
|
ModeInformation->AttributeFlags |= VIDEO_MODE_INTERLACED;
|
|
}
|
|
else
|
|
{
|
|
ModeInformation->AttributeFlags &= ~VIDEO_MODE_INTERLACED;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Fill in the video memory bitmap width and height fields.
|
|
* The descriptions are somewhat ambiguous - assume that
|
|
* "bitmap width" is the same as ScreenStride (bytes from
|
|
* start of one scanline to start of the next) and "bitmap
|
|
* height" refers to the number of complete scanlines which
|
|
* will fit into video memory.
|
|
*/
|
|
ModeInformation->VideoMemoryBitmapWidth = ModeInformation->ScreenStride;
|
|
ModeInformation->VideoMemoryBitmapHeight = (QueryPtr->q_memory_size * QUARTER_MEG) / ModeInformation->VideoMemoryBitmapWidth;
|
|
|
|
return;
|
|
|
|
} /* QuerySingleMode_m() */
|
|
|
|
VOID
|
|
EnableOldMach64MouseCursor(
|
|
PHW_DEVICE_EXTENSION pHwDeviceExtension
|
|
)
|
|
{
|
|
ULONG temp;
|
|
|
|
VideoDebugPrint((1, "Enabling the cursor\n"));
|
|
temp = INPD(GEN_TEST_CNTL);
|
|
temp |= GEN_TEST_CNTL_CursorEna;
|
|
|
|
OUTPD(GEN_TEST_CNTL, temp);
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* VP_STATUS SetCurrentMode_cx(QueryPtr, CrtTable);
|
|
*
|
|
* struct query_structure *QueryPtr; Query information for the card
|
|
* struct st_mode_table *CrtTable; CRT parameter table for desired mode
|
|
*
|
|
* DESCRIPTION:
|
|
* Switch into the specified video mode.
|
|
*
|
|
* RETURN VALUE:
|
|
* NO_ERROR if successful
|
|
* error code if failed
|
|
*
|
|
* NOTE:
|
|
* In the event of an error return by one of the services we call,
|
|
* there is no indication in our error return of which service failed,
|
|
* only the fact that one failed and the error code it returned. If
|
|
* a checked version of the miniport is being run under the kernel
|
|
* debugger, an indication will be printed to the debug terminal.
|
|
*
|
|
* GLOBALS CHANGED:
|
|
* none
|
|
*
|
|
* CALLED BY:
|
|
* IOCTL_VIDEO_SET_CURRENT_MODE packet of ATIMPStartIO()
|
|
*
|
|
* AUTHOR:
|
|
* Robert Wolff
|
|
*
|
|
* CHANGE HISTORY:
|
|
* 96 05 15 Now checks return values from INT 10 calls.
|
|
*
|
|
* TEST HISTORY:
|
|
*
|
|
***************************************************************************/
|
|
|
|
VP_STATUS SetCurrentMode_cx(struct query_structure *QueryPtr, struct st_mode_table *CrtTable)
|
|
{
|
|
VIDEO_X86_BIOS_ARGUMENTS Registers; /* Used in VideoPortInt10() calls */
|
|
ULONG WidthToClear; /* Screen width (in pixels) to clear */
|
|
ULONG ScreenPitch; /* Pitch in units of 8 pixels */
|
|
ULONG ScreenOffset = 0; /* Byte offset - varies with display mode */
|
|
ULONG PixelDepth; /* Colour depth of screen */
|
|
ULONG HorScissors; /* Horizontal scissor values */
|
|
ULONG Scratch; /* Temporary variable */
|
|
int CursorProgOffset; /* Offset of DAC register used to program the cursor */
|
|
VP_STATUS RetVal; /* Value returned by routines called */
|
|
|
|
/*
|
|
* Early versions of the Mach 64 BIOS have a bug where not all registers
|
|
* are set when initializing an accelerator mode. These registers are
|
|
* set when going into the 640x480 8BPP VGAWonder mode.
|
|
*
|
|
* All VGA disabled cards were built after this bug was fixed, so
|
|
* this mode switch is not necessary for them. On these cards, we
|
|
* must not do the mode switch, since it will affect the VGA enabled
|
|
* card rather than the card we are working on.
|
|
*/
|
|
if (phwDeviceExtension->BiosPrefix == BIOS_PREFIX_VGA_ENAB)
|
|
{
|
|
VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
|
|
Registers.Eax = 0x62;
|
|
RetVal = VideoPortInt10(phwDeviceExtension, &Registers);
|
|
if (RetVal != NO_ERROR)
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "SetCurrentMode_cx() failed SVGA mode set\n"));
|
|
return RetVal;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Setting the linear aperture using the BIOS call will set
|
|
* a 4M aperture on 2M and lower cards, and an 8M aperture
|
|
* on 4M cards. Since we force the memory size to 1M in
|
|
* 4BPP modes (workaround for a hardware bug), this can
|
|
* result in writing to the wrong location for memory mapped
|
|
* registers if we switch between 4BPP and other depths
|
|
* (typically when testing a new mode) on a 4M card.
|
|
*
|
|
* To avoid this, set the memory size to its "honest" value
|
|
* before enabling the linear aperture. If we need to cut
|
|
* back to 1M, we will do this after the aperture is set.
|
|
* This will result in the aperture always being the same
|
|
* size, so the memory mapped registers will always be
|
|
* in the same place.
|
|
*
|
|
* When using the VGA aperture, we must set the "honest" value
|
|
* after enabling the aperture but before setting the mode.
|
|
* Otherwise, the system will hang when testing a mode that
|
|
* needs more than 1M of memory from a 4BPP mode.
|
|
*
|
|
* If the linear aperture is not configured, enable the VGA aperture.
|
|
*/
|
|
if (QueryPtr->q_aperture_cfg != 0)
|
|
{
|
|
RestoreMemSize_cx();
|
|
VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
|
|
Registers.Eax = BIOS_APERTURE;
|
|
Registers.Ecx = BIOS_LINEAR_APERTURE;
|
|
RetVal = VideoPortInt10(phwDeviceExtension, &Registers);
|
|
if (RetVal != NO_ERROR)
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "SetCurrentMode_cx() failed to enable linear aperture\n"));
|
|
return RetVal;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
|
|
Registers.Eax = BIOS_APERTURE;
|
|
Registers.Ecx = BIOS_VGA_APERTURE;
|
|
RetVal = VideoPortInt10(phwDeviceExtension, &Registers);
|
|
if (RetVal != NO_ERROR)
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "SetCurrentMode_cx() failed to enable VGA aperture\n"));
|
|
return RetVal;
|
|
}
|
|
OUTP(VGA_GRAX_IND, 6);
|
|
OUTP(VGA_GRAX_DATA, (BYTE)(INP(VGA_GRAX_DATA) & 0xF3));
|
|
}
|
|
|
|
/*
|
|
* Now we can set the accelerator mode.
|
|
*/
|
|
VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
|
|
Registers.Eax = BIOS_LOAD_SET;
|
|
|
|
/*
|
|
* ECX register holds colour depth, gamma correction enable/disable
|
|
* (not used in NT miniport), pitch size, and resolution.
|
|
*/
|
|
Registers.Ecx = CrtTable->ColourDepthInfo;
|
|
|
|
/*
|
|
* Screen pitch differs from horizontal resolution only when using the
|
|
* VGA aperture and horizontal resolution is less than 1024.
|
|
*/
|
|
if ((CrtTable->m_screen_pitch == 1024) && (CrtTable->m_x_size < 1024))
|
|
Registers.Ecx |= BIOS_PITCH_1024;
|
|
else
|
|
Registers.Ecx |= BIOS_PITCH_HOR_RES;
|
|
|
|
/*
|
|
* On the 68860 DAC and ?T internal DACs, we must enable gamma
|
|
* correction for all pixel depths where the palette is not used.
|
|
*/
|
|
if (((QueryPtr->q_DAC_type == DAC_ATI_68860) ||
|
|
(QueryPtr->q_DAC_type == DAC_INTERNAL_CT) ||
|
|
(QueryPtr->q_DAC_type == DAC_INTERNAL_GT) ||
|
|
(QueryPtr->q_DAC_type == DAC_INTERNAL_VT)) &&
|
|
(QueryPtr->q_pix_depth > 8))
|
|
{
|
|
Registers.Ecx |= BIOS_ENABLE_GAMMA;
|
|
}
|
|
/*
|
|
* Fix 4bpp bugs by setting memory size to 1Meg. We do not
|
|
* need to switch back to the "honest" memory size for
|
|
* other pixel depths unless we are using the VGA aperture,
|
|
* since this was done for linear apertures before we enabled
|
|
* the aperture in order to ensure the same aperture size
|
|
* (and therefore the same locations for memory mapped
|
|
* registers) is used for all modes.
|
|
*/
|
|
else if (QueryPtr->q_pix_depth == 4)
|
|
{
|
|
OUTPD(MEM_CNTL, (INPD(MEM_CNTL) & ~MEM_CNTL_MemSizeMsk) | MEM_CNTL_MemSize1Mb);
|
|
}
|
|
else if (QueryPtr->q_aperture_cfg == 0)
|
|
{
|
|
RestoreMemSize_cx();
|
|
}
|
|
|
|
switch(CrtTable->m_x_size)
|
|
{
|
|
case 640:
|
|
Registers.Ecx |= BIOS_RES_640x480;
|
|
break;
|
|
|
|
case 800:
|
|
Registers.Ecx |= BIOS_RES_800x600;
|
|
break;
|
|
|
|
case 1024:
|
|
Registers.Ecx |= BIOS_RES_1024x768;
|
|
break;
|
|
|
|
case 1152:
|
|
/*
|
|
* Only "Other" mode that the config program will
|
|
* install for production cards.
|
|
*/
|
|
Registers.Ecx |= BIOS_RES_OEM;
|
|
break;
|
|
|
|
case 1280:
|
|
Registers.Ecx |= BIOS_RES_1280x1024;
|
|
break;
|
|
|
|
case 1600:
|
|
Registers.Ecx |= BIOS_RES_1600x1200;
|
|
break;
|
|
}
|
|
|
|
if (CrtTable->Refresh == DEFAULT_REFRESH)
|
|
{
|
|
RetVal = VideoPortInt10(phwDeviceExtension, &Registers);
|
|
if (RetVal != NO_ERROR)
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "SetCurrentMode_cx() failed mode set for default refresh\n"));
|
|
return RetVal;
|
|
}
|
|
if (phwDeviceExtension->BiosPrefix != BIOS_PREFIX_VGA_ENAB)
|
|
{
|
|
VideoDebugPrint((DEBUG_DETAIL, "Have set hardware default refresh on VGA-disabled card\n"));
|
|
/*
|
|
* On VGA-disabled cards, the INT 10 call will leave the
|
|
* DAC mask set to 0x00 (in palette modes, treat all pixels
|
|
* as if they are colour 0, regardless of what colour they
|
|
* really are). We must set it to 0xFF (in palette modes,
|
|
* use all bits of the value written to each pixel) in order
|
|
* to get the screen to display properly. This has no effect
|
|
* on non-palette (16BPP and higher) modes.
|
|
*/
|
|
OUTP_LBHW(DAC_REGS, 0xFF); /* DAC_MASK */
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RetVal = SetModeFromTable_cx(CrtTable, Registers);
|
|
if (RetVal != NO_ERROR)
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "SetCurrentMode_cx() failed call to SetModeFromTable_cx()\n"));
|
|
return RetVal;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If the LFB is disabled, and we had to round up the pitch
|
|
* to 2048 (1152x864, 1280x1024, or 1600x1200), set the pitch
|
|
* registers manually, because there's no option in the
|
|
* INT 10 call to set them to anything other than 1024 or the
|
|
* screen width.
|
|
*/
|
|
if (CrtTable->m_screen_pitch == 2048)
|
|
{
|
|
OUTPD(CRTC_OFF_PITCH, ((INPD(CRTC_OFF_PITCH) & 0x000FFFFF) | ((2048/8) << 22)));
|
|
OUTPD(SRC_OFF_PITCH, ((INPD(SRC_OFF_PITCH) & 0x000FFFFF) | ((2048/8) << 22)));
|
|
OUTPD(DST_OFF_PITCH, ((INPD(DST_OFF_PITCH) & 0x000FFFFF) | ((2048/8) << 22)));
|
|
}
|
|
/*
|
|
* On 800x600, we must round the pitch up to a multiple of 64 to avoid
|
|
* screen warping on some DACs. Set the pitch registers to correspond
|
|
* to this.
|
|
*/
|
|
else if (CrtTable->m_screen_pitch == 832)
|
|
{
|
|
OUTPD(CRTC_OFF_PITCH, ((INPD(CRTC_OFF_PITCH) & 0x000FFFFF) | ((832/8) << 22)));
|
|
OUTPD(SRC_OFF_PITCH, ((INPD(SRC_OFF_PITCH) & 0x000FFFFF) | ((832/8) << 22)));
|
|
OUTPD(DST_OFF_PITCH, ((INPD(DST_OFF_PITCH) & 0x000FFFFF) | ((832/8) << 22)));
|
|
}
|
|
|
|
|
|
/*
|
|
* Set up the hardware cursor with colour 0 black and colour 1 white.
|
|
* Do this here rather than in Initialize_cx() because the cursor
|
|
* colours don't "take" unless we are in accelerator mode.
|
|
*
|
|
* On cards with 68860 DACs, the CUR_CLR0/1 registers don't set
|
|
* the cursor colours. Instead, the colours must be set using the
|
|
* DAC_CNTL and DAC_REGS registers. The cursor colour settings
|
|
* are independent of pixel depth because the 68860 doesn't
|
|
* support 4BPP, which is the only depth that requires a different
|
|
* setting for the cursor colours.
|
|
*
|
|
* Cursor colour initialization is done unconditionally, rather than
|
|
* only on the first graphics mode set, because otherwise testing a
|
|
* different pixel depth (most commonly testing 1024x768 4BPP when
|
|
* 1024x768 16BPP configured) may corrupt the cursor colours.
|
|
*/
|
|
if ((QueryPtr->q_DAC_type == DAC_ATI_68860) ||
|
|
(QueryPtr->q_DAC_type == DAC_TVP3026) ||
|
|
(QueryPtr->q_DAC_type == DAC_IBM514))
|
|
{
|
|
OUTP(DAC_CNTL, (BYTE)((INP(DAC_CNTL) & 0xFC) | 1));
|
|
|
|
/*
|
|
* On TVP3026 DAC, skip the OVERSCAN colour register.
|
|
*/
|
|
if (QueryPtr->q_DAC_type == DAC_TVP3026)
|
|
{
|
|
OUTP(DAC_REGS, 1);
|
|
CursorProgOffset = 1; /* DAC_DATA */
|
|
}
|
|
else if (QueryPtr->q_DAC_type == DAC_ATI_68860)
|
|
{
|
|
OUTP(DAC_REGS, 0);
|
|
CursorProgOffset = 1; /* DAC_DATA */
|
|
}
|
|
else /* if (QueryPtr->q_DAC_type == DAC_IBM514) */
|
|
{
|
|
OUTP_HBHW(DAC_REGS, 1); /* Auto-increment */
|
|
OUTP(DAC_REGS, 0x40);
|
|
OUTP_HBLW(DAC_REGS, 0);
|
|
CursorProgOffset = 2; /* DAC_MASK */
|
|
}
|
|
|
|
LioOutp(DAC_REGS, 0, CursorProgOffset); /* Colour 0 red */
|
|
LioOutp(DAC_REGS, 0, CursorProgOffset); /* Colour 0 green */
|
|
LioOutp(DAC_REGS, 0, CursorProgOffset); /* Colour 0 blue */
|
|
|
|
LioOutp(DAC_REGS, 0xFF, CursorProgOffset); /* Colour 1 red */
|
|
LioOutp(DAC_REGS, 0xFF, CursorProgOffset); /* Colour 1 green */
|
|
LioOutp(DAC_REGS, 0xFF, CursorProgOffset); /* Colour 1 blue */
|
|
|
|
|
|
OUTP(DAC_CNTL, (BYTE)((INP(DAC_CNTL) & 0xFC)));
|
|
}
|
|
|
|
else /* if (DAC not one of ATI68860, TVP3026, or IBM514) */
|
|
{
|
|
OUTPD(CUR_CLR0, 0x00000000);
|
|
/*
|
|
* On most Mach 64 cards, we must use only the lower 4 bits
|
|
* when setting up the white part of the cursor. On the
|
|
* ?T, however, we must set all 8 bits for each of the colour
|
|
* components.
|
|
*
|
|
* Verify that the VT/GT still need this after the final ASIC
|
|
* becomes available.
|
|
*/
|
|
if ((QueryPtr->q_pix_depth == 4) &&
|
|
(QueryPtr->q_DAC_type != DAC_INTERNAL_CT) &&
|
|
(QueryPtr->q_DAC_type != DAC_INTERNAL_GT) &&
|
|
(QueryPtr->q_DAC_type != DAC_INTERNAL_VT))
|
|
{
|
|
OUTPD(CUR_CLR1, 0x0F0F0F0F);
|
|
}
|
|
else
|
|
{
|
|
OUTPD(CUR_CLR1, 0xFFFFFFFF);
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* phwDeviceExtension->ReInitializing becomes TRUE in
|
|
* IOCTL_VIDEO_SET_COLOR_REGISTERS packet of ATIMPStartIO().
|
|
*
|
|
* If this is the first time we are going into graphics mode,
|
|
* Turn on the graphics engine. Otherwise, set the palette
|
|
* to the last set of colours that was selected while in
|
|
* accelerator mode.
|
|
*/
|
|
if (phwDeviceExtension->ReInitializing)
|
|
{
|
|
SetPalette_cx(phwDeviceExtension->Clut,
|
|
phwDeviceExtension->FirstEntry,
|
|
phwDeviceExtension->NumEntries);
|
|
}
|
|
else
|
|
{
|
|
|
|
/*
|
|
* Turn on the graphics engine.
|
|
*/
|
|
OUTPD(GEN_TEST_CNTL, (INPD(GEN_TEST_CNTL) | GEN_TEST_CNTL_GuiEna));
|
|
}
|
|
|
|
/*
|
|
* If we are using a 68860 DAC or ?T internal DAC in a non-palette
|
|
* mode, identity map the palette.
|
|
*/
|
|
if (((QueryPtr->q_DAC_type == DAC_ATI_68860) ||
|
|
(QueryPtr->q_DAC_type == DAC_INTERNAL_CT) ||
|
|
(QueryPtr->q_DAC_type == DAC_INTERNAL_GT) ||
|
|
(QueryPtr->q_DAC_type == DAC_INTERNAL_VT)) &&
|
|
(QueryPtr->q_pix_depth > 8))
|
|
IdentityMapPalette_cx();
|
|
|
|
|
|
/*
|
|
* Clear the screen regardless of whether or not this is the
|
|
* first time we are going into graphics mode. This is done
|
|
* because in 3.50 and later releases of Windows NT, the
|
|
* screen will be filled with garbage if we don't clear it.
|
|
*
|
|
* 24BPP is not a legal setting for DP_DST_PIX_WID@DP_PIX_WID.
|
|
* Instead, use 8BPP, but tell the engine that the screen is
|
|
* 3 times as wide as it actually is.
|
|
*/
|
|
if (CrtTable->ColourDepthInfo == BIOS_DEPTH_24BPP)
|
|
{
|
|
WidthToClear = CrtTable->m_x_size * 3;
|
|
ScreenPitch = (CrtTable->m_screen_pitch * 3) / 8;
|
|
PixelDepth = BIOS_DEPTH_8BPP;
|
|
/*
|
|
* Horizontal scissors are only valid in the range
|
|
* -4096 to +4095. If the horizontal resolution
|
|
* is high enough to put the scissor outside this
|
|
* range, clamp the scissors to the maximum
|
|
* permitted value.
|
|
*/
|
|
HorScissors = QueryPtr->q_desire_x * 3;
|
|
if (HorScissors > 4095)
|
|
HorScissors = 4095;
|
|
HorScissors <<= 16;
|
|
}
|
|
else
|
|
{
|
|
WidthToClear = CrtTable->m_x_size;
|
|
ScreenPitch = CrtTable->m_screen_pitch / 8;
|
|
PixelDepth = CrtTable->ColourDepthInfo;
|
|
HorScissors = (QueryPtr->q_desire_x) << 16;
|
|
}
|
|
|
|
/*
|
|
* On some DAC/memory combinations, some modes which require more
|
|
* than 2M of memory (1152x764 24BPP, 1280x1024 24BPP, and
|
|
* 1600x1200 16BPP) will have screen tearing at the 2M boundary.
|
|
*
|
|
* As a workaround, the offset field of all 3 CRTC/SRC/DST_OFF_PITCH
|
|
* registers must be set to put the 2M boundary at the start
|
|
* of a scanline.
|
|
*
|
|
* Other DAC/memory combinations are unaffected, but since this
|
|
* fix is nearly harmless (only ill effect is to make DCI unusable
|
|
* in these modes), we can catch all future combinations which
|
|
* suffer from this problem by assuming that all DAC/memory
|
|
* combinations are affected.
|
|
*/
|
|
if ((QueryPtr->q_pix_depth == 24) &&
|
|
(QueryPtr->q_desire_x == 1280))
|
|
{
|
|
ScreenOffset = 0x40;
|
|
}
|
|
else if ((QueryPtr->q_pix_depth == 24) &&
|
|
(QueryPtr->q_desire_x == 1152))
|
|
{
|
|
ScreenOffset = 0x160;
|
|
}
|
|
else if ((QueryPtr->q_pix_depth == 16) &&
|
|
(QueryPtr->q_desire_x == 1600))
|
|
{
|
|
ScreenOffset = 0x90;
|
|
}
|
|
else /* all other DAC/resolution/pixel depth combinations */
|
|
{
|
|
ScreenOffset = 0;
|
|
}
|
|
|
|
CheckFIFOSpace_cx(TWO_WORDS);
|
|
Scratch = INPD(CRTC_OFF_PITCH) & ~CRTC_OFF_PITCH_Offset;
|
|
Scratch |= ScreenOffset;
|
|
OUTPD(CRTC_OFF_PITCH, Scratch);
|
|
Scratch = INPD(SRC_OFF_PITCH) & ~SRC_OFF_PITCH_Offset;
|
|
Scratch |= ScreenOffset;
|
|
OUTPD(SRC_OFF_PITCH, Scratch);
|
|
|
|
|
|
/*
|
|
* The pixel widths for destination,
|
|
* source, and host must be the same.
|
|
*/
|
|
PixelDepth |= ((PixelDepth << 8) | (PixelDepth << 16));
|
|
|
|
CheckFIFOSpace_cx(ELEVEN_WORDS);
|
|
|
|
OUTPD(DP_WRITE_MASK, 0xFFFFFFFF);
|
|
OUTPD(DST_OFF_PITCH, (ScreenPitch << 22) | ScreenOffset);
|
|
OUTPD(DST_CNTL, (DST_CNTL_XDir | DST_CNTL_YDir));
|
|
OUTPD(DP_PIX_WIDTH, PixelDepth);
|
|
OUTPD(DP_SRC, (DP_FRGD_SRC_FG | DP_BKGD_SRC_BG | DP_MONO_SRC_ONE));
|
|
OUTPD(DP_MIX, ((MIX_FN_PAINT << 16) | MIX_FN_PAINT));
|
|
OUTPD(DP_FRGD_CLR, 0x0);
|
|
OUTPD(SC_LEFT_RIGHT, HorScissors);
|
|
OUTPD(SC_TOP_BOTTOM, (CrtTable->m_y_size) << 16);
|
|
OUTPD(DST_Y_X, 0);
|
|
OUTPD(DST_HEIGHT_WIDTH, (WidthToClear << 16) | CrtTable->m_y_size);
|
|
|
|
if (WaitForIdle_cx() == FALSE)
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "SetCurrentMode_cx() failed WaitForIdle_cx()\n"));
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
|
|
} /* SetCurrentMode_cx() */
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* void SetPalette_cx(lpPalette, StartIndex, Count);
|
|
*
|
|
* PPALETTEENTRY lpPalette; Colour values to plug into palette
|
|
* USHORT StartIndex; First palette entry to set
|
|
* USHORT Count; Number of palette entries to set
|
|
*
|
|
* DESCRIPTION:
|
|
* Set the desired number of palette entries to the specified colours,
|
|
* starting at the specified index. Colour values are stored in
|
|
* doublewords, in the order (low byte to high byte) RGBx.
|
|
*
|
|
* GLOBALS CHANGED:
|
|
* none
|
|
*
|
|
* CALLED BY:
|
|
* SetCurrentMode_cx() and IOCTL_VIDEO_SET_COLOR_REGISTERS packet
|
|
* of ATIMPStartIO()
|
|
*
|
|
* AUTHOR:
|
|
* unknown
|
|
*
|
|
* CHANGE HISTORY:
|
|
*
|
|
* TEST HISTORY:
|
|
*
|
|
***************************************************************************/
|
|
|
|
void SetPalette_cx(PULONG lpPalette, USHORT StartIndex, USHORT Count)
|
|
{
|
|
int i;
|
|
BYTE *pPal=(BYTE *)lpPalette;
|
|
struct query_structure *Query; /* Information about the graphics card */
|
|
|
|
Query = (struct query_structure *) (phwDeviceExtension->CardInfo);
|
|
|
|
/*
|
|
* In the current rev of the 88800GX, the memory mapped access
|
|
* to the DAC_REGS register is broken but the I/O mapped access
|
|
* works properly. Force the use of the I/O mapped access.
|
|
*/
|
|
phwDeviceExtension->aVideoAddressMM[DAC_REGS] = 0;
|
|
|
|
/*
|
|
* If a video capture card is hooked up to the feature connector,
|
|
* it will only "see" the palette being set if we use the VGA
|
|
* palette registers. This applies only in 4 and 8BPP, and is
|
|
* not necessary for when we identity map the palette (needed
|
|
* on certain DACs in 16BPP and above).
|
|
*
|
|
* In a multi-headed setup, only the card with the VGA enabled is
|
|
* able to be programmed using the VGA registers. All others must
|
|
* be programmed using the accelerator registers. Since this is
|
|
* the only card where we can hook up a video capture card to the
|
|
* feature connector, we don't lose "snooping" capability by
|
|
* programming VGA-disabled cards through the accelerator registers.
|
|
*/
|
|
if ((Query->q_pix_depth <= 8) && (phwDeviceExtension->BiosPrefix == BIOS_PREFIX_VGA_ENAB))
|
|
{
|
|
VideoDebugPrint((DEBUG_DETAIL, "Setting palette via VGA registers\n"));
|
|
/*
|
|
* DAC_W_INDEX is 8 bytes into second block of VGA registers.
|
|
* We do not have a separate OUTP()able register for this one.
|
|
*/
|
|
LioOutp(VGA_END_BREAK_PORT, (BYTE)StartIndex, 8);
|
|
|
|
for (i=0; i<Count; i++) /* this is number of colours to update */
|
|
{
|
|
/*
|
|
* DAC_DATA is 9 bytes into second block of VGA registers.
|
|
* We do not have a separate OUTP()able register for this one.
|
|
*/
|
|
LioOutp(VGA_END_BREAK_PORT, *pPal++, 9); /* red */
|
|
LioOutp(VGA_END_BREAK_PORT, *pPal++, 9); /* green */
|
|
LioOutp(VGA_END_BREAK_PORT, *pPal++, 9); /* blue */
|
|
pPal++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
VideoDebugPrint((DEBUG_DETAIL, "Setting palette via accelerator registers\n"));
|
|
OUTP(DAC_REGS,(BYTE)StartIndex); /* load DAC_W_INDEX@DAC_REGS with StartIndex */
|
|
|
|
for (i=0; i<Count; i++) /* this is number of colours to update */
|
|
{
|
|
/*
|
|
* DAC_DATA@DAC_REGS is high byte of low word.
|
|
*/
|
|
OUTP_HBLW(DAC_REGS, *pPal++); /* red */
|
|
OUTP_HBLW(DAC_REGS, *pPal++); /* green */
|
|
OUTP_HBLW(DAC_REGS, *pPal++); /* blue */
|
|
pPal++;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Victor Tango requires a few registers to be re-initialized after
|
|
* setting the palette.
|
|
*/
|
|
if (Query->q_DAC_type == DAC_INTERNAL_VT)
|
|
{
|
|
OUTP_LBHW(DAC_REGS, 0xFF); /* DAC_MASK */
|
|
OUTP(DAC_REGS, 0xFF); /* DAC_W_INDEX */
|
|
}
|
|
|
|
return;
|
|
|
|
} /* SetPalette_cx() */
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* void IdentityMapPalette_cx(void);
|
|
*
|
|
* DESCRIPTION:
|
|
* Set the entire palette to a grey scale whose intensity at each
|
|
* index is equal to the index value.
|
|
*
|
|
* GLOBALS CHANGED:
|
|
* none
|
|
*
|
|
* CALLED BY:
|
|
* SetCurrentMode_cx()
|
|
*
|
|
* AUTHOR:
|
|
* unknown
|
|
*
|
|
* CHANGE HISTORY:
|
|
*
|
|
* TEST HISTORY:
|
|
*
|
|
***************************************************************************/
|
|
|
|
void IdentityMapPalette_cx(void)
|
|
{
|
|
unsigned long Index;
|
|
struct query_structure *Query; /* Information about the graphics card */
|
|
|
|
Query = (struct query_structure *) (phwDeviceExtension->CardInfo);
|
|
|
|
/*
|
|
* In the current rev of the 88800GX, the memory mapped access
|
|
* to the DAC_REGS register is broken but the I/O mapped access
|
|
* works properly. Force the use of the I/O mapped access.
|
|
*/
|
|
phwDeviceExtension->aVideoAddressMM[DAC_REGS] = 0;
|
|
|
|
OUTP(DAC_REGS, 0); // Start at first palette entry.
|
|
|
|
for (Index=0; Index<256; Index++) // Fill the whole palette.
|
|
{
|
|
/*
|
|
* DAC_DATA@DAC_REGS is high byte of low word.
|
|
*/
|
|
OUTP_HBLW(DAC_REGS,(BYTE)(Index)); // red
|
|
OUTP_HBLW(DAC_REGS,(BYTE)(Index)); // green
|
|
OUTP_HBLW(DAC_REGS,(BYTE)(Index)); // blue
|
|
}
|
|
|
|
/*
|
|
* Victor Tango requires a few registers to be re-initialized after
|
|
* setting the palette.
|
|
*/
|
|
if (Query->q_DAC_type == DAC_INTERNAL_VT)
|
|
{
|
|
OUTP_LBHW(DAC_REGS, 0xFF); /* DAC_MASK */
|
|
OUTP(DAC_REGS, 0xFF); /* DAC_W_INDEX */
|
|
}
|
|
|
|
return;
|
|
|
|
} /* IdentityMapPalette_cx() */
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* void ResetDevice_cx(void);
|
|
*
|
|
* DESCRIPTION:
|
|
* Switch back to VGA mode.
|
|
*
|
|
* GLOBALS CHANGED:
|
|
* none
|
|
*
|
|
* CALLED BY:
|
|
* IOCTL_VIDEO_RESET_DEVICE packet of ATIMPStartIO()
|
|
*
|
|
* AUTHOR:
|
|
* Robert Wolff
|
|
*
|
|
* CHANGE HISTORY:
|
|
*
|
|
* TEST HISTORY:
|
|
*
|
|
***************************************************************************/
|
|
|
|
void ResetDevice_cx(void)
|
|
{
|
|
VIDEO_X86_BIOS_ARGUMENTS Registers; /* Used in VideoPortInt10() calls */
|
|
ULONG Scratch;
|
|
|
|
|
|
VideoDebugPrint((DEBUG_NORMAL, "ResetDevice_cx() - entry\n"));
|
|
|
|
VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
|
|
Registers.Eax = BIOS_SET_MODE;
|
|
Registers.Ecx = BIOS_MODE_VGA;
|
|
VideoPortInt10(phwDeviceExtension, &Registers);
|
|
|
|
VideoDebugPrint((DEBUG_DETAIL, "ResetDevice_cx() - VGA controls screen\n"));
|
|
|
|
VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
|
|
Registers.Eax = 0x3;
|
|
VideoPortInt10(phwDeviceExtension, &Registers);
|
|
|
|
VideoDebugPrint((DEBUG_NORMAL, "ResetDevice_cx() - exit\n"));
|
|
|
|
return;
|
|
|
|
} /* ResetDevice_cx() */
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* DWORD GetPowerManagement_cx();
|
|
*
|
|
* DESCRIPTION:
|
|
* Determine our current DPMS state.
|
|
*
|
|
* RETURN VALUE:
|
|
* Current DPMS state (VIDEO_POWER_STATE enumeration)
|
|
*
|
|
* GLOBALS CHANGED:
|
|
* none
|
|
*
|
|
* CALLED BY:
|
|
* ATIMPGetPower()
|
|
*
|
|
* AUTHOR:
|
|
* Robert Wolff
|
|
*
|
|
* CHANGE HISTORY:
|
|
*
|
|
* TEST HISTORY:
|
|
*
|
|
***************************************************************************/
|
|
|
|
DWORD GetPowerManagement_cx(PHW_DEVICE_EXTENSION phwDeviceExtension)
|
|
{
|
|
VIDEO_X86_BIOS_ARGUMENTS Registers; /* Used in VideoPortInt10() calls */
|
|
|
|
ASSERT(phwDeviceExtension != NULL);
|
|
|
|
/*
|
|
* Invoke the BIOS call to get the desired DPMS state. The BIOS call
|
|
* enumeration of DPMS states is in the same order as that in
|
|
* VIDEO_POWER_STATE, but it is zero-based instead of one-based.
|
|
*/
|
|
VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
|
|
Registers.Eax = BIOS_GET_DPMS;
|
|
VideoPortInt10(phwDeviceExtension, &Registers);
|
|
|
|
return (Registers.Ecx + 1);
|
|
} /* GetPowerManagement_cx() */
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* VP_STATUS SetPowerManagement_cx(DpmsState);
|
|
*
|
|
* DWORD DpmsState; Desired DPMS state (VIDEO_POWER_STATE enumeration)
|
|
*
|
|
* DESCRIPTION:
|
|
* Switch into the desired DPMS state.
|
|
*
|
|
* RETURN VALUE:
|
|
* NO_ERROR if successful
|
|
* ERROR_INVALID_PARAMETER if invalid state requested.
|
|
*
|
|
* GLOBALS CHANGED:
|
|
* none
|
|
*
|
|
* CALLED BY:
|
|
* IOCTL_VIDEO_SET_POWER_MANAGEMENT packet of ATIMPStartIO()
|
|
*
|
|
* AUTHOR:
|
|
* Robert Wolff
|
|
*
|
|
* CHANGE HISTORY:
|
|
*
|
|
* TEST HISTORY:
|
|
*
|
|
***************************************************************************/
|
|
|
|
VP_STATUS SetPowerManagement_cx(DWORD DpmsState)
|
|
{
|
|
VIDEO_X86_BIOS_ARGUMENTS Registers; /* Used in VideoPortInt10() calls */
|
|
|
|
/*
|
|
* Only accept valid states.
|
|
*/
|
|
if ((DpmsState < VideoPowerOn) || (DpmsState > VideoPowerOff))
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "SetPowerManagement_cx - invalid DPMS state selected\n"));
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
/*
|
|
* Invoke the BIOS call to set the desired DPMS state. The BIOS call
|
|
* enumeration of DPMS states is in the same order as that in
|
|
* VIDEO_POWER_STATE, but it is zero-based instead of one-based.
|
|
*/
|
|
VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
|
|
Registers.Eax = BIOS_SET_DPMS;
|
|
Registers.Ecx = DpmsState - 1;
|
|
VideoPortInt10(phwDeviceExtension, &Registers);
|
|
|
|
return NO_ERROR;
|
|
|
|
} /* SetPowerManagement_cx() */
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* static VP_STATUS SetModeFromTable_cx(ModeTable, Registers);
|
|
*
|
|
* struct st_mode_table *ModeTable; Mode table to set up screen from
|
|
* VIDEO_X86_BIOS_ARGUMENTS Registers; Registers for INT 10 call
|
|
*
|
|
* DESCRIPTION:
|
|
* Switch into the graphics mode specified by ModeTable.
|
|
*
|
|
* RETURN VALUE:
|
|
* NO_ERROR if successful
|
|
* error code if failed
|
|
*
|
|
* GLOBALS CHANGED:
|
|
* none
|
|
*
|
|
* CALLED BY:
|
|
* SetCurrentMode_cx()
|
|
*
|
|
* AUTHOR:
|
|
* Robert Wolff
|
|
*
|
|
* CHANGE HISTORY:
|
|
* 96 05 15 Now checks return values from INT 10 calls.
|
|
*
|
|
* TEST HISTORY:
|
|
*
|
|
***************************************************************************/
|
|
|
|
static VP_STATUS SetModeFromTable_cx(struct st_mode_table *ModeTable, VIDEO_X86_BIOS_ARGUMENTS Registers)
|
|
{
|
|
#define TBL_SET_BUFFER_SIZE 100
|
|
|
|
PUCHAR MappedBuffer; /* Pointer to buffer used for BIOS query */
|
|
struct cx_bios_set_from_table *CxTable; /* Mode table in Mach 64 BIOS format */
|
|
ULONG Scratch; /* Temporary variable */
|
|
struct query_structure *QueryPtr; /* Query information for the card */
|
|
VIDEO_X86_BIOS_ARGUMENTS TempRegs; /* Used in setting 640x480 8BPP to enable LFB */
|
|
BOOL FlippedPrimrary = FALSE; /* TRUE if we switched to VGA aperture on primrary card */
|
|
UCHAR SavedScreen[TBL_SET_BUFFER_SIZE]; /* Used to restore contents of primrary screen */
|
|
VP_STATUS RetVal; /* Value returned by routines called */
|
|
|
|
/*
|
|
* Get a formatted pointer into the query section of HwDeviceExtension.
|
|
* The CardInfo[] field is an unformatted buffer.
|
|
*/
|
|
QueryPtr = (struct query_structure *) (phwDeviceExtension->CardInfo);
|
|
|
|
/*
|
|
* To set the video mode from a table, we need to write the mode table
|
|
* to a buffer in physical memory below 1M. The nature of this block
|
|
* falls into one of two cases:
|
|
*
|
|
* Primrary (VGA enabled) card:
|
|
* We have already switched into video mode 0x62 (VGA 640x480 8BPP)
|
|
* to set up registers that under some circumstances are not set up
|
|
* by the accelerator mode set, so we have access to a 64k block
|
|
* starting at 0xA0000 which is backed by physical (video) memory
|
|
* and which we can write to without corrupting code and/or data
|
|
* being used by other processes.
|
|
*
|
|
* Secondary (VGA disabled) card:
|
|
* There is a VGA enabled card in the machine, which falls into
|
|
* one of five sub-cases:
|
|
*
|
|
* 1. VGA is in colour text mode
|
|
* We can use the offscreen portion of the buffer, and it doesn't
|
|
* matter whether or not the card is a Mach 64.
|
|
*
|
|
* 2. VGA is in mono text mode
|
|
* We can use the offscreen portion of the buffer, and it doesn't
|
|
* matter whether or not the card is a Mach 64.
|
|
*
|
|
* 3. VGA is in graphics mode
|
|
* We can use the beginning of the graphics screen, and it doesn't
|
|
* matter whether or not the card is a Mach 64.
|
|
*
|
|
* 4. VGA-enabled card is a Mach 64 in accelerator mode
|
|
* We can temporarily flip the primrary card's aperture status
|
|
* from LFB to VGA aperture, and use the start of the VGA
|
|
* aperture.
|
|
*
|
|
* 5. VGA-enabled card is another brand of accelerator, in accelerator mode
|
|
* This case should never occur, since NT should only run one video
|
|
* driver with VgaCompatible set to zero. If it is the ATI driver,
|
|
* a non-ATI card should not be in accelerator mode. If it is the
|
|
* driver for the non-ATI card, we will never receive a request
|
|
* to change into an accelerator mode on our card.
|
|
*
|
|
* We don't need to claim the whole block, but we should claim a bit
|
|
* more than the size of the mode table so the BIOS won't try to access
|
|
* unclaimed memory.
|
|
*/
|
|
if (phwDeviceExtension->BiosPrefix == BIOS_PREFIX_VGA_ENAB)
|
|
{
|
|
VideoDebugPrint((DEBUG_NORMAL, "Setting mode on primrary card\n"));
|
|
MappedBuffer = MapFramebuffer(0xA0000, TBL_SET_BUFFER_SIZE);
|
|
if (MappedBuffer == 0)
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "SetModeFromTable_cx() failed MapFramebuffer()\n"));
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
/*
|
|
* Tell the BIOS to load the CRTC parameters from a table,
|
|
* rather than using the configured refresh rate for this
|
|
* resolution, and let it know where the table is.
|
|
*/
|
|
Registers.Eax = BIOS_LOAD_SET;
|
|
Registers.Edx = 0xA000;
|
|
Registers.Ebx = 0x0000;
|
|
Registers.Ecx &= ~BIOS_RES_MASK; /* Mask out code for configured resolution */
|
|
Registers.Ecx |= BIOS_RES_BUFFER;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* This is a VGA disabled card. First try sub-cases 1 through 3.
|
|
*/
|
|
VideoDebugPrint((DEBUG_NORMAL, "Setting mode on secondary card\n"));
|
|
|
|
MappedBuffer = GetVgaBuffer(TBL_SET_BUFFER_SIZE, 0, &(Registers.Edx), SavedScreen);
|
|
|
|
/*
|
|
* If we were unable to map the buffer, assume we are dealing
|
|
* with sub-case 4. We can't distinguish between sub-cases
|
|
* 4 and 5, since the code to report an error if we issue an
|
|
* invalid BIOS call is in the ATI video BIOS, which won't
|
|
* be present in sub-case 5. Users in this sub-case are on
|
|
* their own.
|
|
*
|
|
* For sub-case 4 (VGA-enabled card is a Mach 64 in accelerator
|
|
* mode), temporarily flip from LFB mode to VGA aperture mode
|
|
* so we can use the VGA aperture without destroying the contents
|
|
* of the screen.
|
|
*/
|
|
if (MappedBuffer == 0)
|
|
{
|
|
FlippedPrimrary = TRUE;
|
|
VideoDebugPrint((DEBUG_DETAIL, "Temporary setting primrary card to VGA aperture\n"));
|
|
VideoPortZeroMemory(&TempRegs, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
|
|
TempRegs.Eax = BIOS_PREFIX_VGA_ENAB | BIOS_APERTURE_LB;
|
|
TempRegs.Ecx = BIOS_VGA_APERTURE;
|
|
RetVal = VideoPortInt10(phwDeviceExtension, &TempRegs);
|
|
if (RetVal != NO_ERROR)
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "SetModeFromTable_cx() failed VGA-enabled flip to VGA aperture\n"));
|
|
return RetVal;
|
|
}
|
|
MappedBuffer = MapFramebuffer(0xA0000, TBL_SET_BUFFER_SIZE);
|
|
if (MappedBuffer == 0)
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "SetModeFromTable_cx() failed to map buffer on VGA-enabled card\n"));
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
Registers.Edx = 0xA000;
|
|
|
|
/*
|
|
* Save the contents of the buffer so that we can restore it
|
|
* after we finish the mode set.
|
|
*/
|
|
for (Scratch = 0; Scratch < TBL_SET_BUFFER_SIZE; Scratch++)
|
|
SavedScreen[Scratch] = VideoPortReadRegisterUchar(&(MappedBuffer[Scratch]));
|
|
}
|
|
|
|
/*
|
|
* Tell the BIOS to load the CRTC parameters from a table,
|
|
* rather than using the configured refresh rate for this
|
|
* resolution, and let it know where the table is.
|
|
*/
|
|
Registers.Eax = BIOS_LOAD_SET;
|
|
Registers.Ebx = 0x0000;
|
|
Registers.Ecx &= ~BIOS_RES_MASK; /* Mask out code for configured resolution */
|
|
Registers.Ecx |= BIOS_RES_BUFFER;
|
|
|
|
} /* end if (VGA disabled card) */
|
|
|
|
CxTable = (struct cx_bios_set_from_table *)MappedBuffer;
|
|
|
|
/*
|
|
* Copy the mode table into the Mach 64 format table. First handle
|
|
* the fields that only require shifting and masking.
|
|
*/
|
|
VideoPortWriteRegisterUshort(&(CxTable->cx_bs_mode_select), (WORD)((Registers.Ecx & BIOS_RES_MASK) | CX_BS_MODE_SELECT_ACC));
|
|
VideoPortWriteRegisterUshort(&(CxTable->cx_bs_h_tot_disp), (WORD)((ModeTable->m_h_disp << 8) | ModeTable->m_h_total));
|
|
VideoPortWriteRegisterUshort(&(CxTable->cx_bs_h_sync_strt_wid), (WORD)((ModeTable->m_h_sync_wid << 8) | ModeTable->m_h_sync_strt));
|
|
VideoPortWriteRegisterUshort(&(CxTable->cx_bs_v_sync_wid), (WORD)(ModeTable->m_v_sync_wid | CX_BS_V_SYNC_WID_CLK));
|
|
VideoPortWriteRegisterUshort(&(CxTable->cx_bs_h_overscan), ModeTable->m_h_overscan);
|
|
VideoPortWriteRegisterUshort(&(CxTable->cx_bs_v_overscan), ModeTable->m_v_overscan);
|
|
VideoPortWriteRegisterUshort(&(CxTable->cx_bs_overscan_8b), ModeTable->m_overscan_8b);
|
|
VideoPortWriteRegisterUshort(&(CxTable->cx_bs_overscan_gr), ModeTable->m_overscan_gr);
|
|
|
|
/*
|
|
* Next take care of fields which must be translated from our
|
|
* "canned" mode tables.
|
|
*
|
|
* The cx_crtc_gen_cntl field has only 3 bits that we use: interlace,
|
|
* MUX mode (all 1280x1024 noninterlaced modes), and force use of
|
|
* all parameters from the table (this bit is used by all the
|
|
* "canned" tables).
|
|
*/
|
|
if ((ModeTable->m_disp_cntl) & 0x10)
|
|
VideoPortWriteRegisterUshort(&(CxTable->cx_bs_flags), CX_BS_FLAGS_INTERLACED | CX_BS_FLAGS_ALL_PARMS);
|
|
else if ((ModeTable->m_x_size > 1024) && (ModeTable->ClockFreq >= 100000000L))
|
|
VideoPortWriteRegisterUshort(&(CxTable->cx_bs_flags), CX_BS_FLAGS_MUX | CX_BS_FLAGS_ALL_PARMS);
|
|
else
|
|
VideoPortWriteRegisterUshort(&(CxTable->cx_bs_flags), CX_BS_FLAGS_ALL_PARMS);
|
|
/*
|
|
* Vertical parameters other than sync width are in skip-2 in
|
|
* the "canned" tables, but need to be in linear form for the Mach 64.
|
|
*/
|
|
VideoPortWriteRegisterUshort(&(CxTable->cx_bs_v_total), (WORD)(((ModeTable->m_v_total >> 1) & 0x0FFFC) | (ModeTable->m_v_total & 0x03)));
|
|
VideoPortWriteRegisterUshort(&(CxTable->cx_bs_v_disp), (WORD)(((ModeTable->m_v_disp >> 1) & 0x0FFFC) | (ModeTable->m_v_disp & 0x03)));
|
|
VideoPortWriteRegisterUshort(&(CxTable->cx_bs_v_sync_strt), (WORD)(((ModeTable->m_v_sync_strt >> 1) & 0x0FFFC) | (ModeTable->m_v_sync_strt & 0x03)));
|
|
/*
|
|
* The cx_dot_clock field takes the pixel clock frequency in units
|
|
* of 10 kHz.
|
|
*/
|
|
VideoPortWriteRegisterUshort(&(CxTable->cx_bs_dot_clock), (WORD)(ModeTable->ClockFreq / 10000L));
|
|
|
|
/*
|
|
* Now set up fields which have constant values.
|
|
*/
|
|
VideoPortWriteRegisterUshort(&(CxTable->cx_bs_reserved_1), 0);
|
|
VideoPortWriteRegisterUshort(&(CxTable->cx_bs_reserved_2), 0);
|
|
|
|
/*
|
|
* Some Mach64 cards need to have an internal flag set up before
|
|
* they can switch into certain resolutions. Cards which have
|
|
* these resolutions configured using INSTALL.EXE don't need this
|
|
* flag set up, so we don't need to do it when switching to a
|
|
* hardware default mode. Since we don't know if the card needs
|
|
* this flag for the resolution we are using, set it for all
|
|
* "canned" mode tables.
|
|
*
|
|
* Unfortunately, this flag will disable automatic "kickdown"
|
|
* to a lower refresh rate for high pixel depths when "use
|
|
* hardware default refresh rate" is selected. To avoid this
|
|
* problem, save the contents of the scratchpad register, set
|
|
* the flag, then after we set the mode we want, restore the
|
|
* contents of the scratchpad register.
|
|
*/
|
|
Scratch = INPD(SCRATCH_REG1);
|
|
OUTPD(SCRATCH_REG1, Scratch | 0x00000200);
|
|
|
|
RetVal = VideoPortInt10(phwDeviceExtension, &Registers);
|
|
if (RetVal != NO_ERROR)
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "SetModeFromTable_cx() failed mode set\n"));
|
|
return RetVal;
|
|
}
|
|
|
|
/*
|
|
* If we are dealing with a VGA-disabled card (typically in a
|
|
* multiheaded setup, but under rare circumstances someone may
|
|
* be using a VGA-disabled Mach 64 with a separate VGA card),
|
|
* we must clean up after ourselves. First of all, the DAC_MASK
|
|
* register will have been left at zero by the BIOS call, which
|
|
* inhibits display of palette modes. Next, we must restore the
|
|
* contents of the buffer we used to store the CRT parameter table.
|
|
*
|
|
* Finally, if we obtained the buffer by setting a VGA-enabled
|
|
* Mach 64 in accelerator mode to use the VGA aperture, we must
|
|
* restore it to its previous aperture status. Since this will
|
|
* only happen in a multiheaded setup, and we only support PCI
|
|
* cards in such a setup (i.e. all cards have LFB available),
|
|
* we can safely assume that the VGA-enabled card was originally
|
|
* configured for LFB mode.
|
|
*/
|
|
if (phwDeviceExtension->BiosPrefix != BIOS_PREFIX_VGA_ENAB)
|
|
{
|
|
VideoDebugPrint((DEBUG_DETAIL, "Cleaning up after mode set on VGA-disabled card\n"));
|
|
OUTP_LBHW(DAC_REGS, 0xFF); /* DAC_MASK */
|
|
|
|
for (Scratch = 0; Scratch < TBL_SET_BUFFER_SIZE; Scratch++)
|
|
VideoPortWriteRegisterUchar(&(MappedBuffer[Scratch]), SavedScreen[Scratch]);
|
|
|
|
if (FlippedPrimrary == TRUE)
|
|
{
|
|
VideoDebugPrint((DEBUG_DETAIL, "Setting primrary card back to LFB mode\n"));
|
|
VideoPortZeroMemory(&TempRegs, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
|
|
TempRegs.Eax = BIOS_PREFIX_VGA_ENAB | BIOS_APERTURE_LB;
|
|
TempRegs.Ecx = BIOS_LINEAR_APERTURE;
|
|
RetVal = VideoPortInt10(phwDeviceExtension, &TempRegs);
|
|
if (RetVal != NO_ERROR)
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "SetModeFromTable_cx() failed VGA-enabled flip to linear aperture\n"));
|
|
return RetVal;
|
|
}
|
|
}
|
|
}
|
|
OUTPD(SCRATCH_REG1, Scratch);
|
|
VideoPortFreeDeviceBase(phwDeviceExtension, MappedBuffer);
|
|
|
|
return NO_ERROR;
|
|
|
|
} /* SetModeFromTable_cx() */
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* void RestoreMemSize_cx(void);
|
|
*
|
|
* DESCRIPTION:
|
|
* Restore the "memory size" register on the card when switching out
|
|
* of a mode which requires this register to be set to a specific value.
|
|
*
|
|
* GLOBALS CHANGED:
|
|
* none
|
|
*
|
|
* CALLED BY:
|
|
* SetCurrentMode_cx() and ATIMPResetHw()
|
|
*
|
|
* AUTHOR:
|
|
* Robert Wolff
|
|
*
|
|
* CHANGE HISTORY:
|
|
*
|
|
* TEST HISTORY:
|
|
*
|
|
***************************************************************************/
|
|
|
|
void RestoreMemSize_cx(void)
|
|
{
|
|
struct query_structure *QueryPtr; /* Query information for the card */
|
|
ULONG Scratch; /* Temporary variable */
|
|
|
|
/*
|
|
* Get a formatted pointer into the query section of HwDeviceExtension.
|
|
*/
|
|
QueryPtr = (struct query_structure *) (phwDeviceExtension->CardInfo);
|
|
|
|
Scratch = INPD(MEM_CNTL) & ~MEM_CNTL_MemSizeMsk;
|
|
switch(QueryPtr->q_memory_size)
|
|
{
|
|
case VRAM_512k:
|
|
Scratch |= MEM_CNTL_MemSize512k;
|
|
break;
|
|
|
|
case VRAM_1mb:
|
|
Scratch |= MEM_CNTL_MemSize1Mb;
|
|
break;
|
|
|
|
case VRAM_2mb:
|
|
Scratch |= MEM_CNTL_MemSize2Mb;
|
|
break;
|
|
|
|
case VRAM_4mb:
|
|
Scratch |= MEM_CNTL_MemSize4Mb;
|
|
break;
|
|
|
|
case VRAM_6mb:
|
|
Scratch |= MEM_CNTL_MemSize6Mb;
|
|
break;
|
|
|
|
case VRAM_8mb:
|
|
Scratch |= MEM_CNTL_MemSize8Mb;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
OUTPD(MEM_CNTL, Scratch);
|
|
|
|
return;
|
|
|
|
} /* RestoreMemSize_cx() */
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* VP_STATUS ShareVideoMemory_cx(RequestPacket, QueryPtr);
|
|
*
|
|
* PVIDEO_REQUEST_PACKET RequestPacket; Request packet with input and output buffers
|
|
* struct query_structure *QueryPtr; Query information for the card
|
|
*
|
|
* DESCRIPTION:
|
|
* Allow applications to do direct screen access through DCI.
|
|
*
|
|
* RETURN VALUE:
|
|
* NO_ERROR if successful
|
|
* error code if failed
|
|
*
|
|
* CALLED BY:
|
|
* IOCTL_VIDEO_SHARE_VIDEO_MEMORY packet of ATIMPStartIO()
|
|
*
|
|
* AUTHOR:
|
|
* Robert Wolff
|
|
*
|
|
* CHANGE HISTORY:
|
|
*
|
|
* TEST HISTORY:
|
|
*
|
|
***************************************************************************/
|
|
|
|
VP_STATUS ShareVideoMemory_cx(PVIDEO_REQUEST_PACKET RequestPacket, struct query_structure *QueryPtr)
|
|
{
|
|
PVIDEO_SHARE_MEMORY InputPtr; /* Pointer to input structure */
|
|
PVIDEO_SHARE_MEMORY_INFORMATION OutputPtr; /* Pointer to output structure */
|
|
PHYSICAL_ADDRESS ShareAddress; /* Physical address of video memory */
|
|
PVOID VirtualAddress; /* Virtual address to map video memory at */
|
|
ULONG SharedViewSize; /* Size of block to share */
|
|
ULONG SpaceType; /* Sparse or dense space? */
|
|
VP_STATUS Status; /* Status to return */
|
|
|
|
/*
|
|
* On some DAC/memory combinations, some modes which require more
|
|
* than 2M of memory (1152x764 24BPP, 1280x1024 24BPP, and
|
|
* 1600x1200 16BPP) will have screen tearing at the 2M boundary.
|
|
*
|
|
* As a workaround, the display driver must start the framebuffer
|
|
* at an offset which will put the 2M boundary at the start of a
|
|
* scanline.
|
|
*
|
|
* Other DAC/memory combinations are unaffected, but since this
|
|
* fix is nearly harmless (only ill effect is to make DCI unusable
|
|
* in these modes), we can catch all future combinations which
|
|
* suffer from this problem by assuming that all DAC/memory
|
|
* combinations are affected.
|
|
*
|
|
* Since this requires anyone making direct access to video memory
|
|
* to be aware of the workaround, we can't make the memory available
|
|
* through DCI.
|
|
*/
|
|
if (((QueryPtr->q_pix_depth == 24) && (QueryPtr->q_desire_x == 1280)) ||
|
|
((QueryPtr->q_pix_depth == 24) && (QueryPtr->q_desire_x == 1152)) ||
|
|
((QueryPtr->q_pix_depth == 16) && (QueryPtr->q_desire_x == 1600)))
|
|
return ERROR_INVALID_FUNCTION;
|
|
|
|
InputPtr = RequestPacket->InputBuffer;
|
|
|
|
if ((InputPtr->ViewOffset > phwDeviceExtension->VideoRamSize) ||
|
|
((InputPtr->ViewOffset + InputPtr->ViewSize) > phwDeviceExtension->VideoRamSize))
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "ShareVideoMemory_cx() - access beyond video memory\n"));
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
RequestPacket->StatusBlock->Information = sizeof(VIDEO_SHARE_MEMORY_INFORMATION);
|
|
|
|
/*
|
|
* Beware: the input buffer and the output buffer are the same buffer,
|
|
* and therefore data should not be copied from one to the other.
|
|
*/
|
|
VirtualAddress = InputPtr->ProcessHandle;
|
|
SharedViewSize = InputPtr->ViewSize;
|
|
|
|
SpaceType = 0;
|
|
#if defined(_ALPHA_)
|
|
/*
|
|
* Use dense space mapping whenever we can, because that will
|
|
* allow us to support DCI and direct GDI access.
|
|
*
|
|
* Dense space is extremely slow with ISA cards on the newer Alphas,
|
|
* because any byte- or word-write requires a read/modify/write
|
|
* operation, and the ALpha can only ever do 64-bit reads when in
|
|
* dense mode. As a result, these operations would always require
|
|
* 4 reads and 2 writes on the ISA bus. Also, some older Alphas
|
|
* don't support dense space mapping.
|
|
*
|
|
* Any Alpha that supports PCI can support dense space mapping, and
|
|
* because the bus is wider and faster, the read/modify/write has
|
|
* less of an impact on performance.
|
|
*/
|
|
if (QueryPtr->q_bus_type == BUS_PCI)
|
|
SpaceType = 4;
|
|
#endif
|
|
|
|
/*
|
|
* NOTE: we are ignoring ViewOffset
|
|
*/
|
|
ShareAddress.QuadPart = phwDeviceExtension->PhysicalFrameAddress.QuadPart;
|
|
|
|
|
|
/*
|
|
* If the LFB is enabled, use ordinary mapping. If we have only
|
|
* the paged aperture, we must map to banked memory. Since the
|
|
* LFB is always aligned on a 4M boundary (8M boundary for 8M
|
|
* aperture), this check for the paged aperture will never falsely
|
|
* detect a LFB as paged.
|
|
*/
|
|
if (phwDeviceExtension->PhysicalFrameAddress.LowPart == 0x0A0000)
|
|
{
|
|
/*
|
|
* On some versions of the DDK, VideoPortMapBankedMemory() is
|
|
* not available. If this is the case, force an error.
|
|
* This routine should be available in all versions of
|
|
* the DDK which support DCI, since it is used for DCI
|
|
* support on cards with banked apertures.
|
|
*/
|
|
#if defined(IOCTL_VIDEO_SHARE_VIDEO_MEMORY)
|
|
Status = VideoPortMapBankedMemory(
|
|
phwDeviceExtension,
|
|
ShareAddress,
|
|
&SharedViewSize,
|
|
&SpaceType,
|
|
&VirtualAddress,
|
|
0x10000, /* Only first 64k of 128k aperture available */
|
|
FALSE, /* No separate read/write banks */
|
|
BankMap_cx, /* Our bank-mapping routine */
|
|
(PVOID) phwDeviceExtension);
|
|
#else
|
|
Status = ERROR_INVALID_FUNCTION;
|
|
#endif
|
|
}
|
|
else /* LFB */
|
|
{
|
|
Status = VideoPortMapMemory(phwDeviceExtension,
|
|
ShareAddress,
|
|
&SharedViewSize,
|
|
&SpaceType,
|
|
&VirtualAddress);
|
|
}
|
|
|
|
OutputPtr = RequestPacket->OutputBuffer;
|
|
OutputPtr->SharedViewOffset = InputPtr->ViewOffset;
|
|
OutputPtr->VirtualAddress = VirtualAddress;
|
|
OutputPtr->SharedViewSize = SharedViewSize;
|
|
|
|
return Status;
|
|
|
|
} /* ShareVideoMemory_cx() */
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
*
|
|
* void BankMap_cx(BankRead, BankWrite, Context);
|
|
*
|
|
* ULONG BankRead; Bank to read
|
|
* ULONG BankWrite; Bank to write
|
|
* PVOID Context; Pointer to hardware-specific information
|
|
*
|
|
* DESCRIPTION:
|
|
* Map the selected bank of video memory into the 64k VGA aperture.
|
|
* We don't support separate read and write banks, so we use BankWrite
|
|
* to set the read/write bank, and ignore BankRead.
|
|
*
|
|
* CALLED BY:
|
|
* This is an entry point, rather than being called
|
|
* by other miniport functions.
|
|
*
|
|
* NOTE:
|
|
* This function is called directly by the memory manager during page
|
|
* fault handling, and so cannot be made pageable.
|
|
*
|
|
* AUTHOR:
|
|
* Robert Wolff
|
|
*
|
|
* CHANGE HISTORY:
|
|
*
|
|
* TEST HISTORY:
|
|
*
|
|
***************************************************************************/
|
|
|
|
void BankMap_cx(ULONG BankRead, ULONG BankWrite, PVOID Context)
|
|
{
|
|
OUTPD(MEM_VGA_WP_SEL, (BankWrite*2) | (BankWrite*2 + 1) << 16);
|
|
OUTPD(MEM_VGA_RP_SEL, (BankWrite*2) | (BankWrite*2 + 1) << 16);
|
|
|
|
return;
|
|
|
|
} /* BankMap_cx() */
|